[ELF] Print symbols with non-default versions for better "undefined symbol" diagnostics

When reporting an "undefined symbol" diagnostic:

* We don't print @ for the reference.
* We don't print @ or @@ for the definition. https://bugs.llvm.org/show_bug.cgi?id=45318

This can lead to confusing diagnostics:

```
// foo may be foo@v2
ld.lld: error: undefined symbol: foo
>>> referenced by t1.o:(.text+0x1)
// foo may be foo@v1 or foo@@v1
>>> did you mean: foo
>>> defined in: t.so
```

There are 2 ways a symbol in symtab may get truncated:

* A @@ definition may be truncated *early* by SymbolTable::insert().
  The name ends with a '\0'.
* A @ definition/reference may be truncated *later* by Symbol::parseSymbolVersion().
  The name ends with a '@'.

This patch detects the second case and improves the diagnostics. The first case is
not improved but the second case is sufficient to make diagnostics not confusing.

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D76999
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index cb7ee88..42c8a71 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -31,7 +31,18 @@
   return std::string(symName);
 }
 
-std::string toString(const elf::Symbol &b) { return demangle(b.getName()); }
+std::string toString(const elf::Symbol &sym) {
+  StringRef name = sym.getName();
+  std::string ret = demangle(name);
+
+  // If sym has a non-default version, its name may have been truncated at '@'
+  // by Symbol::parseSymbolVersion(). Add the trailing part. This check is safe
+  // because every symbol name ends with '\0'.
+  if (name.data()[name.size()] == '@')
+    ret += name.data() + name.size();
+  return ret;
+}
+
 std::string toELFString(const Archive::Symbol &b) {
   return demangle(b.getName());
 }