This is the mail archive of the libc-alpha@sourceware.cygnus.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]

Bug in ld-linux 2.1.2pre2 - absolute symbols are relocated + Patch


Hi.

There's a bug in ld-linux and libdl.so glibc2.1.2pre2.

Absolute symbols in dynamically loaded ELF objects are relocated.

I believe this is contrary to the specs, and to the usual meaning of `absolute 
symbol'.

I have code which depends upon the ability to address absolutely, and am 
therefore interested in having this bug fixed.

Herewith a patch.  Is there any likelihood of its getting into 2.1.2?

Colin.


diff -c elf/dl-lookup.c ../glibc-2.1.2.old/elf/dl-lookup.c
*** elf/dl-lookup.c	Tue Feb 23 05:04:22 1999
--- ../glibc-2.1.2.old/elf/dl-lookup.c	Tue Jul 27 13:03:37 1999
***************
*** 23,29 ****
  #include <elf/ldsodefs.h>
  #include "dl-hash.h"
  #include <dl-machine.h>
! 
  #include <assert.h>
  
  #define VERSTAG(tag)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
--- 23,29 ----
  #include <elf/ldsodefs.h>
  #include "dl-hash.h"
  #include <dl-machine.h>
! #include <stdio-common/_itoa.h>
  #include <assert.h>
  
  #define VERSTAG(tag)	(DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (tag))
***************
*** 327,330 ****
--- 327,398 ----
    map->l_buckets = hash;
    hash += map->l_nbuckets;
    map->l_chain = hash;
+ }
+ 
+ void _dl_dump_reloc(Elf32_Rel *reloc, Elf32_Addr *const reloc_addr)
+ {
+     char buf[20];
+     char *p;
+  
+     if (!reloc) {
+         _dl_debug_message(1, "NULL reloc");
+     }
+ 
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (reloc_addr, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, "reloc @", p, NULL);
+ 
+     if (reloc_addr) {
+         buf[sizeof buf - 1] = '\0';
+         memset ((void *) buf, ' ',sizeof buf - 1);
+         p = _itoa_word (*reloc_addr, &buf[sizeof buf - 3], 16, 0);
+         _dl_debug_message (1, " content:", p, NULL);
+     }
+ 
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (reloc->r_info, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, " r_info:", p, NULL);
+ 
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (reloc->r_offset, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, " r_offset:", p, "\n", NULL);
+ }
+ 
+ void _dl_dump_sym(struct link_map *map, Elf32_Sym *sym)
+ {
+     const char *strtab;
+     char buf[20];
+     char *p;
+ 
+     if (!sym || !map) {
+         _dl_debug_message(1, "NULL Symbol", NULL);
+         return;
+     }
+ #if 0
+     strtab = (const char *) map->l_info[DT_STRTAB]->d_un.d_ptr;
+     if (strtab && sym->st_name) {
+         _dl_debug_message (1, "Symbol ", strtab + sym->st_name, NULL);
+     } else {
+         _dl_debug_message (1, "Symbol ANONYMOUS", NULL);
+     }
+ #endif
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (sym->st_value, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, " value 0x", p, NULL);
+ 
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (sym->st_info, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, " info 0x", p, NULL);
+ 
+     buf[sizeof buf - 1] = '\0';
+     memset ((void *) buf, ' ',sizeof buf - 1);
+     p = _itoa_word (sym->st_shndx, &buf[sizeof buf - 3], 16, 0);
+     _dl_debug_message (1, " shndx 0x", p, NULL);
+ 
+     _dl_debug_message (1, "\n", NULL);
  }
diff -c elf/dl-runtime.c ../glibc-2.1.2.old/elf/dl-runtime.c
*** elf/dl-runtime.c	Fri Jul 16 04:32:41 1999
--- ../glibc-2.1.2.old/elf/dl-runtime.c	Mon Jul 26 18:47:47 1999
***************
*** 91,100 ****
  
    /* Currently value contains the base load address of the object
       that defines sym.  Now add in the symbol offset.  */
!   value = (sym ? value + sym->st_value : 0);
  
!   /* And now perhaps the relocation addend.  */
!   value = elf_machine_plt_value (l, reloc, value);
  
    /* Finally, fix up the plt itself.  */
    elf_machine_fixup_plt (l, reloc, rel_addr, value);
--- 91,104 ----
  
    /* Currently value contains the base load address of the object
       that defines sym.  Now add in the symbol offset.  */
!   if (sym->st_shndx != SHN_ABS) {
!       value = (sym ? value + sym->st_value : 0);
  
!       /* And now perhaps the relocation addend.  */
!       value = elf_machine_plt_value (l, reloc, value);
!   } else {
!       value = sym ? sym->st_value : 0;
!   }
  
    /* Finally, fix up the plt itself.  */
    elf_machine_fixup_plt (l, reloc, rel_addr, value);
***************
*** 167,176 ****
  
        /* Currently value contains the base load address of the object
  	 that defines sym.  Now add in the symbol offset.  */
!       value = (sym ? value + sym->st_value : 0);
  
!       /* And now perhaps the relocation addend.  */
!       value = elf_machine_plt_value (l, reloc, value);
  
        /* Store the result for later runs.  */
        *resultp = value;
--- 171,184 ----
  
        /* Currently value contains the base load address of the object
  	 that defines sym.  Now add in the symbol offset.  */
!       if (sym->st_shndx != SHN_ABS) {
!           value = (sym ? value + sym->st_value : 0);
  
!           /* And now perhaps the relocation addend.  */
!           value = elf_machine_plt_value (l, reloc, value);
!       } else {
!           value = sym ? sym->st_value : 0;
!       }
  
        /* Store the result for later runs.  */
        *resultp = value;
diff -c elf/dl-symbol.c ../glibc-2.1.2.old/elf/dl-symbol.c
*** elf/dl-symbol.c	Sun Sep  6 19:08:04 1998
--- ../glibc-2.1.2.old/elf/dl-symbol.c	Mon Jul 26 18:06:46 1999
***************
*** 30,34 ****
    const ElfW(Sym) *ref = NULL;
    loadbase = _dl_lookup_symbol (name, &ref, map->l_local_scope, map->l_name,
  				0);
!   return loadbase + ref->st_value;
  }
--- 30,38 ----
    const ElfW(Sym) *ref = NULL;
    loadbase = _dl_lookup_symbol (name, &ref, map->l_local_scope, map->l_name,
  				0);
!   if (ref->st_shndx != SHN_ABS) {
!       return loadbase + ref->st_value;
!   } else {
!       return ref->st_value;
!   }
  }
diff -c elf/dlsym.c ../glibc-2.1.2.old/elf/dlsym.c
*** elf/dlsym.c	Wed Feb  3 21:29:22 1999
--- ../glibc-2.1.2.old/elf/dlsym.c	Mon Jul 26 18:50:09 1999
***************
*** 95,99 ****
    args.name = name;
  
    return (_dlerror_run (dlsym_doit, &args)
! 	  ? NULL : (void *) (args.loadbase + args.ref->st_value));
  }
--- 95,102 ----
    args.name = name;
  
    return (_dlerror_run (dlsym_doit, &args)
! 	  ? NULL
!           : (void *) (((args.ref->st_shndx != SHN_ABS)
!                       ?args.loadbase :0)
!           + args.ref->st_value));
  }
diff -c elf/dlvsym.c ../glibc-2.1.2.old/elf/dlvsym.c
*** elf/dlvsym.c	Wed Feb  3 21:29:39 1999
--- ../glibc-2.1.2.old/elf/dlvsym.c	Mon Jul 26 18:50:33 1999
***************
*** 110,115 ****
    args.version.filename = NULL;
  
    return (_dlerror_run (dlvsym_doit, &args)
! 	  ? NULL : (void *) (args.loadbase + args.ref->st_value));
  }
  weak_alias (__dlvsym, dlvsym)
--- 110,120 ----
    args.version.filename = NULL;
  
    return (_dlerror_run (dlvsym_doit, &args)
! 	  ? NULL
!           : (void *) (((args.ref->st_shndx != SHN_ABS)
!                       ?args.loadbase :0)
!           + args.ref->st_value));
! 
!   /*	  ? NULL : (void *) (args.loadbase + args.ref->st_value));*/
  }
  weak_alias (__dlvsym, dlvsym)
diff -c elf/do-lookup.h ../glibc-2.1.2.old/elf/do-lookup.h
*** elf/do-lookup.h	Sat May  8 07:10:25 1999
--- ../glibc-2.1.2.old/elf/do-lookup.h	Tue Jul 27 11:04:11 1999
***************
*** 24,30 ****
  # define FCT do_lookup
  # define ARG
  #endif
! 
  /* Inner part of the lookup functions.  We return a value > 0 if we
     found the symbol, the value 0 if nothing is found and < 0 if
     something bad happened.  */
--- 24,30 ----
  # define FCT do_lookup
  # define ARG
  #endif
! #include <stdio-common/_itoa.h>
  /* Inner part of the lookup functions.  We return a value > 0 if we
     found the symbol, the value 0 if nothing is found and < 0 if
     something bad happened.  */
***************
*** 63,69 ****
  
        /* Print some debugging info if wanted.  */
        if (_dl_debug_symbols)
! 	_dl_debug_message (1, "symbol=", undef_name, ";  lookup in file=",
  			   map->l_name[0] ? map->l_name : _dl_argv[0],
  			   "\n", NULL);
  
--- 63,69 ----
  
        /* Print some debugging info if wanted.  */
        if (_dl_debug_symbols)
! 	_dl_debug_message (1, "woo=", undef_name, ";  lookup in file=",
  			   map->l_name[0] ? map->l_name : _dl_argv[0],
  			   "\n", NULL);
  
***************
*** 153,158 ****
--- 153,161 ----
        if (sym != NULL)
  	{
  	found_it:
+             if (_dl_debug_symbols && sym) {
+                 _dl_dump_sym(map, sym);
+             }
  	  switch (ELFW(ST_BIND) (sym->st_info))
  	    {
  	    case STB_GLOBAL:
diff -c sysdeps/i386/dl-machine.h ../glibc-2.1.2.old/sysdeps/i386/dl-machine.h
*** sysdeps/i386/dl-machine.h	Sun Feb 21 05:19:47 1999
--- ../glibc-2.1.2.old/sysdeps/i386/dl-machine.h	Tue Jul 27 12:51:56 1999
***************
*** 313,318 ****
--- 313,324 ----
  		 const Elf32_Sym *sym, const struct r_found_version *version,
  		 Elf32_Addr *const reloc_addr)
  {
+ #if 0
+     if (_dl_debug_reloc) {
+         _dl_dump_reloc(reloc, reloc_addr);
+     }
+ #endif
+ 
    if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
      {
  #ifndef RTLD_BOOTSTRAP
***************
*** 324,331 ****
      {
        const Elf32_Sym *const refsym = sym;
        Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
!       if (sym)
! 	value += sym->st_value;
  
        switch (ELF32_R_TYPE (reloc->r_info))
  	{
--- 330,347 ----
      {
        const Elf32_Sym *const refsym = sym;
        Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
!       if (sym) {
!           if (_dl_debug_symbols)
!               _dl_dump_sym(map, sym);
! 
!           if (sym->st_shndx != SHN_ABS) {
!               value += sym->st_value;
!           } else
!               value = sym->st_value;
!       }
!       if (_dl_debug_reloc) {
!           _dl_dump_reloc(reloc, reloc_addr);
!       }
  
        switch (ELF32_R_TYPE (reloc->r_info))
  	{
***************
*** 389,394 ****
--- 405,413 ----
    Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
    /* Check for unexpected PLT reloc type.  */
    assert (ELF32_R_TYPE (reloc->r_info) == R_386_JMP_SLOT);
+   if (_dl_debug_reloc) {
+       _dl_dump_reloc(reloc, reloc);
+   }
    *reloc_addr += l_addr;
  }

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