--- /dev/null
+# 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"
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);
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; }
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;
// 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;
}
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;