xref: /aosp_15_r20/bionic/linker/linker_soinfo.h (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 #include <link.h>
32 
33 #include <list>
34 #include <memory>
35 #include <string>
36 #include <vector>
37 
38 #include "async_safe/CHECK.h"
39 #include "linker_namespaces.h"
40 #include "linker_tls.h"
41 #include "private/bionic_elf_tls.h"
42 #include "private/bionic_globals.h"
43 
44 #define FLAG_LINKED           0x00000001
45 #define FLAG_EXE              0x00000004 // The main executable
46 #define FLAG_LINKER           0x00000010 // The linker itself
47 #define FLAG_GNU_HASH         0x00000040 // uses gnu hash
48 #define FLAG_MAPPED_BY_CALLER 0x00000080 // the map is reserved by the caller
49                                          // and should not be unmapped
50 #define FLAG_IMAGE_LINKED     0x00000100 // Is image linked - this is a guard on link_image.
51                                          // The difference between this flag and
52                                          // FLAG_LINKED is that FLAG_LINKED
53                                          // means is set when load_group is
54                                          // successfully loaded whereas this
55                                          // flag is set to avoid linking image
56                                          // when link_image called for the
57                                          // second time. This situation happens
58                                          // when load group is crossing
59                                          // namespace boundary twice and second
60                                          // local group depends on the same libraries.
61 #define FLAG_RESERVED         0x00000200 // This flag was set when there is at least one
62                                          // outstanding thread_local dtor
63                                          // registered with this soinfo. In such
64                                          // a case the actual unload is
65                                          // postponed until the last thread_local
66                                          // destructor associated with this
67                                          // soinfo is executed and this flag is
68                                          // unset.
69 #define FLAG_PRELINKED        0x00000400 // prelink_image has successfully processed this soinfo
70 #define FLAG_GLOBALS_TAGGED   0x00000800 // globals have been tagged by MTE.
71 #define FLAG_NEW_SOINFO       0x40000000 // new soinfo format
72 
73 #define SOINFO_VERSION 6
74 
75 ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
76 
77 typedef void (*linker_dtor_function_t)();
78 typedef void (*linker_ctor_function_t)(int, char**, char**);
79 
80 // An entry within a SymbolLookupList.
81 struct SymbolLookupLib {
82   uint32_t gnu_maskwords_ = 0;
83   uint32_t gnu_shift2_ = 0;
84   ElfW(Addr)* gnu_bloom_filter_ = nullptr;
85 
86   const char* strtab_;
87   size_t strtab_size_;
88   const ElfW(Sym)* symtab_;
89   const ElfW(Versym)* versym_;
90 
91   const uint32_t* gnu_chain_;
92   size_t gnu_nbucket_;
93   uint32_t* gnu_bucket_;
94 
95   soinfo* si_ = nullptr;
96 
needs_sysv_lookupSymbolLookupLib97   bool needs_sysv_lookup() const { return si_ != nullptr && gnu_bloom_filter_ == nullptr; }
98 };
99 
100 // A list of libraries to search for a symbol.
101 class SymbolLookupList {
102   std::vector<SymbolLookupLib> libs_;
103   SymbolLookupLib sole_lib_;
104   const SymbolLookupLib* begin_;
105   const SymbolLookupLib* end_;
106   size_t slow_path_count_ = 0;
107 
108  public:
109   explicit SymbolLookupList(soinfo* si);
110   SymbolLookupList(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
111   void set_dt_symbolic_lib(soinfo* symbolic_lib);
112 
begin()113   const SymbolLookupLib* begin() const { return begin_; }
end()114   const SymbolLookupLib* end() const { return end_; }
needs_slow_path()115   bool needs_slow_path() const { return slow_path_count_ > 0; }
116 };
117 
118 class SymbolName {
119  public:
SymbolName(const char * name)120   explicit SymbolName(const char* name)
121       : name_(name), has_elf_hash_(false), has_gnu_hash_(false),
122         elf_hash_(0), gnu_hash_(0) { }
123 
get_name()124   const char* get_name() {
125     return name_;
126   }
127 
128   uint32_t elf_hash();
129   uint32_t gnu_hash();
130 
131  private:
132   const char* name_;
133   bool has_elf_hash_;
134   bool has_gnu_hash_;
135   uint32_t elf_hash_;
136   uint32_t gnu_hash_;
137 
138   DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolName);
139 };
140 
141 struct version_info {
version_infoversion_info142   constexpr version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {}
143 
144   uint32_t elf_hash;
145   const char* name;
146   const soinfo* target_si;
147 };
148 
149 // TODO(dimitry): remove reference from soinfo member functions to this class.
150 class VersionTracker;
151 
152 struct soinfo_tls {
153   TlsSegment segment;
154   size_t module_id = kTlsUninitializedModuleId;
155 };
156 
157 #if defined(__work_around_b_24465209__)
158 #define SOINFO_NAME_LEN 128
159 #endif
160 
161 struct soinfo {
162 #if defined(__work_around_b_24465209__)
163  private:
164   char old_name_[SOINFO_NAME_LEN];
165 #endif
166  public:
167   const ElfW(Phdr)* phdr;
168   size_t phnum;
169 #if defined(__work_around_b_24465209__)
170   ElfW(Addr) unused0; // DO NOT USE, maintained for compatibility.
171 #endif
172   ElfW(Addr) base;
173   size_t size;
174 
175 #if defined(__work_around_b_24465209__)
176   uint32_t unused1;  // DO NOT USE, maintained for compatibility.
177 #endif
178 
179   ElfW(Dyn)* dynamic;
180 
181 #if defined(__work_around_b_24465209__)
182   uint32_t unused2; // DO NOT USE, maintained for compatibility
183   uint32_t unused3; // DO NOT USE, maintained for compatibility
184 #endif
185 
186   soinfo* next;
187  private:
188   uint32_t flags_;
189 
190   const char* strtab_;
191   ElfW(Sym)* symtab_;
192 
193   size_t nbucket_;
194   size_t nchain_;
195   uint32_t* bucket_;
196   uint32_t* chain_;
197 
198 #if !defined(__LP64__)
199   ElfW(Addr)** unused4; // DO NOT USE, maintained for compatibility
200 #endif
201 
202 #if defined(USE_RELA)
203   ElfW(Rela)* plt_rela_;
204   size_t plt_rela_count_;
205 
206   ElfW(Rela)* rela_;
207   size_t rela_count_;
208 #else
209   ElfW(Rel)* plt_rel_;
210   size_t plt_rel_count_;
211 
212   ElfW(Rel)* rel_;
213   size_t rel_count_;
214 #endif
215 
216   linker_ctor_function_t* preinit_array_;
217   size_t preinit_array_count_;
218 
219   linker_ctor_function_t* init_array_;
220   size_t init_array_count_;
221   linker_dtor_function_t* fini_array_;
222   size_t fini_array_count_;
223 
224   linker_ctor_function_t init_func_;
225   linker_dtor_function_t fini_func_;
226 
227 #if defined(__arm__)
228  public:
229   // ARM EABI section used for stack unwinding.
230   uint32_t* ARM_exidx;
231   size_t ARM_exidx_count;
232  private:
233 #endif
234   size_t ref_count_;
235  public:
236   link_map link_map_head;
237 
238   bool constructors_called;
239 
240   // When you read a virtual address from the ELF file, add this
241   // value to get the corresponding address in the process' address space.
242   ElfW(Addr) load_bias;
243 
244 #if !defined(__LP64__)
245   bool has_text_relocations;
246 #endif
247   bool has_DT_SYMBOLIC;
248 
249  public:
250   soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
251          off64_t file_offset, int rtld_flags);
252   ~soinfo();
253 
254   void call_constructors();
255   void call_destructors();
256   void call_pre_init_constructors();
257   bool prelink_image(bool deterministic_memtag_globals = false);
258   bool link_image(const SymbolLookupList& lookup_list, soinfo* local_group_root,
259                   const android_dlextinfo* extinfo, size_t* relro_fd_offset);
260   bool protect_relro();
261 
262   void tag_globals(bool deterministic_memtag_globals);
263   ElfW(Addr) apply_memtag_if_mte_globals(ElfW(Addr) sym_addr) const;
264 
265   void add_child(soinfo* child);
266   void remove_all_links();
267 
268   ino_t get_st_ino() const;
269   dev_t get_st_dev() const;
270   off64_t get_file_offset() const;
271 
272   uint32_t get_rtld_flags() const;
273   uint32_t get_dt_flags_1() const;
274   void set_dt_flags_1(uint32_t dt_flags_1);
275 
276   soinfo_list_t& get_children();
277   const soinfo_list_t& get_children() const;
278 
279   soinfo_list_t& get_parents();
280 
281   const ElfW(Sym)* find_symbol_by_name(SymbolName& symbol_name, const version_info* vi) const;
282 
283   ElfW(Sym)* find_symbol_by_address(const void* addr);
284 
resolve_symbol_addresssoinfo285   ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const {
286     if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) {
287       return call_ifunc_resolver(s->st_value + load_bias);
288     }
289 
290     return static_cast<ElfW(Addr)>(s->st_value + load_bias);
291   }
292 
293   const char* get_string(ElfW(Word) index) const;
294   bool can_unload() const;
295   bool is_gnu_hash() const;
296 
has_min_versionsoinfo297   bool inline has_min_version(uint32_t min_version __unused) const {
298 #if defined(__work_around_b_24465209__)
299     return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
300 #else
301     // If you make this return non-true in the case where
302     // __work_around_b_24465209__ is not defined, you will have to change
303     // memtag_dynamic_entries() and vma_names().
304     return true;
305 #endif
306   }
307 
ElfWsoinfo308   const ElfW(Versym)* get_versym_table() const {
309     return has_min_version(2) ? versym_ : nullptr;
310   }
311 
312   bool is_linked() const;
313   bool is_linker() const;
314   bool is_main_executable() const;
315 
316   void set_linked();
317   void set_linker_flag();
318   void set_main_executable();
319   void set_nodelete();
320 
321   size_t increment_ref_count();
322   size_t decrement_ref_count();
323   size_t get_ref_count() const;
324 
325   soinfo* get_local_group_root() const;
326 
327   void set_soname(const char* soname);
328   const char* get_soname() const;
329   void set_realpath(const char* path);
330   const char* get_realpath() const;
331   const ElfW(Versym)* get_versym(size_t n) const;
332   ElfW(Addr) get_verneed_ptr() const;
333   size_t get_verneed_cnt() const;
334   ElfW(Addr) get_verdef_ptr() const;
335   size_t get_verdef_cnt() const;
336 
337   int get_target_sdk_version() const;
338 
339   void set_dt_runpath(const char *);
340   const std::vector<std::string>& get_dt_runpath() const;
341   android_namespace_t* get_primary_namespace();
342   void add_secondary_namespace(android_namespace_t* secondary_ns);
343   android_namespace_list_t& get_secondary_namespaces();
344 
get_tlssoinfo345   soinfo_tls* get_tls() const {
346     return has_min_version(5) ? tls_.get() : nullptr;
347   }
348 
349   void set_mapped_by_caller(bool reserved_map);
350   bool is_mapped_by_caller() const;
351 
352   uintptr_t get_handle() const;
353   void generate_handle();
354   void* to_handle();
355 
356   SymbolLookupLib get_lookup_lib();
357 
358   void set_gap_start(ElfW(Addr) gap_start);
359   ElfW(Addr) get_gap_start() const;
360 
361   void set_gap_size(size_t gap_size);
362   size_t get_gap_size() const;
363 
memtag_dynamic_entriessoinfo364   const memtag_dynamic_entries_t* memtag_dynamic_entries() const {
365 #ifdef __aarch64__
366 #ifdef __work_around_b_24465209__
367 #error "Assuming aarch64 does not use versioned soinfo."
368 #endif
369     return &memtag_dynamic_entries_;
370 #endif
371     return nullptr;
372   }
memtag_globalssoinfo373   void* memtag_globals() const {
374     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
375     return entries ? entries->memtag_globals : nullptr;
376   }
memtag_globalsszsoinfo377   size_t memtag_globalssz() const {
378     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
379     return entries ? entries->memtag_globalssz : 0U;
380   }
has_memtag_modesoinfo381   bool has_memtag_mode() const {
382     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
383     return entries ? entries->has_memtag_mode : false;
384   }
memtag_modesoinfo385   unsigned memtag_mode() const {
386     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
387     return entries ? entries->memtag_mode : 0U;
388   }
memtag_heapsoinfo389   bool memtag_heap() const {
390     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
391     return entries ? entries->memtag_heap : false;
392   }
memtag_stacksoinfo393   bool memtag_stack() const {
394     const memtag_dynamic_entries_t* entries = memtag_dynamic_entries();
395     return entries ? entries->memtag_stack : false;
396   }
397 
set_should_pad_segmentssoinfo398   void set_should_pad_segments(bool should_pad_segments) {
399    should_pad_segments_ = should_pad_segments;
400   }
should_pad_segmentssoinfo401   bool should_pad_segments() const { return should_pad_segments_; }
should_tag_memtag_globalssoinfo402   bool should_tag_memtag_globals() const {
403     return !is_linker() && memtag_globals() && memtag_globalssz() > 0 && __libc_mte_enabled();
404   }
vma_namessoinfo405   std::list<std::string>* vma_names() {
406 #ifdef __aarch64__
407 #ifdef __work_around_b_24465209__
408 #error "Assuming aarch64 does not use versioned soinfo."
409 #endif
410     return &vma_names_;
411 #endif
412     return nullptr;
413 };
414 
set_should_use_16kib_app_compatsoinfo415   void set_should_use_16kib_app_compat(bool should_use_16kib_app_compat) {
416     should_use_16kib_app_compat_ = should_use_16kib_app_compat;
417   }
should_use_16kib_app_compatsoinfo418   bool should_use_16kib_app_compat() const { return should_use_16kib_app_compat_; }
419 
set_compat_relro_startsoinfo420   void set_compat_relro_start(ElfW(Addr) start) { compat_relro_start_ = start; }
compat_relro_startsoinfo421   ElfW(Addr) compat_relro_start() const { return compat_relro_start_; }
422 
set_compat_relro_sizesoinfo423   void set_compat_relro_size(ElfW(Addr) size) { compat_relro_size_ = size; }
compat_relro_sizesoinfo424   ElfW(Addr) compat_relro_size() const { return compat_relro_start_; }
425 
426  private:
427   bool is_image_linked() const;
428   void set_image_linked();
429 
430   const ElfW(Sym)* gnu_lookup(SymbolName& symbol_name, const version_info* vi) const;
431   const ElfW(Sym)* elf_lookup(SymbolName& symbol_name, const version_info* vi) const;
432   ElfW(Sym)* gnu_addr_lookup(const void* addr);
433   ElfW(Sym)* elf_addr_lookup(const void* addr);
434 
435  public:
436   bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
437                            const char* sym_name, const version_info** vi);
438 
439  private:
440   bool relocate(const SymbolLookupList& lookup_list);
441 
442   // This part of the structure is only available
443   // when FLAG_NEW_SOINFO is set in this->flags.
444   uint32_t version_;
445 
446   // version >= 0
447   dev_t st_dev_;
448   ino_t st_ino_;
449 
450   // dependency graph
451   soinfo_list_t children_;
452   soinfo_list_t parents_;
453 
454   // version >= 1
455   off64_t file_offset_;
456   uint32_t rtld_flags_;
457   uint32_t dt_flags_1_;
458   size_t strtab_size_;
459 
460   // version >= 2
461 
462   size_t gnu_nbucket_;
463   uint32_t* gnu_bucket_;
464   uint32_t* gnu_chain_;
465   uint32_t gnu_maskwords_;
466   uint32_t gnu_shift2_;
467   ElfW(Addr)* gnu_bloom_filter_;
468 
469   soinfo* local_group_root_;
470 
471   uint8_t* android_relocs_;
472   size_t android_relocs_size_;
473 
474   std::string soname_;
475   std::string realpath_;
476 
477   const ElfW(Versym)* versym_;
478 
479   ElfW(Addr) verdef_ptr_;
480   size_t verdef_cnt_;
481 
482   ElfW(Addr) verneed_ptr_;
483   size_t verneed_cnt_;
484 
485   int target_sdk_version_;
486 
487   // version >= 3
488   std::vector<std::string> dt_runpath_;
489   android_namespace_t* primary_namespace_;
490   android_namespace_list_t secondary_namespaces_;
491   uintptr_t handle_;
492 
493   friend soinfo* get_libdl_info(const soinfo& linker_si);
494 
495   // version >= 4
496   ElfW(Relr)* relr_;
497   size_t relr_count_;
498 
499   // version >= 5
500   std::unique_ptr<soinfo_tls> tls_;
501   std::vector<TlsDynamicResolverArg> tlsdesc_args_;
502 
503   // version >= 6
504   ElfW(Addr) gap_start_;
505   size_t gap_size_;
506 
507   // __aarch64__ only, which does not use versioning.
508   memtag_dynamic_entries_t memtag_dynamic_entries_;
509   std::list<std::string> vma_names_;
510 
511   // Pad gaps between segments when memory mapping?
512   bool should_pad_segments_ = false;
513 
514   // Use app compat mode when loading 4KiB max-page-size ELFs on 16KiB page-size devices?
515   bool should_use_16kib_app_compat_ = false;
516 
517   // RELRO region for 16KiB compat loading
518   ElfW(Addr) compat_relro_start_ = 0;
519   ElfW(Addr) compat_relro_size_ = 0;
520 };
521 
522 // This function is used by dlvsym() to calculate hash of sym_ver
523 uint32_t calculate_elf_hash(const char* name);
524 
525 const char* fix_dt_needed(const char* dt_needed, const char* sopath);
526 
527 template<typename F>
for_each_dt_needed(const soinfo * si,F action)528 void for_each_dt_needed(const soinfo* si, F action) {
529   for (const ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
530     if (d->d_tag == DT_NEEDED) {
531       action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath()));
532     }
533   }
534 }
535 
536 const ElfW(Sym)* soinfo_do_lookup(const char* name, const version_info* vi,
537                                   soinfo** si_found_in, const SymbolLookupList& lookup_list);
538