DwarfLineEntry
Description
One row of the line-number matrix. address is the file-relative virtual address (the same address-space as ElfSymbol.value), so a caller who already did runtime_addr - module_base (e.g. via SymbolResolver) can feed the result directly to DwarfLinesResolve.
Fields
| Name | Description |
|---|---|
address |
Code address this row applies to. |
file |
Source filename (borrowed from internal string pool). |
dir |
Compilation directory hint, may be NULL. |
line |
Source line number (1-based, 0 means “no line”). |
column |
Source column (1-based, 0 means “no column”). |
is_stmt |
True at statement boundaries — preferred breakpoints. |
end_sequence |
True for the synthetic row that closes a contiguous range. Lookups never return such a row. |
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Dwarf.h:56:
bool is_stmt;
bool end_sequence;
} DwarfLineEntry;
typedef Vec(DwarfLineEntry) DwarfLineEntries;- In
Dwarf.h:58:
} DwarfLineEntry;
typedef Vec(DwarfLineEntry) DwarfLineEntries;
///
- In
Dwarf.h:113:
/// TAGS: Parser, DWARF, Lookup
///
const DwarfLineEntry *DwarfLinesResolve(const DwarfLines *self, u64 vaddr);
///
cache_entry->dwarf_ok = DwarfLinesBuildFromElf(&cache_entry->dwarf, &cache_entry->elf, self->allocator);
}
const DwarfLineEntry *de = NULL;
if (cache_entry->dwarf_ok) {
de = DwarfLinesResolve(&cache_entry->dwarf, file_relative);- In
Dwarf.c:302:
U64Vec *pending_dir_offsets
) {
DwarfLineEntry e;
MemSet(&e, 0, sizeof(e));
e.address = st->address;- In
Dwarf.c:670:
// ---------------------------------------------------------------------------
const DwarfLineEntry *DwarfLinesResolve(const DwarfLines *self, u64 vaddr) {
if (!self || VecLen(&self->entries) == 0)
return NULL;- In
Dwarf.c:678:
// by end_sequence rows; vaddr must not exceed the sequence's
// closing row.
const DwarfLineEntry *best = NULL;
const DwarfLineEntry *seq_open = NULL;
for (u64 i = 0; i < VecLen(&self->entries); ++i) {- In
Dwarf.c:679:
// closing row.
const DwarfLineEntry *best = NULL;
const DwarfLineEntry *seq_open = NULL;
for (u64 i = 0; i < VecLen(&self->entries); ++i) {
const DwarfLineEntry *e = VecPtrAt(&self->entries, i);- In
Dwarf.c:681:
const DwarfLineEntry *seq_open = NULL;
for (u64 i = 0; i < VecLen(&self->entries); ++i) {
const DwarfLineEntry *e = VecPtrAt(&self->entries, i);
if (e->end_sequence) {
// Sequence ends at this row's address (exclusive upper).
- In
Dwarf.Mut.c:234:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x3000);
// Out-of-range file -> no file string (NULL), not a bogus pointer.
ok = ok && e && e->file == NULL;- In
Dwarf.Mut.c:305:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x3300);
// file present, but dir index 0 -> dir must be NULL, not pool+42.
ok = ok && e && e->file && ZstrFindSubstring(e->file, "only.c") != NULL;- In
Dwarf.Mut.c:321:
static bool first_real_row_address(const DwarfLines *lines, u64 *out) {
for (u64 i = 0; i < VecLen(&lines->entries); ++i) {
const DwarfLineEntry *e = &VecAt(&lines->entries, i);
if (!e->end_sequence) {
*out = e->address;- In
Dwarf.c:72:
bool ok = false;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, file_relative);
if (e && e->file && ZstrFindSubstring(e->file, "Dwarf.c") != NULL && e->line > 0) {
ok = true;- In
Dwarf.c:589:
// Address 0x2000 -> source.c:10
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->file && ZstrFindSubstring(e->file, "source.c") != NULL && e->line == 10;- In
Dwarf.c:1120:
bool ok = true;
// The special opcode emitted a row at 0x3002, line 95.
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x3002);
ok = ok && e && e->line == 95 && e->address == 0x3002;
// Just below 0x3002 there is no covering row (only the special-opcode
- In
Dwarf.c:1155:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x5001);
ok = ok && e && e->line == 51 && e->address == 0x5001;
ok = ok && DwarfLinesResolve(&fx.lines, 0x5000) == NULL;- In
Dwarf.c:1189:
bool ok = true;
// Row landed at 0x7000 + 17 = 0x7011.
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x7011);
ok = ok && e && e->address == 0x7011 && e->line == 42;
// 255-13=242 (sub_to_add mutation -> 268, /14 = 19 -> addr 0x7013) and
- In
Dwarf.c:1230:
bool ok = true;
// A row must exist at 0x9000 with line 75 (special opcode 13 emitted it).
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x9000);
ok = ok && e && e->address == 0x9000 && e->line == 75;
lines_fixture_close(&fx);- In
Dwarf.c:1261:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0xB000);
ok = ok && e && e->file;
// Must be "other.c" (file 2), and NOT "source.c". `st.file = f` mutated
- In
Dwarf.c:1291:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0xB800);
ok = ok && e && e->file && ZstrFindSubstring(e->file, "source.c") != NULL;
lines_fixture_close(&fx);- In
Dwarf.c:1320:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0xD000);
ok = ok && e && e->column == 37;
lines_fixture_close(&fx);- In
Dwarf.c:1353:
bool ok = true;
const DwarfLineEntry *e0 = DwarfLinesResolve(&fx.lines, 0xF000);
ok = ok && e0 && e0->is_stmt == true;
const DwarfLineEntry *e1 = DwarfLinesResolve(&fx.lines, 0xF010);- In
Dwarf.c:1355:
const DwarfLineEntry *e0 = DwarfLinesResolve(&fx.lines, 0xF000);
ok = ok && e0 && e0->is_stmt == true;
const DwarfLineEntry *e1 = DwarfLinesResolve(&fx.lines, 0xF010);
ok = ok && e1 && e1->is_stmt == false;
lines_fixture_close(&fx);- In
Dwarf.c:1400:
bool ok = true;
const DwarfLineEntry *e1 = DwarfLinesResolve(&fx.lines, 0x11000);
ok = ok && e1 && e1->line == 500;
// Second sequence's row: line must be 7 (clean reset), not 506.
- In
Dwarf.c:1403:
ok = ok && e1 && e1->line == 500;
// Second sequence's row: line must be 7 (clean reset), not 506.
const DwarfLineEntry *e2 = DwarfLinesResolve(&fx.lines, 0x12000);
ok = ok && e2 && e2->line == 7;
lines_fixture_close(&fx);- In
Dwarf.c:1433:
bool ok = true;
// The real row resolves.
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x13000);
ok = ok && e && e->line == 10;
// An address inside [0x13000, 0x13020) still maps to the real row.
- In
Dwarf.c:1476:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x00150000u);
// 4-byte decode must reconstruct the full address 0x150000 and emit the
// row there. A broken == 4 branch / wrong decode / address = const moves
- In
Dwarf.c:1535:
// malformed record must not have produced a second resolvable row at
// an out-of-range address derived from over-read bytes.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x17000);
// The only acceptable success is: either no rows, or the single safe
// row, with end correctly bounded.
- In
Dwarf.c:1579:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&fx.lines, 0x18000);
ok = ok && e && e->address == 0x18000 && e->line == 22;
lines_fixture_close(&fx);- In
Dwarf.c:1625:
if (built) {
// First row at 0x5000, line 42.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x5000);
ok = ok && e && e->line == 42;
// The byte right before the fixed advance still maps to row 1.
- In
Dwarf.c:1662:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x8000 + 0x7abc);
ok = ok && e && e->address == 0x8000 + 0x7abc;
// Just below the second row -> still the first row.
- In
Dwarf.c:1708:
if (built) {
// The special opcode emitted exactly one real row at 0x6002:14.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x6002);
ok = ok && e && e->address == 0x6002 && e->line == 14;
// Below the emitted address -> nothing (no row at/below 0x6002
- In
Dwarf.c:1745:
if (built) {
// First special opcode: same address (addr_adv 0), line 42.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x7000);
ok = ok && e && e->address == 0x7000 && e->line == 42;
// Second special opcode: address advanced by 3, line 48.
- In
Dwarf.c:1778:
u64 real_rows = 0;
for (u64 i = 0; i < VecLen(&lines.entries); ++i) {
const DwarfLineEntry *e = &VecAt(&lines.entries, i);
if (!e->end_sequence)
++real_rows;- In
Dwarf.c:1783:
}
ok = ok && real_rows >= 1;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x9002);
ok = ok && e && e->address == 0x9002;
DwarfLinesDeinit(&lines);- In
Dwarf.c:1828:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0xA000);
ok = ok && e && e->address == 0xA000 && e->line == 7;
DwarfLinesDeinit(&lines);- In
Dwarf.c:1977:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0xB000);
ok = ok && e && e->address == 0xB000 && e->line == 5;
DwarfLinesDeinit(&lines);- In
Dwarf.c:2026:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0xC000);
ok = ok && e && e->address == 0xC000 && e->line == 3;
DwarfLinesDeinit(&lines);- In
Dwarf.c:2063:
bool ok = built;
if (built) {
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0xD000);
ok = ok && e && e->address == 0xD000 && e->line == 10;
e = DwarfLinesResolve(&lines, 0xE000);- In
Dwarf.c:2141:
ok = ok && VecLen(&lines.entries) == 3;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->file && ZstrFindSubstring(e->file, "second.c") != NULL;
ok = ok && e && e->dir && ZstrFindSubstring(e->dir, "real_dir") != NULL;- In
Dwarf.c:2207:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x3000);
ok = ok && e && e->file && ZstrFindSubstring(e->file, "first.c") != NULL;
ok = ok && e && e->line == 7;- In
Dwarf.c:2262:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x5001);
ok = ok && e && e->address == 0x5001;
ok = ok && e && e->line == 3;- In
Dwarf.c:2336:
// Sequence 1: 0x6000 -> second.c:100
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x6000);
ok = ok && e && e->file && ZstrFindSubstring(e->file, "second.c") != NULL;
ok = ok && e && e->line == 100;- In
Dwarf.c:2433:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x8000);
ok = ok && e && e->line == 4;
ok = ok && e && e->is_stmt == false;- In
Dwarf.c:2478:
ok = ok && VecLen(&lines.entries) >= 2;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->file && ZstrCompare(e->file, "source.c") == 0 && e->line == 10;- In
Dwarf.c:2592:
if (built) {
// Exact hit on the first row's address.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->line == 10;
// Strictly inside the first row's [0x2000, 0x2008) span -> line 10.
- In
Dwarf.c:2648:
// Sanity: the file/dir tables really populated (otherwise the
// CuStrings vectors never allocate and the leak is unobservable).
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->file && ZstrCompare(e->file, "source.c") == 0;
DwarfLinesDeinit(&lines);- In
Dwarf.c:2694:
// The pool must really hold the "source.c" string so its buffer
// is a distinct live allocation the deinit has to release.
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->file && ZstrCompare(e->file, "source.c") == 0;
// After the build there must be live allocations to release.
- In
Dwarf.c:2760:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x2000);
ok = ok && e && e->line == 10;
ok = ok && e && e->file && ZstrFindSubstring(e->file, "second.c") != NULL;- In
Dwarf.c:2813:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x4000);
// Only an exact table-skip places the program at the SET_ADDRESS opcode,
// so the row exists at 0x4000 with line 42 and file "first.c".
- In
Dwarf.c:2872:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x4400);
ok = ok && e && e->address == 0x4400 && e->line == 22;
ok = ok && e && e->file && ZstrFindSubstring(e->file, "second.c") != NULL;- In
Dwarf.c:2978:
bool ok = true;
const DwarfLineEntry *e = DwarfLinesResolve(&lines, 0x6000);
ok = ok && e && e->address == 0x6000 && e->line == 10;
Last updated on