libdwfl/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 10 Oct 2012 06:04:01 +0000 (08:04 +0200)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 10 Oct 2012 06:04:01 +0000 (08:04 +0200)
* dwfl_module_addrsym.c (dwfl_module_addrsym): New function binding_value.  Use
it for both zero and non-zero size symbols comparisons.

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

Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
libdwfl/ChangeLog
libdwfl/dwfl_module_addrsym.c
tests/ChangeLog
tests/run-addrname-test.sh
tests/testfile64.bz2 [new file with mode: 0644]

index 403b0ec..4a5f4eb 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * dwfl_module_addrsym.c (dwfl_module_addrsym): New function
+       binding_value.  Use it for both zero and non-zero size symbols
+       comparisons.
+
 2012-10-01  Mark Wielaard  <mjw@redhat.com>
 
        * cu.c (cudie_offset): Don't use type_sig8, it might not be
index 4e0646e..fdc95fc 100644 (file)
@@ -106,12 +106,26 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 
              if (sym.st_size == 0 || addr - sym.st_value < sym.st_size)
                {
+                 /* Return GELF_ST_BIND as higher-is-better integer.  */
+                 inline int binding_value (const GElf_Sym *symp)
+                   {
+                     switch (GELF_ST_BIND (symp->st_info))
+                     {
+                       case STB_GLOBAL:
+                         return 3;
+                       case STB_WEAK:
+                         return 2;
+                       case STB_LOCAL:
+                         return 1;
+                       default:
+                         return 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)))
+                     || binding_value (closest_sym) < binding_value (&sym))
                    {
                      if (sym.st_size != 0)
                        {
@@ -133,13 +147,17 @@ 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
+                               && (binding_value (closest_sym)
+                                   <= binding_value (&sym)))
+                              || (closest_sym->st_size >= sym.st_size
+                                  && (binding_value (closest_sym)
+                                      < binding_value (&sym)))))
                    {
                      *closest_sym = sym;
                      closest_shndx = shndx;
index 37e214e..ac1a1f8 100644 (file)
@@ -1,3 +1,8 @@
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * run-addrname-test.sh: New test for symbol preferences.
+       * testfile64.bz2: New file.
+
 2012-10-01  Mark Wielaard  <mjw@redhat.com>
 
        * Makefile.am (TESTS_ENVIRONMENT): Define valgrind_cmd if USE_VALGRIND.
index 3531643..034cf6f 100755 (executable)
@@ -211,4 +211,85 @@ 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
+testfiles testfile64
+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 (file)
index 0000000..674bd53
Binary files /dev/null and b/tests/testfile64.bz2 differ