forked from OSchip/llvm-project
[dsymutil] Upstream emitting of papertrail warnings.
When running dsymutil as part of your build system, it can be desirable for warnings to be part of the end product, rather than just being emitted to the output stream. This patch upstreams that functionality. Differential revision: https://reviews.llvm.org/D44639 llvm-svn: 328965
This commit is contained in:
parent
3f0bda296d
commit
9e3e7a99e8
|
@ -70,6 +70,13 @@ OPTIONS
|
|||
|
||||
Specifies a ``path`` to prepend to all debug symbol object file paths.
|
||||
|
||||
.. option:: --papertrail
|
||||
|
||||
When running dsymutil as part of your build system, it can be desirable for
|
||||
warnings to be part of the end product, rather than just being emitted to the
|
||||
output stream. When enabled warnings are embedded in the linked DWARF debug
|
||||
information.
|
||||
|
||||
.. option:: -s, --symtab
|
||||
|
||||
Dumps the symbol table found in *executable* or object file(s) and exits.
|
||||
|
|
|
@ -746,6 +746,7 @@ void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
RUN: RC_DEBUG_OPTIONS=1 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
|
|
@ -13,6 +13,7 @@ HELP: -no-swiftmodule-timestamp
|
|||
HELP: -num-threads=<n>
|
||||
HELP: -o=<filename>
|
||||
HELP: -oso-prepend-path=<path>
|
||||
HELP: -papertrail
|
||||
HELP: -symtab
|
||||
HELP: -toolchain
|
||||
HELP: -update
|
||||
|
|
|
@ -80,7 +80,7 @@ NOT-FOUND-NEXT: triple: 'x86_64-apple-darwin'
|
|||
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: ---
|
||||
|
|
|
@ -176,6 +176,11 @@ public:
|
|||
return make_range(Symbols.begin(), Symbols.end());
|
||||
}
|
||||
|
||||
bool empty() const { return Symbols.empty(); }
|
||||
|
||||
void addWarning(StringRef Warning) { Warnings.push_back(Warning); }
|
||||
const std::vector<std::string> &getWarnings() const { return Warnings; }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
#ifndef NDEBUG
|
||||
void dump() const;
|
||||
|
@ -194,6 +199,8 @@ private:
|
|||
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
|
||||
uint8_t Type;
|
||||
|
||||
std::vector<std::string> Warnings;
|
||||
|
||||
/// For YAMLIO support.
|
||||
///@{
|
||||
friend yaml::MappingTraits<dsymutil::DebugMapObject>;
|
||||
|
|
|
@ -1481,6 +1481,10 @@ private:
|
|||
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 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
|||
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 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -24,10 +24,12 @@ using namespace llvm::object;
|
|||
class MachODebugMapParser {
|
||||
public:
|
||||
MachODebugMapParser(StringRef BinaryPath, ArrayRef<std::string> Archs,
|
||||
StringRef PathPrefix = "", bool Verbose = false)
|
||||
StringRef PathPrefix = "",
|
||||
bool PaperTrailWarnings = false, bool Verbose = false)
|
||||
: BinaryPath(BinaryPath), Archs(Archs.begin(), Archs.end()),
|
||||
PathPrefix(PathPrefix), MainBinaryHolder(Verbose),
|
||||
CurrentObjectHolder(Verbose), CurrentDebugMapObject(nullptr) {}
|
||||
PathPrefix(PathPrefix), PaperTrailWarnings(PaperTrailWarnings),
|
||||
MainBinaryHolder(Verbose), CurrentObjectHolder(Verbose),
|
||||
CurrentDebugMapObject(nullptr) {}
|
||||
|
||||
/// Parses and returns the DebugMaps of the input binary. The binary contains
|
||||
/// multiple maps in case it is a universal binary.
|
||||
|
@ -42,6 +44,7 @@ private:
|
|||
std::string BinaryPath;
|
||||
SmallVector<StringRef, 1> Archs;
|
||||
std::string PathPrefix;
|
||||
bool PaperTrailWarnings;
|
||||
|
||||
/// Owns the MemoryBuffer for the main binary.
|
||||
BinaryHolder MainBinaryHolder;
|
||||
|
@ -102,6 +105,13 @@ private:
|
|||
warn_ostream() << "("
|
||||
<< MachOUtils::getArchName(Result->getTriple().getArchName())
|
||||
<< ") " << File << " " << Msg << "\n";
|
||||
|
||||
if (PaperTrailWarnings) {
|
||||
if (!File.empty())
|
||||
Result->addDebugMapObject(File, sys::TimePoint<std::chrono::seconds>());
|
||||
if (Result->end() != Result->begin())
|
||||
(*--Result->end())->addWarning(Msg.str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -522,13 +532,14 @@ namespace llvm {
|
|||
namespace dsymutil {
|
||||
llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||
parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs,
|
||||
StringRef PrependPath, bool Verbose, bool InputIsYAML) {
|
||||
if (!InputIsYAML) {
|
||||
MachODebugMapParser Parser(InputFile, Archs, PrependPath, Verbose);
|
||||
return Parser.parse();
|
||||
} else {
|
||||
StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
|
||||
bool InputIsYAML) {
|
||||
if (InputIsYAML)
|
||||
return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
|
||||
}
|
||||
|
||||
MachODebugMapParser Parser(InputFile, Archs, PrependPath, PaperTrailWarnings,
|
||||
Verbose);
|
||||
return Parser.parse();
|
||||
}
|
||||
|
||||
bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs,
|
||||
|
|
|
@ -147,6 +147,11 @@ static opt<std::string>
|
|||
Toolchain("toolchain", desc("Embed toolchain information in dSYM bundle."),
|
||||
cat(DsymCategory));
|
||||
|
||||
static opt<bool>
|
||||
PaperTrailWarnings("papertrail",
|
||||
desc("Embed warnings in the linked DWARF debug info."),
|
||||
cat(DsymCategory));
|
||||
|
||||
static bool createPlistFile(llvm::StringRef Bin, llvm::StringRef BundleRoot) {
|
||||
if (NoOutput)
|
||||
return true;
|
||||
|
@ -430,6 +435,12 @@ int main(int argc, char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (getenv("RC_DEBUG_OPTIONS"))
|
||||
PaperTrailWarnings = true;
|
||||
|
||||
if (PaperTrailWarnings && InputIsYAMLDebugMap)
|
||||
warn_ostream() << "Paper trail warnings are not supported for YAML input";
|
||||
|
||||
for (const auto &Arch : ArchFlags)
|
||||
if (Arch != "*" && Arch != "all" &&
|
||||
!llvm::object::MachOObjectFile::isValidArch(Arch)) {
|
||||
|
@ -445,8 +456,9 @@ int main(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
|
||||
auto DebugMapPtrsOrErr = parseDebugMap(InputFile, ArchFlags, OsoPrependPath,
|
||||
Verbose, InputIsYAMLDebugMap);
|
||||
auto DebugMapPtrsOrErr =
|
||||
parseDebugMap(InputFile, ArchFlags, OsoPrependPath, PaperTrailWarnings,
|
||||
Verbose, InputIsYAMLDebugMap);
|
||||
|
||||
if (auto EC = DebugMapPtrsOrErr.getError()) {
|
||||
error_ostream() << "cannot parse the debug map for '" << InputFile
|
||||
|
|
|
@ -59,7 +59,8 @@ struct LinkOptions {
|
|||
/// returned when the file is universal (aka fat) binary.
|
||||
ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
|
||||
parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs,
|
||||
StringRef PrependPath, bool Verbose, bool InputIsYAML);
|
||||
StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
|
||||
bool InputIsYAML);
|
||||
|
||||
/// Dump the symbol table
|
||||
bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs,
|
||||
|
|
Loading…
Reference in New Issue