diff options
Diffstat (limited to 'ldso/include')
-rw-r--r-- | ldso/include/dl-defs.h | 2 | ||||
-rw-r--r-- | ldso/include/dl-elf.h | 50 | ||||
-rw-r--r-- | ldso/include/dl-hash.h | 35 | ||||
-rw-r--r-- | ldso/include/ldso.h | 9 |
4 files changed, 80 insertions, 16 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index 2d6303cfe..cbbaa3cea 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -225,7 +225,7 @@ typedef struct { /* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been dlopen()ed successfully, when they're dlclose()d. */ #ifndef DL_LIB_UNMAP -# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->loadaddr, (LEN))) +# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->mapaddr, (LEN))) #endif /* Define this to verify that a library named LIBNAME, whose ELF diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index cbb2100b1..40c88b9da 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -15,6 +15,7 @@ /* Forward declarations for stuff defined in ld_hash.h */ struct dyn_elf; struct elf_resolve; +struct r_scope_elem; #include <dl-defs.h> #ifdef __LDSO_CACHE_SUPPORT__ @@ -30,16 +31,16 @@ static __inline__ void _dl_unmap_cache(void) { } extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size); extern int _dl_parse_relocation_information(struct dyn_elf *rpnt, - unsigned long rel_addr, unsigned long rel_size); + struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size); extern struct elf_resolve * _dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, int trace_loaded_objects); extern struct elf_resolve * _dl_load_elf_shared_library(int secure, - struct dyn_elf **rpnt, char *libname); + struct dyn_elf **rpnt, const char *libname); extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, int trace_loaded_objects); extern int _dl_linux_resolve(void); -extern int _dl_fixup(struct dyn_elf *rpnt, int flag); +extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag); extern void _dl_protect_relro (struct elf_resolve *l); /* @@ -84,24 +85,47 @@ extern void _dl_protect_relro (struct elf_resolve *l); #endif /* OS and/or GNU dynamic extensions */ + +#define OS_NUM_BASE 1 /* for DT_RELOCCOUNT */ + #ifdef __LDSO_GNU_HASH_SUPPORT__ -# define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */ +# define OS_NUM_GNU_HASH 1 /* for DT_GNU_HASH entry */ +#else +# define OS_NUM_GNU_HASH 0 +#endif + +#ifdef __LDSO_PRELINK_SUPPORT__ +# define OS_NUM_PRELINK 6 /* for DT_GNU_PRELINKED entry */ #else -# define OS_NUM 1 /* for DT_RELOCCOUNT entry */ +# define OS_NUM_PRELINK 0 #endif +#define OS_NUM (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK) + #ifndef ARCH_DYNAMIC_INFO /* define in arch specific code, if needed */ # define ARCH_NUM 0 #endif -#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM) +#define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM) /* Keep ARCH specific entries into dynamic section at the end of the array */ #define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM) #ifdef __LDSO_GNU_HASH_SUPPORT__ /* GNU hash comes just after the relocation count */ # define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1) +#else +# define DT_GNU_HASH_IDX DT_RELCONT_IDX +#endif + +#ifdef __LDSO_PRELINK_SUPPORT__ +/* GNU prelink comes just after the GNU hash if present */ +#define DT_GNU_PRELINKED_IDX (DT_GNU_HASH_IDX + 1) +#define DT_GNU_CONFLICT_IDX (DT_GNU_HASH_IDX + 2) +#define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3) +#define DT_GNU_LIBLIST_IDX (DT_GNU_HASH_IDX + 4) +#define DT_GNU_LIBLISTSZ_IDX (DT_GNU_HASH_IDX + 5) +#define DT_CHECKSUM_IDX (DT_GNU_HASH_IDX + 6) #endif extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], @@ -150,6 +174,20 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info if (dpnt->d_tag == DT_GNU_HASH) dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr; #endif +#ifdef __LDSO_PRELINK_SUPPORT__ + if (dpnt->d_tag == DT_GNU_PRELINKED) + dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_GNU_CONFLICT) + dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr; + if (dpnt->d_tag == DT_GNU_CONFLICTSZ) + dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_GNU_LIBLIST) + dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr; + if (dpnt->d_tag == DT_GNU_LIBLISTSZ) + dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_CHECKSUM) + dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val; +#endif } #ifdef ARCH_DYNAMIC_INFO else { diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index 34bed1b4b..b1927e49a 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -25,6 +25,19 @@ struct dyn_elf { struct dyn_elf * prev; }; +struct sym_val { + const ElfW(Sym) *s; + struct elf_resolve *m; +}; + +/* 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. */ @@ -60,8 +73,13 @@ struct elf_resolve { #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; - struct dyn_elf * symbol_scope; + /* 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. */ @@ -128,6 +146,7 @@ struct elf_resolve { #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; @@ -139,17 +158,17 @@ extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, /* Only need extra arg with some configurations */ #if !((defined(USE_TLS) && USE_TLS) || defined __FDPIC__) -# define _dl_lookup_hash(n, r, m, c, tpntp) _dl_lookup_hash(n, r, m, c) -# define _dl_find_hash(n, r, m, t, tpntp) _dl_find_hash(n, r, m, t) +# define _dl_lookup_hash(n, r, m, s, c, tpnt) _dl_lookup_hash(n, r, m, s, c) +# define _dl_find_hash(n, r, m, s, t, tpntp) _dl_find_hash(n, r, m, s, t) #endif -extern char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt, - struct elf_resolve *mytpnt, int type_class, +extern char *_dl_lookup_hash(const char *name, struct r_scope_elem *scope, + struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class, struct elf_resolve **tpntp); -static __always_inline char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, - struct elf_resolve *mytpnt, int type_class, +static __always_inline char *_dl_find_hash(const char *name, struct r_scope_elem *scope, + struct elf_resolve *mytpnt, struct sym_val *symbol, int type_class, struct elf_resolve **tpntp) { - return _dl_lookup_hash(name, rpnt, mytpnt, type_class, tpntp); + return _dl_lookup_hash(name, scope, mytpnt, symbol, type_class, tpntp); } extern int _dl_linux_dynamic_link(void); diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 69b5dd75a..9aa610e7b 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -27,6 +27,7 @@ /* Pull in compiler and arch stuff */ #include <stdlib.h> #include <stdarg.h> +#include <stddef.h> /* for ptrdiff_t */ #define _FCNTL_H #include <bits/fcntl.h> #include <bits/wordsize.h> @@ -72,6 +73,12 @@ extern char *_dl_preload; /* Things to be loaded before the libs */ extern char *_dl_ldsopath; /* Where the shared lib loader was found */ extern const char *_dl_progname; /* The name of the executable being run */ extern size_t _dl_pagesize; /* Store the page size for use later */ +#ifdef __LDSO_PRELINK_SUPPORT__ +extern char *_dl_trace_prelink; /* Library for prelinking trace */ +extern struct elf_resolve *_dl_trace_prelink_map; /* Library map for prelinking trace */ +#else +#define _dl_trace_prelink 0 +#endif #if defined(USE_TLS) && USE_TLS extern void _dl_add_to_slotinfo (struct link_map *l); @@ -144,7 +151,7 @@ extern void _dl_dprintf(int, const char *, ...); # define DL_GET_READY_TO_RUN_EXTRA_ARGS #endif -extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, +extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv DL_GET_READY_TO_RUN_EXTRA_PARMS); |