diff options
28 files changed, 902 insertions, 258 deletions
| @@ -294,6 +294,15 @@ endef  cmd_hcompile.u = $(HOSTCC) $(filter-out $(PHONY),$^) $(DEPS-$(notdir $@)) -o $@ $(BUILD_LDFLAGS) $(BUILD_LDFLAGS-$(notdir $(^D))) $(BUILD_LDFLAGS-$(notdir $@)) $(BUILD_CFLAGS) $(BUILD_CFLAGS-$(notdir $(^D))) $(BUILD_CFLAGS-$(notdir $@))  cmd_hcompile.o = $(HOSTCC) $(filter-out $(PHONY),$<) $(DEPS-$(notdir $@)) -c -o $@ $(BUILD_CFLAGS) $(BUILD_CFLAGS-$(notdir $(^D))) $(BUILD_CFLAGS-$(notdir $@)) +define create-lds +	$(Q)$(RM) $@.lds +	$(Q)$(CC) -nostdlib -nostartfiles -shared -Wl,-z,combreloc \ +	-Wl,-z,relro -Wl,--hash-style=gnu -Wl,-z,defs \ +	-Wl,--verbose 2>&1 | LC_ALL=C \ +	sed -e '/^=========/,/^=========/!d;/^=========/d' \ +	-e 's/\. = .* + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' > $@.lds +endef +  define link.so  	$(Q)$(RM) $@ $@.$(2) $(dir $@)$(1)  	@$(disp_ld) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index aa459e06a..35ce854dd 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -342,6 +342,34 @@ config LDSO_BASE_FILENAME  	  WARNING: Changing the default prefix could cause problems with  	           binutils' ld ! +config LDSO_STANDALONE_SUPPORT +	bool "Dynamic linker stand-alone mode support" +	depends on HAVE_SHARED +	default n +	help +	  The dynamic linker can be run either indirectly through running some +	  dynamically linked program or library (in which case no command line +	  options to the dynamic linker can be passed and, in the ELF case, the +	  dynamic linker which is stored in the .interp section of the program +	  is executed) or directly by running: + +	  /lib/ld-uClibc.so.*  [OPTIONS] [PROGRAM [ARGUMENTS]] + +	  Stand-alone execution is a prerequisite for adding prelink +	  capabilities to uClibc dynamic linker, as well useful for testing an +	  updated version of the dynamic linker without breaking the system. + +config LDSO_PRELINK_SUPPORT +	bool "Dynamic linker prelink support" +	depends on HAVE_SHARED +	default n +	select LDSO_STANDALONE_SUPPORT +	help +	  The dynamic linker can be used in stand-alone mode by the prelink tool +	  for prelinking ELF shared libraries and binaries to speed up startup +	  time. It also is able to load and handle prelinked libraries and +	  binaries at runtime. +  config UCLIBC_STATIC_LDCONFIG  	bool "Link ldconfig statically"  	depends on HAVE_SHARED 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 d8b3e3ef4..c7effc588 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -30,6 +30,14 @@ struct symbol_ref {    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. */ @@ -65,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. */ @@ -133,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; @@ -142,7 +156,7 @@ 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 dyn_elf *rpnt, +extern char *_dl_find_hash(const char *name, struct r_scope_elem *scope,  		struct elf_resolve *mytpnt, int type_class,  		struct symbol_ref *symbol); 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); diff --git a/ldso/ldso/Makefile.in b/ldso/ldso/Makefile.in index e71ae1563..c9dcebd60 100644 --- a/ldso/ldso/Makefile.in +++ b/ldso/ldso/Makefile.in @@ -62,8 +62,16 @@ ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS)  lib-so-y += $(ldso)  objclean-y += CLEAN_ldso/ldso +ifeq ($(LDSO_PRELINK_SUPPORT),y) +# Use a specific linker script for ld.so +LDFLAGS-$(UCLIBC_LDSO_NAME).so += -T $(ldso:.$(ABI_VERSION)=).lds +endif +  $(ldso): $(ldso:.$(ABI_VERSION)=)  $(ldso:.$(ABI_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a +ifeq ($(LDSO_PRELINK_SUPPORT),y) +	$(call create-lds) +endif  	$(call link.so,$(ldso_FULL_NAME),$(ABI_VERSION))  $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y) diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 707b31743..5ae85dd2e 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -69,7 +69,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **) instr_addr;  	/* Get the address of the GOT entry */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope,  				 tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", @@ -99,9 +99,9 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	int i; @@ -181,7 +181,7 @@ fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)  #endif  static int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,  	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -216,6 +216,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  			return 1;  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +					&sym_ref, elf_machine_type_class(reloc_type));  		def_mod = sym_ref.tpnt;  	} else {  		/* @@ -308,7 +311,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  }  static int -_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,  		   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -347,8 +350,8 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  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)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/avr32/elfinterp.c b/ldso/ldso/avr32/elfinterp.c index 2d0dbf366..c3c5b4907 100644 --- a/ldso/ldso/avr32/elfinterp.c +++ b/ldso/ldso/avr32/elfinterp.c @@ -51,7 +51,8 @@ unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)  	symname = strtab + sym->st_name;  	new_addr = (unsigned long) _dl_find_hash(symname, -						 tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +						 &_dl_loaded_modules->symbol_scope, tpnt, +						 ELF_RTYPE_CLASS_PLT, NULL);  	entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);  	*entry = new_addr; @@ -62,9 +63,9 @@ unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_func)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))  {  	Elf32_Sym *symtab; @@ -115,7 +116,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  	return 0;  } -static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +static int _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -148,6 +149,9 @@ static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  				    _dl_progname, symname);  			return 0;  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +				&sym_ref, elf_machine_type_class(reloc_type));  	}  #if defined(__SUPPORT_LD_DEBUG__) @@ -186,9 +190,10 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  int _dl_parse_relocation_information(struct dyn_elf *rpnt, +				     struct r_scope_elem *scope,  				     unsigned long rel_addr,  				     unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size,  			 _dl_do_reloc);  } diff --git a/ldso/ldso/bfin/elfinterp.c b/ldso/ldso/bfin/elfinterp.c index 48470d50b..42c113c50 100644 --- a/ldso/ldso/bfin/elfinterp.c +++ b/ldso/ldso/bfin/elfinterp.c @@ -67,7 +67,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  	got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);  	/* Get the address to be used to fill in the GOT entry.  */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, NULL, 0, &sym_ref); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);  	if (!new_addr) {  		new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);  		if (!new_addr) { @@ -101,9 +101,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))  {  	unsigned int i; @@ -152,7 +152,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,  	      ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -197,6 +197,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  				     _dl_progname, symname);  			_dl_exit (1);  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +				&sym_ref, elf_machine_type_class(reloc_type));  		symbol_tpnt = sym_ref.tpnt;  	} @@ -281,7 +284,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  static int  _dl_do_lazy_reloc (struct elf_resolve *tpnt, -		   struct dyn_elf *scope __attribute__((unused)), +		   struct r_scope_elem *scope __attribute__((unused)),  		   ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)),  		   char *strtab __attribute__((unused)))  { @@ -327,9 +330,9 @@ _dl_parse_lazy_relocation_information  int  _dl_parse_relocation_information -(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)  { -  return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +  return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  }  /* We don't have copy relocs.  */ diff --git a/ldso/ldso/cris/elfinterp.c b/ldso/ldso/cris/elfinterp.c index 3cb8297e1..c3af90b99 100644 --- a/ldso/ldso/cris/elfinterp.c +++ b/ldso/ldso/cris/elfinterp.c @@ -66,7 +66,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry. */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);  		_dl_exit(1); @@ -91,9 +91,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	int symtab_index; @@ -150,7 +150,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -186,6 +186,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  		}  		symbol_addr += rpnt->r_addend; +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +				&sym_ref, elf_machine_type_class(reloc_type));  	}  #if defined (__SUPPORT_LD_DEBUG__) @@ -230,7 +233,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -282,8 +285,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  int  _dl_parse_relocation_information(struct dyn_elf *rpnt, +				 struct r_scope_elem *scope,  				 unsigned long rel_addr,  				 unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/dl-debug.c b/ldso/ldso/dl-debug.c index 7ce8bfbce..8a548195f 100644 --- a/ldso/ldso/dl-debug.c +++ b/ldso/ldso/dl-debug.c @@ -104,3 +104,59 @@ static void debug_reloc(ElfW(Sym) *symtab, char *strtab, ELF_RELOC *rpnt)  #define debug_reloc(symtab, strtab, rpnt)  #endif /* __SUPPORT_LD_DEBUG__ */ + +#ifdef __LDSO_PRELINK_SUPPORT__ +static void +internal_function +_dl_debug_lookup (const char *undef_name, struct elf_resolve *undef_map, +					const ElfW(Sym) *ref, struct symbol_ref *value, int type_class) +{ +#ifdef SHARED +  unsigned long symbol_addr; + +  if (_dl_trace_prelink) +    { +      int conflict = 0; +      struct symbol_ref val = { NULL, NULL }; + +      if ((_dl_trace_prelink_map == NULL +	   || _dl_trace_prelink_map == _dl_loaded_modules) +	  && undef_map != _dl_loaded_modules) +	{ +		symbol_addr = (unsigned long) +					  _dl_find_hash(undef_name, &undef_map->symbol_scope, +									undef_map, type_class, &val); + +	  if (val.sym != value->sym || val.tpnt != value->tpnt) +	    conflict = 1; +	} + +      if (value->sym +	  && (__builtin_expect (ELF_ST_TYPE(value->sym->st_info) +				== STT_TLS, 0))) +	type_class = 4; + +      if (conflict +	  || _dl_trace_prelink_map == undef_map +	  || _dl_trace_prelink_map == NULL +	  || type_class == 4) +	{ +	  _dl_dprintf (1, "%s %x %x -> %x %x ", +		      conflict ? "conflict" : "lookup", +		      (size_t) undef_map->mapaddr, +		      (size_t) (((ElfW(Addr)) ref) - undef_map->mapaddr), +		      (size_t) (value->tpnt ? value->tpnt->mapaddr : 0), +		      (size_t) (value->sym ? value->sym->st_value : 0)); +	  if (conflict) +	    _dl_dprintf (1, "x %x %x ", +			(size_t) (val.tpnt ? val.tpnt->mapaddr : 0), +			(size_t) (val.sym ? val.sym->st_value : 0)); +	  _dl_dprintf (1, "/%x %s\n", type_class, undef_name); +	} +} +#endif +} + +#else +#define _dl_debug_lookup(undef_name, undef_map, ref, value, type_class) +#endif diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 5562e0784..d72dd5ae2 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -322,7 +322,7 @@ goof:   */  struct elf_resolve *_dl_load_elf_shared_library(int secure, -	struct dyn_elf **rpnt, char *libname) +	struct dyn_elf **rpnt, const char *libname)  {  	ElfW(Ehdr) *epnt;  	unsigned long dynamic_addr = 0; @@ -343,7 +343,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	size_t relro_size = 0;  	struct stat st;  	uint32_t *p32; -	DL_LOADADDR_TYPE lib_loadaddr; +	DL_LOADADDR_TYPE lib_loadaddr = 0;  	DL_INIT_LOADADDR_EXTRA_DECLS  	libaddr = 0; @@ -397,11 +397,15 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  		return NULL;  	} -	if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1 +	if ((epnt->e_type != ET_DYN +#ifdef __LDSO_STANDALONE_SUPPORT__ +		&& epnt->e_type != ET_EXEC +#endif +		) || (epnt->e_machine != MAGIC1  #ifdef MAGIC2  				&& epnt->e_machine != MAGIC2  #endif -				)) +			))  	{  		_dl_internal_error_number =  			(epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC); @@ -426,7 +430,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  		if (ppnt->p_type == PT_LOAD) {  			/* See if this is a PIC library. */ -			if (i == 0 && ppnt->p_vaddr > 0x1000000) { +			if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {  				piclib = 0;  				minvma = ppnt->p_vaddr;  			} @@ -462,14 +466,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  		ppnt++;  	} +#ifdef __LDSO_STANDALONE_SUPPORT__ +	if (epnt->e_type == ET_EXEC) +		piclib = 0; +#endif +  	DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname);  	maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN;  	minvma = minvma & ~0xffffU;  	flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ; -	if (!piclib) -		flags |= MAP_FIXED;  	if (piclib == 0 || piclib == 1) {  		status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), @@ -488,7 +495,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	/* Get the memory to store the library */  	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; -	DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum); +	DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);  	for (i = 0; i < epnt->e_phnum; i++) {  		if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) { @@ -510,12 +517,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  			char *tryaddr;  			ssize_t size; -			/* See if this is a PIC library. */ -			if (i == 0 && ppnt->p_vaddr > 0x1000000) { -				piclib = 0; -				/* flags |= MAP_FIXED; */ -			} -  			if (ppnt->p_flags & PF_W) {  				unsigned long map_size;  				char *cpnt; @@ -559,7 +560,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  				  }  				tryaddr = piclib == 2 ? piclib2map -				  : ((char*) (piclib ? libaddr : 0) + +				  : ((char*) (piclib ? libaddr : lib_loadaddr) +  				     (ppnt->p_vaddr & PAGE_ALIGN));  				size = (ppnt->p_vaddr & ADDR_ALIGN) @@ -644,7 +645,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  				if (map_size < ppnt->p_vaddr + ppnt->p_memsz  				    && !piclib2map) { -					tryaddr = map_size + (char*)(piclib ? libaddr : 0); +					tryaddr = map_size + (char*)(piclib ? libaddr : lib_loadaddr);  					status = (char *) _dl_mmap(tryaddr,  						ppnt->p_vaddr + ppnt->p_memsz - map_size,  						LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0); @@ -655,7 +656,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  			} else {  				tryaddr = (piclib == 2 ? 0  					   : (char *) (ppnt->p_vaddr & PAGE_ALIGN) -					   + (piclib ? libaddr : 0)); +					   + (piclib ? libaddr : lib_loadaddr));  				size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;  				status = (char *) _dl_mmap  					   (tryaddr, size, LXFLAGS(ppnt->p_flags), @@ -679,8 +680,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	}  	_dl_close(infile); -	/* For a non-PIC library, the addresses are all absolute */ -	if (piclib) { +	/* +	 * The dynamic_addr must be take into acount lib_loadaddr value, to note +	 * it is zero when the SO has been mapped to the elf's physical addr +	 */ +	if (lib_loadaddr) {  		dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);  	} @@ -711,7 +715,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  		ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];  		for (i = 0; i < epnt->e_phnum; i++, ppnt++) {  			if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { -				_dl_mprotect((void *) ((piclib ? libaddr : 0) + +				_dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) +  							(ppnt->p_vaddr & PAGE_ALIGN)),  						(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,  						PROT_READ | PROT_WRITE | PROT_EXEC); @@ -727,13 +731,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,  			dynamic_addr, 0); +	tpnt->mapaddr = libaddr;  	tpnt->relro_addr = relro_addr;  	tpnt->relro_size = relro_size;  	tpnt->st_dev = st.st_dev;  	tpnt->st_ino = st.st_ino; -	tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff); +	tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);  	tpnt->n_phent = epnt->e_phnum;  	tpnt->rtld_flags |= rtld_flags; +#ifdef __LDSO_STANDALONE_SUPPORT__ +	tpnt->l_entry = epnt->e_entry; +#endif  #if defined(USE_TLS) && USE_TLS  	if (tlsppnt) { @@ -755,7 +763,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  		tpnt->l_tls_modid = _dl_next_tls_modid ();  		/* We know the load address, so add it to the offset. */ +#ifdef __LDSO_STANDALONE_SUPPORT__ +		if ((tpnt->l_tls_initimage != NULL) && piclib) +#else  		if (tpnt->l_tls_initimage != NULL) +#endif  		{  # ifdef __SUPPORT_LD_DEBUG_EARLY__  			unsigned int tmp = (unsigned int) tpnt->l_tls_initimage; @@ -772,7 +784,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	/*  	 * Add this object into the symbol chain  	 */ -	if (*rpnt) { +	if (*rpnt +#ifdef __LDSO_STANDALONE_SUPPORT__ +		/* Do not create a new chain entry for the main executable */ +		&& (*rpnt)->dyn +#endif +		) {  		(*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf));  		_dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf));  		(*rpnt)->next->prev = (*rpnt); @@ -789,9 +806,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	}  #endif  	(*rpnt)->dyn = tpnt; -	tpnt->symbol_scope = _dl_symbol_tables;  	tpnt->usage_count++; +#ifdef __LDSO_STANDALONE_SUPPORT__ +	tpnt->libtype = (epnt->e_type == ET_DYN) ? elf_lib : elf_executable; +#else  	tpnt->libtype = elf_lib; +#endif  	/*  	 * OK, the next thing we need to do is to insert the dynamic linker into @@ -817,7 +837,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  }  /* now_flag must be RTLD_NOW or zero */ -int _dl_fixup(struct dyn_elf *rpnt, int now_flag) +int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)  {  	int goof = 0;  	struct elf_resolve *tpnt; @@ -825,7 +845,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)  	ElfW(Addr) reloc_addr;  	if (rpnt->next) -		goof = _dl_fixup(rpnt->next, now_flag); +		goof = _dl_fixup(rpnt->next, scope, now_flag);  	if (goof)  		return goof;  	tpnt = rpnt->dyn; @@ -852,10 +872,15 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)  		relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];  		if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */  			reloc_size -= relative_count * sizeof(ELF_RELOC); -			elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count); +			if (tpnt->loadaddr +#ifdef __LDSO_PRELINK_SUPPORT__ +				|| (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]) +#endif +				) +				elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);  			reloc_addr += relative_count * sizeof(ELF_RELOC);  		} -		goof += _dl_parse_relocation_information(rpnt, +		goof += _dl_parse_relocation_information(rpnt, scope,  				reloc_addr,  				reloc_size);  		tpnt->init_flag |= RELOCS_DONE; @@ -871,7 +896,7 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)  					tpnt->dynamic_info[DT_JMPREL],  					tpnt->dynamic_info [DT_PLTRELSZ]);  		} else { -			goof += _dl_parse_relocation_information(rpnt, +			goof += _dl_parse_relocation_information(rpnt, scope,  					tpnt->dynamic_info[DT_JMPREL],  					tpnt->dynamic_info[DT_PLTRELSZ]);  		} diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 0454d61bf..2ec883a86 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -146,7 +146,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  		tpnt->chains = hash_addr;  	}  	tpnt->loadaddr = loadaddr; -	tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0);  	for (i = 0; i < DYNAMIC_SIZE; i++)  		tpnt->dynamic_info[i] = dynamic_info[i];  	return tpnt; @@ -268,16 +267,18 @@ _dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long   * This function resolves externals, and this is either called when we process   * relocations or when we call an entry in the PLT table for the first time.   */ -char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, +char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_resolve *mytpnt,  	int type_class, struct symbol_ref *sym_ref)  {  	struct elf_resolve *tpnt = NULL;  	ElfW(Sym) *symtab; +	int i = 0;  	unsigned long elf_hash_number = 0xffffffff;  	const ElfW(Sym) *sym = NULL;  	char *weak_result = NULL; +	struct r_scope_elem *loop_scope;  #ifdef __LDSO_GNU_HASH_SUPPORT__  	unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); @@ -288,57 +289,64 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *  		if (mytpnt)  			tpnt = mytpnt;  	} else -	for (; rpnt; rpnt = rpnt->next) { -		tpnt = rpnt->dyn; - -		if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { -			if (mytpnt == tpnt) -				; -			else { -				struct init_fini_list *tmp; - -				for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { -					if (tmp->tpnt == tpnt) -						break; +	for (loop_scope = scope; loop_scope && !sym; loop_scope = loop_scope->next) { +		for (i = 0; i < loop_scope->r_nlist; i++) { +			tpnt = loop_scope->r_list[i]; + +			if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { +				if (mytpnt == tpnt) +					; +				else { +					struct init_fini_list *tmp; + +					for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { +						if (tmp->tpnt == tpnt) +							break; +					} +					if (!tmp) +						continue;  				} -				if (!tmp) -					continue;  			} -		} -		/* Don't search the executable when resolving a copy reloc. */ -		if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) -			continue; +			/* Don't search the executable when resolving a copy reloc. */ +			if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) +				continue; -		/* If the hash table is empty there is nothing to do here.  */ -		if (tpnt->nbucket == 0) -			continue; +			/* If the hash table is empty there is nothing to do here.  */ +			if (tpnt->nbucket == 0) +				continue; -		symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); +			symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);  #ifdef __LDSO_GNU_HASH_SUPPORT__ -		/* Prefer GNU hash style, if any */ -		if (tpnt->l_gnu_bitmask) { -			sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); -			if (sym != NULL) -				/* If sym has been found, do not search further */ -				break; -		} else { +			/* Prefer GNU hash style, if any */ +			if (tpnt->l_gnu_bitmask) { +				sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); +				if (sym != NULL) +					/* If sym has been found, do not search further */ +					break; +			} else {  #endif -		/* Use the old SysV-style hash table */ +				/* Use the old SysV-style hash table */ -		/* Calculate the old sysv hash number only once */ -		if (elf_hash_number == 0xffffffff) -			elf_hash_number = _dl_elf_hash((const unsigned char *)name); +				/* Calculate the old sysv hash number only once */ +				if (elf_hash_number == 0xffffffff) +					elf_hash_number = _dl_elf_hash((const unsigned char *)name); -		sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); -		if (sym != NULL) -			break; +				sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); +				if (sym != NULL) +					/* If sym has been found, do not search further */ +					break;  #ifdef __LDSO_GNU_HASH_SUPPORT__ -		} +			}  #endif -	} /* end of for (; rpnt; rpnt = rpnt->next) { */ +		} /* End of inner for */ +	}  	if (sym) { +		if (sym_ref) { +			sym_ref->sym = sym; +			sym_ref->tpnt = tpnt; +		}  		/* At this point we have found the requested symbol, do binding */  #if defined(USE_TLS) && USE_TLS  		if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index a51b583a4..4799846ee 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -94,6 +94,11 @@  /* Pull in all the arch specific stuff */  #include "dl-startup.h" +#ifdef __LDSO_PRELINK_SUPPORT__ +/* These defined magically in the linker script.  */ +extern char _begin[] attribute_hidden; +#endif +  /* Static declarations */  static int (*_dl_elf_main) (int, char **, char **); @@ -164,11 +169,26 @@ DL_START(unsigned long args)  		aux_dat += 2;  	} -	/* locate the ELF header.   We need this done as soon as possible -	 * (esp since SEND_STDERR() needs this on some platforms... */ +	/* +	 * Locate the dynamic linker ELF header. We need this done as soon as +	 * possible (esp since SEND_STDERR() needs this on some platforms... +	 */ + +#ifdef __LDSO_PRELINK_SUPPORT__ +	/* +	 * The `_begin' symbol created by the linker script points to ld.so ELF +	 * We use it if the kernel is not passing a valid address through the auxvt. +	 */ + +	if (!auxvt[AT_BASE].a_un.a_val) +		auxvt[AT_BASE].a_un.a_val =  (Elf32_Addr) &_begin; +	/* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */ +	DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address()); +#else  	if (!auxvt[AT_BASE].a_un.a_val)  		auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();  	DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val); +#endif  	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;  	/* Check the ELF header to make sure everything looks ok.  */ @@ -183,7 +203,7 @@ DL_START(unsigned long args)  		_dl_exit(0);  	}  	SEND_EARLY_STDERR_DEBUG("ELF header="); -	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1); +	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1);  	/* Locate the global offset table.  Since this code must be PIC  	 * we can take advantage of the magic offset register, if we @@ -192,7 +212,7 @@ DL_START(unsigned long args)  	DL_BOOT_COMPUTE_GOT(got);  	/* Now, finally, fix up the location of the dynamic stuff */ -	DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr); +	DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)header);  	SEND_EARLY_STDERR_DEBUG("First Dynamic section entry=");  	SEND_ADDRESS_STDERR_DEBUG(dpnt, 1); @@ -258,7 +278,12 @@ DL_START(unsigned long args)  			if (!indx && relative_count) {  				rel_size -= relative_count * sizeof(ELF_RELOC); -				elf_machine_relative(load_addr, rel_addr, relative_count); +				if (load_addr +#ifdef __LDSO_PRELINK_SUPPORT__ +					|| !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX] +#endif +					) +					elf_machine_relative(load_addr, rel_addr, relative_count);  				rel_addr += relative_count * sizeof(ELF_RELOC);  			} @@ -321,12 +346,12 @@ DL_START(unsigned long args)  	__rtld_stack_end = (void *)(argv - 1); -	_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv -			     DL_GET_READY_TO_RUN_EXTRA_ARGS); +	_dl_elf_main = (int (*)(int, char **, char **)) +			_dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, auxvt, envp, argv +					     DL_GET_READY_TO_RUN_EXTRA_ARGS);  	/* Transfer control to the application.  */  	SEND_STDERR_DEBUG("transfering control to application @ "); -	_dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val;  	SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1);  #if !defined(START) diff --git a/ldso/ldso/frv/elfinterp.c b/ldso/ldso/frv/elfinterp.c index 4b94033de..726b58b09 100644 --- a/ldso/ldso/frv/elfinterp.c +++ b/ldso/ldso/frv/elfinterp.c @@ -54,7 +54,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  	  DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr);  	/* Get the address to be used to fill in the GOT entry.  */ -	new_addr = _dl_find_hash_mod(symname, tpnt->symbol_scope, NULL, 0, +	new_addr = _dl_find_hash_mod(symname, &_dl_loaded_modules->symbol_scope, NULL, 0,  				     &new_tpnt);  	if (!new_addr) {  		new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0, @@ -91,9 +91,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	unsigned int i; @@ -146,7 +146,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,  	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -276,7 +276,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  static int  _dl_do_lazy_reloc (struct elf_resolve *tpnt, -		   struct dyn_elf *scope __attribute_used__, +		   struct r_scope_elem *scope __attribute_used__,  		   ELF_RELOC *rpnt, Elf32_Sym *symtab __attribute_used__,  		   char *strtab __attribute_used__)  { @@ -325,9 +325,9 @@ _dl_parse_lazy_relocation_information  int  _dl_parse_relocation_information -(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +(struct dyn_elf *rpnt, struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)  { -  return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +  return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  }  /* We don't have copy relocs.  */ diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index 0017c239b..33c14402a 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -71,7 +71,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry. */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);  		_dl_exit(1); @@ -98,9 +98,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	unsigned int i; @@ -156,7 +156,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -190,13 +190,15 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  		if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)  					&& ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))  			return 1; +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +					&sym_ref, elf_machine_type_class(reloc_type));  		tls_tpnt = sym_ref.tpnt;  	} else {  		symbol_addr = symtab[symtab_index].st_value;  		tls_tpnt = tpnt;  	} -  #if defined (__SUPPORT_LD_DEBUG__)  	old_val = *reloc_addr;  #endif @@ -266,7 +268,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -315,8 +317,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  int  _dl_parse_relocation_information(struct dyn_elf *rpnt, +				 struct r_scope_elem *scope,  				 unsigned long rel_addr,  				 unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index ea4ad0f1c..2ff441194 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -57,6 +57,12 @@ struct r_debug *_dl_debug_addr = NULL;	/* Used to communicate with the gdb debug  void *(*_dl_malloc_function) (size_t size) = NULL;  void (*_dl_free_function) (void *p) = NULL; +#ifdef __LDSO_PRELINK_SUPPORT__ +char *_dl_trace_prelink                      = NULL;	/* Library for prelinking trace */ +struct elf_resolve *_dl_trace_prelink_map    = NULL;	/* Library module for prelinking trace */ +bool _dl_verbose				= true;					/* On by default */ +bool prelinked					= false; +#endif  static int _dl_secure = 1; /* Are we dealing with setuid stuff? */  #ifdef __SUPPORT_LD_DEBUG__ @@ -70,8 +76,18 @@ char *_dl_debug_bindings  = NULL;  int   _dl_debug_file      = 2;  #endif -/* Needed for standalone execution. */ +#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__) +/* Not hidden, needed for standalone execution. */ +/* + * FIXME: align dl_start for SH to other archs so that we can keep this symbol + *        hidden and we don't need to handle in __uClibc_main + */ + +unsigned long _dl_skip_args = 0; +#else  unsigned long attribute_hidden _dl_skip_args = 0; +#endif +  const char *_dl_progname = UCLIBC_LDSO;      /* The name of the executable being run */  #include "dl-startup.c"  #include "dl-symbols.c" @@ -97,6 +113,7 @@ static unsigned char *_dl_malloc_addr = NULL;	/* Lets _dl_malloc use the already  static unsigned char *_dl_mmap_zero   = NULL;	/* Also used by _dl_malloc */  static struct elf_resolve **init_fini_list; +static struct elf_resolve **scope_elem_list;  static unsigned int nlist; /* # items in init_fini_list */  extern void _start(void); @@ -274,20 +291,101 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)  	}  } -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 +#ifdef __LDSO_PRELINK_SUPPORT__ +static void trace_objects(struct elf_resolve *tpnt, char *str_name) +{ +	if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0) +		_dl_trace_prelink_map = tpnt; +	if (tpnt->libtype == elf_executable) { +/* Main executeble */ +		_dl_dprintf(1, "\t%s => %s (%x, %x)", tpnt->libname, tpnt->libname, +					tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr)); +	} else { +/* Preloaded, Needed or interpreter */ +		_dl_dprintf(1, "\t%s => %s (%x, %x)", str_name, tpnt->libname, +					tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr)); +	} + +	if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid)) +		_dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid, +					(size_t) tpnt->l_tls_offset); +	else +		_dl_dprintf (1, "\n"); +} +#endif + +static struct elf_resolve * add_ldso(struct elf_resolve *tpnt, +									 DL_LOADADDR_TYPE load_addr, +									 ElfW(auxv_t) auxvt[AT_EGID + 1], +									 struct dyn_elf *rpnt) +{ +		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; +		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) +								DL_RELOC_ADDR(load_addr, epnt->e_phoff); +		int j; +		struct stat st; + +		tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr, +					      tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr, +					      0); + +		tpnt->mapaddr = load_addr; +		if (_dl_stat(tpnt->libname, &st) >= 0) { +			tpnt->st_dev = st.st_dev; +			tpnt->st_ino = st.st_ino; +		} +		tpnt->n_phent = epnt->e_phnum; +		tpnt->ppnt = myppnt; +		for (j = 0; j < epnt->e_phnum; j++, myppnt++) { +			if (myppnt->p_type ==  PT_GNU_RELRO) { +				tpnt->relro_addr = myppnt->p_vaddr; +				tpnt->relro_size = myppnt->p_memsz; +				break; +			} +		} +		tpnt->libtype = program_interpreter; +		if (rpnt) { +			rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); +			rpnt->next->prev = rpnt; +			rpnt = rpnt->next; +		} else { +			rpnt = _dl_zalloc(sizeof(struct dyn_elf)); +		} +		rpnt->dyn = tpnt; +		tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ + +	return tpnt; +} + +static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list, +										struct elf_resolve *map) +{ +	struct elf_resolve **p = list; +	struct init_fini_list *q; + +	*p++ = map; +	map->init_flag |= DL_RESERVED; +	if (map->init_fini) +		for (q = map->init_fini; q; q = q->next) +			if (! (q->tpnt->init_flag & DL_RESERVED)) +				p += _dl_build_local_scope (p, q->tpnt); +	return p - list; +} + +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)  {  	ElfW(Addr) app_mapaddr = 0;  	ElfW(Phdr) *ppnt;  	ElfW(Dyn) *dpnt;  	char *lpntstr; -	unsigned int i; +	unsigned int i, cnt, nscope_elem;  	int unlazy = 0, trace_loaded_objects = 0;  	struct dyn_elf *rpnt;  	struct elf_resolve *tcurr;  	struct elf_resolve *tpnt1; +	struct elf_resolve *ldso_tpnt = NULL;  	struct elf_resolve app_tpnt_tmp;  	struct elf_resolve *app_tpnt = &app_tpnt_tmp;  	struct r_debug *debug_addr; @@ -295,7 +393,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	unsigned long *_dl_envp;		/* The environment address */  	ElfW(Addr) relro_addr = 0;  	size_t relro_size = 0; -	struct stat st; +	struct r_scope_elem *global_scope; +	struct elf_resolve **local_scope; +  #if defined(USE_TLS) && USE_TLS  	void *tcbp = NULL;  #endif @@ -327,10 +427,12 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  		_dl_progname = argv[0];  	} +#ifndef __LDSO_STANDALONE_SUPPORT__  	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { -		_dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n"); +		_dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");  		_dl_exit(1);  	} +#endif  	/* Start to build the tables of the modules that are required for  	 * this beast to run.  We start with the basic executable, and then @@ -382,6 +484,99 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	_dl_init_static_tls = &_dl_nothread_init_static_tls;  #endif +#ifdef __LDSO_STANDALONE_SUPPORT__ +	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { +		char *ptmp; +		unsigned int *aux_dat = (unsigned int *) argv; +		int argc = aux_dat[-1]; + +		tpnt->libname = argv[0]; +		while (argc > 1) +			if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) { +				_dl_library_path = argv[2]; +				_dl_skip_args += 2; +				argc -= 2; +				argv += 2; +			} else +				break; + +	/* +	 * If we have no further argument the program was called incorrectly. +	 * Grant the user some education. +	 */ + +		if (argc < 2) { +			_dl_dprintf(1, "\ +Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ +You have invoked `ld.so', the helper program for shared library executables.\n\ +This program usually lives in the file `/lib/ld.so', and special directives\n\ +in executable files using ELF shared libraries tell the system's program\n\ +loader to load the helper program from this file.  This helper program loads\n\ +the shared libraries needed by the program executable, prepares the program\n\ +to run, and runs it.  You may invoke this helper program directly from the\n\ +command line to load and run an ELF executable file; this is like executing\n\ +that file itself, but always uses this helper program from the file you\n\ +specified, instead of the helper program file specified in the executable\n\ +file you run.  This is mostly of use for maintainers to test new versions\n\ +of this helper program; chances are you did not intend to run this program.\n\ +\n\ +  --library-path PATH   use given PATH instead of content of the environment\n\ +                        variable LD_LIBRARY_PATH\n"); +			_dl_exit(1); +		} + +		++_dl_skip_args; +		++argv; +		_dl_progname = argv[0]; + +		_dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf)); +		/* +		 * It needs to load the _dl_progname and to map it +		 * Usually it is the main application launched by means of the ld.so +		 * but it could be also a shared object (when ld.so used for tracing) +		 * We keep the misleading app_tpnt name to avoid variable pollution +		 */ +		app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname); +		if (!app_tpnt) { +			_dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname); +			_dl_exit(16); +		} +		/* +		 * FIXME: it needs to properly handle a PIE executable +		 * Usually for a main application, loadaddr is computed as difference +		 * between auxvt entry points and phdr, so if it is not 0, that it is a +		 * PIE executable. In this case instead we need to set the loadaddr to 0 +		 * because we are actually mapping the ELF for the main application by +		 * ourselves. So the PIE case must be checked. +		 */ + +		app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; + +		/* +		 * This is used by gdb to locate the chain of shared libraries that are +		 * currently loaded. +		 */ +		debug_addr = _dl_zalloc(sizeof(struct r_debug)); +		ppnt = (ElfW(Phdr) *)app_tpnt->ppnt; +		for (i = 0; i < app_tpnt->n_phent; i++, ppnt++) { +			if (ppnt->p_type == PT_DYNAMIC) { +				dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr); +				_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr); +			} +		} + +		/* Store the path where the shared lib loader was found +		 * for later use +		 */ +		_dl_ldsopath = _dl_strdup(tpnt->libname); +		ptmp = _dl_strrchr(_dl_ldsopath, '/'); +		if (ptmp != _dl_ldsopath) +			*ptmp = '\0'; + +		_dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname); +	} else { +#endif +  	/* At this point we are now free to examine the user application,  	 * and figure out which libraries are supposed to be called.  Until  	 * we have this list, we will not be completely ready for dynamic @@ -469,7 +664,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  			app_tpnt->mapaddr = app_mapaddr;  			app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;  			app_tpnt->usage_count++; -			app_tpnt->symbol_scope = _dl_symbol_tables;  			lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);  #ifdef ALLOW_ZERO_PLTGOT  			if (lpnt) @@ -530,14 +724,18 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	 * case the executable is actually an ET_DYN object.  	 */  	if (app_tpnt->l_tls_initimage != NULL) { +		unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;  		app_tpnt->l_tls_initimage =  			(char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;  		_dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", -			(unsigned int)app_tpnt->l_tls_initimage, -			app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size); +			tmp, app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size);  	}  #endif +#ifdef __LDSO_STANDALONE_SUPPORT__ +	} /* ! ldso standalone mode */ +#endif +  #ifdef __SUPPORT_LD_DEBUG__  	_dl_debug = _dl_getenv("LD_DEBUG", envp);  	if (_dl_debug) { @@ -586,6 +784,16 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	}  #endif +#ifdef __LDSO_PRELINK_SUPPORT__ +{ +	char *ld_warn = _dl_getenv ("LD_WARN", envp); + +	if (ld_warn && *ld_warn == '\0') +		_dl_verbose = false; +} +	_dl_trace_prelink = _dl_getenv("LD_TRACE_PRELINKING", envp); +#endif +  	if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) {  		trace_loaded_objects++;  	} @@ -639,7 +847,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);  				if (!tpnt1) {  #ifdef __LDSO_LDD_SUPPORT__ -					if (trace_loaded_objects) +					if (trace_loaded_objects || _dl_trace_prelink)  						_dl_dprintf(1, "\t%s => not found\n", str);  					else  #endif @@ -653,7 +861,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  					_dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);  #ifdef __LDSO_LDD_SUPPORT__ -					if (trace_loaded_objects && +					if (trace_loaded_objects && !_dl_trace_prelink &&  					    tpnt1->usage_count == 1) {  						/* This is a real hack to make  						 * ldd not print the library @@ -730,7 +938,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  			tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects);  			if (!tpnt1) {  # ifdef __LDSO_LDD_SUPPORT__ -				if (trace_loaded_objects) +				if (trace_loaded_objects || _dl_trace_prelink)  					_dl_dprintf(1, "\t%s => not found\n", cp2);  				else  # endif @@ -744,7 +952,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  				_dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);  # ifdef __LDSO_LDD_SUPPORT__ -				if (trace_loaded_objects && +				if (trace_loaded_objects && !_dl_trace_prelink &&  				    tpnt1->usage_count == 1) {  					_dl_dprintf(1, "\t%s => %s (%x)\n",  						    cp2, tpnt1->libname, @@ -775,14 +983,21 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  				lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val);  				name = _dl_get_last_path_component(lpntstr); -				if (_dl_strcmp(name, UCLIBC_LDSO) == 0) -					continue; -  				_dl_if_debug_dprint("\tfile='%s';  needed by '%s'\n", lpntstr, _dl_progname); -				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects)))	{ +				if (_dl_strcmp(name, UCLIBC_LDSO) == 0) { +						if (!ldso_tpnt) { +							/* Insert the ld.so only once */ +							ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt); +						} +						ldso_tpnt->usage_count++; +						tpnt1 = ldso_tpnt; +				} else +					tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects); + +				if (!tpnt1) {  #ifdef __LDSO_LDD_SUPPORT__ -					if (trace_loaded_objects) { +					if (trace_loaded_objects || _dl_trace_prelink) {  						_dl_dprintf(1, "\t%s => not found\n", lpntstr);  						continue;  					} else @@ -803,7 +1018,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  				_dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname);  #ifdef __LDSO_LDD_SUPPORT__ -				if (trace_loaded_objects && +				if (trace_loaded_objects && !_dl_trace_prelink &&  				    tpnt1->usage_count == 1) {  					_dl_dprintf(1, "\t%s => %s (%x)\n",  						    lpntstr, tpnt1->libname, @@ -815,12 +1030,18 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	}  	_dl_unmap_cache(); -	--nlist; /* Exclude the application. */ +	/* Keep track of the number of elements in the global scope */ +	nscope_elem = nlist; + +	if (_dl_loaded_modules->libtype == elf_executable) { +		--nlist; /* Exclude the application. */ +		tcurr = _dl_loaded_modules->next; +	} else +		tcurr = _dl_loaded_modules;  	init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *));  	i = 0; -	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { +	for (; tcurr; tcurr = tcurr->next)  		init_fini_list[i++] = tcurr; -	}  	/* Sort the INIT/FINI list in dependency order. */  	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { @@ -866,41 +1087,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	 * functions in the dynamic linker and to relocate the interpreter  	 * again once all libs are loaded.  	 */ -	if (tpnt) { -		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; -		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff); -		int j; - -		tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr, -					      tpnt->dynamic_info, -					      (unsigned long)tpnt->dynamic_addr, -					      0); - -		if (_dl_stat(tpnt->libname, &st) >= 0) { -			tpnt->st_dev = st.st_dev; -			tpnt->st_ino = st.st_ino; -		} -		tpnt->n_phent = epnt->e_phnum; -		tpnt->ppnt = myppnt; -		for (j = 0; j < epnt->e_phnum; j++, myppnt++) { -			if (myppnt->p_type ==  PT_GNU_RELRO) { -				tpnt->relro_addr = myppnt->p_vaddr; -				tpnt->relro_size = myppnt->p_memsz; -				break; -			} -		} -		tpnt->libtype = program_interpreter; +	if (!ldso_tpnt) { +		tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt);  		tpnt->usage_count++; -		tpnt->symbol_scope = _dl_symbol_tables; -		if (rpnt) { -			rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); -			rpnt->next->prev = rpnt; -			rpnt = rpnt->next; -		} else { -			rpnt = _dl_zalloc(sizeof(struct dyn_elf)); -		} -		rpnt->dyn = tpnt; -		tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ +		nscope_elem++; +	} else +		tpnt = ldso_tpnt; +  #ifdef RERELOCATE_LDSO  		/* Only rerelocate functions for now. */  		tpnt->init_flag = RELOCS_DONE; @@ -913,16 +1106,44 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  		tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;  #endif  		tpnt = NULL; + +	/* +	 * Allocate the global scope array. +	 */ +	scope_elem_list = (struct elf_resolve **) _dl_malloc(nscope_elem * sizeof(struct elf_resolve *)); + +	for (i = 0, tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) +		scope_elem_list[i++] = tcurr; + +	_dl_loaded_modules->symbol_scope.r_list = scope_elem_list; +	_dl_loaded_modules->symbol_scope.r_nlist = nscope_elem; +	/* +	 * The symbol scope of the application, that is the first entry of the +	 * _dl_loaded_modules list, is just the global scope to be used for the +	 * symbol lookup. +	 */ +	global_scope = &_dl_loaded_modules->symbol_scope; + +	/* Build the local scope for each loaded modules. */ +	local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *)); +	i = 1; +	for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { +		unsigned int k; +		cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]); +		tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *)); +		tcurr->symbol_scope.r_nlist = cnt; +		_dl_memcpy (tcurr->symbol_scope.r_list, local_scope, cnt * sizeof (struct elf_resolve *)); +		/* Restoring the init_flag.*/ +		for (k = 1; k < nscope_elem; k++) +			scope_elem_list[k]->init_flag &= ~DL_RESERVED;  	} +	_dl_free(local_scope); +  #ifdef __LDSO_LDD_SUPPORT__ -	/* End of the line for ldd.... */ -	if (trace_loaded_objects) { -		_dl_dprintf(1, "\t%s => %s (%x)\n", -			    rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1, -			    rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr)); +	/* Exit if LD_TRACE_LOADED_OBJECTS is on. */ +	if (trace_loaded_objects && !_dl_trace_prelink)  		_dl_exit(0); -	}  #endif  #if defined(USE_TLS) && USE_TLS @@ -952,6 +1173,90 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  # endif  #endif +#ifdef __LDSO_PRELINK_SUPPORT__ +	if (_dl_trace_prelink) { + +		unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1); + +		for (i = 0; i < nscope_trace; i++) +			trace_objects(scope_elem_list[i], +				_dl_get_last_path_component(scope_elem_list[i]->libname)); + +		if (_dl_verbose) +			/* Warn about undefined symbols. */ +			if (_dl_symbol_tables) +				if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy)) +					_dl_exit(-1); +		_dl_exit(0); +	} + +	if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) { +		ElfW(Lib) *liblist, *liblistend; +		struct elf_resolve **r_list, **r_listend, *l; +		const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB]; + +		_dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0); +		liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]; +		liblistend = (ElfW(Lib) *) +		((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]); +		r_list = _dl_loaded_modules->symbol_scope.r_list; +		r_listend = r_list + nscope_elem; + +		for (; r_list < r_listend && liblist < liblistend; r_list++) { +			l = *r_list; + +			if (l == _dl_loaded_modules) +				continue; + +			/* If the library is not mapped where it should, fail.  */ +			if (l->loadaddr) +				break; + +			/* Next, check if checksum matches.  */ +			if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 || +				l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum) +				break; + +			if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 || +				(l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp)) +				break; + +			if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0) +				break; + +			++liblist; +		} + + +		if (r_list == r_listend && liblist == liblistend) +			prelinked = true; + +	} + +	_dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed"); + +	if (prelinked) { +		if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) { +			ELF_RELOC *conflict; +			unsigned long conflict_size; + +			_dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0); +			conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]; +			conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX]; +			_dl_parse_relocation_information(_dl_symbol_tables, global_scope, +				(unsigned long) conflict, conflict_size); +		} + +		/* Mark all the objects so we know they have been already relocated.  */ +		for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { +			tpnt->init_flag |= RELOCS_DONE; +			if (tpnt->relro_size) +				_dl_protect_relro (tpnt); +		} +	} else +#endif + +	{  	_dl_debug_early("Beginning relocation fixups\n"); @@ -970,13 +1275,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	 * order so that COPY directives work correctly.  	 */  	if (_dl_symbol_tables) -		if (_dl_fixup(_dl_symbol_tables, unlazy)) +		if (_dl_fixup(_dl_symbol_tables, global_scope, unlazy))  			_dl_exit(-1);  	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {  		if (tpnt->relro_size)  			_dl_protect_relro (tpnt);  	} +	} /* not prelinked */  #if defined(USE_TLS) && USE_TLS  	if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0) @@ -1007,7 +1313,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	 * ld.so.1, so we have to look up each symbol individually.  	 */ -	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0, NULL); +	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);  	if (_dl_envp)  		*_dl_envp = (unsigned long) envp; @@ -1063,27 +1369,34 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  	/* Find the real malloc function and make ldso functions use that from now on */  	_dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc", -			_dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); +			global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);  #if defined(USE_TLS) && USE_TLS  	/* Find the real functions and make ldso functions use them from now on */  	_dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t) -		_dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); +		_dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);  	_dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t) -		_dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); +		_dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);  	_dl_free_function = (void (*)(void *)) (intptr_t) -		_dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); +		_dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);  	_dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t) -		_dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); +		_dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);  #endif  	/* Notify the debugger that all objects are now mapped in.  */  	_dl_debug_addr->r_state = RT_CONSISTENT;  	_dl_debug_state(); + +#ifdef __LDSO_STANDALONE_SUPPORT__ +	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) +		return (void *) app_tpnt->l_entry; +	else +#endif +		return (void *) auxvt[AT_ENTRY].a_un.a_val;  }  #include "dl-hash.c" diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index 3dfd50e96..8ad4ae58b 100644 --- a/ldso/ldso/m68k/elfinterp.c +++ b/ldso/ldso/m68k/elfinterp.c @@ -70,7 +70,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry. */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);  		_dl_exit(1); @@ -94,9 +94,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			   ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))  {  	unsigned int i; @@ -151,7 +151,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	     ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -184,6 +184,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);  			_dl_exit(1);  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +						&sym_ref, elf_machine_type_class(reloc_type));  	}  #if defined (__SUPPORT_LD_DEBUG__) @@ -257,7 +260,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  #undef LAZY_RELOC_WORKS  #ifdef LAZY_RELOC_WORKS  static int -_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -306,14 +309,15 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  #ifdef LAZY_RELOC_WORKS  	(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);  #else -	_dl_parse_relocation_information(rpnt, rel_addr, rel_size); +	_dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope, rel_addr, rel_size);  #endif  }  int  _dl_parse_relocation_information(struct dyn_elf *rpnt, +				 struct r_scope_elem *scope,  				 unsigned long rel_addr,  				 unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 2886f333d..3ca403609 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -56,7 +56,7 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index,  	symname = strtab + sym->st_name;  	new_addr = (unsigned long) _dl_find_hash(symname, -			tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +			&_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",  				_dl_progname, symname); @@ -111,7 +111,7 @@ __dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry. */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);  		_dl_exit(1); @@ -145,7 +145,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  int _dl_parse_relocation_information(struct dyn_elf *xpnt, -	unsigned long rel_addr, unsigned long rel_size) +	struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size)  {  	ElfW(Sym) *symtab;  	ELF_RELOC *rpnt; @@ -161,6 +161,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,  	unsigned long old_val=0;  #endif +	struct symbol_ref sym_ref = { NULL, NULL };  	/* Now parse the relocation information */  	rel_size = rel_size / sizeof(ElfW(Rel));  	rpnt = (ELF_RELOC *) rel_addr; @@ -169,6 +170,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,  	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];  	got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT]; +  	for (i = 0; i < rel_size; i++, rpnt++) {  		reloc_addr = (unsigned long *) (tpnt->loadaddr +  			(unsigned long) rpnt->r_offset); @@ -186,11 +188,14 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,  		if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) {  			symbol_addr = (unsigned long)_dl_find_hash(symname, -								   tpnt->symbol_scope, +								   scope,  								   tpnt, -								   elf_machine_type_class(reloc_type), NULL); +								   elf_machine_type_class(reloc_type), &sym_ref);  			if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))  				return 1; +			if (_dl_trace_prelink) +				_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +							&sym_ref, elf_machine_type_class(reloc_type));  		}  		if (!symtab_index) {  			/* Relocs against STN_UNDEF are usually treated as using a @@ -213,12 +218,11 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,  # endif  			{  				struct elf_resolve *tls_tpnt = NULL; -				struct symbol_ref sym_ref;  				sym_ref.sym =  &symtab[symtab_index];  				sym_ref.tpnt =  NULL;  				if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) { -					symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope, +					symbol_addr = (unsigned long) _dl_find_hash(symname, scope,  						tpnt, elf_machine_type_class(reloc_type), &sym_ref);  					tls_tpnt = sym_ref.tpnt;  				} @@ -318,7 +322,6 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,  				_dl_exit(1);  			}  		} -  	}  #if defined (__SUPPORT_LD_DEBUG__)  	if (_dl_debug_reloc && _dl_debug_detail && reloc_addr) @@ -362,12 +365,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)  				}  				else {  					*got_entry = (unsigned long) _dl_find_hash(strtab + -						sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +						sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  				}  			}  			else if (sym->st_shndx == SHN_COMMON) {  				*got_entry = (unsigned long) _dl_find_hash(strtab + -					sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +					sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  			}  			else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC &&  				*got_entry != sym->st_value && tmp_lazy) { @@ -379,7 +382,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)  			}  			else {  				*got_entry = (unsigned long) _dl_find_hash(strtab + -					sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +					sym->st_name, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  			}  			got_entry++; diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c index dd35eef54..78085ecb0 100644 --- a/ldso/ldso/powerpc/elfinterp.c +++ b/ldso/ldso/powerpc/elfinterp.c @@ -139,7 +139,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	/* Get the address of the GOT entry */  	finaladdr = (Elf32_Addr) _dl_find_hash(symname, -			tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +			&_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!finaladdr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname);  		_dl_exit(1); @@ -182,7 +182,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static __inline__ int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,  	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -215,6 +215,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  			&& (ELF32_ST_TYPE(sym_ref.sym->st_info) != STT_TLS  				&& ELF32_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)))  			return 1; +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +						&sym_ref, elf_machine_type_class(reloc_type));  		tls_tpnt = sym_ref.tpnt;  	} else {  		symbol_addr = sym_ref.sym->st_value; @@ -387,9 +390,9 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  static __inline__ int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	unsigned int i; @@ -442,7 +445,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  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)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index be3b98cf6..293bfe31e 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -69,7 +69,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **) instr_addr;  	/* Get the address of the GOT entry */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); @@ -95,9 +95,9 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	unsigned int i; @@ -148,7 +148,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  static int -_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,  	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -189,6 +189,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  			/* Let the caller to handle the error: it may be non fatal if called from dlopen */  			return 1;  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +							&sym_ref, elf_machine_type_class(reloc_type));  		tls_tpnt = sym_ref.tpnt;  	} @@ -255,7 +258,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,  static int -_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,  		   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -297,7 +300,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  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)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/sh64/elfinterp.c b/ldso/ldso/sh64/elfinterp.c index 990aed155..caf9f0e14 100644 --- a/ldso/ldso/sh64/elfinterp.c +++ b/ldso/ldso/sh64/elfinterp.c @@ -73,7 +73,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	/* Get the address of the GOT entry */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",  			    _dl_progname, symname); @@ -102,10 +102,10 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	return (unsigned long)new_addr;  } -static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		     unsigned long rel_addr, unsigned long rel_size,  		     int (*reloc_fnc)(struct elf_resolve *tpnt, -				      struct dyn_elf *scope, +				      struct r_scope_elem *scope,  				      ELF_RELOC *rpnt, Elf32_Sym *symtab,  				      char *strtab))  { @@ -162,7 +162,7 @@ static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  	return 0;  } -static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, +static int _dl_do_reloc(struct elf_resolve *tpnt,struct r_scope_elem *scope,  			ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {          int reloc_type; @@ -203,6 +203,9 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,  				     _dl_progname, symname);  			_dl_exit (1);  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +				&sym_ref, elf_machine_type_class(reloc_type));  	}  #ifdef __SUPPORT_LD_DEBUG__ @@ -290,7 +293,7 @@ static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope,  	return 0;  } -static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type, symtab_index, lsb; @@ -335,7 +338,7 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  }  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)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index 443f65bde..3c928073b 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -80,7 +80,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);  		_dl_exit(1); @@ -107,9 +107,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		unsigned long rel_addr, unsigned long rel_size, -		int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, +		int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			   ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))  {  	unsigned int i; @@ -164,7 +164,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			 ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -200,6 +200,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  			return 1;  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +						&sym_ref, elf_machine_type_class(reloc_type));  		tls_tpnt = sym_ref.tpnt;  	} else {  		/* Relocs against STN_UNDEF are usually treated as using a @@ -310,7 +313,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  #undef __SPARC_LAZY_RELOC_WORKS  #ifdef __SPARC_LAZY_RELOC_WORKS  static int -_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -358,14 +361,16 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  #ifdef __SPARC_LAZY_RELOC_WORKS  	(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);  #else -	_dl_parse_relocation_information(rpnt, rel_addr, rel_size); +	_dl_parse_relocation_information(rpnt, &_dl_loaded_modules->symbol_scope, +									rel_addr, rel_size);  #endif  }  int  _dl_parse_relocation_information(struct dyn_elf *rpnt, +				 struct r_scope_elem *scope,  				 unsigned long rel_addr,  				 unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c index 15d773388..a36b1154c 100644 --- a/ldso/ldso/x86_64/elfinterp.c +++ b/ldso/ldso/x86_64/elfinterp.c @@ -70,7 +70,7 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **)instr_addr;  	/* Get the address of the GOT entry. */ -	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely(!new_addr)) {  		_dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname);  		_dl_exit(1); @@ -94,9 +94,9 @@ _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)  }  static int -_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	  unsigned long rel_addr, unsigned long rel_size, -	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, +	  int (*reloc_fnc)(struct elf_resolve *tpnt, struct r_scope_elem *scope,  			   ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab))  {  	unsigned int i; @@ -151,7 +151,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  	     ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -186,6 +186,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  			/* This may be non-fatal if called from dlopen. */  			return 1;  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +						&sym_ref, elf_machine_type_class(reloc_type));  		tls_tpnt = sym_ref.tpnt;  	} else {  		/* Relocs against STN_UNDEF are usually treated as using a @@ -195,7 +198,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  		tls_tpnt = tpnt;  	} -  #if defined (__SUPPORT_LD_DEBUG__)  	old_val = *reloc_addr;  #endif @@ -276,7 +278,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,  }  static int -_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,  		  ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)  {  	int reloc_type; @@ -326,8 +328,9 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,  int  _dl_parse_relocation_information(struct dyn_elf *rpnt, +				 struct r_scope_elem *scope,  				 unsigned long rel_addr,  				 unsigned long rel_size)  { -	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +	return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);  } diff --git a/ldso/ldso/xtensa/elfinterp.c b/ldso/ldso/xtensa/elfinterp.c index 8eb600916..93edc1ff2 100644 --- a/ldso/ldso/xtensa/elfinterp.c +++ b/ldso/ldso/xtensa/elfinterp.c @@ -56,7 +56,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  	got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr);  	/* Get the address of the GOT entry.  */ -	new_addr = _dl_find_hash (symname, tpnt->symbol_scope, tpnt, +	new_addr = _dl_find_hash (symname, &_dl_loaded_modules->symbol_scope, tpnt,  							  ELF_RTYPE_CLASS_PLT, NULL);  	if (unlikely (!new_addr)) {  		_dl_dprintf (2, "%s: can't resolve symbol '%s'\n", @@ -82,9 +82,9 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)  static int -_dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_parse (struct elf_resolve *tpnt, struct r_scope_elem *scope,  		   unsigned long rel_addr, unsigned long rel_size, -		   int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, +		   int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope,  							 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))  {  	unsigned int i; @@ -140,7 +140,7 @@ _dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope,  static int -_dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,  			  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -177,6 +177,9 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,  						 _dl_progname, symname);  			_dl_exit (1);  		} +		if (_dl_trace_prelink) +			_dl_debug_lookup (symname, tpnt, &symtab[symtab_index], +						&sym_ref, elf_machine_type_class(reloc_type));  	}  #if defined (__SUPPORT_LD_DEBUG__) @@ -223,7 +226,7 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,  static int -_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,  				   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)  {  	int reloc_type; @@ -270,9 +273,10 @@ _dl_parse_lazy_relocation_information (struct dyn_elf *rpnt,  int  _dl_parse_relocation_information (struct dyn_elf *rpnt, +								  struct r_scope_elem *scope,  								  unsigned long rel_addr,  								  unsigned long rel_size)  { -	return _dl_parse (rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, +	return _dl_parse (rpnt->dyn, scope, rel_addr, rel_size,  					  _dl_do_reloc);  } diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index b88bc4819..f95341be7 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -55,7 +55,7 @@ extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid);  extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,  	struct elf_resolve *, char *, int); -extern int _dl_fixup(struct dyn_elf *rpnt, int lazy); +extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int lazy);  extern void _dl_protect_relro(struct elf_resolve * tpnt);  extern int _dl_errno;  extern struct dyn_elf *_dl_symbol_tables; @@ -271,6 +271,21 @@ void dl_cleanup(void)  	}  } +static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list, +	struct elf_resolve *map) +{ +	struct elf_resolve **p = list; +	struct init_fini_list *q; + +	*p++ = map; +	map->init_flag |= DL_RESERVED; +	if (map->init_fini) +		for (q = map->init_fini; q; q = q->next) +			if (! (q->tpnt->init_flag & DL_RESERVED)) +				p += _dl_build_local_scope (p, q->tpnt); +	return p - list; +} +  void *dlopen(const char *libname, int flag)  {  	struct elf_resolve *tpnt, *tfrom; @@ -283,6 +298,8 @@ void *dlopen(const char *libname, int flag)  	unsigned int nlist, i;  	struct elf_resolve **init_fini_list;  	static bool _dl_init; +	struct elf_resolve **local_scope; +	struct r_scope_elem *ls;  #if defined(USE_TLS) && USE_TLS  	bool any_tls = false;  #endif @@ -458,6 +475,23 @@ void *dlopen(const char *libname, int flag)  		}  	} +	/* Build the local scope for the dynamically loaded modules. */ +	local_scope = _dl_malloc(nlist * sizeof(struct elf_resolve *)); /* Could it allocated on stack? */ +	for (i = 0; i < nlist; i++) +		if (init_fini_list[i]->symbol_scope.r_nlist == 0) { +			int k, cnt; +			cnt = _dl_build_local_scope(local_scope, init_fini_list[i]); +			init_fini_list[i]->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *)); +			init_fini_list[i]->symbol_scope.r_nlist = cnt; +			_dl_memcpy (init_fini_list[i]->symbol_scope.r_list, local_scope, +					cnt * sizeof (struct elf_resolve *)); +			/* Restoring the init_flag.*/ +			for (k = 0; k < nlist; k++) +				init_fini_list[k]->init_flag &= ~DL_RESERVED; +		} + +	_dl_free(local_scope); +  	/* Sort the INIT/FINI list in dependency order. */  	for (runp2 = dep_list; runp2; runp2 = runp2->next) {  		unsigned int j, k; @@ -505,8 +539,13 @@ void *dlopen(const char *libname, int flag)  	 */  	_dl_perform_mips_global_got_relocations(tpnt, !now_flag);  #endif +	/* Get the tail of the list */ +	for (ls = &_dl_loaded_modules->symbol_scope; ls && ls->next; ls = ls->next); -	if (_dl_fixup(dyn_chain, now_flag)) +	/* Extend the global scope by adding the local scope of the dlopened DSO. */ +	ls->next = &dyn_chain->dyn->symbol_scope; + +	if (_dl_fixup(dyn_chain, &_dl_loaded_modules->symbol_scope, now_flag))  		goto oops;  	if (relro_ptr) { @@ -668,7 +707,7 @@ void *dlsym(void *vhandle, const char *name)  	tpnt = NULL;  	if (handle == _dl_symbol_tables)  		tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ -	ret = _dl_find_hash(name2, handle, tpnt, 0, &sym_ref); +	ret = _dl_find_hash(name2, &handle->dyn->symbol_scope, tpnt, 0, &sym_ref);  #if defined(USE_TLS) && USE_TLS && defined SHARED  	if (sym_ref.tpnt) { @@ -709,6 +748,7 @@ static int do_dlclose(void *vhandle, int need_fini)  	struct dyn_elf *handle;  	unsigned int end;  	unsigned int i, j; +	struct r_scope_elem *ls;  #if defined(USE_TLS) && USE_TLS  	bool any_tls = false;  	size_t tls_free_start = NO_TLS_OFFSET; @@ -874,7 +914,7 @@ static int do_dlclose(void *vhandle, int need_fini)  			}  #endif -			DL_LIB_UNMAP (tpnt, end); +			DL_LIB_UNMAP (tpnt, end - tpnt->mapaddr);  			/* Free elements in RTLD_LOCAL scope list */  			for (runp = tpnt->rtld_local; runp; runp = tmp) {  				tmp = runp->next; @@ -898,6 +938,16 @@ static int do_dlclose(void *vhandle, int need_fini)  				}  			} +			if (handle->dyn == tpnt) { +				/* Unlink the local scope from global one */ +				for (ls = &_dl_loaded_modules->symbol_scope; ls; ls = ls->next) +					if (ls->next->r_list[0] == tpnt) { +						_dl_if_debug_print("removing symbol_scope: %s\n", tpnt->libname); +						break; +					} +				ls->next = ls->next->next; +			} +  			/* Next, remove tpnt from the global symbol table list */  			if (_dl_symbol_tables) {  				if (_dl_symbol_tables->dyn == tpnt) { @@ -919,6 +969,7 @@ static int do_dlclose(void *vhandle, int need_fini)  				}  			}  			free(tpnt->libname); +			free(tpnt->symbol_scope.r_list);  			free(tpnt);  		}  	} diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 58f6643b2..36c0c6c63 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -153,6 +153,10 @@ extern void (*__fini_array_end []) (void) attribute_hidden;  # endif  #endif +#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (SHARED) && defined __sh__ +extern unsigned long _dl_skip_args; +#endif +  attribute_hidden const char *__uclibc_progname = "";  #ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__  const char *program_invocation_short_name = ""; @@ -341,11 +345,23 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc,      __rtld_fini = rtld_fini; +#if defined __LDSO_STANDALONE_SUPPORT__ && defined SHARED && defined __sh__ +	/* +	 * Skip ld.so and its arguments +	 * Other archs except for SH do this in _dl_start before passing +	 * control to the application. +	 * FIXME: align SH _dl_start to other archs and remove this from here, +	 *        so that we can keep the visibility hidden. +	 */ +	argc -= _dl_skip_args; +	argv += _dl_skip_args; +#endif +      /* The environment begins right after argv.  */      __environ = &argv[argc + 1];      /* If the first thing after argv is the arguments -     * the the environment is empty. */ +     * then the environment is empty. */      if ((char *) __environ == *argv) {  	/* Make __environ point to the NULL at argv[argc] */  	__environ = &argv[argc]; | 
