feature. See also
. The project being documented here (as the example) is the Zig library itself.
Dwarf.scanAllCompileUnits
fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void
File
Code
fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void {
var fr: Reader = .fixed(di.section(.debug_info).?);
var this_unit_offset: u64 = 0;
var attrs_buf = std.array_list.Managed(Die.Attr).init(gpa);
defer attrs_buf.deinit();
while (this_unit_offset < fr.buffer.len) {
fr.seek = @intCast(this_unit_offset);
const unit_header = try readUnitHeader(&fr, endian);
if (unit_header.unit_length == 0) return;
const next_offset = unit_header.header_length + unit_header.unit_length;
const version = try fr.takeInt(u16, endian);
if (version < 2 or version > 5) return bad();
var address_size: u8 = undefined;
var debug_abbrev_offset: u64 = undefined;
if (version >= 5) {
const unit_type = try fr.takeByte();
if (unit_type != UT.compile) return bad();
address_size = try fr.takeByte();
debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian);
} else {
debug_abbrev_offset = try readFormatSizedInt(&fr, unit_header.format, endian);
address_size = try fr.takeByte();
}
const abbrev_table = try di.getAbbrevTable(gpa, debug_abbrev_offset);
var max_attrs: usize = 0;
for (abbrev_table.abbrevs) |abbrev| {
max_attrs = @max(max_attrs, abbrev.attrs.len);
}
try attrs_buf.resize(max_attrs);
var compile_unit_die = (try parseDie(
&fr,
attrs_buf.items,
abbrev_table,
unit_header.format,
endian,
address_size,
)) orelse return bad();
if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
compile_unit_die.attrs = try gpa.dupe(Die.Attr, compile_unit_die.attrs);
var compile_unit: CompileUnit = .{
.version = version,
.format = unit_header.format,
.addr_size_bytes = address_size,
.pc_range = null,
.die = compile_unit_die,
.str_offsets_base = if (compile_unit_die.getAttr(AT.str_offsets_base)) |fv| try fv.getUInt(usize) else 0,
.addr_base = if (compile_unit_die.getAttr(AT.addr_base)) |fv| try fv.getUInt(usize) else 0,
.rnglists_base = if (compile_unit_die.getAttr(AT.rnglists_base)) |fv| try fv.getUInt(usize) else 0,
.loclists_base = if (compile_unit_die.getAttr(AT.loclists_base)) |fv| try fv.getUInt(usize) else 0,
.frame_base = compile_unit_die.getAttr(AT.frame_base),
.src_loc_cache = null,
};
compile_unit.pc_range = x: {
if (compile_unit_die.getAttrAddr(di, endian, AT.low_pc, &compile_unit)) |low_pc| {
if (compile_unit_die.getAttr(AT.high_pc)) |high_pc_value| {
const pc_end = switch (high_pc_value.*) {
.addr => |value| value,
.udata => |offset| low_pc + offset,
else => return bad(),
};
break :x PcRange{
.start = low_pc,
.end = pc_end,
};
} else {
break :x null;
}
} else |err| {
if (err != error.MissingDebugInfo) return err;
break :x null;
}
};
try di.compile_unit_list.append(gpa, compile_unit);
this_unit_offset += next_offset;
}
}