| /* vi: set sw=4 ts=4: */ |
| /* |
| * Copyright (C) 2000-2006 by Erik Andersen <andersen@codepoet.org> |
| * |
| * GNU Lesser General Public License version 2.1 or later. |
| */ |
| |
| #ifndef _LD_HASH_H_ |
| #define _LD_HASH_H_ |
| |
| #ifndef RTLD_NEXT |
| #define RTLD_NEXT ((void*)-1) |
| #endif |
| |
| struct init_fini { |
| struct elf_resolve **init_fini; |
| unsigned long nlist; /* Number of entries in init_fini */ |
| }; |
| |
| struct dyn_elf { |
| struct elf_resolve * dyn; |
| struct dyn_elf * next_handle; /* Used by dlopen et al. */ |
| struct init_fini init_fini; |
| struct dyn_elf * next; |
| struct dyn_elf * prev; |
| }; |
| |
| struct symbol_ref { |
| const ElfW(Sym) *sym; |
| struct elf_resolve *tpnt; |
| }; |
| |
| /* Structure to describe a single list of scope elements. The lookup |
| functions get passed an array of pointers to such structures. */ |
| struct r_scope_elem { |
| struct elf_resolve **r_list; /* Array of maps for the scope. */ |
| unsigned int r_nlist; /* Number of entries in the scope. */ |
| struct r_scope_elem *next; |
| }; |
| |
| struct elf_resolve { |
| /* These entries must be in this order to be compatible with the interface used |
| by gdb to obtain the list of symbols. */ |
| DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */ |
| char *libname; /* Absolute file name object was found in. */ |
| ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */ |
| struct elf_resolve * next; |
| struct elf_resolve * prev; |
| /* Nothing after this address is used by gdb. */ |
| |
| #if defined(USE_TLS) && USE_TLS |
| /* Thread-local storage related info. */ |
| |
| /* Start of the initialization image. */ |
| void *l_tls_initimage; |
| /* Size of the initialization image. */ |
| size_t l_tls_initimage_size; |
| /* Size of the TLS block. */ |
| size_t l_tls_blocksize; |
| /* Alignment requirement of the TLS block. */ |
| size_t l_tls_align; |
| /* Offset of first byte module alignment. */ |
| size_t l_tls_firstbyte_offset; |
| # ifndef NO_TLS_OFFSET |
| # define NO_TLS_OFFSET 0 |
| # endif |
| /* For objects present at startup time: offset in the static TLS block. */ |
| ptrdiff_t l_tls_offset; |
| /* Index of the module in the dtv array. */ |
| size_t l_tls_modid; |
| /* Nonzero if _dl_init_static_tls should be called for this module */ |
| unsigned int l_need_tls_init:1; |
| #endif |
| |
| ElfW(Addr) mapaddr; |
| #ifdef __LDSO_STANDALONE_SUPPORT__ |
| /* Store the entry point from the ELF header (e_entry) */ |
| ElfW(Addr) l_entry; |
| #endif |
| enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; |
| /* This is the local scope of the shared object */ |
| struct r_scope_elem symbol_scope; |
| unsigned short usage_count; |
| unsigned short int init_flag; |
| unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ |
| Elf_Symndx nbucket; |
| |
| #ifdef __LDSO_GNU_HASH_SUPPORT__ |
| /* Data needed to support GNU hash style */ |
| Elf32_Word l_gnu_bitmask_idxbits; |
| Elf32_Word l_gnu_shift; |
| const ElfW(Addr) *l_gnu_bitmask; |
| |
| union |
| { |
| const Elf32_Word *l_gnu_chain_zero; |
| const Elf_Symndx *elf_buckets; |
| }; |
| #else |
| Elf_Symndx *elf_buckets; |
| #endif |
| |
| struct init_fini_list *init_fini; |
| struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ |
| /* |
| * These are only used with ELF style shared libraries |
| */ |
| Elf_Symndx nchain; |
| |
| #ifdef __LDSO_GNU_HASH_SUPPORT__ |
| union |
| { |
| const Elf32_Word *l_gnu_buckets; |
| const Elf_Symndx *chains; |
| }; |
| #else |
| Elf_Symndx *chains; |
| #endif |
| unsigned long dynamic_info[DYNAMIC_SIZE]; |
| |
| unsigned long n_phent; |
| ElfW(Phdr) * ppnt; |
| |
| ElfW(Addr) relro_addr; |
| size_t relro_size; |
| |
| dev_t st_dev; /* device */ |
| ino_t st_ino; /* inode */ |
| |
| #ifdef __powerpc__ |
| /* this is used to store the address of relocation data words, so |
| * we don't have to calculate it every time, which requires a divide */ |
| unsigned long data_words; |
| #endif |
| |
| #ifdef __FDPIC__ |
| /* Every loaded module holds a hashtable of function descriptors of |
| functions defined in it, such that it's easy to release the |
| memory when the module is dlclose()d. */ |
| struct funcdesc_ht *funcdesc_ht; |
| #endif |
| }; |
| |
| #define RELOCS_DONE 0x000001 |
| #define JMP_RELOCS_DONE 0x000002 |
| #define INIT_FUNCS_CALLED 0x000004 |
| #define FINI_FUNCS_CALLED 0x000008 |
| #define DL_OPENED 0x000010 |
| #define DL_RESERVED 0x000020 |
| |
| extern struct dyn_elf * _dl_symbol_tables; |
| extern struct elf_resolve * _dl_loaded_modules; |
| extern struct dyn_elf * _dl_handles; |
| |
| extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, |
| DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info, |
| unsigned long dynamic_addr, unsigned long dynamic_size); |
| |
| extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope, |
| struct elf_resolve *mytpnt, int type_class, |
| struct symbol_ref *symbol); |
| |
| extern int _dl_linux_dynamic_link(void); |
| |
| extern char * _dl_library_path; |
| extern char * _dl_not_lazy; |
| |
| static __inline__ int _dl_symbol(char * name) |
| { |
| if (name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') |
| return 0; |
| return 1; |
| } |
| |
| #define LD_ERROR_NOFILE 1 |
| #define LD_ERROR_NOZERO 2 |
| #define LD_ERROR_NOTELF 3 |
| #define LD_ERROR_NOTMAGIC 4 |
| #define LD_ERROR_NOTDYN 5 |
| #define LD_ERROR_MMAP_FAILED 6 |
| #define LD_ERROR_NODYNAMIC 7 |
| #define LD_ERROR_TLS_FAILED 8 |
| #define LD_WRONG_RELOCS 9 |
| #define LD_BAD_HANDLE 10 |
| #define LD_NO_SYMBOL 11 |
| |
| #endif /* _LD_HASH_H_ */ |