]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add some extra symbol comparisons, based on those from the DARWIN branch.
authorNicholas Nethercote <njn@valgrind.org>
Wed, 29 Apr 2009 05:08:15 +0000 (05:08 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Wed, 29 Apr 2009 05:08:15 +0000 (05:08 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9677

coregrind/m_debuginfo/storage.c

index f71099d659a91ada406a88069f143dc1a03cf89f..343cf3b12aa5af6312fa65cb6564295142ecc859 100644 (file)
@@ -1018,14 +1018,26 @@ static Int compare_DiSym ( void* va, void* vb )
 }
 
 
-/* Two symbols have the same address.  Which name do we prefer?
+/* Two symbols have the same address.  Which name do we prefer?  In order:
 
-   The general rule is to prefer the shorter symbol name.  If the
-   symbol contains a '@', which means it is versioned, then the length
-   up to the '@' is used for length comparison purposes (so
-   "foo@GLIBC_2.4.2" is considered shorter than "foobar"), but if two
-   symbols have the same length, the one with the version string is
-   preferred.  If all else fails, use alphabetical ordering.
+   - Prefer "PMPI_<foo>" over "MPI_<foo>".
+
+   - Else, prefer a non-NULL name over a NULL one.
+
+   - Else, prefer a non-whitespace name over an all-whitespace name.
+
+   - Else, prefer the shorter symbol name.  If the symbol contains a
+     version symbol ('@' on Linux, other platforms may differ), which means it
+     is versioned, then the length up to the version symbol is used for length
+     comparison purposes (so "foo@GLIBC_2.4.2" is considered shorter than
+     "foobar"). 
+     
+   - Else, if two symbols have the same length, prefer a versioned symbol over
+     a non-versioned symbol.
+     
+   - Else, use alphabetical ordering.
+
+   - Otherwise, they must be the same;  use the symbol with the lower address.
 
    Very occasionally this goes wrong (eg. 'memcmp' and 'bcmp' are
    aliases in glibc, we choose the 'bcmp' symbol because it's shorter,
@@ -1046,8 +1058,14 @@ static DiSym* prefersym ( struct _DebugInfo* di, DiSym* a, DiSym* b )
    vlena = VG_(strlen)(a->name);
    vlenb = VG_(strlen)(b->name);
 
-   vpa = VG_(strchr)(a->name, '@');
-   vpb = VG_(strchr)(b->name, '@');
+#if defined(VGO_linux) || defined(VGO_aix5)
+#  define VERSION_CHAR '@'
+#else
+#  error Unknown OS
+#endif
+
+   vpa = VG_(strchr)(a->name, VERSION_CHAR);
+   vpb = VG_(strchr)(b->name, VERSION_CHAR);
 
    if (vpa)
       vlena = vpa - a->name;
@@ -1066,6 +1084,42 @@ static DiSym* prefersym ( struct _DebugInfo* di, DiSym* a, DiSym* b )
       preferA = True; goto out;
    }
 
+   /* Prefer non-empty name. */
+   if (vlena  &&  !vlenb) {
+      preferA = True; goto out;
+   }
+   if (vlenb  &&  !vlena) {
+      preferB = True; goto out;
+   }
+
+   /* Prefer non-whitespace name. */
+   {
+      Bool blankA = True;
+      Bool blankB = True;
+      Char *s;
+      s = a->name;
+      while (*s) {
+         if (!VG_(isspace)(*s++)) {
+            blankA = False;
+            break;
+         }
+      }
+      s = b->name;
+      while (*s) {
+         if (!VG_(isspace)(*s++)) {
+            blankB = False;
+            break;
+         }
+      }
+
+      if (!blankA  &&  blankB) {
+         preferA = True; goto out;
+      }
+      if (!blankB  &&  blankA) {
+         preferB = True; goto out;
+      }
+   }
+
    /* Select the shortest unversioned name */
    if (vlena < vlenb) {
       preferA = True; goto out;
@@ -1091,8 +1145,9 @@ static DiSym* prefersym ( struct _DebugInfo* di, DiSym* a, DiSym* b )
    if (cmp > 0) {
       preferB = True; goto out;
    }
-   /* If we get here, they are the same (?!).  That's very odd.  In
-      this case we could choose either (arbitrarily), but might as
+   /* If we get here, they are the same name. */
+
+   /* In this case we could choose either (arbitrarily), but might as
       well choose the one with the lowest DiSym* address, so as to try
       and make the comparison mechanism more stable (a la sorting
       parlance).  Also, skip the diagnostic printing in this case. */