Re-land "[dsymutil] Fix handling of common symbols in multiple object files."
authorJonas Devlieghere <jonas@devlieghere.com>
Wed, 9 Oct 2019 16:19:13 +0000 (16:19 +0000)
committerJonas Devlieghere <jonas@devlieghere.com>
Wed, 9 Oct 2019 16:19:13 +0000 (16:19 +0000)
The original patch got reverted because it hit a long-standing legacy
issue on Windows that prevents files from being named `com`. Thanks
Kristina & Jeremy for pointing this out.

llvm-svn: 374178

llvm/test/tools/dsymutil/Inputs/private/tmp/common/common.x86_64 [new file with mode: 0755]
llvm/test/tools/dsymutil/Inputs/private/tmp/common/common1.o [new file with mode: 0644]
llvm/test/tools/dsymutil/Inputs/private/tmp/common/common2.o [new file with mode: 0644]
llvm/test/tools/dsymutil/X86/common-sym-multi.test [new file with mode: 0644]
llvm/tools/dsymutil/MachODebugMapParser.cpp

diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common.x86_64 b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common.x86_64
new file mode 100755 (executable)
index 0000000..8260af4
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common.x86_64 differ
diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common1.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common1.o
new file mode 100644 (file)
index 0000000..f238fc8
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common1.o differ
diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common2.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common2.o
new file mode 100644 (file)
index 0000000..a1d637c
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/common/common2.o differ
diff --git a/llvm/test/tools/dsymutil/X86/common-sym-multi.test b/llvm/test/tools/dsymutil/X86/common-sym-multi.test
new file mode 100644 (file)
index 0000000..1f33b37
--- /dev/null
@@ -0,0 +1,39 @@
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/common.x86_64 -f -o - | llvm-dwarfdump -debug-info - | FileCheck %s
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/common.x86_64 -dump-debug-map | FileCheck %s --check-prefix DEBUGMAP
+
+The test was compiled from two source files:
+$ cd /private/tmp/common
+$ cat common1.c
+int i[1000];
+int main() {
+  return i[1];
+}
+$ cat common2.c
+extern int i[1000];
+int bar() {
+  return i[0];
+}
+$ clang -fcommon -g -c common1.c -o common1.o
+$ clang -fcommon -g -c common2.c -o common2.o
+$ clang -fcommon -g common1.o common2.o -o common.x86_64
+
+CHECK: DW_TAG_compile_unit
+CHECK:   DW_TAG_variable
+CHECK-NOT: {{NULL|DW_TAG}}
+CHECK:     DW_AT_name{{.*}}"i"
+CHECK-NOT: {{NULL|DW_TAG}}
+CHECK:     DW_AT_location{{.*}}DW_OP_addr 0x100001000)
+
+CHECK: DW_TAG_compile_unit
+CHECK:   DW_TAG_variable
+CHECK-NOT: {{NULL|DW_TAG}}
+CHECK:     DW_AT_name{{.*}}"i"
+CHECK-NOT: {{NULL|DW_TAG}}
+CHECK:     DW_AT_location{{.*}}DW_OP_addr 0x100001000)
+
+DEBUGMAP: filename:{{.*}}common1.o
+DEBUGMAP: symbols:
+DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000
+DEBUGMAP: filename:{{.*}}common2.o
+DEBUGMAP: symbols:
+DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000
index 27379c2..487fbff 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
+#include <vector>
 
 namespace {
 using namespace llvm;
@@ -51,6 +52,8 @@ private:
   StringRef MainBinaryStrings;
   /// The constructed DebugMap.
   std::unique_ptr<DebugMap> Result;
+  /// List of common symbols that need to be added to the debug map.
+  std::vector<std::string> CommonSymbols;
 
   /// Map of the currently processed object file symbol addresses.
   StringMap<Optional<uint64_t>> CurrentObjectAddresses;
@@ -81,6 +84,8 @@ private:
                                STE.n_value);
   }
 
+  void addCommonSymbols();
+
   /// Dump the symbol table output header.
   void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
 
@@ -122,11 +127,32 @@ void MachODebugMapParser::resetParserState() {
   CurrentDebugMapObject = nullptr;
 }
 
+/// Commons symbols won't show up in the symbol map but might need to be
+/// relocated. We can add them to the symbol table ourselves by combining the
+/// information in the object file (the symbol name) and the main binary (the
+/// address).
+void MachODebugMapParser::addCommonSymbols() {
+  for (auto &CommonSymbol : CommonSymbols) {
+    uint64_t CommonAddr = getMainBinarySymbolAddress(CommonSymbol);
+    if (CommonAddr == 0) {
+      // The main binary doesn't have an address for the given symbol.
+      continue;
+    }
+    if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/,
+                                          CommonAddr, 0 /*size*/)) {
+      // The symbol is already present.
+      continue;
+    }
+  }
+  CommonSymbols.clear();
+}
+
 /// Create a new DebugMapObject. This function resets the state of the
 /// parser that was referring to the last object file and sets
 /// everything up to add symbols to the new one.
 void MachODebugMapParser::switchToNewDebugMapObject(
     StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
+  addCommonSymbols();
   resetParserState();
 
   SmallString<80> Path(PathPrefix);
@@ -466,10 +492,15 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols(
     // relocations will use the symbol itself, and won't need an
     // object file address. The object file address field is optional
     // in the DebugMap, leave it unassigned for these symbols.
-    if (Sym.getFlags() & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))
+    uint32_t Flags = Sym.getFlags();
+    if (Flags & SymbolRef::SF_Absolute) {
       CurrentObjectAddresses[*Name] = None;
-    else
+    } else if (Flags & SymbolRef::SF_Common) {
+      CurrentObjectAddresses[*Name] = None;
+      CommonSymbols.push_back(*Name);
+    } else {
       CurrentObjectAddresses[*Name] = Addr;
+    }
   }
 }