[pr21886] Change MCJIT/ELF to support MSVC C++ mangled symbol.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 22 Jan 2015 14:20:45 +0000 (14:20 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 22 Jan 2015 14:20:45 +0000 (14:20 +0000)
The ELF format is used on Windows by the MCJIT engine. Thus, on Windows, the
ELFObjectWriter can encounter symbols mangled using the MS Visual Studio C++
name mangling. Symbols mangled using the MSVC C++ name mangling can legally
have "@@@" as a substring. The EFLObjectWriter should not interpret the "@@@"
substring as specifying GNU-style symbol versioning. The ELFObjectWriter
therefore check for the MSVC C++ name mangling prefix which is either "?", "@?",
"imp_?" or "imp_?@".

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226830 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/ELFObjectWriter.cpp
test/MC/ELF/symver-msvc.s [new file with mode: 0644]

index 4dcf910e01a7267a0d8bdb12bc5f4d017440a707..d82dad8093e4080cae8034bf185de671cefc4479 100644 (file)
@@ -1033,16 +1033,43 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout,
       assert(MSD.SectionIndex && "Invalid section index!");
     }
 
-    // The @@@ in symbol version is replaced with @ in undefined symbols and
-    // @@ in defined ones.
+    // The @@@ in symbol version is replaced with @ in undefined symbols and @@
+    // in defined ones.
+    //
+    // FIXME: All name handling should be done before we get to the writer,
+    // including dealing with GNU-style version suffixes.  Fixing this isn’t
+    // trivial.
+    //
+    // We thus have to be careful to not perform the symbol version replacement
+    // blindly:
+    //
+    // The ELF format is used on Windows by the MCJIT engine.  Thus, on
+    // Windows, the ELFObjectWriter can encounter symbols mangled using the MS
+    // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC
+    // C++ name mangling can legally have "@@@" as a sub-string. In that case,
+    // the EFLObjectWriter should not interpret the "@@@" sub-string as
+    // specifying GNU-style symbol versioning. The ELFObjectWriter therefore
+    // checks for the MSVC C++ name mangling prefix which is either "?", "@?",
+    // "__imp_?" or "__imp_@?".
+    //
+    // It would have been interesting to perform the MS mangling prefix check
+    // only when the target triple is of the form *-pc-windows-elf. But, it
+    // seems that this information is not easily accessible from the
+    // ELFObjectWriter.
     StringRef Name = Symbol.getName();
-    SmallString<32> Buf;
-    size_t Pos = Name.find("@@@");
-    if (Pos != StringRef::npos) {
-      Buf += Name.substr(0, Pos);
-      unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
-      Buf += Name.substr(Pos + Skip);
-      Name = Buf;
+    if (!Name.startswith("?") && !Name.startswith("@?") &&
+        !Name.startswith("__imp_?") && !Name.startswith("__imp_@?")) {
+      // This symbol isn't following the MSVC C++ name mangling convention. We
+      // can thus safely interpret the @@@ in symbol names as specifying symbol
+      // versioning.
+      SmallString<32> Buf;
+      size_t Pos = Name.find("@@@");
+      if (Pos != StringRef::npos) {
+        Buf += Name.substr(0, Pos);
+        unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1;
+        Buf += Name.substr(Pos + Skip);
+        Name = Buf;
+      }
     }
 
     // Sections have their own string table
diff --git a/test/MC/ELF/symver-msvc.s b/test/MC/ELF/symver-msvc.s
new file mode 100644 (file)
index 0000000..d6730ca
--- /dev/null
@@ -0,0 +1,59 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-windows-elf %s -o - | llvm-readobj -r -t | FileCheck %s
+
+// Verify that MSVC C++ mangled symbols are not affected by the ELF
+// GNU-style symbol versioning. The ELF format is used on Windows by
+// the MCJIT execution engine.
+
+        .long "??_R0?AVexception@std@@@8"
+        .long "@??_R0?AVinvalid_argument@std@@@8"
+        .long "__imp_??_R0?AVlogic_error@std@@@8"
+        .long "__imp_@??_R0PAVexception@std@@@8"
+
+
+// CHECK:       Relocations [
+// CHECK-NEXT:    Section (2) .rela.text {
+// CHECK-NEXT:      0x0 R_X86_64_32 ??_R0?AVexception@std@@@8 0x0
+// CHECK-NEXT:      0x4 R_X86_64_32 @??_R0?AVinvalid_argument@std@@@8 0x0
+// CHECK-NEXT:      0x8 R_X86_64_32 __imp_??_R0?AVlogic_error@std@@@8 0x0
+// CHECK-NEXT:      0xC R_X86_64_32 __imp_@??_R0PAVexception@std@@@8 0x0
+// CHECK-NEXT:    }
+// CHECK-NEXT:  ]
+
+// CHECK:       Symbols [
+// CHECK:         Symbol {
+// CHECK:           Name: ??_R0?AVexception@std@@@8 (102)
+// CHECK-NEXT:      Value: 0x0
+// CHECK-NEXT:      Size: 0
+// CHECK-NEXT:      Binding: Global (0x1)
+// CHECK-NEXT:      Type: None (0x0)
+// CHECK-NEXT:      Other: 0
+// CHECK-NEXT:      Section: Undefined (0x0)
+// CHECK-NEXT:    }
+// CHECK-NEXT:    Symbol {
+// CHECK-NEXT:      Name: @??_R0?AVinvalid_argument@std@@@8 (1)
+// CHECK-NEXT:      Value: 0x0
+// CHECK-NEXT:      Size: 0
+// CHECK-NEXT:      Binding: Global (0x1)
+// CHECK-NEXT:      Type: None (0x0)
+// CHECK-NEXT:      Other: 0
+// CHECK-NEXT:      Section: Undefined (0x0)
+// CHECK-NEXT:    }
+// CHECK-NEXT:    Symbol {
+// CHECK-NEXT:      Name: __imp_??_R0?AVlogic_error@std@@@8 (35)
+// CHECK-NEXT:      Value: 0x0
+// CHECK-NEXT:      Size: 0
+// CHECK-NEXT:      Binding: Global (0x1)
+// CHECK-NEXT:      Type: None (0x0)
+// CHECK-NEXT:      Other: 0
+// CHECK-NEXT:      Section: Undefined (0x0)
+// CHECK-NEXT:    }
+// CHECK-NEXT:    Symbol {
+// CHECK-NEXT:      Name: __imp_@??_R0PAVexception@std@@@8 (69)
+// CHECK-NEXT:      Value: 0x0
+// CHECK-NEXT:      Size: 0
+// CHECK-NEXT:      Binding: Global (0x1)
+// CHECK-NEXT:      Type: None (0x0)
+// CHECK-NEXT:      Other: 0
+// CHECK-NEXT:      Section: Undefined (0x0)
+// CHECK-NEXT:    }
+// CHECK-NEXT:  ]