This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
Bug in ld-linux 2.1.2pre2 - absolute symbols are relocated + Patch
- To: bug-glibc@sourceware.cygnus.com
- Subject: Bug in ld-linux 2.1.2pre2 - absolute symbols are relocated + Patch
- From: Colin McCormack <colin@field.medicine.adelaide.edu.au>
- Date: Mon, 02 Aug 1999 22:58:26 +1000
- cc: libc-alpha@sourceware.cygnus.com
- Reply-To: colin@field.medicine.adelaide.edu.au
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;
}