[llvm] r368963 - [llvm-objdump] Add warning messages if disassembly + source for problematic inputs
Michael Pozulp via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 14 22:15:22 PDT 2019
Author: pozulp
Date: Wed Aug 14 22:15:22 2019
New Revision: 368963
URL: http://llvm.org/viewvc/llvm-project?rev=368963&view=rev
Log:
[llvm-objdump] Add warning messages if disassembly + source for problematic inputs
Summary: Addresses https://bugs.llvm.org/show_bug.cgi?id=41905
Reviewers: jhenderson, rupprecht, grimar
Reviewed By: jhenderson, grimar
Subscribers: RKSimon, MaskRay, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62462
Modified:
llvm/trunk/include/llvm/DebugInfo/DIContext.h
llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp
llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test
llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-missing-source.test
llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test
llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
llvm/trunk/tools/llvm-objdump/llvm-objdump.h
llvm/trunk/tools/llvm-xray/func-id-helper.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/DIContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DIContext.h?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DIContext.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DIContext.h Wed Aug 14 22:15:22 2019
@@ -28,6 +28,10 @@ namespace llvm {
/// A format-neutral container for source line information.
struct DILineInfo {
+ // DILineInfo contains "<invalid>" for function/filename it cannot fetch.
+ static constexpr const char *const BadString = "<invalid>";
+ // Use "??" instead of "<invalid>" to make our output closer to addr2line.
+ static constexpr const char *const Addr2LineBadString = "??";
std::string FileName;
std::string FunctionName;
Optional<StringRef> Source;
@@ -38,7 +42,7 @@ struct DILineInfo {
// DWARF-specific.
uint32_t Discriminator = 0;
- DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
+ DILineInfo() : FileName(BadString), FunctionName(BadString) {}
bool operator==(const DILineInfo &RHS) const {
return Line == RHS.Line && Column == RHS.Column &&
@@ -61,9 +65,9 @@ struct DILineInfo {
void dump(raw_ostream &OS) {
OS << "Line info: ";
- if (FileName != "<invalid>")
+ if (FileName != BadString)
OS << "file '" << FileName << "', ";
- if (FunctionName != "<invalid>")
+ if (FunctionName != BadString)
OS << "function '" << FunctionName << "', ";
OS << "line " << Line << ", ";
OS << "column " << Column << ", ";
@@ -109,7 +113,7 @@ struct DIGlobal {
uint64_t Start = 0;
uint64_t Size = 0;
- DIGlobal() : Name("<invalid>") {}
+ DIGlobal() : Name(DILineInfo::BadString) {}
};
struct DILocal {
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Wed Aug 14 22:15:22 2019
@@ -1111,8 +1111,8 @@ DILineInfoTable DWARFContext::getLineInf
if (!CU)
return Lines;
- std::string FunctionName = "<invalid>";
uint32_t StartLine = 0;
+ std::string FunctionName(DILineInfo::BadString);
getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
FunctionName, StartLine);
Modified: llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp (original)
+++ llvm/trunk/lib/DebugInfo/Symbolize/DIPrinter.cpp Wed Aug 14 22:15:22 2019
@@ -30,11 +30,6 @@
namespace llvm {
namespace symbolize {
-// By default, DILineInfo contains "<invalid>" for function/filename it
-// cannot fetch. We replace it to "??" to make our output closer to addr2line.
-static const char kDILineInfoBadString[] = "<invalid>";
-static const char kBadString[] = "??";
-
// Prints source code around in the FileName the Line.
void DIPrinter::printContext(const std::string &FileName, int64_t Line) {
if (PrintSourceContext <= 0)
@@ -68,16 +63,16 @@ void DIPrinter::printContext(const std::
void DIPrinter::print(const DILineInfo &Info, bool Inlined) {
if (PrintFunctionNames) {
std::string FunctionName = Info.FunctionName;
- if (FunctionName == kDILineInfoBadString)
- FunctionName = kBadString;
+ if (FunctionName == DILineInfo::BadString)
+ FunctionName = DILineInfo::Addr2LineBadString;
StringRef Delimiter = PrintPretty ? " at " : "\n";
StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
OS << Prefix << FunctionName << Delimiter;
}
std::string Filename = Info.FileName;
- if (Filename == kDILineInfoBadString)
- Filename = kBadString;
+ if (Filename == DILineInfo::BadString)
+ Filename = DILineInfo::Addr2LineBadString;
else if (Basenames)
Filename = llvm::sys::path::filename(Filename);
if (!Verbose) {
@@ -115,8 +110,8 @@ DIPrinter &DIPrinter::operator<<(const D
DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
std::string Name = Global.Name;
- if (Name == kDILineInfoBadString)
- Name = kBadString;
+ if (Name == DILineInfo::BadString)
+ Name = DILineInfo::Addr2LineBadString;
OS << Name << "\n";
OS << Global.Start << " " << Global.Size << "\n";
return *this;
Modified: llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test Wed Aug 14 22:15:22 2019
@@ -1,5 +1,5 @@
## Test llvm-objdump's --source behaviour when a line number is greater than the
-## file length.
+## file length and ensure that we emit a warning.
# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll
# RUN: sed -e "s,line: 7,line: 9999,g" %t.ll > %t2.ll
@@ -8,9 +8,11 @@
# RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll
# RUN: llvm-objdump --source %t.o | FileCheck %s --check-prefixes=CHECK,GOOD
-# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not="int *b = &a;"
+# RUN: llvm-objdump --source %t2.o 2> %t2.e | FileCheck %s --check-prefixes=CHECK --implicit-check-not="int *b = &a;"
+# RUN: FileCheck %s --input-file %t2.e --check-prefixes=WARN
# CHECK: main:
# CHECK-NEXT: ; int main() {
+# WARN: warning: debug info line number 9999 exceeds the number of lines in {{.*}}source-interleave-x86_64.c
# GOOD: ; int *b = &a;
# CHECK: ; return *b + foo();
Modified: llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-missing-source.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-missing-source.test?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-missing-source.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-missing-source.test Wed Aug 14 22:15:22 2019
@@ -1,5 +1,5 @@
## Test that if the source cannot be found that disassembly is still printed,
-## and that no source is printed.
+## that no source is printed, and that we emit a warning.
# RUN: sed -e "s,SRC_COMPDIR,%/t,g" %p/Inputs/source-interleave.ll > %t.ll
# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t2.ll
@@ -7,9 +7,11 @@
# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll
# RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll
-# RUN: llvm-objdump --source %t.o | FileCheck %s --implicit-check-not='main()'
+# RUN: llvm-objdump --source %t.o 2> %t.e | FileCheck %s --check-prefixes=CHECK --implicit-check-not='main()'
# RUN: llvm-objdump --source %t2.o | FileCheck %s --check-prefixes=CHECK,SOURCE
+# RUN: FileCheck %s --input-file %t.e --check-prefixes=WARN
+# WARN: warning: failed to find source {{.*}}source-interleave-x86_64.c
# CHECK: 0000000000000010 main:
# SOURCE-NEXT: ; int main() {
# CHECK-NEXT: 10: 55 pushq %rbp
Modified: llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test Wed Aug 14 22:15:22 2019
@@ -1,13 +1,15 @@
## Test that if an object has no debug information, only the disassembly is
-## printed when --source is specified.
+## printed when --source is specified, and that we emit a warning.
# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll
# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll
# RUN: llvm-objcopy --strip-debug %t.o %t2.o
# RUN: llvm-objdump --source %t.o | FileCheck %s --check-prefixes=CHECK,SOURCE
-# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not='main()'
+# RUN: llvm-objdump --source %t2.o 2> %t2.e | FileCheck %s --check-prefixes=CHECK --implicit-check-not='main()'
+# RUN: FileCheck %s --input-file %t2.e --check-prefixes=WARN
+# WARN: warning: failed to parse debug information for {{.*}}2.o
# CHECK: 0000000000000010 main:
# SOURCE-NEXT: ; int main() {
# CHECK-NEXT: 10: 55 pushq %rbp
Modified: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp Wed Aug 14 22:15:22 2019
@@ -521,7 +521,7 @@ void FileAnalysis::parseSectionContents(
continue;
}
- if (LineInfo->FileName == "<invalid>")
+ if (LineInfo->FileName == DILineInfo::BadString)
continue;
}
Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Wed Aug 14 22:15:22 2019
@@ -51,6 +51,7 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
@@ -385,12 +386,7 @@ LLVM_ATTRIBUTE_NORETURN void error(Twine
exit(1);
}
-void warn(StringRef Message) {
- WithColor::warning(errs(), ToolName) << Message << ".\n";
- errs().flush();
-}
-
-static void warn(Twine Message) {
+void warn(Twine Message) {
// Output order between errs() and outs() matters especially for archive
// files where the output is per member object.
outs().flush();
@@ -552,17 +548,22 @@ protected:
DILineInfo OldLineInfo;
const ObjectFile *Obj = nullptr;
std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
- // File name to file contents of source
+ // File name to file contents of source.
std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
- // Mark the line endings of the cached source
+ // Mark the line endings of the cached source.
std::unordered_map<std::string, std::vector<StringRef>> LineCache;
+ // Keep track of missing sources.
+ StringSet<> MissingSources;
+ // Only emit 'no debug info' warning once.
+ bool WarnedNoDebugInfo;
private:
bool cacheSource(const DILineInfo& LineInfoFile);
public:
SourcePrinter() = default;
- SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) {
+ SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch)
+ : Obj(Obj), WarnedNoDebugInfo(false) {
symbolize::LLVMSymbolizer::Options SymbolizerOpts;
SymbolizerOpts.PrintFunctions = DILineInfoSpecifier::FunctionNameKind::None;
SymbolizerOpts.Demangle = false;
@@ -572,6 +573,7 @@ public:
virtual ~SourcePrinter() = default;
virtual void printSourceLine(raw_ostream &OS,
object::SectionedAddress Address,
+ StringRef ObjectFilename,
StringRef Delimiter = "; ");
};
@@ -581,8 +583,12 @@ bool SourcePrinter::cacheSource(const DI
Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source);
} else {
auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName);
- if (!BufferOrError)
+ if (!BufferOrError) {
+ if (MissingSources.insert(LineInfo.FileName).second)
+ warn("failed to find source " + LineInfo.FileName);
+
return false;
+ }
Buffer = std::move(*BufferOrError);
}
// Chomp the file to get lines
@@ -603,20 +609,33 @@ bool SourcePrinter::cacheSource(const DI
void SourcePrinter::printSourceLine(raw_ostream &OS,
object::SectionedAddress Address,
+ StringRef ObjectFilename,
StringRef Delimiter) {
if (!Symbolizer)
return;
DILineInfo LineInfo = DILineInfo();
auto ExpectedLineInfo = Symbolizer->symbolizeCode(*Obj, Address);
+ std::string ErrorMessage;
if (!ExpectedLineInfo)
- consumeError(ExpectedLineInfo.takeError());
+ ErrorMessage = toString(ExpectedLineInfo.takeError());
else
LineInfo = *ExpectedLineInfo;
- if ((LineInfo.FileName == "<invalid>") || LineInfo.Line == 0 ||
- ((OldLineInfo.Line == LineInfo.Line) &&
- (OldLineInfo.FileName == LineInfo.FileName)))
+ if (LineInfo.FileName == DILineInfo::BadString) {
+ if (!WarnedNoDebugInfo) {
+ std::string Warning =
+ "failed to parse debug information for " + ObjectFilename.str();
+ if (!ErrorMessage.empty())
+ Warning += ": " + ErrorMessage;
+ warn(Warning);
+ WarnedNoDebugInfo = true;
+ }
+ return;
+ }
+
+ if (LineInfo.Line == 0 || ((OldLineInfo.Line == LineInfo.Line) &&
+ (OldLineInfo.FileName == LineInfo.FileName)))
return;
if (PrintLines)
@@ -627,8 +646,12 @@ void SourcePrinter::printSourceLine(raw_
return;
auto LineBuffer = LineCache.find(LineInfo.FileName);
if (LineBuffer != LineCache.end()) {
- if (LineInfo.Line > LineBuffer->second.size())
+ if (LineInfo.Line > LineBuffer->second.size()) {
+ warn(formatv(
+ "debug info line number {0} exceeds the number of lines in {1}",
+ LineInfo.Line, LineInfo.FileName));
return;
+ }
// Vector begins at 0, line numbers are non-zero
OS << Delimiter << LineBuffer->second[LineInfo.Line - 1] << '\n';
}
@@ -667,10 +690,10 @@ public:
ArrayRef<uint8_t> Bytes,
object::SectionedAddress Address, raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI,
- SourcePrinter *SP,
+ SourcePrinter *SP, StringRef ObjectFilename,
std::vector<RelocationRef> *Rels = nullptr) {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
+ SP->printSourceLine(OS, Address, ObjectFilename);
size_t Start = OS.tell();
if (!NoLeadingAddr)
@@ -711,9 +734,10 @@ public:
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
object::SectionedAddress Address, raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
+ StringRef ObjectFilename,
std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, "");
if (!MI) {
printLead(Bytes, Address.Address, OS);
OS << " <unknown>";
@@ -750,7 +774,7 @@ public:
OS << Separator;
Separator = "\n";
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address, "");
+ SP->printSourceLine(OS, Address, ObjectFilename, "");
printLead(Bytes, Address.Address, OS);
OS << Preamble;
Preamble = " ";
@@ -780,9 +804,10 @@ public:
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
object::SectionedAddress Address, raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
+ StringRef ObjectFilename,
std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
+ SP->printSourceLine(OS, Address, ObjectFilename);
if (MI) {
SmallString<40> InstStr;
@@ -831,9 +856,10 @@ public:
void printInst(MCInstPrinter &IP, const MCInst *MI, ArrayRef<uint8_t> Bytes,
object::SectionedAddress Address, raw_ostream &OS,
StringRef Annot, MCSubtargetInfo const &STI, SourcePrinter *SP,
+ StringRef ObjectFilename,
std::vector<RelocationRef> *Rels) override {
if (SP && (PrintSource || PrintLines))
- SP->printSourceLine(OS, Address);
+ SP->printSourceLine(OS, Address, ObjectFilename);
if (!NoLeadingAddr)
OS << format("%8" PRId64 ":", Address.Address / 8);
if (!NoShowRawInsn) {
@@ -1382,10 +1408,10 @@ static void disassembleObject(const Targ
if (Size == 0)
Size = 1;
- PIP.printInst(
- *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size),
- {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, outs(),
- "", *STI, &SP, &Rels);
+ PIP.printInst(*IP, Disassembled ? &Inst : nullptr,
+ Bytes.slice(Index, Size),
+ {SectionAddr + Index + VMAAdjustment, Section.getIndex()},
+ outs(), "", *STI, &SP, Obj->getFileName(), &Rels);
outs() << CommentStream.str();
Comments.clear();
Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.h?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/llvm-objdump.h (original)
+++ llvm/trunk/tools/llvm-objdump/llvm-objdump.h Wed Aug 14 22:15:22 2019
@@ -129,7 +129,7 @@ void printSectionHeaders(const object::O
void printSectionContents(const object::ObjectFile *O);
void printSymbolTable(const object::ObjectFile *O, StringRef ArchiveName,
StringRef ArchitectureName = StringRef());
-void warn(StringRef Message);
+void warn(Twine Message);
LLVM_ATTRIBUTE_NORETURN void error(Twine Message);
LLVM_ATTRIBUTE_NORETURN void report_error(StringRef File, Twine Message);
LLVM_ATTRIBUTE_NORETURN void report_error(Error E, StringRef File);
Modified: llvm/trunk/tools/llvm-xray/func-id-helper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-xray/func-id-helper.cpp?rev=368963&r1=368962&r2=368963&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-xray/func-id-helper.cpp (original)
+++ llvm/trunk/tools/llvm-xray/func-id-helper.cpp Wed Aug 14 22:15:22 2019
@@ -36,7 +36,7 @@ std::string FuncIdConversionHelper::Symb
ModuleAddress.SectionIndex = object::SectionedAddress::UndefSection;
if (auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, ModuleAddress)) {
auto &DI = *ResOrErr;
- if (DI.FunctionName == "<invalid>")
+ if (DI.FunctionName == DILineInfo::BadString)
F << "@(" << std::hex << It->second << ")";
else
F << DI.FunctionName;
More information about the llvm-commits
mailing list