From 239c566d12f5ecc6bfcec36384fabcf27a013f2a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 Apr 2009 05:08:15 +0000 Subject: [PATCH] Add some extra symbol comparisons, based on those from the DARWIN branch. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9677 --- coregrind/m_debuginfo/storage.c | 77 ++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index f71099d659..343cf3b12a 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -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_" over "MPI_". + + - 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. */ -- 2.47.3