fn read(r: *Reader, header_section_offset: u64, section: Section, endian: Endian) !EntryHeader {
const unit_header = try Dwarf.readUnitHeader(r, endian);
if (unit_header.unit_length == 0) return .terminator;
// Next is a value which will disambiguate CIEs and FDEs. Annoyingly, LSB Core makes this
// value always 4-byte, whereas DWARF makes it depend on the `dwarf.Format`.
const cie_ptr_or_id_size: u8 = switch (section) {
.eh_frame => 4,
.debug_frame => switch (unit_header.format) {
.@"32" => 4,
.@"64" => 8,
},
};
const cie_ptr_or_id = switch (cie_ptr_or_id_size) {
4 => try r.takeInt(u32, endian),
8 => try r.takeInt(u64, endian),
else => unreachable,
};
const remaining_bytes = unit_header.unit_length - cie_ptr_or_id_size;
// If this entry is a CIE, then `cie_ptr_or_id` will have this value, which is different
// between the DWARF `.debug_frame` section and the LSB Core `.eh_frame` section.
const cie_id: u64 = switch (section) {
.eh_frame => 0,
.debug_frame => switch (unit_header.format) {
.@"32" => maxInt(u32),
.@"64" => maxInt(u64),
},
};
if (cie_ptr_or_id == cie_id) {
return .{ .cie = .{
.format = unit_header.format,
.bytes_len = remaining_bytes,
} };
}
// This is an FDE -- `cie_ptr_or_id` points to the associated CIE. Unfortunately, the format
// of that pointer again differs between `.debug_frame` and `.eh_frame`.
const cie_offset = switch (section) {
.eh_frame => try std.math.sub(u64, header_section_offset + unit_header.header_length, cie_ptr_or_id),
.debug_frame => cie_ptr_or_id,
};
return .{ .fde = .{
.cie_offset = cie_offset,
.bytes_len = remaining_bytes,
} };
}