From 6630516b0a000e0ac9769eceda72881f788b23b0 Mon Sep 17 00:00:00 2001 From: Carmelo Amoroso Date: Wed, 7 Nov 2007 15:14:50 +0000 Subject: Added support for GNU hash style into dynamic linker --- ldso/include/dl-elf.h | 21 +++++++++++++++++++-- ldso/include/dl-hash.h | 25 +++++++++++++++++++++++++ ldso/include/ldso.h | 10 +++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) (limited to 'ldso/include') diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 9d8da0d13..3e418622d 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -84,8 +84,11 @@ extern void _dl_protect_relro (struct elf_resolve *l); #endif /* OS and/or GNU dynamic extensions */ -#define OS_NUM 1 -#define DT_RELCONT_IDX DT_NUM +#ifdef __LDSO_GNU_HASH_SUPPORT__ +# define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */ +#else +# define OS_NUM 1 /* for DT_RELOCCOUNT entry */ +#endif #ifndef ARCH_DYNAMIC_INFO /* define in arch specific code, if needed */ @@ -93,6 +96,13 @@ extern void _dl_protect_relro (struct elf_resolve *l); #endif #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) +#endif extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, DL_LOADADDR_TYPE load_off); @@ -131,6 +141,10 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], if (dpnt->d_tag == DT_FLAGS_1 && (dpnt->d_un.d_val & DF_1_NOW)) dynamic_info[DT_BIND_NOW] = 1; +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (dpnt->d_tag == DT_GNU_HASH) + dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr; +#endif } #ifdef ARCH_DYNAMIC_INFO else { @@ -149,6 +163,9 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], ADJUST_DYN_INFO(DT_SYMTAB, load_off); ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off); ADJUST_DYN_INFO(DT_JMPREL, load_off); +#ifdef __LDSO_GNU_HASH_SUPPORT__ + ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off); +#endif #undef ADJUST_DYN_INFO } diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index c21094020..5239467c1 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -40,14 +40,39 @@ struct elf_resolve { 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; diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 40ac12a57..d96d137e9 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -66,9 +66,17 @@ extern int _dl_debug_file; _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __FUNCTION__, __LINE__, ## args); # define _dl_if_debug_dprint(fmt, args...) \ do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0) +# define _dl_assert(expr) \ + do { \ + if (!(expr)) { \ + __dl_debug_dprint("assert(%s)\n", #expr); \ + _dl_exit(45); \ + } \ + } while (0) #else -# define _dl_debug_dprint(fmt, args...) +# define __dl_debug_dprint(fmt, args...) # define _dl_if_debug_dprint(fmt, args...) +# define _dl_assert(expr) # define _dl_debug_file 2 #endif /* __SUPPORT_LD_DEBUG__ */ -- cgit v1.2.3