]> granicus.if.org Git - llvm/commitdiff
[dsymutil] Fix handling of common symbols in multiple object files.
authorJonas Devlieghere <jonas@devlieghere.com>
Wed, 9 Oct 2019 04:16:18 +0000 (04:16 +0000)
committerJonas Devlieghere <jonas@devlieghere.com>
Wed, 9 Oct 2019 04:16:18 +0000 (04:16 +0000)
For common symbols the linker emits only a single symbol entry in the
debug map. This caused dsymutil to not relocate common symbols when
linking DWARF coming form object files that did not have this entry.
This patch fixes that by keeping track of common symbols in the object
files and synthesizing a debug map entry for them using the address from
the main binary.

Differential revision: https://reviews.llvm.org/D68680

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

test/tools/dsymutil/Inputs/private/tmp/common/com [new file with mode: 0755]
test/tools/dsymutil/Inputs/private/tmp/common/com1.o [new file with mode: 0644]
test/tools/dsymutil/Inputs/private/tmp/common/com2.o [new file with mode: 0644]
test/tools/dsymutil/X86/common-sym-multi.test [new file with mode: 0644]
tools/dsymutil/MachODebugMapParser.cpp

diff --git a/test/tools/dsymutil/Inputs/private/tmp/common/com b/test/tools/dsymutil/Inputs/private/tmp/common/com
new file mode 100755 (executable)
index 0000000..3aec975
Binary files /dev/null and b/test/tools/dsymutil/Inputs/private/tmp/common/com differ
diff --git a/test/tools/dsymutil/Inputs/private/tmp/common/com1.o b/test/tools/dsymutil/Inputs/private/tmp/common/com1.o
new file mode 100644 (file)
index 0000000..32c05ad
Binary files /dev/null and b/test/tools/dsymutil/Inputs/private/tmp/common/com1.o differ
diff --git a/test/tools/dsymutil/Inputs/private/tmp/common/com2.o b/test/tools/dsymutil/Inputs/private/tmp/common/com2.o
new file mode 100644 (file)
index 0000000..a22d1af
Binary files /dev/null and b/test/tools/dsymutil/Inputs/private/tmp/common/com2.o differ
diff --git a/test/tools/dsymutil/X86/common-sym-multi.test b/test/tools/dsymutil/X86/common-sym-multi.test
new file mode 100644 (file)
index 0000000..008362e
--- /dev/null
@@ -0,0 +1,39 @@
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/com -f -o - | llvm-dwarfdump -debug-info - | FileCheck %s
+RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/common/com -dump-debug-map | FileCheck %s --check-prefix DEBUGMAP
+
+The test was compiled from two source files:
+$ cd /private/tmp/common
+$ cat com1.c
+int i[1000];
+int main() {
+  return i[1];
+}
+$ cat com2.c
+extern int i[1000];
+int bar() {
+  return i[0];
+}
+$ clang -fcommon -g -c com1.c -o com1.o
+$ clang -fcommon -g -c com2.c -o com2.o
+$ clang -fcommon -g com1.o com2.o -o com
+
+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:{{.*}}com1.o
+DEBUGMAP: symbols:
+DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000
+DEBUGMAP: filename:{{.*}}com2.o
+DEBUGMAP: symbols:
+DEBUGMAP: sym: _i, binAddr: 0x0000000100001000, size: 0x00000000
index 27379c232decd5900c2df30058fb9fcac3f82e2e..487fbfff50cfac342d1f3b50eddefeb116f9813b 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;
+    }
   }
 }