This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
Re: evolution vs prelink on debian ppc sid
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jack Howarth <howarth at bromo dot med dot uc dot edu>
- Cc: libc-alpha at sources dot redhat dot com
- Date: Fri, 27 Sep 2002 00:12:42 +0200
- Subject: Re: evolution vs prelink on debian ppc sid
- References: <200209261939.PAA85487@bromo.msbb.uc.edu>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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