[patch] Improve ELF symbols preference (global > weak)

Jan Kratochvil jan.kratochvil at redhat.com
Mon Oct 8 18:53:57 UTC 2012


Hi,

debuggers like GDB display symbol name 'raise' but elfutils have been
displaying 'gsignal' instead.

$ mv core.`ulimit -c unlimited;./backtrace-child --gencore --run` ./backtrace-child.core 
$ ./backtrace ./backtrace-child{,.core}
[...]
TID 9971:
FAIL: # 0 0x7fe4ec6bd285      gsignal
->
PASS: # 0 0x7fe4ec6bd285      raise
# 1 0x7fe4ec6beb9b - 1  abort
# 2 0x7fe4ece7fa75 - 1  sigusr2
# 3 0x7fe4ece7fbd0 - 1  stdarg
# 4 0x7fe4ece7fbee - 1  backtracegen
# 5 0x7fe4ece7fc05 - 1  start
# 6 0x7fe4eca46d90 - 1  start_thread
# 7 0x7fe4ec77819d - 1  clone

This is because:
readelf -Ws /lib64/libc.so.6
Symbol table '.symtab' contains 7720 entries:
  6650: 000000326ca36250   100 FUNC    WEAK   DEFAULT   12 gsignal
  6675: 000000326ca36250   100 FUNC    GLOBAL DEFAULT   12 raise

I believe when there are both such symbols STB_GLOBAL should be preferred over
STB_WEAK (which should be preferred over STB_LOCAL).

Testcase for this patch is the whole testsuite of:
	[API RFC] unwinder
	https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/002618.html
There is check_gsignal for it in tests/run-backtrace.sh.  As there are shipped
non-x86* core files and self-contained -static files with ELF symbols the test
does not depend on host system.  Still maybe some more thorough testcase for
symbols priorities could be there, currently there is not.


Thanks,
Jan


diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index 4e0646e..7ea6289 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -133,13 +143,13 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 			}
 		    }
 		  /* When the beginning of its range is no closer,
-		     the end of its range might be.  But do not
-		     replace a global symbol with a local!  */
+		     the end of its range might be.  Prefer STB_GLOBAL over
+		     STB_WEAK and STB_WEAK over STB_LOCAL.  */
 		  else if (sym.st_size != 0
 			   && closest_sym->st_value == sym.st_value
-			   && closest_sym->st_size > sym.st_size
-			   && (GELF_ST_BIND (closest_sym->st_info)
-			       <= GELF_ST_BIND (sym.st_info)))
+			   && closest_sym->st_size >= sym.st_size
+			   && (GELF_ST_BIND (sym.st_info) == STB_GLOBAL
+			    || GELF_ST_BIND (closest_sym->st_info) == STB_LOCAL))
 		    {
 		      *closest_sym = sym;
 		      closest_shndx = shndx;


More information about the elfutils-devel mailing list