]> granicus.if.org Git - llvm/commitdiff
[dsymutil] Fix handling of empty CUs in LTO links.
authorFrederic Riss <friss@apple.com>
Thu, 9 Feb 2017 19:41:55 +0000 (19:41 +0000)
committerFrederic Riss <friss@apple.com>
Thu, 9 Feb 2017 19:41:55 +0000 (19:41 +0000)
r288399 introduced the DIEUnit class, and in the process broke
the corner case where dsymutil generates an empty CU during an
LTO link. This restores the logic and adds a test for the corner
case.

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

test/tools/dsymutil/X86/generate-empty-CU.test [new file with mode: 0644]
tools/dsymutil/DwarfLinker.cpp

diff --git a/test/tools/dsymutil/X86/generate-empty-CU.test b/test/tools/dsymutil/X86/generate-empty-CU.test
new file mode 100644 (file)
index 0000000..2336114
--- /dev/null
@@ -0,0 +1,33 @@
+# RUN: llvm-dsymutil -f -o - -oso-prepend-path=%p/.. -y %s | llvm-dwarfdump - | FileCheck %s
+
+# This test on links the Dwarf for an LTO binary and on purpose doesn't retain
+# any symbol in the second CU out of 3. This is the only case where dsymutil
+# will generate an empty CU and it requires special handling.
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename:        /Inputs/basic-lto.macho.x86_64.o
+    timestamp:       1417654896
+    symbols:
+      - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000F40, size: 0x00000010 }
+      - { sym: _bar, objAddr: 0x0000000000000050, binAddr: 0x0000000100000F90, size: 0x00000024 }
+...
+
+.debug_info contents:
+CHECK: Compile Unit: length = 0x0000007d version = 0x0002 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000081)
+
+CHECK: DW_TAG_compile_unit
+CHECK:        DW_AT_name {{.*}} "basic1.c"
+CHECK:   DW_TAG_subprogram
+                DW_AT_name {{.*}} "main"
+
+CHECK: Compile Unit: length = 0x00000007 version = 0x0002 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0000008c)
+
+CHECK: Compile Unit: length = 0x00000089 version = 0x0002 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000119)
+
+CHECK: DW_TAG_compile_unit
+CHECK:        DW_AT_name {{.*}} "basic3.c"
+
+CHECK:   DW_TAG_subprogram [7] *
+CHECK:          DW_AT_name {{.*}} = "bar"
index 2fe4f29d40858e0579d62d9b23d64a4552239bdd..35cefaa69e8c16870bc00c5979e8da6cd9f0d828 100644 (file)
@@ -197,11 +197,8 @@ public:
 
   CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
               StringRef ClangModuleName)
-      : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(),
-                                            OrigUnit.getAddressByteSize(),
-                                            OrigUnit.getUnitDIE().getTag()),
-          LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc),
-          ClangModuleName(ClangModuleName) {
+      : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
+        Ranges(RangeAlloc), ClangModuleName(ClangModuleName) {
     Info.resize(OrigUnit.getNumDIEs());
 
     auto CUDie = OrigUnit.getUnitDIE(false);
@@ -219,8 +216,15 @@ public:
 
   unsigned getUniqueID() const { return ID; }
 
+  void createOutputDIE() {
+    NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(),
+                    OrigUnit.getUnitDIE().getTag());
+  }
+
   DIE *getOutputUnitDIE() const {
-    return &const_cast<DIEUnit &>(NewUnit).getUnitDie();
+    if (NewUnit)
+      return &const_cast<DIEUnit &>(*NewUnit).getUnitDie();
+    return nullptr;
   }
 
   bool hasODR() const { return HasODR; }
@@ -329,7 +333,7 @@ private:
   DWARFUnit &OrigUnit;
   unsigned ID;
   std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
-  DIEUnit NewUnit;
+  Optional<DIEUnit> NewUnit;
 
   uint64_t StartOffset;
   uint64_t NextUnitOffset;
@@ -397,7 +401,8 @@ uint64_t CompileUnit::computeNextUnitOffset() {
   // The root DIE might be null, meaning that the Unit had nothing to
   // contribute to the linked output. In that case, we will emit the
   // unit header without any actual DIE.
-  NextUnitOffset += NewUnit.getUnitDie().getSize();
+  if (NewUnit)
+    NextUnitOffset += NewUnit->getUnitDie().getSize();
   return NextUnitOffset;
 }
 
@@ -3357,12 +3362,13 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(
   for (auto &CurrentUnit : CompileUnits) {
     auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE();
     CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize);
-    // Clonse the InputDIE into your Unit DIE in our compile unit since it
-    // already has a DIE inside of it.
-    if (!cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */,
-                  11 /* Unit Header size */, 0,
-                  CurrentUnit->getOutputUnitDIE()))
-      continue;
+    if (CurrentUnit->getInfo(0).Keep) {
+      // Clone the InputDIE into your Unit DIE in our compile unit since it
+      // already has a DIE inside of it.
+      CurrentUnit->createOutputDIE();
+      cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */,
+               11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE());
+    }
     Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset();
     if (Linker.Options.NoOutput)
       continue;