}
-/* 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,
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;
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;
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. */