This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils 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: [patch] Improve ELF symbols preference (global > weak)


On Mon, 08 Oct 2012 21:55:25 +0200, Roland McGrath wrote:
> When there are multiple matches that are STB_GLOBAL and have the same
> st_size, your change will take the last one instead of the first.
> I don't think we want that.

OK this way?


Thanks,
Jan


libdwfl/
2012-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* dwfl_module_addrsym.c (dwfl_module_addrsym): New macro BIND_PREF.
	Use it for both zero and non-zero size symbols comparisons.

tests/
2012-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* run-addrname-test.sh: New test for symbol preferences.
	* testfile64.bz2: New file.

diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index 4e0646e..dcc2a7a 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -106,12 +106,15 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 
 	      if (sym.st_size == 0 || addr - sym.st_value < sym.st_size)
 		{
+#define BIND_PREF(sym)							\
+  (GELF_ST_BIND ((sym).st_info) == STB_GLOBAL				\
+   ? 3 : (GELF_ST_BIND ((sym).st_info) == STB_WEAK			\
+	  ? 2 : (GELF_ST_BIND ((sym).st_info) == STB_LOCAL ? 1 : 0)))
 		  /* This symbol is a better candidate than the current one
 		     if it's closer to ADDR or is global when it was local.  */
 		  if (closest_name == NULL
 		      || closest_sym->st_value < sym.st_value
-		      || (GELF_ST_BIND (closest_sym->st_info)
-			  < GELF_ST_BIND (sym.st_info)))
+		      || BIND_PREF (*closest_sym) < BIND_PREF (sym))
 		    {
 		      if (sym.st_size != 0)
 			{
@@ -133,18 +136,22 @@ 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.  Otherwise follow
+		     GELF_ST_BIND preference.  If all are equal prefer
+		     the first symbol found.  */
 		  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
+			        && BIND_PREF (*closest_sym) <= BIND_PREF (sym))
+			       || (closest_sym->st_size >= sym.st_size
+				   && (BIND_PREF (*closest_sym)
+				       < BIND_PREF (sym)))))
 		    {
 		      *closest_sym = sym;
 		      closest_shndx = shndx;
 		      closest_name = name;
 		    }
+#undef BIND_PREF
 		}
 	    }
 	}
diff --git a/tests/run-addrname-test.sh b/tests/run-addrname-test.sh
index 3531643..1a98631 100755
--- a/tests/run-addrname-test.sh
+++ b/tests/run-addrname-test.sh
@@ -211,4 +211,84 @@ local_outer+0x9
 ??:0
 EOF
 
+#	.macro global label size
+#\label:	.globl \label
+#	.size \label, \size
+#	.endm
+#	.macro weak label size
+#\label:	.weak \label
+#	.size \label, \size
+#	.endm
+#	.macro local label size
+#\label:	.size \label, \size
+#	.endm
+#	.macro offset val
+#	.ifne (. - _start) - \val
+#	.err
+#	.endif
+#	.byte \val
+#	.endm
+#
+#_start:
+#	offset 0
+#
+#	local glocal, 1
+#	weak gweak, 1
+#	global gglobal1, 2
+#	global gglobal2, 1
+#	global gglobal3, 1
+#	offset 1
+#	/* Symbols end here.  */
+#	offset 2
+#	/* gglobal1 ends here.  */
+#	offset 3
+#
+#	local g0local, 0
+#	weak g0weak, 0
+#	global g0global1, 0
+#	global g0global2, 0
+#	offset 4
+#
+#	local wlocal, 1
+#	weak wweak1, 2
+#	weak wweak2, 1
+#	weak wweak3, 1
+#	offset 5
+#	/* Symbols end here.  */
+#	offset 6
+#	/* wweak1 ends here.  */
+#	offset 7
+#
+#	local w0local, 0
+#	weak w0weak1, 0
+#	weak w0weak2, 0
+#	offset 8
+#
+#	local llocal1, 2
+#	local llocal2, 1
+#	local llocal3, 1
+#	offset 9
+#	/* Symbols end here.  */
+#	offset 10
+#	/* llocal1 ends here.  */
+#	offset 11
+#
+#	local l0local1, 0
+#	local l0local2, 0
+#	offset 12
+testrun_compare ../src/addr2line -S -e testfile64 1 4 5 8 9 12 <<\EOF
+gglobal2
+??:0
+g0global2
+??:0
+wweak2
+??:0
+w0weak2
+??:0
+llocal2
+??:0
+l0local2
+??:0
+EOF
+
 exit 0
diff --git a/tests/testfile64.bz2 b/tests/testfile64.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..674bd5397137e49a3781b04cb50018d937340011
GIT binary patch
literal 395
zcmV;60d)RCT4*^jL0KkKS*zvL!2kiRfB1j@=*eM)c>!aDK>)ta{NT_82oNA3U;r=y
zYX+<|(v#IUpriFqQ`9ufp!A-TCPsq(a)dYUs(XQ)Pmrh%Xao}d5#0iXZ?2(a)z9M(HR;5
zXahq=hCtD#ng*DJiwmabqM7gEtAsjEIf9~vRiA<f9`>pd2~C&Z1o9(GUTGSJ61fo&
z%_5RFm8&WNFvKLWHGqIquWbPWkizy0|2ZfNKKXNI&-+SCb)<x9qTQ)4-c5}Vg)I$<
zDg&{E7TF23#0+Q_9Jq;fBj*R!8Jsm;NukV4#KSsiMT8Z++>kODHk(b27rLYu<(gEO
z>3}(|5DKdR{>2sI0<%S(a)p<*sQMvca)yLLkp60X$^Hi8&9#^ota1~0+1-33B{Kp+r7
zU}SdrzO6pSSj9$-G=cny`UOK980RlS&Ww!%*h-5jX4)Hq#yZIoF%4P>%Vb<6JcLfj
pTM&vjR<)mpw7j*1N{*Du34jUjIIUqy29p1axgwk>NLBLcV1V8+t4RO=

literal 0
HcmV?d00001


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