[uClibc] buildroot in an uClibc env

Alexandre Oliva aoliva at redhat.com
Tue Feb 17 23:59:44 UTC 2004


On Feb 15, 2004, "Joakim Tjernlund" <Joakim.Tjernlund at lumentis.se> wrote:

>> A new class would use the STT_FUNC above.  I've implemented this in my
>> 0.9.23-based tree, but I'll have to update it to mainline after your
>> patch goes in.

> Well, the patch is in now. Perhaps you could demonstrate(with a
> patch) what you want to do with dl_find_hash?

Here's an updated patch of what I posted as part of the FR-V FDPIC
patch.

Some rationale for the changes:

loadaddr is not just a pointer in FR-V FDPIC, since different segments
relocate by different values.  It's defined as a struct containing a
pointer to a load map data structure and a pointer to the module's
GOT.

Callers of _dl_find_hash often need to tell in which module the symbol
that was found was defined.  I introduced this ugly way to get callers
to obtain this information, with an adaptor function just to minimize
changes in other ports.  I'd very much like to officially change the
interface of _dl_find_addr such that it returned not the symbol
address, but rather a tuple (tpnt,sym[,address]), a bit like glibc
does.  The need for tpnt is that some relocations in FR-V FDPIC
resolve not only to the symbol address, but also to the GOT of the
module holding the symbol.

I hope this explanation is enough for you to figure out what's going
on with the patch.  I won't post the entire updated patch right now,
but you can probably figure out that DL_FIND_HASH_VALUE and
DL_RELOC_ADDR's default actions are equivalent to current behavior,
and are overridden only in the frv header files.

E.g., DL_FIND_HASH_VALUE in frv/dl-sysdep.h is defined as:

/* We want to return to dlsym() a function descriptor if the symbol
   turns out to be a function.  */
#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \
  (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \
   && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \
   ? _dl_funcdesc_for (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr),    \
 		       (TPNT)->loadaddr.got_value)			     \
   : DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr))

of course, dlsym() is adjusted to pass in ELF_RTYPE_CLASS_DLSYM as the
type class.

diff -u -p -d -u -p -d -u -p -r1.18 dl-hash.c
--- dl-hash.c	14 Feb 2004 11:30:31 -0000	1.18
+++ dl-hash.c	17 Feb 2004 23:39:09 -0000
@@ -92,8 +92,8 @@ struct elf_resolve *_dl_check_hashed_fil
  * externals properly.
  */
 struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
-	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
-	unsigned long dynamic_size)
+	DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info,
+	unsigned long dynamic_addr, unsigned long dynamic_size)
 {
 	unsigned long *hash_addr;
 	struct elf_resolve *tpnt;
@@ -120,14 +120,18 @@ struct elf_resolve *_dl_add_elf_hash_tab
 	tpnt->libtype = loaded_file;
 
 	if (dynamic_info[DT_HASH] != 0) {
-		hash_addr = (unsigned long *) (intptr_t)(dynamic_info[DT_HASH] + loadaddr);
+		hash_addr = (unsigned long *) (intptr_t)
+		  DL_RELOC_ADDR (dynamic_info[DT_HASH], loadaddr);
 		tpnt->nbucket = *hash_addr++;
 		tpnt->nchain = *hash_addr++;
 		tpnt->elf_buckets = hash_addr;
 		hash_addr += tpnt->nbucket;
 		tpnt->chains = hash_addr;
 	}
-	tpnt->loadaddr = (ElfW(Addr))loadaddr;
+#if defined (__SUPPORT_LD_DEBUG__)
+	else _dl_dprintf(2, "no hash table for tpnt %x\n", tpnt);
+#endif
+	tpnt->loadaddr = loadaddr;
 	for (i = 0; i < 24; i++)
 		tpnt->dynamic_info[i] = dynamic_info[i];
 #ifdef __mips__
@@ -153,8 +157,8 @@ struct elf_resolve *_dl_add_elf_hash_tab
  * 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 *rpnt1,
-		    int type_class)
+char *__dl_find_hash(const char *name, struct dyn_elf *rpnt1,
+		     int type_class, struct elf_resolve **tpntp)
 {
 	struct elf_resolve *tpnt;
 	int si;
@@ -162,11 +166,11 @@ char *_dl_find_hash(const char *name, st
 	char *strtab;
 	Elf32_Sym *symtab;
 	unsigned long elf_hash_number, hn;
-	char *weak_result;
+	const ElfW(Sym) *weak_sym = 0;
+	struct elf_resolve *weak_tpnt = 0;
 	struct dyn_elf *rpnt;
 	const ElfW(Sym) *sym;
 
-	weak_result = 0;
 	elf_hash_number = _dl_elf_hash(name);
 
 	/*
@@ -204,15 +208,31 @@ char *_dl_find_hash(const char *name, st
 			tpnt = rpnt->dyn;
 
 			/* Don't search the executable when resolving a copy reloc. */
-			if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
+			if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
 				continue;
 
+#if defined (__SUPPORT_LD_DEBUG__)
+			if (tpnt->nbucket == 0) {
+				_dl_dprintf(2, "tpnt %x has nbucket == 0\n", tpnt);
+#if 0
+				_dl_dprintf(2, "while resolving %s in scope %x\n",
+					    name, rpnt);
+				_dl_dprintf(2, "(looking at tpnt %s at %x)\n",
+					    tpnt->libname,
+					    DL_LOADADDR_BASE(tpnt->loadaddr));
+#endif
+				_dl_exit(17);
+			}
+#endif
 			/*
 			 * Avoid calling .urem here.
 			 */
 			do_rem(hn, elf_hash_number, tpnt->nbucket);
-			symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-			strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+			symtab = (Elf32_Sym *) (intptr_t)
+			  DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB],
+					 tpnt->loadaddr);
+			strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB],
+						tpnt->loadaddr);
 
 			for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
 				sym = &symtab[si];
@@ -236,18 +256,34 @@ once that hack has been fixed.
 */
 
 						if(_dl_symbol((char *)name)) {
-						if (!weak_result)
-							weak_result = (char *)tpnt->loadaddr + sym->st_value;
+						if (!weak_sym) {
+							weak_tpnt = tpnt;
+							weak_sym = sym;
+						}
 						break;
 						}
 #endif
 					case STB_GLOBAL:
-						return (char*)tpnt->loadaddr + sym->st_value;
+						if (tpntp)
+							*tpntp = tpnt;
+						return DL_FIND_HASH_VALUE
+						  (tpnt, type_class, sym);
 					default:	/* Local symbols not handled here */
 						break;
 				}
 			}
 		}
 	}
-	return weak_result;
+	if (weak_sym) {
+		if (tpntp)
+			*tpntp = weak_tpnt;
+		return DL_FIND_HASH_VALUE (weak_tpnt, type_class, weak_sym);
+	}
+	return NULL;
+}
+
+char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
+		    int type_class)
+{
+  return __dl_find_hash(name, rpnt1, type_class, NULL);
 }


-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Happy GNU Year!                     oliva@{lsd.ic.unicamp.br, gnu.org}
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist                Professional serial bug killer



More information about the uClibc mailing list