Browse Source

Blackfin FD-PIC patch 3/6.
Change _dl_find_hash to _dl_lookup_hash, as on the NPTL branch.
_dl_find_hash is now a wrapper function around it; unlike on the NPTL branch,
it retains the old interface so that not all callers need to be changed.

_dl_lookup_hash can optionally give its caller a pointer to the module where
the symbol was found.

Introduce ELF_RTYPE_CLASS_DLSYM for lookups from libdl.

Spelling fixes in the Blackfin port, since Alex Oliva's original version of
these patches used _dl_find_hash_mod as the name of the function rather than
_dl_lookup_hash.

Bernd Schmidt 16 years ago
parent
commit
95586b5663
6 changed files with 61 additions and 14 deletions
  1. 7 0
      ldso/include/dl-defs.h
  2. 5 0
      ldso/include/dl-elf.h
  3. 16 2
      ldso/include/dl-hash.h
  4. 3 5
      ldso/ldso/bfin/elfinterp.c
  5. 29 6
      ldso/ldso/dl-hash.c
  6. 1 1
      ldso/libdl/libdl.c

+ 7 - 0
ldso/include/dl-defs.h

@@ -181,4 +181,11 @@ typedef struct {
 #define __C_SYMBOL_PREFIX__ "_"
 #endif
 
+/* Define this if you want to modify the VALUE returned by
+   _dl_find_hash for this reloc TYPE.  TPNT is the module in which the
+   matching SYM was found.  */
+#ifndef DL_FIND_HASH_VALUE
+# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr))
+#endif
+
 #endif	/* _LD_DEFS_H */

+ 5 - 0
ldso/include/dl-elf.h

@@ -183,6 +183,11 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
 #endif
 #define ELF_RTYPE_CLASS_PLT	(0x1)
 
+/* dlsym() calls _dl_find_hash with this value, that enables
+   DL_FIND_HASH_VALUE to return something different than the symbol
+   itself, e.g., a function descriptor.  */
+#define ELF_RTYPE_CLASS_DLSYM 0x80000000
+
 
 /* Convert between the Linux flags for page protections and the
    ones specified in the ELF standard. */

+ 16 - 2
ldso/include/dl-hash.h

@@ -105,8 +105,22 @@ 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 * rpnt1,
-			    struct elf_resolve *mytpnt, int type_class);
+extern char * _dl_lookup_hash(const char * name, struct dyn_elf * rpnt,
+			      struct elf_resolve *mytpnt, int type_class
+#ifdef __FDPIC__
+			      , struct elf_resolve **tpntp
+#endif
+			      );
+
+static __always_inline char *_dl_find_hash(const char *name, struct dyn_elf *rpnt,
+					   struct elf_resolve *mytpnt, int type_class)
+{
+#ifdef __FDPIC__
+	return _dl_lookup_hash(name, rpnt, mytpnt, type_class, NULL);
+#else
+	return _dl_lookup_hash(name, rpnt, mytpnt, type_class);
+#endif
+}
 
 extern int _dl_linux_dynamic_link(void);
 

+ 3 - 5
ldso/ldso/bfin/elfinterp.c

@@ -72,11 +72,9 @@ _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_mod(symname, tpnt->symbol_scope, NULL, 0,
-				     &new_tpnt);
+	new_addr = _dl_lookup_hash(symname, tpnt->symbol_scope, NULL, 0, &new_tpnt);
 	if (!new_addr) {
-		new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0,
-					     &new_tpnt);
+		new_addr = _dl_lookup_hash(symname, NULL, NULL, 0, &new_tpnt);
 		if (!new_addr) {
 			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 				    _dl_progname, symname);
@@ -188,7 +186,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 	} else {
 
 		symbol_addr = (unsigned long)
-		  _dl_find_hash_mod(symname, scope, NULL, 0, &symbol_tpnt);
+		  _dl_lookup_hash(symname, scope, NULL, 0, &symbol_tpnt);
 
 		/*
 		 * We want to allow undefined references to weak symbols - this might

+ 29 - 6
ldso/ldso/dl-hash.c

@@ -257,7 +257,12 @@ _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, int type_class)
+char *_dl_lookup_hash(const char *name, struct dyn_elf *rpnt,
+		      struct elf_resolve *mytpnt, int type_class
+#ifdef __FDPIC__
+		      , struct elf_resolve **tpntp
+#endif
+		      )
 {
 	struct elf_resolve *tpnt = NULL;
 	ElfW(Sym) *symtab;
@@ -265,7 +270,8 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *
 	unsigned long elf_hash_number = 0xffffffff;
 	const ElfW(Sym) *sym = NULL;
 
-	char *weak_result = NULL;
+	const ElfW(Sym) *weak_sym = 0;
+	struct elf_resolve *weak_tpnt = 0;
 
 #ifdef __LDSO_GNU_HASH_SUPPORT__
 	unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name);
@@ -326,15 +332,32 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *
 #if 0
 /* Perhaps we should support old style weak symbol handling
  * per what glibc does when you export LD_DYNAMIC_WEAK */
-				if (!weak_result)
-					weak_result = (char *) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value);
+				if (!weak_sym) {
+					weak_tpnt = tpnt;
+					weak_sym = sym;
+				}
 				break;
 #endif
 			case STB_GLOBAL:
-				return (char*) DL_RELOC_ADDR(tpnt->loadaddr, sym->st_value);
+#ifdef __FDPIC__
+				if (tpntp)
+					*tpntp = tpnt;
+#endif
+				return DL_FIND_HASH_VALUE (tpnt, type_class, sym);
 			default:	/* Local symbols not handled here */
 				break;
 		}
 	}
-	return weak_result;
+	if (weak_sym) {
+#ifdef __FDPIC__
+		if (tpntp)
+			*tpntp = weak_tpnt;
+#endif
+		return DL_FIND_HASH_VALUE (weak_tpnt, type_class, weak_sym);
+	}
+#ifdef __FDPIC__
+	if (tpntp)
+		*tpntp = NULL;
+#endif
+	return NULL;
 }

+ 1 - 1
ldso/libdl/libdl.c

@@ -500,7 +500,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);
+	ret = _dl_find_hash(name2, handle, tpnt, ELF_RTYPE_CLASS_DLSYM);
 
 	/*
 	 * Nothing found.