17 using namespace dwarf;
23 TotalLength =
Version = PrologueLength = 0;
24 MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
27 StandardOpcodeLengths.clear();
28 IncludeDirectories.clear();
33 OS <<
"Line table prologue:\n"
34 <<
format(
" total_length: 0x%8.8" PRIx64
"\n", TotalLength)
36 <<
format(
" prologue_length: 0x%8.8" PRIx64
"\n", PrologueLength)
37 <<
format(
" min_inst_length: %u\n", MinInstLength)
38 <<
format(
Version >= 4 ?
"max_ops_per_inst: %u\n" :
"", MaxOpsPerInst)
39 <<
format(
" default_is_stmt: %u\n", DefaultIsStmt)
40 <<
format(
" line_base: %i\n", LineBase)
41 <<
format(
" line_range: %u\n", LineRange)
42 <<
format(
" opcode_base: %u\n", OpcodeBase);
44 for (
uint32_t i = 0;
i < StandardOpcodeLengths.size(); ++
i)
45 OS <<
format(
"standard_opcode_lengths[%s] = %u\n",
48 if (!IncludeDirectories.empty())
49 for (
uint32_t i = 0;
i < IncludeDirectories.size(); ++
i)
50 OS <<
format(
"include_directories[%3u] = '",
i + 1)
51 << IncludeDirectories[
i] <<
"'\n";
53 if (!FileNames.empty()) {
54 OS <<
" Dir Mod Time File Len File Name\n"
55 <<
" ---- ---------- ---------- -----------"
59 OS <<
format(
"file_names[%3u] %4" PRIu64
" ",
i + 1, fileEntry.
DirIdx)
60 <<
format(
"0x%8.8" PRIx64
" 0x%8.8" PRIx64
" ", fileEntry.
ModTime,
62 << fileEntry.
Name <<
'\n';
69 const uint64_t prologue_offset = *offset_ptr;
72 TotalLength = debug_line_data.
getU32(offset_ptr);
73 if (TotalLength == UINT32_MAX) {
75 TotalLength = debug_line_data.
getU64(offset_ptr);
76 }
else if (TotalLength > 0xffffff00) {
84 debug_line_data.
getUnsigned(offset_ptr, sizeofPrologueLength());
85 const uint64_t end_prologue_offset = PrologueLength + *offset_ptr;
86 MinInstLength = debug_line_data.
getU8(offset_ptr);
88 MaxOpsPerInst = debug_line_data.
getU8(offset_ptr);
89 DefaultIsStmt = debug_line_data.
getU8(offset_ptr);
90 LineBase = debug_line_data.
getU8(offset_ptr);
91 LineRange = debug_line_data.
getU8(offset_ptr);
92 OpcodeBase = debug_line_data.
getU8(offset_ptr);
94 StandardOpcodeLengths.reserve(OpcodeBase - 1);
96 uint8_t op_len = debug_line_data.
getU8(offset_ptr);
97 StandardOpcodeLengths.push_back(op_len);
100 while (*offset_ptr < end_prologue_offset) {
101 const char *s = debug_line_data.
getCStr(offset_ptr);
103 IncludeDirectories.push_back(s);
108 while (*offset_ptr < end_prologue_offset) {
109 const char *
name = debug_line_data.
getCStr(offset_ptr);
110 if (name && name[0]) {
116 FileNames.push_back(fileEntry);
122 if (*offset_ptr != end_prologue_offset) {
123 fprintf(stderr,
"warning: parsing line table prologue at 0x%8.8" PRIx64
124 " should have ended at 0x%8.8" PRIx64
125 " but it ended at 0x%8.8" PRIx64
"\n",
126 prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr);
137 EpilogueBegin =
false;
147 IsStmt = default_is_stmt;
151 EpilogueBegin =
false;
155 OS <<
format(
"0x%16.16" PRIx64
" %6u %6u",
Address, Line, Column)
156 <<
format(
" %6u %3u %13u ",
File, Isa, Discriminator)
157 << (IsStmt ?
" is_stmt" :
"") << (
BasicBlock ?
" basic_block" :
"")
158 << (PrologueEnd ?
" prologue_end" :
"")
159 << (EpilogueBegin ?
" epilogue_begin" :
"")
160 << (EndSequence ?
" end_sequence" :
"") <<
'\n';
180 OS <<
"Address Line Column File ISA Discriminator Flags\n"
181 <<
"------------------ ------ ------ ------ --- ------------- "
183 for (
const Row &R : Rows) {
195 DWARFDebugLine::ParsingState::ParsingState(
struct LineTable *
LT)
197 resetRowAndSequence();
200 void DWARFDebugLine::ParsingState::resetRowAndSequence() {
201 Row.reset(LineTable->Prologue.DefaultIsStmt);
205 void DWARFDebugLine::ParsingState::appendRowToMatrix(
uint32_t offset) {
213 LineTable->appendRow(Row);
214 if (Row.EndSequence) {
219 LineTable->appendSequence(
Sequence);
227 LineTableConstIter pos = LineTableMap.find(offset);
228 if (pos != LineTableMap.end())
236 std::pair<LineTableIter, bool> pos =
237 LineTableMap.insert(LineTableMapTy::value_type(offset,
LineTable()));
240 if (!LT->
parse(debug_line_data, RelocMap, &offset))
249 const uint32_t debug_line_offset = *offset_ptr;
255 *offset_ptr = debug_line_offset;
262 ParsingState State(
this);
264 while (*offset_ptr < end_offset) {
265 uint8_t opcode = debug_line_data.
getU8(offset_ptr);
271 uint64_t len = debug_line_data.
getULEB128(offset_ptr);
272 uint32_t arg_size = len - (*offset_ptr - ext_offset);
274 uint8_t sub_opcode = debug_line_data.
getU8(offset_ptr);
275 switch (sub_opcode) {
276 case DW_LNE_end_sequence:
284 State.Row.EndSequence =
true;
285 State.appendRowToMatrix(*offset_ptr);
286 State.resetRowAndSequence();
289 case DW_LNE_set_address:
299 if (AI != RMap->
end()) {
300 const std::pair<uint8_t, int64_t> &R = AI->second;
302 debug_line_data.
getAddress(offset_ptr) + R.second;
304 State.Row.Address = debug_line_data.
getAddress(offset_ptr);
308 case DW_LNE_define_file:
331 fileEntry.
Name = debug_line_data.
getCStr(offset_ptr);
339 case DW_LNE_set_discriminator:
340 State.Row.Discriminator = debug_line_data.
getULEB128(offset_ptr);
346 (*offset_ptr) += arg_size;
356 State.appendRowToMatrix(*offset_ptr);
359 case DW_LNS_advance_pc:
367 case DW_LNS_advance_line:
370 State.Row.Line += debug_line_data.
getSLEB128(offset_ptr);
373 case DW_LNS_set_file:
376 State.Row.File = debug_line_data.
getULEB128(offset_ptr);
379 case DW_LNS_set_column:
382 State.Row.Column = debug_line_data.
getULEB128(offset_ptr);
385 case DW_LNS_negate_stmt:
388 State.Row.IsStmt = !State.Row.IsStmt;
391 case DW_LNS_set_basic_block:
394 State.Row.BasicBlock =
true;
397 case DW_LNS_const_add_pc:
411 uint64_t addr_offset =
413 State.Row.Address += addr_offset;
417 case DW_LNS_fixed_advance_pc:
427 State.Row.Address += debug_line_data.
getU16(offset_ptr);
430 case DW_LNS_set_prologue_end:
433 State.Row.PrologueEnd =
true;
436 case DW_LNS_set_epilogue_begin:
439 State.Row.EpilogueBegin =
true;
445 State.Row.Isa = debug_line_data.
getULEB128(offset_ptr);
455 for (uint8_t
i = 0;
i < opcode_length; ++
i)
495 uint64_t addr_offset =
497 int32_t line_offset =
499 State.Row.Line += line_offset;
500 State.Row.Address += addr_offset;
501 State.appendRowToMatrix(*offset_ptr);
503 State.Row.Discriminator = 0;
507 if (!State.Sequence.Empty) {
508 fprintf(stderr,
"warning: last sequence in debug line table is not"
513 if (!Sequences.empty()) {
528 uint64_t address)
const {
530 return UnknownRowIndex;
540 if (row_pos == last_row) {
544 if (row_pos->Address > address) {
545 if (row_pos == first_row)
546 return UnknownRowIndex;
554 if (Sequences.empty())
555 return UnknownRowIndex;
558 sequence.
LowPC = address;
564 if (seq_pos == last_seq) {
565 found_seq = Sequences.back();
566 }
else if (seq_pos->LowPC == address) {
567 found_seq = *seq_pos;
569 if (seq_pos == first_seq)
570 return UnknownRowIndex;
571 found_seq = *(seq_pos - 1);
573 return findRowInSeq(found_seq, address);
577 uint64_t address, uint64_t size, std::vector<uint32_t> &result)
const {
578 if (Sequences.empty())
580 uint64_t end_addr = address + size;
583 sequence.
LowPC = address;
588 if (seq_pos == last_seq || seq_pos->LowPC != address) {
589 if (seq_pos == first_seq)
593 if (!seq_pos->containsPC(address))
601 while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
606 if (seq_pos == start_pos)
607 first_row_index = findRowInSeq(cur_seq, address);
610 uint32_t last_row_index = findRowInSeq(cur_seq, end_addr - 1);
611 if (last_row_index == UnknownRowIndex)
614 assert(first_row_index != UnknownRowIndex);
615 assert(last_row_index != UnknownRowIndex);
617 for (
uint32_t i = first_row_index;
i <= last_row_index; ++
i) {
636 std::string &Result)
const {
640 const char *FileName = Entry.
Name;
641 if (Kind != FileLineInfoKind::AbsoluteFilePath ||
648 uint64_t IncludeDirIndex = Entry.
DirIdx;
649 const char *IncludeDir =
"";
651 if (IncludeDirIndex > 0 &&
658 if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
664 Result = FilePath.
str();
672 uint32_t RowIndex = lookupAddress(Address);
676 const auto &
Row = Rows[RowIndex];
RowVector::const_iterator RowIter
bool is_relative(const Twine &path)
Is path relative?
static bool orderByAddress(const Row &LHS, const Row &RHS)
StringRef LNStandardString(unsigned Standard)
bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
SequenceVector::const_iterator SequenceIter
const LineTable * getLineTable(uint32_t offset) const
DILineInfo - a format-neutral container for source line information.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void postAppend()
Called after a row is appended to the matrix.
bool is_absolute(const Twine &path)
Is path absolute?
Row(bool default_is_stmt=false)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
LLVM Basic Block Representation.
void dump(raw_ostream &OS) const
void dump(raw_ostream &OS) const
bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr)
void dump(raw_ostream &OS) const
bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, uint32_t *offset_ptr)
Parse prologue and all rows.
const LineTable * getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset)
bool lookupAddressRange(uint64_t address, uint64_t size, std::vector< uint32_t > &result) const
uint32_t lookupAddress(uint64_t address) const
std::vector< const char * > IncludeDirectories
bool hasFileAtIndex(uint64_t FileIndex) const
uint32_t sizeofTotalLength() const
iterator_range< detail::value_sequence_iterator< ValueT > > seq(ValueT Begin, ValueT End)
std::vector< uint8_t > StandardOpcodeLengths
void reset(bool default_is_stmt)
StringRef str() const
Explicit conversion to StringRef.
bool containsPC(uint64_t pc) const
static void clear(coro::Shape &Shape)
std::vector< FileNameEntry > FileNames
static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
iterator find(const KeyT &Val)
bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind