Index: llvm/lib/CodeGen/AsmPrinter/DIE.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -746,6 +746,7 @@ case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; + case dwarf::DW_FORM_string: break; case dwarf::DW_FORM_data16: break; } Index: llvm/test/tools/dsymutil/X86/papertrail-warnings.test =================================================================== --- /dev/null +++ llvm/test/tools/dsymutil/X86/papertrail-warnings.test @@ -0,0 +1,30 @@ +RUN: RC_DEBUG_OPTIONS=1 llvm-dsymutil -f %p/../Inputs/basic.macho.x86_64 -o - | llvm-dwarfdump -v - | FileCheck %s + +CHECK: .debug_info contents: +CHECK: Compile Unit: +CHECK: DW_TAG_compile_unit [1] * +CHECK: DW_AT_producer {{.*}}"dsymutil +CHECK: DW_AT_name {{.*}}"/Inputs/basic1.macho.x86_64.o" +CHECK: DW_TAG_constant [2] +CHECK: DW_AT_name {{.*}}"dsymutil_warning" +CHECK: DW_AT_artificial [DW_FORM_flag] (0x01) +CHECK: DW_AT_const_value {{.*}}"unable to open object file: No such file or directory" +CHECK: NULL +CHECK: Compile Unit: +CHECK: DW_TAG_compile_unit [1] * +CHECK: DW_AT_producer {{.*}}"dsymutil +CHECK: DW_AT_name {{.*}}"/Inputs/basic2.macho.x86_64.o" +CHECK: DW_TAG_constant [2] +CHECK: DW_AT_name {{.*}}"dsymutil_warning" +CHECK: DW_AT_artificial [DW_FORM_flag] (0x01) +CHECK: DW_AT_const_value {{.*}}"unable to open object file: No such file or directory" +CHECK: NULL +CHECK: Compile Unit: +CHECK: DW_TAG_compile_unit [1] * +CHECK: DW_AT_producer {{.*}}"dsymutil +CHECK: DW_AT_name {{.*}}"/Inputs/basic3.macho.x86_64.o" +CHECK: DW_TAG_constant [2] +CHECK: DW_AT_name {{.*}}"dsymutil_warning" +CHECK: DW_AT_artificial [DW_FORM_flag] (0x01) +CHECK: DW_AT_const_value {{.*}}"unable to open object file: No such file or directory" +CHECK: NULL \ No newline at end of file Index: llvm/test/tools/dsymutil/debug-map-parsing.test =================================================================== --- llvm/test/tools/dsymutil/debug-map-parsing.test +++ llvm/test/tools/dsymutil/debug-map-parsing.test @@ -80,7 +80,7 @@ NOT-FOUND-NEXT: binary-path:{{.*}}/Inputs/basic.macho.x86_64 NOT-FOUND-NEXT: ... -Check that we correctly error out on invalid executatble. +Check that we correctly error out on invalid executable. NO-EXECUTABLE: cannot parse{{.*}}/inexistant': {{[Nn]o}} such file NO-EXECUTABLE-NOT: --- Index: llvm/tools/dsymutil/DebugMap.h =================================================================== --- llvm/tools/dsymutil/DebugMap.h +++ llvm/tools/dsymutil/DebugMap.h @@ -176,6 +176,11 @@ return make_range(Symbols.begin(), Symbols.end()); } + bool empty() const { return Symbols.empty(); } + + void addWarning(StringRef Warning) { Warnings.push_back(Warning); } + const std::vector &getWarnings() const { return Warnings; } + void print(raw_ostream &OS) const; #ifndef NDEBUG void dump() const; @@ -194,6 +199,8 @@ DenseMap AddressToMapping; uint8_t Type; + std::vector Warnings; + /// For YAMLIO support. ///@{ friend yaml::MappingTraits; Index: llvm/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinker.cpp +++ llvm/tools/dsymutil/DwarfLinker.cpp @@ -1481,6 +1481,10 @@ MaxDwarfVersion = Version; } + /// Emit warnings as Dwarf compile units to leave a trail after linking. + bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map, + OffsetsStringPool &StringPool); + /// Keeps track of relocations. class RelocationManager { struct ValidReloc { @@ -4118,6 +4122,64 @@ } } +bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO, + const DebugMap &Map, + OffsetsStringPool &StringPool) { + if (DMO.getWarnings().empty() || !DMO.empty()) + return false; + + Streamer->switchToDebugInfoSection(/* Version */ 2); + DIE *CUDie = DIE::get(DIEAlloc, dwarf::DW_TAG_compile_unit); + CUDie->setOffset(11); + StringRef Producer = StringPool.internString("dsymutil"); + StringRef File = StringPool.internString(DMO.getObjectFilename()); + CUDie->addValue(DIEAlloc, dwarf::DW_AT_producer, dwarf::DW_FORM_strp, + DIEInteger(StringPool.getStringOffset(Producer))); + DIEBlock *String = new (DIEAlloc) DIEBlock(); + DIEBlocks.push_back(String); + for (auto &C : File) + String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, + DIEInteger(C)); + String->addValue(DIEAlloc, dwarf::Attribute(0), dwarf::DW_FORM_data1, + DIEInteger(0)); + + CUDie->addValue(DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_string, String); + for (const auto &Warning : DMO.getWarnings()) { + DIE &ConstDie = CUDie->addChild(DIE::get(DIEAlloc, dwarf::DW_TAG_constant)); + ConstDie.addValue( + DIEAlloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, + DIEInteger(StringPool.getStringOffset("dsymutil_warning"))); + ConstDie.addValue(DIEAlloc, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, + DIEInteger(1)); + ConstDie.addValue(DIEAlloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_strp, + DIEInteger(StringPool.getStringOffset(Warning))); + } + unsigned Size = 4 /* FORM_strp */ + File.size() + 1 + + DMO.getWarnings().size() * (4 + 1 + 4) + + 1 /* End of children */; + DIEAbbrev Abbrev = CUDie->generateAbbrev(); + AssignAbbrev(Abbrev); + CUDie->setAbbrevNumber(Abbrev.getNumber()); + Size += getULEB128Size(Abbrev.getNumber()); + // Abbreviation ordering needed for classic compatibility. + for (auto &Child : CUDie->children()) { + Abbrev = Child.generateAbbrev(); + AssignAbbrev(Abbrev); + Child.setAbbrevNumber(Abbrev.getNumber()); + Size += getULEB128Size(Abbrev.getNumber()); + } + CUDie->setSize(Size); + auto &Asm = Streamer->getAsmPrinter(); + Asm.EmitInt32(11 + CUDie->getSize() - 4); + Asm.EmitInt16(2); + Asm.EmitInt32(0); + Asm.EmitInt8(Map.getTriple().isArch64Bit() ? 8 : 4); + Streamer->emitDIE(*CUDie); + OutputDebugInfoSize += 11 /* Header */ + Size; + + return true; +} + bool DwarfLinker::link(const DebugMap &Map) { if (!createStreamer(Map.getTriple(), OutFile)) return false; @@ -4184,8 +4246,10 @@ continue; } - if (!LinkContext.ObjectFile) + if (emitPaperTrailWarnings(LinkContext.DMO, Map, OffsetsStringPool)) + continue; + if (!LinkContext.ObjectFile) continue; // Look for relocations that correspond to debug map entries. @@ -4232,6 +4296,11 @@ } } + // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway, + // to be able to emit papertrail warnings. + if (MaxDwarfVersion == 0) + MaxDwarfVersion = 3; + ThreadPool pool(2); // These variables manage the list of processed object files. Index: llvm/tools/dsymutil/MachODebugMapParser.cpp =================================================================== --- llvm/tools/dsymutil/MachODebugMapParser.cpp +++ llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -102,6 +102,13 @@ warn_ostream() << "(" << MachOUtils::getArchName(Result->getTriple().getArchName()) << ") " << File << " " << Msg << "\n"; + + if (getenv("RC_DEBUG_OPTIONS")) { + if (!File.empty()) + Result->addDebugMapObject(File, sys::TimePoint()); + if (Result->end() != Result->begin()) + (*--Result->end())->addWarning(Msg.str()); + } } };