This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: evolution vs prelink on debian ppc sid


On Thu, Sep 26, 2002 at 03:39:57PM -0400, Jack Howarth wrote:
> Jakub,
>    I'll generate the debug logs you asked for tonight on
> my debian ppc sid machine when I get home. However I finally
> got all of evolution and all libs it uses rebuilt on
> entropy.crashing.org using the current rawhide srpms. I
> am seeing effectively the same behavior there as I do on
> my debian ppc sid box. Prelinked evolution segfaults
> whereas unprelinked does not. 
>    I am curious. Have you tried prelinking evolution on
> i386 rawhide?

The main difference on IA-32 is that because of binary base address
0x8048000 there is place to grow downwards and thus .dynstr doesn't have
to migrate in a different PT_LOAD.
But I verified on your box that in fact what we were talking about is why
evolution crashes.
Here is an untested patch.

2002-09-27  Jakub Jelinek  <jakub@redhat.com>

	* elf/dl-addr.c (VERSYMIDX, ADDRIDX): Define.
	(_dl_addr): Set dli_fbase to l_map_start unconditionally.
	Set dli_fname to _dl_argv[0] only for main program.
	Compute and use symtabend instead of strtab for end of symtab.
	Break the loop on first symbol with invaild st_name.

--- libc/elf/dl-addr.c.jj	2002-08-04 20:23:20.000000000 +0200
+++ libc/elf/dl-addr.c	2002-09-27 00:03:09.000000000 +0200
@@ -21,6 +21,13 @@
 #include <stddef.h>
 #include <ldsodefs.h>
 
+#ifndef VERSYMIDX
+# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
+#endif
+#ifndef ADDRIDX
+# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+		       + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+#endif
 
 int
 internal_function
@@ -28,7 +35,7 @@ _dl_addr (const void *address, Dl_info *
 {
   const ElfW(Addr) addr = DL_LOOKUP_ADDRESS (address);
   struct link_map *l, *match;
-  const ElfW(Sym) *symtab, *matchsym;
+  const ElfW(Sym) *symtab, *matchsym, *symtabend;
   const char *strtab;
   ElfW(Word) strtabsize;
 
@@ -60,30 +67,55 @@ _dl_addr (const void *address, Dl_info *
 
   /* Now we know what object the address lies in.  */
   info->dli_fname = match->l_name;
-  info->dli_fbase = (void *) match->l_addr;
+  info->dli_fbase = (void *) match->l_map_start;
 
   /* If this is the main program the information is incomplete.  */
-  if (__builtin_expect (info->dli_fbase == NULL, 0))
-    {
-      info->dli_fname = _dl_argv[0];
-      info->dli_fbase = (void *) match->l_map_start;
-    }
+  if (__builtin_expect (*info->dli_fname == '\0', 0))
+    info->dli_fname = _dl_argv[0];
 
   symtab = (const void *) D_PTR (match, l_info[DT_SYMTAB]);
   strtab = (const void *) D_PTR (match, l_info[DT_STRTAB]);
   strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
 
-  /* We assume that the string table follows the symbol table, because
-     there is no way in ELF to know the size of the dynamic symbol table!!  */
-  for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
-    if (addr >= match->l_addr + symtab->st_value
-	&& ((symtab->st_size == 0 && addr == match->l_addr + symtab->st_value)
-	    || addr < match->l_addr + symtab->st_value + symtab->st_size)
-	&& symtab->st_name < strtabsize
-	&& (matchsym == NULL || matchsym->st_value < symtab->st_value)
-	&& (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
-	    || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
-      matchsym = symtab;
+  if (match->l_name[0] != '\0')
+    /* We assume that the string table follows the symbol table, because
+       there is no way in ELF to know the size of the dynamic symbol table!!  */
+    symtabend = (const ElfW(Sym) *) strtab;
+  else
+    {
+      /* Prelinking an executable might move strtab away from symtab.  */
+      static int tags = { DT_STRTAB, DT_JMPREL, DT_RELA, DT_REL, DT_HASH,
+			  DT_INIT, DT_INIT_ARRAY, DT_FINI_ARRAY,
+			  DT_PREINIT_ARRAY, ADDRIDX (DT_GNU_CONFLICT),
+			  ADDRIDX (DT_GNU_LIBLIST), VERSYMIDX (DT_VERSYM),
+			  VERSYMIDX (DT_VERDEF), VERSYMIDX (DT_VERNEED) };
+      int tag;
+
+      for (symtabend = (const ElfW(Sym) *) -1, tag = 0;
+	   tag < sizeof (tags) / sizeof (tags[0]); tag++)
+	{
+	  if (D_PTR (match, l_info[tags[tag]]) >= symtab
+	      && D_PTR (match, l_info[tags[tag]]) < symtabend)
+	    symtabend
+	      = (const ElfW(Sym) *) D_PTR (match, l_info[tags[tag]]);
+	}
+      if (symtabend == (const ElfW(Sym) *) -1)
+	symtabend = symtab;
+    }
+
+  for (matchsym = NULL; symtab < symtabend; ++symtab)
+    {
+      if (symtab->st_name >= strtabsize)
+	break;
+      if (addr >= match->l_addr + symtab->st_value
+	  && ((symtab->st_size == 0
+	       && addr == match->l_addr + symtab->st_value)
+	      || addr < match->l_addr + symtab->st_value + symtab->st_size)
+	  && (matchsym == NULL || matchsym->st_value < symtab->st_value)
+	  && (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+	      || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
+	matchsym = symtab;
+    }
 
   if (matchsym)
     {


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]