Add some extra symbol comparisons, based on those from the DARWIN branch.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9677
This commit is contained in:
Nicholas Nethercote 2009-04-29 05:08:15 +00:00
parent 437821f592
commit 239c566d12

View 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. */