13124c3e0SJohn Polstra /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3e6209940SPedro F. Giffuni * 49bfb1dfcSJohn Polstra * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 53124c3e0SJohn Polstra * All rights reserved. 63124c3e0SJohn Polstra * 73124c3e0SJohn Polstra * Redistribution and use in source and binary forms, with or without 83124c3e0SJohn Polstra * modification, are permitted provided that the following conditions 93124c3e0SJohn Polstra * are met: 103124c3e0SJohn Polstra * 1. Redistributions of source code must retain the above copyright 113124c3e0SJohn Polstra * notice, this list of conditions and the following disclaimer. 123124c3e0SJohn Polstra * 2. Redistributions in binary form must reproduce the above copyright 133124c3e0SJohn Polstra * notice, this list of conditions and the following disclaimer in the 143124c3e0SJohn Polstra * documentation and/or other materials provided with the distribution. 153124c3e0SJohn Polstra * 163124c3e0SJohn Polstra * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 173124c3e0SJohn Polstra * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 183124c3e0SJohn Polstra * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 193124c3e0SJohn Polstra * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 203124c3e0SJohn Polstra * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 213124c3e0SJohn Polstra * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 223124c3e0SJohn Polstra * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 233124c3e0SJohn Polstra * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 243124c3e0SJohn Polstra * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 253124c3e0SJohn Polstra * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 263124c3e0SJohn Polstra */ 273124c3e0SJohn Polstra 283124c3e0SJohn Polstra #ifndef RTLD_H /* { */ 293124c3e0SJohn Polstra #define RTLD_H 1 303124c3e0SJohn Polstra 315e6220d9SDavid E. O'Brien #include <machine/elf.h> 323124c3e0SJohn Polstra #include <sys/types.h> 33926ea445SJohn Polstra #include <sys/queue.h> 343124c3e0SJohn Polstra 355e6220d9SDavid E. O'Brien #include <elf-hints.h> 362001f720SDoug Rabson #include <link.h> 370e9a2605SKonstantin Belousov #include <stdarg.h> 38168bbfa7SConrad Meyer #include <stdbool.h> 398569deafSKonstantin Belousov #include <setjmp.h> 403124c3e0SJohn Polstra #include <stddef.h> 413124c3e0SJohn Polstra 426d5d786fSAlexander Kabaev #include "rtld_lock.h" 43d5b537d0SJohn Polstra #include "rtld_machdep.h" 44d5b537d0SJohn Polstra 453124c3e0SJohn Polstra #define NEW(type) ((type *) xmalloc(sizeof(type))) 46758ffbfaSKonstantin Belousov #define CNEW(type) ((type *) xcalloc(1, sizeof(type))) 473124c3e0SJohn Polstra 48017246d0SDoug Rabson extern size_t tls_last_offset; 49017246d0SDoug Rabson extern size_t tls_last_size; 50017246d0SDoug Rabson extern size_t tls_static_space; 5178b64846SAlex Richardson extern Elf_Addr tls_dtv_generation; 52017246d0SDoug Rabson extern int tls_max_index; 5395335dd3SStephen J. Kiernan extern size_t ld_static_tls_extra; 54017246d0SDoug Rabson 55ea8577c7SAlan Cox extern int npagesizes; 56ea8577c7SAlan Cox extern size_t *pagesizes; 57e85eaa93SAndrew Turner extern size_t page_size; 58ea8577c7SAlan Cox 5983aa9cc0SKonstantin Belousov extern int main_argc; 6083aa9cc0SKonstantin Belousov extern char **main_argv; 6183aa9cc0SKonstantin Belousov extern char **environ; 6283aa9cc0SKonstantin Belousov 637360ae0fSJohn Polstra struct stat; 643124c3e0SJohn Polstra struct Struct_Obj_Entry; 653124c3e0SJohn Polstra 669bfb1dfcSJohn Polstra /* Lists of shared objects */ 67926ea445SJohn Polstra typedef struct Struct_Objlist_Entry { 68e3975643SJake Burkholder STAILQ_ENTRY(Struct_Objlist_Entry) link; 69926ea445SJohn Polstra struct Struct_Obj_Entry *obj; 70926ea445SJohn Polstra } Objlist_Entry; 71926ea445SJohn Polstra 72e3975643SJake Burkholder typedef STAILQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; 73926ea445SJohn Polstra 7444a028c3SJohn Polstra /* Types of init and fini functions */ 759bfb1dfcSJohn Polstra typedef void (*InitFunc)(void); 7683aa9cc0SKonstantin Belousov typedef void (*InitArrFunc)(int, char **, char **); 779bfb1dfcSJohn Polstra 789bfb1dfcSJohn Polstra /* Lists of shared object dependencies */ 793124c3e0SJohn Polstra typedef struct Struct_Needed_Entry { 803124c3e0SJohn Polstra struct Struct_Needed_Entry *next; 813124c3e0SJohn Polstra struct Struct_Obj_Entry *obj; 823124c3e0SJohn Polstra unsigned long name; /* Offset of name in string table */ 833124c3e0SJohn Polstra } Needed_Entry; 843124c3e0SJohn Polstra 850eb88f20SAlexander Kabaev typedef struct Struct_Name_Entry { 860eb88f20SAlexander Kabaev STAILQ_ENTRY(Struct_Name_Entry) link; 870eb88f20SAlexander Kabaev char name[1]; 880eb88f20SAlexander Kabaev } Name_Entry; 890eb88f20SAlexander Kabaev 90630df077SJohn Polstra /* Lock object */ 91630df077SJohn Polstra typedef struct Struct_LockInfo { 92630df077SJohn Polstra void *context; /* Client context for creating locks */ 93630df077SJohn Polstra void *thelock; /* The one big lock */ 94630df077SJohn Polstra /* Debugging aids. */ 95630df077SJohn Polstra volatile int rcount; /* Number of readers holding lock */ 96630df077SJohn Polstra volatile int wcount; /* Number of writers holding lock */ 97630df077SJohn Polstra /* Methods */ 98630df077SJohn Polstra void *(*lock_create)(void *context); 99630df077SJohn Polstra void (*rlock_acquire)(void *lock); 100630df077SJohn Polstra void (*wlock_acquire)(void *lock); 101630df077SJohn Polstra void (*rlock_release)(void *lock); 102630df077SJohn Polstra void (*wlock_release)(void *lock); 103630df077SJohn Polstra void (*lock_destroy)(void *lock); 104630df077SJohn Polstra void (*context_destroy)(void *context); 105630df077SJohn Polstra } LockInfo; 106630df077SJohn Polstra 1070eb88f20SAlexander Kabaev typedef struct Struct_Ver_Entry { 1080eb88f20SAlexander Kabaev Elf_Word hash; 1090eb88f20SAlexander Kabaev unsigned int flags; 1100eb88f20SAlexander Kabaev const char *name; 1110eb88f20SAlexander Kabaev const char *file; 1120eb88f20SAlexander Kabaev } Ver_Entry; 1130eb88f20SAlexander Kabaev 11434cb87baSKonstantin Belousov typedef struct Struct_Sym_Match_Result { 11534cb87baSKonstantin Belousov const Elf_Sym *sym_out; 11634cb87baSKonstantin Belousov const Elf_Sym *vsymp; 11734cb87baSKonstantin Belousov int vcount; 11834cb87baSKonstantin Belousov } Sym_Match_Result; 11934cb87baSKonstantin Belousov 1200eb88f20SAlexander Kabaev #define VER_INFO_HIDDEN 0x01 1210eb88f20SAlexander Kabaev 1223124c3e0SJohn Polstra /* 1233124c3e0SJohn Polstra * Shared object descriptor. 1243124c3e0SJohn Polstra * 1253124c3e0SJohn Polstra * Items marked with "(%)" are dynamically allocated, and must be freed 1263124c3e0SJohn Polstra * when the structure is destroyed. 12782531605SJohn Polstra * 12882531605SJohn Polstra * CAUTION: It appears that the JDK port peeks into these structures. 12982531605SJohn Polstra * It looks at "next" and "mapbase" at least. Don't add new members 13082531605SJohn Polstra * near the front, until this can be straightened out. 1313124c3e0SJohn Polstra */ 1323124c3e0SJohn Polstra typedef struct Struct_Obj_Entry { 1333124c3e0SJohn Polstra /* 1343124c3e0SJohn Polstra * These two items have to be set right for compatibility with the 1353124c3e0SJohn Polstra * original ElfKit crt1.o. 1363124c3e0SJohn Polstra */ 137757686b1SMarcel Moolenaar Elf_Size magic; /* Magic number (sanity check) */ 138757686b1SMarcel Moolenaar Elf_Size version; /* Version number of struct format */ 1393124c3e0SJohn Polstra 1409fee0541SKonstantin Belousov TAILQ_ENTRY(Struct_Obj_Entry) next; 1413124c3e0SJohn Polstra char *path; /* Pathname of underlying file (%) */ 142da9f2454SMatthew N. Dodd char *origin_path; /* Directory path of origin file */ 143c0274175SMark Johnston int refcount; /* DAG references */ 144c0274175SMark Johnston int holdcount; /* Count of transient references */ 1453124c3e0SJohn Polstra int dl_refcount; /* Number of times loaded by dlopen */ 1463124c3e0SJohn Polstra 1473124c3e0SJohn Polstra /* These items are computed by map_object() or by digest_phdr(). */ 1483124c3e0SJohn Polstra caddr_t mapbase; /* Base address of mapped region */ 1493124c3e0SJohn Polstra size_t mapsize; /* Size of mapped region in bytes */ 1501eab1be0SJohn Birrell Elf_Addr vaddrbase; /* Base address in shared object file */ 1513124c3e0SJohn Polstra caddr_t relocbase; /* Relocation constant = mapbase - vaddrbase */ 1521eab1be0SJohn Birrell const Elf_Dyn *dynamic; /* Dynamic section */ 1533124c3e0SJohn Polstra caddr_t entry; /* Entry point */ 1541eab1be0SJohn Birrell const Elf_Phdr *phdr; /* Program header if it is mapped, else NULL */ 1553124c3e0SJohn Polstra size_t phsize; /* Size of program header in bytes */ 156a607e5d7SJohn Polstra const char *interp; /* Pathname of the interpreter, if any */ 157212f264cSKonstantin Belousov Elf_Word stack_flags; 1583124c3e0SJohn Polstra 159017246d0SDoug Rabson /* TLS information */ 160017246d0SDoug Rabson int tlsindex; /* Index in DTV for this module */ 161017246d0SDoug Rabson void *tlsinit; /* Base address of TLS init block */ 162017246d0SDoug Rabson size_t tlsinitsize; /* Size of TLS init block for this module */ 163017246d0SDoug Rabson size_t tlssize; /* Size of TLS block for this module */ 164017246d0SDoug Rabson size_t tlsoffset; /* Offset of static TLS block for this module */ 165017246d0SDoug Rabson size_t tlsalign; /* Alignment of static TLS block */ 1662f06c66aSKonstantin Belousov size_t tlspoffset; /* p_offset of the static TLS block */ 167017246d0SDoug Rabson 1683124c3e0SJohn Polstra /* Items from the dynamic section. */ 169d5b537d0SJohn Polstra Elf_Addr *pltgot; /* PLT or GOT, depending on architecture */ 1701eab1be0SJohn Birrell const Elf_Rel *rel; /* Relocation entries */ 1713124c3e0SJohn Polstra unsigned long relsize; /* Size in bytes of relocation info */ 17213575fc4SDoug Rabson const Elf_Rela *rela; /* Relocation entries with addend */ 17313575fc4SDoug Rabson unsigned long relasize; /* Size in bytes of addend relocation info */ 174a7d137fcSFangrui Song const Elf_Relr *relr; /* RELR relocation entries */ 175a7d137fcSFangrui Song unsigned long relrsize; /* Size in bytes of RELR relocations */ 1761eab1be0SJohn Birrell const Elf_Rel *pltrel; /* PLT relocation entries */ 1773124c3e0SJohn Polstra unsigned long pltrelsize; /* Size in bytes of PLT relocation info */ 17813575fc4SDoug Rabson const Elf_Rela *pltrela; /* PLT relocation entries with addend */ 17913575fc4SDoug Rabson unsigned long pltrelasize; /* Size in bytes of PLT addend reloc info */ 1801eab1be0SJohn Birrell const Elf_Sym *symtab; /* Symbol table */ 1813124c3e0SJohn Polstra const char *strtab; /* String table */ 1823124c3e0SJohn Polstra unsigned long strsize; /* Size in bytes of string table */ 1833124c3e0SJohn Polstra 1840eb88f20SAlexander Kabaev const Elf_Verneed *verneed; /* Required versions. */ 1850eb88f20SAlexander Kabaev Elf_Word verneednum; /* Number of entries in verneed table */ 1860eb88f20SAlexander Kabaev const Elf_Verdef *verdef; /* Provided versions. */ 1870eb88f20SAlexander Kabaev Elf_Word verdefnum; /* Number of entries in verdef table */ 1880eb88f20SAlexander Kabaev const Elf_Versym *versyms; /* Symbol versions table */ 1890eb88f20SAlexander Kabaev 190b5393d9fSDoug Rabson const Elf_Hashelt *buckets; /* Hash table buckets array */ 1913124c3e0SJohn Polstra unsigned long nbuckets; /* Number of buckets */ 192b5393d9fSDoug Rabson const Elf_Hashelt *chains; /* Hash table chain array */ 193f6265192SKonstantin Belousov unsigned long nchains; /* Number of entries in chain array */ 194f6265192SKonstantin Belousov 195f6265192SKonstantin Belousov Elf32_Word nbuckets_gnu; /* Number of GNU hash buckets*/ 196f6265192SKonstantin Belousov Elf32_Word symndx_gnu; /* 1st accessible symbol on dynsym table */ 197f6265192SKonstantin Belousov Elf32_Word maskwords_bm_gnu; /* Bloom filter words - 1 (bitmask) */ 198f6265192SKonstantin Belousov Elf32_Word shift2_gnu; /* Bloom filter shift count */ 199f6265192SKonstantin Belousov Elf32_Word dynsymcount; /* Total entries in dynsym table */ 200903e0ffdSAlex Richardson const Elf_Addr *bloom_gnu; /* Bloom filter used by GNU hash func */ 201f6265192SKonstantin Belousov const Elf_Hashelt *buckets_gnu; /* GNU hash table bucket array */ 202f6265192SKonstantin Belousov const Elf_Hashelt *chain_zero_gnu; /* GNU hash table value array (Zeroed) */ 2033124c3e0SJohn Polstra 204903e0ffdSAlex Richardson const char *rpath; /* Search path specified in object */ 205903e0ffdSAlex Richardson const char *runpath; /* Search path with different priority */ 2063124c3e0SJohn Polstra Needed_Entry *needed; /* Shared objects needed by this one (%) */ 2078569deafSKonstantin Belousov Needed_Entry *needed_filtees; 2088569deafSKonstantin Belousov Needed_Entry *needed_aux_filtees; 2093124c3e0SJohn Polstra 2100eb88f20SAlexander Kabaev STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we 2110eb88f20SAlexander Kabaev know about. */ 2120eb88f20SAlexander Kabaev Ver_Entry *vertab; /* Versions required /defined by this object */ 2130eb88f20SAlexander Kabaev int vernum; /* Number of entries in vertab */ 2140eb88f20SAlexander Kabaev 21514a55adfSPeter Wemm Elf_Addr init; /* Initialization function to call */ 21614a55adfSPeter Wemm Elf_Addr fini; /* Termination function to call */ 21783aa9cc0SKonstantin Belousov Elf_Addr preinit_array; /* Pre-initialization array of functions */ 21883aa9cc0SKonstantin Belousov Elf_Addr init_array; /* Initialization array of functions */ 21983aa9cc0SKonstantin Belousov Elf_Addr fini_array; /* Termination array of functions */ 22083aa9cc0SKonstantin Belousov int preinit_array_num; /* Number of entries in preinit_array */ 22183aa9cc0SKonstantin Belousov int init_array_num; /* Number of entries in init_array */ 22283aa9cc0SKonstantin Belousov int fini_array_num; /* Number of entries in fini_array */ 22383aa9cc0SKonstantin Belousov 22483aa9cc0SKonstantin Belousov int32_t osrel; /* OSREL note value */ 225e8927aa6SKonstantin Belousov uint32_t fctl0; /* FEATURE_CONTROL note desc[0] value */ 2263124c3e0SJohn Polstra 22749f90ad2SAlexander Kabaev bool mainprog : 1; /* True if this is the main program */ 22849f90ad2SAlexander Kabaev bool rtld : 1; /* True if this is the dynamic linker */ 229082f959aSKonstantin Belousov bool relocated : 1; /* True if processed by relocate_objects() */ 230ff17bc61SKonstantin Belousov bool ver_checked : 1; /* True if processed by rtld_verify_object_versions */ 23149f90ad2SAlexander Kabaev bool textrel : 1; /* True if there are relocations to text seg */ 23249f90ad2SAlexander Kabaev bool symbolic : 1; /* True if generated with "-Bsymbolic" */ 2339daf6cd0SKonstantin Belousov bool deepbind : 1; /* True if loaded with RTLD_DEEPBIND" */ 23449f90ad2SAlexander Kabaev bool bind_now : 1; /* True if all relocations should be made first */ 23549f90ad2SAlexander Kabaev bool traced : 1; /* Already printed in ldd trace output */ 23649f90ad2SAlexander Kabaev bool jmpslots_done : 1; /* Already have relocated the jump slots */ 23749f90ad2SAlexander Kabaev bool init_done : 1; /* Already have added object to init list */ 238283a4f40SKonstantin Belousov bool tls_static : 1; /* Already allocated offset for static TLS */ 23991880e07SKonstantin Belousov bool tls_dynamic : 1; /* A non-static DTV entry has been allocated */ 24049f90ad2SAlexander Kabaev bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */ 24128551690SKonstantin Belousov bool z_origin : 1; /* Process rpath and soname tokens */ 2422b0b4ee3SKonstantin Belousov bool z_nodelete : 1; /* Do not unload the object and dependencies */ 2430d3bc8a9SKonstantin Belousov bool z_noopen : 1; /* Do not load on dlopen */ 2448569deafSKonstantin Belousov bool z_loadfltr : 1; /* Immediately load filtees */ 2453cf98c19SKonstantin Belousov bool z_interpose : 1; /* Interpose all objects but main */ 246bca2f623SKonstantin Belousov bool z_nodeflib : 1; /* Don't search default library path */ 2473de38154SKonstantin Belousov bool z_global : 1; /* Make the object global */ 248c1a81320SKonstantin Belousov bool z_pie : 1; /* Object proclaimed itself PIE executable */ 24978aaab9fSKonstantin Belousov bool z_initfirst : 1; /* Proceed initializers before other objects */ 2505d00c5a6SKonstantin Belousov bool static_tls : 1; /* Needs static TLS allocation */ 2515d00c5a6SKonstantin Belousov bool static_tls_copied : 1; /* Needs static TLS copying */ 2526c3154f6SAlexander Kabaev bool ref_nodel : 1; /* Refcount increased to prevent dlclose */ 2536c3154f6SAlexander Kabaev bool init_scanned: 1; /* Object is already on init list. */ 2546c3154f6SAlexander Kabaev bool on_fini_list: 1; /* Object is already on fini list. */ 255b8fc1b23SKonstantin Belousov bool dag_inited : 1; /* Object has its DAG initialized. */ 2568569deafSKonstantin Belousov bool filtees_loaded : 1; /* Filtees loaded */ 257968a1897SKonstantin Belousov bool filtees_loading : 1; /* In process of filtees loading */ 2586be4b697SKonstantin Belousov bool irelative : 1; /* Object has R_MACHDEP_IRELATIVE relocs */ 259c5ca0d11SKonstantin Belousov bool irelative_nonplt : 1; /* Object has R_MACHDEP_IRELATIVE non-plt relocs */ 2606be4b697SKonstantin Belousov bool gnu_ifunc : 1; /* Object has references to STT_GNU_IFUNC */ 26174b0daf4SKonstantin Belousov bool non_plt_gnu_ifunc : 1; /* Object has non-plt IFUNC references */ 2624903c73fSKonstantin Belousov bool ifuncs_resolved : 1; /* Object ifuncs were already resolved */ 26383aa9cc0SKonstantin Belousov bool crt_no_init : 1; /* Object' crt does not call _init/_fini */ 264f6265192SKonstantin Belousov bool valid_hash_sysv : 1; /* A valid System V hash hash tag is available */ 265f6265192SKonstantin Belousov bool valid_hash_gnu : 1; /* A valid GNU hash tag is available */ 2660e521992SKonstantin Belousov bool dlopened : 1; /* dlopen()-ed (vs. load statically) */ 2679fee0541SKonstantin Belousov bool marker : 1; /* marker on the global obj list */ 268c0274175SMark Johnston bool unholdfree : 1; /* unmap upon last unhold */ 269510fe58cSMark Johnston bool doomed : 1; /* Object cannot be referenced */ 2702001f720SDoug Rabson 27106db20ffSAndrew Turner MD_OBJ_ENTRY; 27206db20ffSAndrew Turner 2736c3154f6SAlexander Kabaev struct link_map linkmap; /* For GDB and dlinfo() */ 27482531605SJohn Polstra Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ 27582531605SJohn Polstra Objlist dagmembers; /* DAG has these members (%) */ 27682531605SJohn Polstra dev_t dev; /* Object's filesystem's device */ 27782531605SJohn Polstra ino_t ino; /* Object's inode number */ 2781acf0dbaSUlrich Spörlein void *priv; /* Platform-dependent */ 2793124c3e0SJohn Polstra } Obj_Entry; 2803124c3e0SJohn Polstra 2813124c3e0SJohn Polstra #define RTLD_MAGIC 0xd550b87a 2823124c3e0SJohn Polstra #define RTLD_VERSION 1 2833124c3e0SJohn Polstra 2849fee0541SKonstantin Belousov TAILQ_HEAD(obj_entry_q, Struct_Obj_Entry); 2859fee0541SKonstantin Belousov 28622a91927SDoug Rabson #define RTLD_STATIC_TLS_EXTRA 128 287017246d0SDoug Rabson 2880eb88f20SAlexander Kabaev /* Flags to be passed into symlook_ family of functions. */ 2890eb88f20SAlexander Kabaev #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ 2905b646fa1SKonstantin Belousov #define SYMLOOK_DLSYM 0x02 /* Return newest versioned symbol. Used by 2910eb88f20SAlexander Kabaev dlsym. */ 292082f959aSKonstantin Belousov #define SYMLOOK_EARLY 0x04 /* Symlook is done during initialization. */ 29314c35647SKonstantin Belousov #define SYMLOOK_IFUNC 0x08 /* Allow IFUNC processing in 29414c35647SKonstantin Belousov reloc_non_plt(). */ 2950eb88f20SAlexander Kabaev 2960d3bc8a9SKonstantin Belousov /* Flags for load_object(). */ 297abf48e83SKonstantin Belousov #define RTLD_LO_NOLOAD 0x01 /* dlopen() specified RTLD_NOLOAD. */ 298abf48e83SKonstantin Belousov #define RTLD_LO_DLOPEN 0x02 /* Load_object() called from dlopen(). */ 299abf48e83SKonstantin Belousov #define RTLD_LO_TRACE 0x04 /* Only tracing. */ 3008569deafSKonstantin Belousov #define RTLD_LO_NODELETE 0x08 /* Loaded object cannot be closed. */ 3018569deafSKonstantin Belousov #define RTLD_LO_FILTEES 0x10 /* Loading filtee. */ 302082f959aSKonstantin Belousov #define RTLD_LO_EARLY 0x20 /* Do not call ctors, postpone it to the 303082f959aSKonstantin Belousov initialization during the image start. */ 30462af2dc3SKonstantin Belousov #define RTLD_LO_IGNSTLS 0x40 /* Do not allocate static TLS */ 3051659238aSKonstantin Belousov #define RTLD_LO_DEEPBIND 0x80 /* Force symbolic for this object */ 3060d3bc8a9SKonstantin Belousov 307c15e7faaSJohn Polstra /* 308c15e7faaSJohn Polstra * Symbol cache entry used during relocation to avoid multiple lookups 309c15e7faaSJohn Polstra * of the same symbol. 310c15e7faaSJohn Polstra */ 311c15e7faaSJohn Polstra typedef struct Struct_SymCache { 312c15e7faaSJohn Polstra const Elf_Sym *sym; /* Symbol table entry */ 313c15e7faaSJohn Polstra const Obj_Entry *obj; /* Shared object which defines it */ 314c15e7faaSJohn Polstra } SymCache; 315c15e7faaSJohn Polstra 3168569deafSKonstantin Belousov /* 3178569deafSKonstantin Belousov * This structure provides a reentrant way to keep a list of objects and 3188569deafSKonstantin Belousov * check which ones have already been processed in some way. 3198569deafSKonstantin Belousov */ 3208569deafSKonstantin Belousov typedef struct Struct_DoneList { 3218569deafSKonstantin Belousov const Obj_Entry **objs; /* Array of object pointers */ 3228569deafSKonstantin Belousov unsigned int num_alloc; /* Allocated size of the array */ 3238569deafSKonstantin Belousov unsigned int num_used; /* Number of array slots used */ 3248569deafSKonstantin Belousov } DoneList; 3258569deafSKonstantin Belousov 3268569deafSKonstantin Belousov struct Struct_RtldLockState { 3278569deafSKonstantin Belousov int lockstate; 328a7bc470aSKonstantin Belousov sigjmp_buf env; 3298569deafSKonstantin Belousov }; 3308569deafSKonstantin Belousov 331bca2f623SKonstantin Belousov struct fill_search_info_args { 332bca2f623SKonstantin Belousov int request; 333bca2f623SKonstantin Belousov unsigned int flags; 334bca2f623SKonstantin Belousov struct dl_serinfo *serinfo; 335bca2f623SKonstantin Belousov struct dl_serpath *serpath; 336bca2f623SKonstantin Belousov char *strspace; 337bca2f623SKonstantin Belousov }; 338bca2f623SKonstantin Belousov 3398569deafSKonstantin Belousov /* 3408569deafSKonstantin Belousov * The pack of arguments and results for the symbol lookup functions. 3418569deafSKonstantin Belousov */ 3428569deafSKonstantin Belousov typedef struct Struct_SymLook { 3438569deafSKonstantin Belousov const char *name; 3448569deafSKonstantin Belousov unsigned long hash; 345f6265192SKonstantin Belousov uint32_t hash_gnu; 3468569deafSKonstantin Belousov const Ver_Entry *ventry; 3478569deafSKonstantin Belousov int flags; 3488569deafSKonstantin Belousov const Obj_Entry *defobj_out; 3498569deafSKonstantin Belousov const Elf_Sym *sym_out; 3508569deafSKonstantin Belousov struct Struct_RtldLockState *lockstate; 3518569deafSKonstantin Belousov } SymLook; 3528569deafSKonstantin Belousov 35347315d6dSKonstantin Belousov enum { 35447315d6dSKonstantin Belousov LD_BIND_NOW = 0, 35547315d6dSKonstantin Belousov LD_PRELOAD, 35647315d6dSKonstantin Belousov LD_LIBMAP, 35747315d6dSKonstantin Belousov LD_LIBRARY_PATH, 35847315d6dSKonstantin Belousov LD_LIBRARY_PATH_FDS, 35947315d6dSKonstantin Belousov LD_LIBMAP_DISABLE, 36047315d6dSKonstantin Belousov LD_BIND_NOT, 36147315d6dSKonstantin Belousov LD_DEBUG, 36247315d6dSKonstantin Belousov LD_ELF_HINTS_PATH, 36347315d6dSKonstantin Belousov LD_LOADFLTR, 36447315d6dSKonstantin Belousov LD_LIBRARY_PATH_RPATH, 36547315d6dSKonstantin Belousov LD_PRELOAD_FDS, 36647315d6dSKonstantin Belousov LD_DYNAMIC_WEAK, 36747315d6dSKonstantin Belousov LD_TRACE_LOADED_OBJECTS, 36847315d6dSKonstantin Belousov LD_UTRACE, 36947315d6dSKonstantin Belousov LD_DUMP_REL_PRE, 37047315d6dSKonstantin Belousov LD_DUMP_REL_POST, 37147315d6dSKonstantin Belousov LD_TRACE_LOADED_OBJECTS_PROGNAME, 37247315d6dSKonstantin Belousov LD_TRACE_LOADED_OBJECTS_FMT1, 37347315d6dSKonstantin Belousov LD_TRACE_LOADED_OBJECTS_FMT2, 37447315d6dSKonstantin Belousov LD_TRACE_LOADED_OBJECTS_ALL, 37547315d6dSKonstantin Belousov LD_SHOW_AUXV, 37647315d6dSKonstantin Belousov LD_STATIC_TLS_EXTRA, 377860c4d94SKonstantin Belousov LD_NO_DL_ITERATE_PHDR_AFTER_FORK, 37847315d6dSKonstantin Belousov }; 37947315d6dSKonstantin Belousov 3800c4f9ecdSKonstantin Belousov void _rtld_error(const char *, ...) __printflike(1, 2) __exported; 38129f36d0bSEd Maste void rtld_die(void) __dead2; 382e24348dfSKonstantin Belousov const char *rtld_strerror(int); 383a08d92deSJessica Clarke Obj_Entry *map_object(int, const char *, const struct stat *, bool); 384e24348dfSKonstantin Belousov void *xcalloc(size_t, size_t); 385e24348dfSKonstantin Belousov void *xmalloc(size_t); 386e24348dfSKonstantin Belousov char *xstrdup(const char *); 387feaae6baSKonstantin Belousov void *xmalloc_aligned(size_t size, size_t align, size_t offset); 38813575fc4SDoug Rabson extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 389d48dde6fSNathan Whitehorn extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */ 390e35ddbe4SKonstantin Belousov extern bool ld_bind_not; 391aef199e5SKonstantin Belousov extern bool ld_fast_sigblock; 39213575fc4SDoug Rabson 393e24348dfSKonstantin Belousov void dump_relocations(Obj_Entry *); 394e24348dfSKonstantin Belousov void dump_obj_relocations(Obj_Entry *); 395e24348dfSKonstantin Belousov void dump_Elf_Rel(Obj_Entry *, const Elf_Rel *, u_long); 396e24348dfSKonstantin Belousov void dump_Elf_Rela(Obj_Entry *, const Elf_Rela *, u_long); 397c5d061c1SMatthew N. Dodd 39813575fc4SDoug Rabson /* 39913575fc4SDoug Rabson * Function declarations. 40013575fc4SDoug Rabson */ 40147315d6dSKonstantin Belousov const char *ld_get_env_var(int idx); 402e85eaa93SAndrew Turner uintptr_t rtld_round_page(uintptr_t); 403e85eaa93SAndrew Turner uintptr_t rtld_trunc_page(uintptr_t); 40429e3a065SEd Maste Elf32_Word elf_hash(const char *); 405185db83cSJohn Polstra const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *, 4068569deafSKonstantin Belousov const Obj_Entry **, int, SymCache *, struct Struct_RtldLockState *); 4072c297acbSMatthew N. Dodd void lockdflt_init(void); 40883aa9cc0SKonstantin Belousov void digest_notes(Obj_Entry *, Elf_Addr, Elf_Addr); 4099fee0541SKonstantin Belousov Obj_Entry *globallist_curr(const Obj_Entry *obj); 4109fee0541SKonstantin Belousov Obj_Entry *globallist_next(const Obj_Entry *obj); 411926ea445SJohn Polstra void obj_free(Obj_Entry *); 412926ea445SJohn Polstra Obj_Entry *obj_new(void); 4134d7f08c8SKonstantin Belousov Obj_Entry *obj_from_addr(const void *); 414d5b537d0SJohn Polstra void _rtld_bind_start(void); 4156be4b697SKonstantin Belousov void *rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def); 4168569deafSKonstantin Belousov void symlook_init(SymLook *, const char *); 4178569deafSKonstantin Belousov int symlook_obj(SymLook *, const Obj_Entry *); 418960f40b8SJessica Clarke void *tls_get_addr_common(struct tcb *tcb, int index, size_t offset); 419017246d0SDoug Rabson void *allocate_tls(Obj_Entry *, void *, size_t, size_t); 420017246d0SDoug Rabson void free_tls(void *, size_t, size_t); 421*48fd0845SJessica Clarke void *allocate_module_tls(struct tcb *tcb, int index); 422017246d0SDoug Rabson bool allocate_tls_offset(Obj_Entry *obj); 423ddab7ee8SDoug Rabson void free_tls_offset(Obj_Entry *obj); 4240eb88f20SAlexander Kabaev const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long); 425ca8c8dc3SKonstantin Belousov int convert_prot(int elfflags); 42663fc4e82SKonstantin Belousov bool check_elf_headers(const Elf_Ehdr *hdr, const char *path); 4273124c3e0SJohn Polstra 42894040887SMatthew N. Dodd /* 42994040887SMatthew N. Dodd * MD function declarations. 43094040887SMatthew N. Dodd */ 43194040887SMatthew N. Dodd int do_copy_relocations(Obj_Entry *); 432082f959aSKonstantin Belousov int reloc_non_plt(Obj_Entry *, Obj_Entry *, int flags, 433082f959aSKonstantin Belousov struct Struct_RtldLockState *); 4344849c3a5SMichal Meloun int reloc_plt(Obj_Entry *, int flags, struct Struct_RtldLockState *); 435082f959aSKonstantin Belousov int reloc_jmpslots(Obj_Entry *, int flags, struct Struct_RtldLockState *); 4366be4b697SKonstantin Belousov int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *); 437c5ca0d11SKonstantin Belousov int reloc_iresolve_nonplt(Obj_Entry *, struct Struct_RtldLockState *); 438082f959aSKonstantin Belousov int reloc_gnu_ifunc(Obj_Entry *, int flags, struct Struct_RtldLockState *); 43933658afdSJessica Clarke void ifunc_init(Elf_Auxinfo *[__min_size(AT_COUNT)]); 44041fc6f68SMarius Strobl void init_pltgot(Obj_Entry *); 441017246d0SDoug Rabson void allocate_initial_tls(Obj_Entry *); 44294040887SMatthew N. Dodd 4433124c3e0SJohn Polstra #endif /* } */ 444