[Symbolizer] Support for Missing Line Numbers. (#82240)

LLVM Symbolizer attempt to symbolize addresses of optimized binaries
reports missing line numbers for some cases. It maybe due to compiler
which sometimes cannot map an instruction to line number due to
optimizations. Symbolizer should handle those cases gracefully.

Adding an option '--skip-line-zero' to symbolizer so as to report the
nearest non-zero line number.

---------

Co-authored-by: Amit Pandey <amit.pandey@amd.com>
This commit is contained in:
Amit Kumar Pandey 2024-08-05 13:38:34 +05:30 committed by GitHub
parent fc83e97f6e
commit 0886440ef0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 260 additions and 38 deletions

View File

@ -93,7 +93,7 @@ std::optional<DILineInfo> DWARFCache::getDILineInfo(uint64_t offset,
DILineInfo info;
for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
if (lt->getFileLineInfoForAddress(
{offset, sectionIndex}, nullptr,
{offset, sectionIndex}, false, nullptr,
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
return info;
}

View File

@ -207,6 +207,33 @@ Example 7 - Addresses as symbol names:
foz
/tmp/test.h:1:0
Example 8 - :option:`--skip-line-zero` output for an address with no line correspondence (an address associated with line zero):
.. code-block:: c
// test.c
int foo = 0;
int x = 1234;
int main() {
if (x)
return foo;
else
return x;
}
These files are built as follows:
.. code-block:: console
$ clang -g -O2 -S test.c -o test.s
$ llvm-mc -filetype=obj -triple=x86_64-unknown-linux test.s -o test.o
.. code-block:: console
$ llvm-symbolizer --obj=test.o --skip-line-zero 0xa
main
/tmp/test.c:5:7 (approximate)
OPTIONS
-------
@ -216,6 +243,12 @@ OPTIONS
This can be used to perform lookups as if the object were relocated by the
offset.
.. option:: --skip-line-zero
If an address does not have an associated line number, use the last line
number from the current sequence in the line-table. Such lines are labeled
as "approximate" in the output as they may be misleading.
.. option:: --basenames, -s
Print just the file's name without any directories, instead of the

View File

@ -30,6 +30,7 @@ namespace llvm {
/// A format-neutral container for source line information.
struct DILineInfo {
static constexpr const char *const ApproxString = "(approximate)";
// 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.
@ -50,6 +51,7 @@ struct DILineInfo {
// DWARF-specific.
uint32_t Discriminator = 0;
bool IsApproximateLine = false;
DILineInfo()
: FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
}
@ -153,13 +155,14 @@ struct DILineInfoSpecifier {
AbsoluteFilePath
};
using FunctionNameKind = DINameKind;
FileLineInfoKind FLIKind;
FunctionNameKind FNKind;
bool ApproximateLine;
DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue,
FunctionNameKind FNKind = FunctionNameKind::None)
: FLIKind(FLIKind), FNKind(FNKind) {}
FunctionNameKind FNKind = FunctionNameKind::None,
bool ApproximateLine = false)
: FLIKind(FLIKind), FNKind(FNKind), ApproximateLine(ApproximateLine) {}
inline bool operator==(const DILineInfoSpecifier &RHS) const {
return FLIKind == RHS.FLIKind && FNKind == RHS.FNKind;

View File

@ -240,7 +240,8 @@ public:
/// Returns the index of the row with file/line info for a given address,
/// or UnknownRowIndex if there is no such row.
uint32_t lookupAddress(object::SectionedAddress Address) const;
uint32_t lookupAddress(object::SectionedAddress Address,
bool *IsApproximateLine = nullptr) const;
bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const;
@ -267,7 +268,7 @@ public:
/// Fills the Result argument with the file and line information
/// corresponding to Address. Returns true on success.
bool getFileLineInfoForAddress(object::SectionedAddress Address,
const char *CompDir,
bool Approximate, const char *CompDir,
DILineInfoSpecifier::FileLineInfoKind Kind,
DILineInfo &Result) const;
@ -301,7 +302,8 @@ public:
getSourceByIndex(uint64_t FileIndex,
DILineInfoSpecifier::FileLineInfoKind Kind) const;
uint32_t lookupAddressImpl(object::SectionedAddress Address) const;
uint32_t lookupAddressImpl(object::SectionedAddress Address,
bool *IsApproximateLine = nullptr) const;
bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const;

View File

@ -52,6 +52,7 @@ public:
struct Options {
FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName;
FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath;
bool SkipLineZero = false;
bool UseSymbolTable = true;
bool Demangle = true;
bool RelativeAddresses = false;

View File

@ -1743,8 +1743,8 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
if (Spec.FLIKind != FileLineInfoKind::None) {
if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
LineTable->getFileLineInfoForAddress(
{Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
Spec.FLIKind, Result);
{Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
CU->getCompilationDir(), Spec.FLIKind, Result);
}
}
@ -1838,9 +1838,10 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
if (Spec.FLIKind != FileLineInfoKind::None) {
DILineInfo Frame;
LineTable = getLineTableForUnit(CU);
if (LineTable && LineTable->getFileLineInfoForAddress(
{Address.Address, Address.SectionIndex},
CU->getCompilationDir(), Spec.FLIKind, Frame))
if (LineTable &&
LineTable->getFileLineInfoForAddress(
{Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
CU->getCompilationDir(), Spec.FLIKind, Frame))
InliningInfo.addFrame(Frame);
}
return InliningInfo;
@ -1866,8 +1867,8 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
// For the topmost routine, get file/line info from line table.
if (LineTable)
LineTable->getFileLineInfoForAddress(
{Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
Spec.FLIKind, Frame);
{Address.Address, Address.SectionIndex}, Spec.ApproximateLine,
CU->getCompilationDir(), Spec.FLIKind, Frame);
} else {
// Otherwise, use call file, call line and call column from
// previous DIE in inlined chain.

View File

@ -158,13 +158,12 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
for (uint32_t I = 0; I != FileNames.size(); ++I) {
const FileNameEntry &FileEntry = FileNames[I];
OS << format("file_names[%3u]:\n", I + FileBase);
OS << " name: ";
OS << format("file_names[%3u]:\n", I + FileBase);
OS << " name: ";
FileEntry.Name.dump(OS, DumpOptions);
OS << '\n'
<< format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
OS << '\n' << format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
if (ContentTypes.HasMD5)
OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
if (ContentTypes.HasModTime)
OS << format(" mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
if (ContentTypes.HasLength)
@ -604,9 +603,10 @@ Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(
DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx,
const DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
if (!DebugLineData.isValidOffset(Offset))
return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx64
" is not a valid debug line section offset",
Offset);
return createStringError(errc::invalid_argument,
"offset 0x%8.8" PRIx64
" is not a valid debug line section offset",
Offset);
std::pair<LineTableIter, bool> Pos =
LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
@ -966,7 +966,8 @@ Error DWARFDebugLine::LineTable::parse(
if (Cursor && Verbose) {
*OS << " (";
DWARFFormValue::dumpAddress(*OS, OpcodeAddressSize, State.Row.Address.Address);
DWARFFormValue::dumpAddress(*OS, OpcodeAddressSize,
State.Row.Address.Address);
*OS << ')';
}
}
@ -1159,8 +1160,7 @@ Error DWARFDebugLine::LineTable::parse(
// DW_LNS_advance_pc. Such assemblers, however, can use
// DW_LNS_fixed_advance_pc instead, sacrificing compression.
{
uint16_t PCOffset =
TableData.getRelocatedValue(Cursor, 2);
uint16_t PCOffset = TableData.getRelocatedValue(Cursor, 2);
if (Cursor) {
State.Row.Address.Address += PCOffset;
State.Row.OpIndex = 0;
@ -1312,11 +1312,12 @@ uint32_t DWARFDebugLine::LineTable::findRowInSeq(
return RowPos - Rows.begin();
}
uint32_t DWARFDebugLine::LineTable::lookupAddress(
object::SectionedAddress Address) const {
uint32_t
DWARFDebugLine::LineTable::lookupAddress(object::SectionedAddress Address,
bool *IsApproximateLine) const {
// Search for relocatable addresses
uint32_t Result = lookupAddressImpl(Address);
uint32_t Result = lookupAddressImpl(Address, IsApproximateLine);
if (Result != UnknownRowIndex ||
Address.SectionIndex == object::SectionedAddress::UndefSection)
@ -1324,11 +1325,15 @@ uint32_t DWARFDebugLine::LineTable::lookupAddress(
// Search for absolute addresses
Address.SectionIndex = object::SectionedAddress::UndefSection;
return lookupAddressImpl(Address);
return lookupAddressImpl(Address, IsApproximateLine);
}
uint32_t DWARFDebugLine::LineTable::lookupAddressImpl(
object::SectionedAddress Address) const {
uint32_t
DWARFDebugLine::LineTable::lookupAddressImpl(object::SectionedAddress Address,
bool *IsApproximateLine) const {
assert(!IsApproximateLine ||
!*IsApproximateLine && "Make sure IsApproximateLine is appropriately "
"initialized, if provided");
// First, find an instruction sequence containing the given address.
DWARFDebugLine::Sequence Sequence;
Sequence.SectionIndex = Address.SectionIndex;
@ -1337,7 +1342,24 @@ uint32_t DWARFDebugLine::LineTable::lookupAddressImpl(
DWARFDebugLine::Sequence::orderByHighPC);
if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex)
return UnknownRowIndex;
return findRowInSeq(*It, Address);
uint32_t RowIndex = findRowInSeq(*It, Address);
if (RowIndex == UnknownRowIndex || !IsApproximateLine)
return RowIndex;
// Approximation will only be attempted if a valid RowIndex exists.
uint32_t ApproxRowIndex = RowIndex;
// Approximation Loop
for (; ApproxRowIndex >= It->FirstRowIndex; --ApproxRowIndex) {
if (Rows[ApproxRowIndex].Line)
return ApproxRowIndex;
*IsApproximateLine = true;
}
// Approximation Loop fails to find the valid ApproxRowIndex
if (ApproxRowIndex < It->FirstRowIndex)
*IsApproximateLine = false;
return RowIndex;
}
bool DWARFDebugLine::LineTable::lookupAddressRange(
@ -1477,10 +1499,11 @@ bool DWARFDebugLine::Prologue::getFileNameByIndex(
}
bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
object::SectionedAddress Address, const char *CompDir,
object::SectionedAddress Address, bool Approximate, const char *CompDir,
FileLineInfoKind Kind, DILineInfo &Result) const {
// Get the index of row we're looking for in the line table.
uint32_t RowIndex = lookupAddress(Address);
uint32_t RowIndex =
lookupAddress(Address, Approximate ? &Result.IsApproximateLine : nullptr);
if (RowIndex == -1U)
return false;
// Take file number and line/column from the row.

View File

@ -131,7 +131,10 @@ void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
void LLVMPrinter::printSimpleLocation(StringRef Filename,
const DILineInfo &Info) {
OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
OS << Filename << ':' << Info.Line << ':' << Info.Column;
if (Info.IsApproximateLine)
OS << " " << Info.ApproxString;
OS << "\n";
printContext(
SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
}
@ -139,6 +142,8 @@ void LLVMPrinter::printSimpleLocation(StringRef Filename,
void GNUPrinter::printSimpleLocation(StringRef Filename,
const DILineInfo &Info) {
OS << Filename << ':' << Info.Line;
if (Info.IsApproximateLine)
OS << " " << Info.ApproxString;
if (Info.Discriminator)
OS << " (discriminator " << Info.Discriminator << ')';
OS << '\n';
@ -158,6 +163,8 @@ void PlainPrinterBase::printVerbose(StringRef Filename,
OS << " Column: " << Info.Column << '\n';
if (Info.Discriminator)
OS << " Discriminator: " << Info.Discriminator << '\n';
if (Info.IsApproximateLine)
OS << " Approximate: true" << '\n';
}
void LLVMPrinter::printStartAddress(const DILineInfo &Info) {
@ -294,7 +301,7 @@ static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") {
}
static json::Object toJSON(const DILineInfo &LineInfo) {
return json::Object(
json::Object Obj = json::Object(
{{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString
? LineInfo.FunctionName
: ""},
@ -309,6 +316,9 @@ static json::Object toJSON(const DILineInfo &LineInfo) {
{"Line", LineInfo.Line},
{"Column", LineInfo.Column},
{"Discriminator", LineInfo.Discriminator}});
if (LineInfo.IsApproximateLine)
Obj.insert({"Approximate", LineInfo.IsApproximateLine});
return Obj;
}
void JSONPrinter::print(const Request &Request, const DILineInfo &Info) {

View File

@ -71,7 +71,9 @@ LLVMSymbolizer::symbolizeCodeCommon(const T &ModuleSpecifier,
ModuleOffset.Address += Info->getModulePreferredBase();
DILineInfo LineInfo = Info->symbolizeCode(
ModuleOffset, DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions),
ModuleOffset,
DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions,
Opts.SkipLineZero),
Opts.UseSymbolTable);
if (Opts.Demangle)
LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
@ -116,7 +118,9 @@ Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCodeCommon(
ModuleOffset.Address += Info->getModulePreferredBase();
DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
ModuleOffset, DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions),
ModuleOffset,
DILineInfoSpecifier(Opts.PathStyle, Opts.PrintFunctions,
Opts.SkipLineZero),
Opts.UseSymbolTable);
if (Opts.Demangle) {
for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {

View File

@ -0,0 +1,143 @@
## Test the "--skip-line-zero" option.
##
## This test uses handcrafted assembly to produce the following line table:
## Address Line Column File ISA Discriminator OpIndex Flags
## ------------------ ------ ------ ------ --- ------------- ------- -------------
## 0x0000000000001710 1 0 1 0 0 0
## 0x0000000000001714 0 0 1 0 0 0
## 0x0000000000001719 1 2 1 0 0 0
## 0x000000000000171b 1 2 1 0 0 0 end_sequence
## 0x00000000000016c0 0 0 1 0 0 0
## 0x00000000000016cf 2 0 1 0 0 0
## 0x00000000000016d4 0 0 1 0 0 0
## 0x00000000000016d9 0 0 1 0 0 0
## 0x00000000000016df 0 0 1 0 0 0 end_sequence
# REQUIRES: x86-registered-target
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
## Check that without '--skip-line-zero', line zero is displayed for a line-table entry which has no source correspondence.
# RUN: llvm-symbolizer --obj=%t.o -f=none 0x16d4 | FileCheck --strict-whitespace --match-full-lines --check-prefix=DISABLE %s
# DISABLE:main.c:0:0
## Check that the '--skip-line-zero' does not cross sequence boundaries.
## If it fails to find in the current sequence then line zero is returned for the queried address.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero 0x16c0 | FileCheck --strict-whitespace --match-full-lines --check-prefix=FAIL-ACROSS-SEQ %s
# FAIL-ACROSS-SEQ:main.c:0:0
## Check that with '--skip-line-zero', the last non-zero line in the current sequence is displayed.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero 0x1717 | FileCheck --strict-whitespace --match-full-lines --check-prefix=WITHIN-SEQ %s
# WITHIN-SEQ:main.c:1:0 (approximate)
## Check that with '--skip-line-zero', multiple line zero rows are skipped within the current sequence.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero 0x16d9 | FileCheck --strict-whitespace --match-full-lines --check-prefix=MULTIPLE-ROWS %s
# MULTIPLE-ROWS:main.c:2:0 (approximate)
## Check that '--skip-line-zero' only affects the line zero addresses when more than one address is specified.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero 0x16d4 0x1719 | FileCheck --strict-whitespace --match-full-lines --check-prefixes=ENABLE,NO-APPROX %s
# ENABLE:main.c:2:0 (approximate)
# NO-APPROX:main.c:1:2
## Check to ensure that '--skip-line-zero' with '--verbose' enabled displays approximate flag in verbose ouptut.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero --verbose 0x1717 | FileCheck --strict-whitespace --match-full-lines --check-prefix=VERBOSE %s
# VERBOSE: Filename: main.c
# VERBOSE-NEXT: Line: 1
# VERBOSE-NEXT: Column: 0
# VERBOSE-NEXT: Approximate: true
## Check to ensure that '--skip-line-zero' with '--output-style=JSON' displays approximate flag in JSON output.
# RUN: llvm-symbolizer --obj=%t.o -f=none --skip-line-zero --output-style=JSON 0x1717 | FileCheck --strict-whitespace --match-full-lines --check-prefix=JSON %s
# JSON:[{"Address":"0x1717","ModuleName":"{{.*}}{{[/|\]+}}test{{[/|\]+}}tools{{[/|\]+}}llvm-symbolizer{{[/|\]+}}Output{{[/|\]+}}skip-line-zero.s.tmp.o","Symbol":[{"Approximate":true,"Column":0,"Discriminator":0,"FileName":"main.c","FunctionName":"","Line":1,"StartAddress":"","StartFileName":"","StartLine":0}]}]
## main.c
## __attribute__((section("def"))) int foo() { return 1234; }
## int main(void) { return foo()+5678; }
##
## Generated using
## clang -S -gdwarf-4 --target=x86_64-pc-linux -fdebug-prefix-map=/tmp="" main.c -o main.s
##
## Sections belonging to code segment(.text) are removed. Sections related to debug information(other than .debug_line) are modified. Section .debug_line is handwritten. Section .debug_str is deleted.
.section .debug_abbrev,"",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 0 # DW_CHILDREN_no
.byte 16 # DW_AT_stmt_list
.byte 23 # DW_FORM_sec_offset
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 85 # DW_AT_ranges
.byte 23 # DW_FORM_sec_offset
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.section .debug_info,"",@progbits
.Lcu_begin0:
.long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
.Ldebug_info_start0:
.short 4 # DWARF version number
.long .debug_abbrev # Offset Into Abbrev. Section
.byte 8 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x55 DW_TAG_compile_unit
.long .Lline_table_start0 # DW_AT_stmt_list
.quad 0 # DW_AT_low_pc
.long .Ldebug_ranges0 # DW_AT_ranges
.byte 0 # End Of Children Mark
.Ldebug_info_end0:
.section .debug_ranges,"",@progbits
.Ldebug_ranges0:
.quad 0x1710 #.Lfunc_begin0
.quad 0x171b #.Lfunc_end0
.quad 0x16c0 #.Lfunc_begin1
.quad 0x16df #.Lfunc_end1
.quad 0
.quad 0
.section .debug_line,"",@progbits
.Lline_table_start0:
.long .Lunit_end - .Lunit_start # unit length
.Lunit_start:
.short 4 # version
.long .Lprologue_end - .Lprologue_start # header length
.Lprologue_start:
.byte 1 # minimum_instruction_length
.byte 1 # maximum_operations_per_instruction
.byte 0 # default_is_stmt
.byte -5 # line_base
.byte 14 # line_range
.byte 13 # opcode_base
.byte 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 # arguments in standard opcodes
.byte 0 # end of include directories
.asciz "main.c" # filename
.byte 0 # directory index
.byte 0 # modification time
.byte 0 # length of file (unavailable)
.byte 0 # end of filenames
.Lprologue_end:
.byte 0x00, 9, 2 # DW_LNE_set_address
.quad 0x1710 # Address Value
.byte 0x01 # DW_LNS_copy
.byte 0x49 # (address += 4, line += -1, op-index += 0)
.byte 0x05, 2 # DW_LNS_set_column (2)
.byte 0x59 # (address += 5, line += 1, op-index += 0)
.byte 0x02 # DW_LNS_advance_pc
.uleb128 0x02 # (addr += 2, op-index += 0)
.byte 0x00, 1, 1 # DW_LNE_end_sequence
.byte 0x00, 9, 2 # DW_LNE_set_address
.quad 0x16c0 # Address Value
.byte 0x11 # (address += 0, line += -1, op-index += 0)
.byte 0xe6 # (address += 15, line += 2, op-index += 0)
.byte 0x56 # (address += 5, line += -2, op-index += 0)
.byte 0x58 # (address += 5, line += 0, op-index += 0)
.byte 0x02 # DW_LNS_advance_pc
.uleb128 0x06 # (addr += 6, op-index += 0)
.byte 0x00, 1, 1 # DW_LNE_end_sequence
.Lunit_end:

View File

@ -55,6 +55,7 @@ def pretty_print : F<"pretty-print", "Make the output more human friendly">;
defm print_source_context_lines : Eq<"print-source-context-lines", "Print N lines of source file context">;
def relative_address : F<"relative-address", "Interpret addresses as addresses relative to the image base">;
def relativenames : F<"relativenames", "Strip the compilation directory from paths">;
def skip_line_zero : F<"skip-line-zero","If an address does not have an associated line number, use the last line number from the current sequence in the line-table">;
defm untag_addresses : B<"untag-addresses", "", "Remove memory tags from addresses before symbolization">;
def use_dia: F<"dia", "Use the DIA library to access symbols (Windows only)">;
def verbose : F<"verbose", "Print verbose line info">;

View File

@ -490,6 +490,7 @@ int llvm_symbolizer_main(int argc, char **argv, const llvm::ToolContext &) {
} else {
Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
}
Opts.SkipLineZero = Args.hasArg(OPT_skip_line_zero);
Opts.DebugFileDirectory = Args.getAllArgValues(OPT_debug_file_directory_EQ);
Opts.DefaultArch = Args.getLastArgValue(OPT_default_arch_EQ).str();
Opts.Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, !IsAddr2Line);