authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-22 20:36:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-25 04:05:37-07:00
log12686d9b7df8fe4c2663cd8e2136991dc3cf661c
tree033b9cd46af088ef8c4c382155d27f431c57406d
parentafea41947069b5c270d9f8a5a0a34530e48687ed

delete std.debug.FixedBufferReader

now that std.Io.Reader has sufficient debug performance

4 files changed, 295 insertions(+), 363 deletions(-)

lib/std/debug.zig-2
......@@ -14,7 +14,6 @@ const native_os = builtin.os.tag;
1414const native_endian = native_arch.endian();
1515const Writer = std.io.Writer;
1616
17pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
1817pub const Dwarf = @import("debug/Dwarf.zig");
1918pub const Pdb = @import("debug/Pdb.zig");
2019pub const SelfInfo = @import("debug/SelfInfo.zig");
......@@ -1773,7 +1772,6 @@ pub inline fn inValgrind() bool {
17731772
17741773test {
17751774 _ = &Dwarf;
1776 _ = &FixedBufferReader;
17771775 _ = &Pdb;
17781776 _ = &SelfInfo;
17791777 _ = &dumpHex;
lib/std/debug/Dwarf.zig+287-282
......@@ -25,8 +25,9 @@ const assert = std.debug.assert;
2525const cast = std.math.cast;
2626const maxInt = std.math.maxInt;
2727const Path = std.Build.Cache.Path;
28const FixedBufferReader = std.debug.FixedBufferReader;
2928const ArrayList = std.ArrayList;
29const Endian = std.builtin.Endian;
30const Reader = std.Io.Reader;
3031
3132const Dwarf = @This();
3233
......@@ -37,7 +38,7 @@ pub const call_frame = @import("Dwarf/call_frame.zig");
3738/// Useful to temporarily enable while working on this file.
3839const debug_debug_mode = false;
3940
40endian: std.builtin.Endian,
41endian: Endian,
4142sections: SectionArray = null_section_array,
4243is_macho: bool,
4344
......@@ -355,23 +356,23 @@ pub const ExceptionFrameHeader = struct {
355356 pc: usize,
356357 cie: *CommonInformationEntry,
357358 fde: *FrameDescriptionEntry,
359 endian: Endian,
358360 ) !void {
359361 const entry_size = try entrySize(self.table_enc);
360362
361363 var left: usize = 0;
362364 var len: usize = self.fde_count;
363
364 var fbr: FixedBufferReader = .{ .buf = self.entries, .endian = native_endian };
365 var fbr: Reader = .fixed(self.entries);
365366
366367 while (len > 1) {
367368 const mid = left + len / 2;
368369
369 fbr.pos = mid * entry_size;
370 fbr.seek = mid * entry_size;
370371 const pc_begin = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
371 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
372 .pc_rel_base = @intFromPtr(&self.entries[fbr.seek]),
372373 .follow_indirect = true,
373374 .data_rel_base = eh_frame_hdr_ptr,
374 }) orelse return bad();
375 }, endian) orelse return bad();
375376
376377 if (pc < pc_begin) {
377378 len /= 2;
......@@ -383,39 +384,36 @@ pub const ExceptionFrameHeader = struct {
383384 }
384385
385386 if (len == 0) return missing();
386 fbr.pos = left * entry_size;
387 fbr.seek = left * entry_size;
387388
388389 // Read past the pc_begin field of the entry
389390 _ = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
390 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
391 .pc_rel_base = @intFromPtr(&self.entries[fbr.seek]),
391392 .follow_indirect = true,
392393 .data_rel_base = eh_frame_hdr_ptr,
393 }) orelse return bad();
394 }, endian) orelse return bad();
394395
395396 const fde_ptr = cast(usize, try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{
396 .pc_rel_base = @intFromPtr(&self.entries[fbr.pos]),
397 .pc_rel_base = @intFromPtr(&self.entries[fbr.seek]),
397398 .follow_indirect = true,
398399 .data_rel_base = eh_frame_hdr_ptr,
399 }) orelse return bad()) orelse return bad();
400 }, endian) orelse return bad()) orelse return bad();
400401
401402 if (fde_ptr < self.eh_frame_ptr) return bad();
402403
403404 const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0..eh_frame_len];
404405
405406 const fde_offset = fde_ptr - self.eh_frame_ptr;
406 var eh_frame_fbr: FixedBufferReader = .{
407 .buf = eh_frame,
408 .pos = fde_offset,
409 .endian = native_endian,
410 };
407 var eh_frame_fbr: Reader = .fixed(eh_frame);
408 eh_frame_fbr.seek = fde_offset;
411409
412 const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
410 const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame, endian);
413411 if (fde_entry_header.type != .fde) return bad();
414412
415413 // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable
416414 const cie_offset = fde_entry_header.type.fde;
417 try eh_frame_fbr.seekTo(cie_offset);
418 const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
415 eh_frame_fbr.seek = @intCast(cie_offset);
416 const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame, endian);
419417 if (cie_entry_header.type != .cie) return bad();
420418
421419 cie.* = try CommonInformationEntry.parse(
......@@ -426,7 +424,7 @@ pub const ExceptionFrameHeader = struct {
426424 .eh_frame,
427425 cie_entry_header.length_offset,
428426 @sizeOf(usize),
429 native_endian,
427 endian,
430428 );
431429
432430 fde.* = try FrameDescriptionEntry.parse(
......@@ -435,7 +433,7 @@ pub const ExceptionFrameHeader = struct {
435433 true,
436434 cie.*,
437435 @sizeOf(usize),
438 native_endian,
436 endian,
439437 );
440438
441439 if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return missing();
......@@ -460,13 +458,18 @@ pub const EntryHeader = struct {
460458 return self.entry_bytes.len + @as(u8, if (self.format == .@"64") 8 else 4);
461459 }
462460
463 /// Reads a header for either an FDE or a CIE, then advances the fbr to the position after the trailing structure.
464 /// `fbr` must be a FixedBufferReader backed by either the .eh_frame or .debug_frame sections.
465 pub fn read(fbr: *FixedBufferReader, dwarf_section: Section.Id) !EntryHeader {
461 /// Reads a header for either an FDE or a CIE, then advances the fbr to the
462 /// position after the trailing structure.
463 ///
464 /// `fbr` must be backed by either the .eh_frame or .debug_frame sections.
465 ///
466 /// TODO that's a bad API, don't do that. this function should neither require
467 /// a fixed reader nor depend on seeking.
468 pub fn read(fbr: *Reader, dwarf_section: Section.Id, endian: Endian) !EntryHeader {
466469 assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);
467470
468 const length_offset = fbr.pos;
469 const unit_header = try readUnitHeader(fbr);
471 const length_offset = fbr.seek;
472 const unit_header = try readUnitHeader(fbr, endian);
470473 const unit_length = cast(usize, unit_header.unit_length) orelse return bad();
471474 if (unit_length == 0) return .{
472475 .length_offset = length_offset,
......@@ -474,12 +477,12 @@ pub const EntryHeader = struct {
474477 .type = .terminator,
475478 .entry_bytes = &.{},
476479 };
477 const start_offset = fbr.pos;
480 const start_offset = fbr.seek;
478481 const end_offset = start_offset + unit_length;
479 defer fbr.pos = end_offset;
482 defer fbr.seek = end_offset;
480483
481 const id = try fbr.readAddress(unit_header.format);
482 const entry_bytes = fbr.buf[fbr.pos..end_offset];
484 const id = try readAddress(fbr, unit_header.format, endian);
485 const entry_bytes = fbr.buffer[fbr.seek..end_offset];
483486 const cie_id: u64 = switch (dwarf_section) {
484487 .eh_frame => CommonInformationEntry.eh_id,
485488 .debug_frame => switch (unit_header.format) {
......@@ -565,13 +568,13 @@ pub const CommonInformationEntry = struct {
565568 dwarf_section: Section.Id,
566569 length_offset: u64,
567570 addr_size_bytes: u8,
568 endian: std.builtin.Endian,
571 endian: Endian,
569572 ) !CommonInformationEntry {
570573 if (addr_size_bytes > 8) return error.UnsupportedAddrSize;
571574
572 var fbr: FixedBufferReader = .{ .buf = cie_bytes, .endian = endian };
575 var fbr: Reader = .fixed(cie_bytes);
573576
574 const version = try fbr.readByte();
577 const version = try fbr.takeByte();
575578 switch (dwarf_section) {
576579 .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
577580 .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
......@@ -582,9 +585,9 @@ pub const CommonInformationEntry = struct {
582585 var has_aug_data = false;
583586
584587 var aug_str_len: usize = 0;
585 const aug_str_start = fbr.pos;
586 var aug_byte = try fbr.readByte();
587 while (aug_byte != 0) : (aug_byte = try fbr.readByte()) {
588 const aug_str_start = fbr.seek;
589 var aug_byte = try fbr.takeByte();
590 while (aug_byte != 0) : (aug_byte = try fbr.takeByte()) {
588591 switch (aug_byte) {
589592 'z' => {
590593 if (aug_str_len != 0) return bad();
......@@ -592,7 +595,7 @@ pub const CommonInformationEntry = struct {
592595 },
593596 'e' => {
594597 if (has_aug_data or aug_str_len != 0) return bad();
595 if (try fbr.readByte() != 'h') return bad();
598 if (try fbr.takeByte() != 'h') return bad();
596599 has_eh_data = true;
597600 },
598601 else => if (has_eh_data) return bad(),
......@@ -603,15 +606,15 @@ pub const CommonInformationEntry = struct {
603606
604607 if (has_eh_data) {
605608 // legacy data created by older versions of gcc - unsupported here
606 for (0..addr_size_bytes) |_| _ = try fbr.readByte();
609 for (0..addr_size_bytes) |_| _ = try fbr.takeByte();
607610 }
608611
609 const address_size = if (version == 4) try fbr.readByte() else addr_size_bytes;
610 const segment_selector_size = if (version == 4) try fbr.readByte() else null;
612 const address_size = if (version == 4) try fbr.takeByte() else addr_size_bytes;
613 const segment_selector_size = if (version == 4) try fbr.takeByte() else null;
611614
612 const code_alignment_factor = try fbr.readUleb128(u32);
613 const data_alignment_factor = try fbr.readIleb128(i32);
614 const return_address_register = if (version == 1) try fbr.readByte() else try fbr.readUleb128(u8);
615 const code_alignment_factor = try fbr.takeLeb128(u32);
616 const data_alignment_factor = try fbr.takeLeb128(i32);
617 const return_address_register = if (version == 1) try fbr.takeByte() else try fbr.takeLeb128(u8);
615618
616619 var lsda_pointer_enc: u8 = EH.PE.omit;
617620 var personality_enc: ?u8 = null;
......@@ -620,25 +623,25 @@ pub const CommonInformationEntry = struct {
620623
621624 var aug_data: []const u8 = &[_]u8{};
622625 const aug_str = if (has_aug_data) blk: {
623 const aug_data_len = try fbr.readUleb128(usize);
624 const aug_data_start = fbr.pos;
626 const aug_data_len = try fbr.takeLeb128(usize);
627 const aug_data_start = fbr.seek;
625628 aug_data = cie_bytes[aug_data_start..][0..aug_data_len];
626629
627630 const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];
628631 for (aug_str[1..]) |byte| {
629632 switch (byte) {
630633 'L' => {
631 lsda_pointer_enc = try fbr.readByte();
634 lsda_pointer_enc = try fbr.takeByte();
632635 },
633636 'P' => {
634 personality_enc = try fbr.readByte();
637 personality_enc = try fbr.takeByte();
635638 personality_routine_pointer = try readEhPointer(&fbr, personality_enc.?, addr_size_bytes, .{
636 .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[fbr.pos]), pc_rel_offset),
639 .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[fbr.seek]), pc_rel_offset),
637640 .follow_indirect = is_runtime,
638 });
641 }, endian);
639642 },
640643 'R' => {
641 fde_pointer_enc = try fbr.readByte();
644 fde_pointer_enc = try fbr.takeByte();
642645 },
643646 'S', 'B', 'G' => {},
644647 else => return bad(),
......@@ -646,11 +649,11 @@ pub const CommonInformationEntry = struct {
646649 }
647650
648651 // aug_data_len can include padding so the CIE ends on an address boundary
649 fbr.pos = aug_data_start + aug_data_len;
652 fbr.seek = aug_data_start + aug_data_len;
650653 break :blk aug_str;
651654 } else &[_]u8{};
652655
653 const initial_instructions = cie_bytes[fbr.pos..];
656 const initial_instructions = cie_bytes[fbr.seek..];
654657 return .{
655658 .length_offset = length_offset,
656659 .version = version,
......@@ -699,41 +702,41 @@ pub const FrameDescriptionEntry = struct {
699702 is_runtime: bool,
700703 cie: CommonInformationEntry,
701704 addr_size_bytes: u8,
702 endian: std.builtin.Endian,
705 endian: Endian,
703706 ) !FrameDescriptionEntry {
704707 if (addr_size_bytes > 8) return error.InvalidAddrSize;
705708
706 var fbr: FixedBufferReader = .{ .buf = fde_bytes, .endian = endian };
709 var fbr: Reader = .fixed(fde_bytes);
707710
708711 const pc_begin = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
709 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
712 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.seek]), pc_rel_offset),
710713 .follow_indirect = is_runtime,
711 }) orelse return bad();
714 }, endian) orelse return bad();
712715
713716 const pc_range = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
714717 .pc_rel_base = 0,
715718 .follow_indirect = false,
716 }) orelse return bad();
719 }, endian) orelse return bad();
717720
718721 var aug_data: []const u8 = &[_]u8{};
719722 const lsda_pointer = if (cie.aug_str.len > 0) blk: {
720 const aug_data_len = try fbr.readUleb128(usize);
721 const aug_data_start = fbr.pos;
723 const aug_data_len = try fbr.takeLeb128(usize);
724 const aug_data_start = fbr.seek;
722725 aug_data = fde_bytes[aug_data_start..][0..aug_data_len];
723726
724727 const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)
725728 try readEhPointer(&fbr, cie.lsda_pointer_enc, addr_size_bytes, .{
726 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
729 .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.seek]), pc_rel_offset),
727730 .follow_indirect = is_runtime,
728 })
731 }, endian)
729732 else
730733 null;
731734
732 fbr.pos = aug_data_start + aug_data_len;
735 fbr.seek = aug_data_start + aug_data_len;
733736 break :blk lsda_pointer;
734737 } else null;
735738
736 const instructions = fde_bytes[fbr.pos..];
739 const instructions = fde_bytes[fbr.seek..];
737740 return .{
738741 .cie_length_offset = cie.length_offset,
739742 .pc_begin = pc_begin,
......@@ -816,32 +819,37 @@ pub fn getSymbolName(di: *Dwarf, address: u64) ?[]const u8 {
816819pub const ScanError = error{
817820 InvalidDebugInfo,
818821 MissingDebugInfo,
819} || Allocator.Error || std.debug.FixedBufferReader.Error;
822 ReadFailed,
823 EndOfStream,
824 Overflow,
825 StreamTooLong,
826} || Allocator.Error;
820827
821828fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
822 var fbr: FixedBufferReader = .{ .buf = di.section(.debug_info).?, .endian = di.endian };
829 const endian = di.endian;
830 var fbr: Reader = .fixed(di.section(.debug_info).?);
823831 var this_unit_offset: u64 = 0;
824832
825 while (this_unit_offset < fbr.buf.len) {
826 try fbr.seekTo(this_unit_offset);
833 while (this_unit_offset < fbr.buffer.len) {
834 fbr.seek = @intCast(this_unit_offset);
827835
828 const unit_header = try readUnitHeader(&fbr);
836 const unit_header = try readUnitHeader(&fbr, endian);
829837 if (unit_header.unit_length == 0) return;
830838 const next_offset = unit_header.header_length + unit_header.unit_length;
831839
832 const version = try fbr.readInt(u16);
840 const version = try fbr.takeInt(u16, endian);
833841 if (version < 2 or version > 5) return bad();
834842
835843 var address_size: u8 = undefined;
836844 var debug_abbrev_offset: u64 = undefined;
837845 if (version >= 5) {
838 const unit_type = try fbr.readInt(u8);
846 const unit_type = try fbr.takeByte();
839847 if (unit_type != DW.UT.compile) return bad();
840 address_size = try fbr.readByte();
841 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
848 address_size = try fbr.takeByte();
849 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
842850 } else {
843 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
844 address_size = try fbr.readByte();
851 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
852 address_size = try fbr.takeByte();
845853 }
846854 if (address_size != @sizeOf(usize)) return bad();
847855
......@@ -882,15 +890,16 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
882890 };
883891
884892 while (true) {
885 fbr.pos = std.mem.indexOfNonePos(u8, fbr.buf, fbr.pos, &.{
893 fbr.seek = std.mem.indexOfNonePos(u8, fbr.buffer, fbr.seek, &.{
886894 zig_padding_abbrev_code, 0,
887 }) orelse fbr.buf.len;
888 if (fbr.pos >= next_unit_pos) break;
895 }) orelse fbr.buffer.len;
896 if (fbr.seek >= next_unit_pos) break;
889897 var die_obj = (try parseDie(
890898 &fbr,
891899 attrs_bufs[0],
892900 abbrev_table,
893901 unit_header.format,
902 endian,
894903 )) orelse continue;
895904
896905 switch (die_obj.tag_id) {
......@@ -913,30 +922,32 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
913922 if (this_die_obj.getAttr(AT.name)) |_| {
914923 break :x try this_die_obj.getAttrString(di, AT.name, di.section(.debug_str), compile_unit);
915924 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {
916 const after_die_offset = fbr.pos;
917 defer fbr.pos = after_die_offset;
925 const after_die_offset = fbr.seek;
926 defer fbr.seek = after_die_offset;
918927
919928 // Follow the DIE it points to and repeat
920929 const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin, this_unit_offset, next_offset);
921 try fbr.seekTo(ref_offset);
930 fbr.seek = @intCast(ref_offset);
922931 this_die_obj = (try parseDie(
923932 &fbr,
924933 attrs_bufs[2],
925934 abbrev_table, // wrong abbrev table for different cu
926935 unit_header.format,
936 endian,
927937 )) orelse return bad();
928938 } else if (this_die_obj.getAttr(AT.specification)) |_| {
929 const after_die_offset = fbr.pos;
930 defer fbr.pos = after_die_offset;
939 const after_die_offset = fbr.seek;
940 defer fbr.seek = after_die_offset;
931941
932942 // Follow the DIE it points to and repeat
933943 const ref_offset = try this_die_obj.getAttrRef(AT.specification, this_unit_offset, next_offset);
934 try fbr.seekTo(ref_offset);
944 fbr.seek = @intCast(ref_offset);
935945 this_die_obj = (try parseDie(
936946 &fbr,
937947 attrs_bufs[2],
938948 abbrev_table, // wrong abbrev table for different cu
939949 unit_header.format,
950 endian,
940951 )) orelse return bad();
941952 } else {
942953 break :x null;
......@@ -1005,32 +1016,33 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
10051016}
10061017
10071018fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {
1008 var fbr: FixedBufferReader = .{ .buf = di.section(.debug_info).?, .endian = di.endian };
1019 const endian = di.endian;
1020 var fbr: Reader = .fixed(di.section(.debug_info).?);
10091021 var this_unit_offset: u64 = 0;
10101022
10111023 var attrs_buf = std.array_list.Managed(Die.Attr).init(allocator);
10121024 defer attrs_buf.deinit();
10131025
1014 while (this_unit_offset < fbr.buf.len) {
1015 try fbr.seekTo(this_unit_offset);
1026 while (this_unit_offset < fbr.buffer.len) {
1027 fbr.seek = @intCast(this_unit_offset);
10161028
1017 const unit_header = try readUnitHeader(&fbr);
1029 const unit_header = try readUnitHeader(&fbr, endian);
10181030 if (unit_header.unit_length == 0) return;
10191031 const next_offset = unit_header.header_length + unit_header.unit_length;
10201032
1021 const version = try fbr.readInt(u16);
1033 const version = try fbr.takeInt(u16, endian);
10221034 if (version < 2 or version > 5) return bad();
10231035
10241036 var address_size: u8 = undefined;
10251037 var debug_abbrev_offset: u64 = undefined;
10261038 if (version >= 5) {
1027 const unit_type = try fbr.readInt(u8);
1039 const unit_type = try fbr.takeByte();
10281040 if (unit_type != UT.compile) return bad();
1029 address_size = try fbr.readByte();
1030 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
1041 address_size = try fbr.takeByte();
1042 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
10311043 } else {
1032 debug_abbrev_offset = try fbr.readAddress(unit_header.format);
1033 address_size = try fbr.readByte();
1044 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
1045 address_size = try fbr.takeByte();
10341046 }
10351047 if (address_size != @sizeOf(usize)) return bad();
10361048
......@@ -1047,6 +1059,7 @@ fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {
10471059 attrs_buf.items,
10481060 abbrev_table,
10491061 unit_header.format,
1062 endian,
10501063 )) orelse return bad();
10511064
10521065 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
......@@ -1132,7 +1145,7 @@ const DebugRangeIterator = struct {
11321145 section_type: Section.Id,
11331146 di: *const Dwarf,
11341147 compile_unit: *const CompileUnit,
1135 fbr: FixedBufferReader,
1148 fbr: Reader,
11361149
11371150 pub fn init(ranges_value: *const FormValue, di: *const Dwarf, compile_unit: *const CompileUnit) !@This() {
11381151 const section_type = if (compile_unit.version >= 5) Section.Id.debug_rnglists else Section.Id.debug_ranges;
......@@ -1168,36 +1181,36 @@ const DebugRangeIterator = struct {
11681181 else => return err,
11691182 };
11701183
1184 var fbr: Reader = .fixed(debug_ranges);
1185 fbr.seek = cast(usize, ranges_offset) orelse return bad();
1186
11711187 return .{
11721188 .base_address = base_address,
11731189 .section_type = section_type,
11741190 .di = di,
11751191 .compile_unit = compile_unit,
1176 .fbr = .{
1177 .buf = debug_ranges,
1178 .pos = cast(usize, ranges_offset) orelse return bad(),
1179 .endian = di.endian,
1180 },
1192 .fbr = fbr,
11811193 };
11821194 }
11831195
11841196 // Returns the next range in the list, or null if the end was reached.
11851197 pub fn next(self: *@This()) !?PcRange {
1198 const endian = self.di.endian;
11861199 switch (self.section_type) {
11871200 .debug_rnglists => {
1188 const kind = try self.fbr.readByte();
1201 const kind = try self.fbr.takeByte();
11891202 switch (kind) {
11901203 RLE.end_of_list => return null,
11911204 RLE.base_addressx => {
1192 const index = try self.fbr.readUleb128(usize);
1205 const index = try self.fbr.takeLeb128(usize);
11931206 self.base_address = try self.di.readDebugAddr(self.compile_unit.*, index);
11941207 return try self.next();
11951208 },
11961209 RLE.startx_endx => {
1197 const start_index = try self.fbr.readUleb128(usize);
1210 const start_index = try self.fbr.takeLeb128(usize);
11981211 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);
11991212
1200 const end_index = try self.fbr.readUleb128(usize);
1213 const end_index = try self.fbr.takeLeb128(usize);
12011214 const end_addr = try self.di.readDebugAddr(self.compile_unit.*, end_index);
12021215
12031216 return .{
......@@ -1206,10 +1219,10 @@ const DebugRangeIterator = struct {
12061219 };
12071220 },
12081221 RLE.startx_length => {
1209 const start_index = try self.fbr.readUleb128(usize);
1222 const start_index = try self.fbr.takeLeb128(usize);
12101223 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);
12111224
1212 const len = try self.fbr.readUleb128(usize);
1225 const len = try self.fbr.takeLeb128(usize);
12131226 const end_addr = start_addr + len;
12141227
12151228 return .{
......@@ -1218,8 +1231,8 @@ const DebugRangeIterator = struct {
12181231 };
12191232 },
12201233 RLE.offset_pair => {
1221 const start_addr = try self.fbr.readUleb128(usize);
1222 const end_addr = try self.fbr.readUleb128(usize);
1234 const start_addr = try self.fbr.takeLeb128(usize);
1235 const end_addr = try self.fbr.takeLeb128(usize);
12231236
12241237 // This is the only kind that uses the base address
12251238 return .{
......@@ -1228,12 +1241,12 @@ const DebugRangeIterator = struct {
12281241 };
12291242 },
12301243 RLE.base_address => {
1231 self.base_address = try self.fbr.readInt(usize);
1244 self.base_address = try self.fbr.takeInt(usize, endian);
12321245 return try self.next();
12331246 },
12341247 RLE.start_end => {
1235 const start_addr = try self.fbr.readInt(usize);
1236 const end_addr = try self.fbr.readInt(usize);
1248 const start_addr = try self.fbr.takeInt(usize, endian);
1249 const end_addr = try self.fbr.takeInt(usize, endian);
12371250
12381251 return .{
12391252 .start = start_addr,
......@@ -1241,8 +1254,8 @@ const DebugRangeIterator = struct {
12411254 };
12421255 },
12431256 RLE.start_length => {
1244 const start_addr = try self.fbr.readInt(usize);
1245 const len = try self.fbr.readUleb128(usize);
1257 const start_addr = try self.fbr.takeInt(usize, endian);
1258 const len = try self.fbr.takeLeb128(usize);
12461259 const end_addr = start_addr + len;
12471260
12481261 return .{
......@@ -1254,8 +1267,8 @@ const DebugRangeIterator = struct {
12541267 }
12551268 },
12561269 .debug_ranges => {
1257 const start_addr = try self.fbr.readInt(usize);
1258 const end_addr = try self.fbr.readInt(usize);
1270 const start_addr = try self.fbr.takeInt(usize, endian);
1271 const end_addr = try self.fbr.takeInt(usize, endian);
12591272 if (start_addr == 0 and end_addr == 0) return null;
12601273
12611274 // This entry selects a new value for the base address
......@@ -1307,11 +1320,8 @@ fn getAbbrevTable(di: *Dwarf, allocator: Allocator, abbrev_offset: u64) !*const
13071320}
13081321
13091322fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table {
1310 var fbr: FixedBufferReader = .{
1311 .buf = di.section(.debug_abbrev).?,
1312 .pos = cast(usize, offset) orelse return bad(),
1313 .endian = di.endian,
1314 };
1323 var fbr: Reader = .fixed(di.section(.debug_abbrev).?);
1324 fbr.seek = cast(usize, offset) orelse return bad();
13151325
13161326 var abbrevs = std.array_list.Managed(Abbrev).init(allocator);
13171327 defer {
......@@ -1325,20 +1335,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table
13251335 defer attrs.deinit();
13261336
13271337 while (true) {
1328 const code = try fbr.readUleb128(u64);
1338 const code = try fbr.takeLeb128(u64);
13291339 if (code == 0) break;
1330 const tag_id = try fbr.readUleb128(u64);
1331 const has_children = (try fbr.readByte()) == DW.CHILDREN.yes;
1340 const tag_id = try fbr.takeLeb128(u64);
1341 const has_children = (try fbr.takeByte()) == DW.CHILDREN.yes;
13321342
13331343 while (true) {
1334 const attr_id = try fbr.readUleb128(u64);
1335 const form_id = try fbr.readUleb128(u64);
1344 const attr_id = try fbr.takeLeb128(u64);
1345 const form_id = try fbr.takeLeb128(u64);
13361346 if (attr_id == 0 and form_id == 0) break;
13371347 try attrs.append(.{
13381348 .id = attr_id,
13391349 .form_id = form_id,
13401350 .payload = switch (form_id) {
1341 FORM.implicit_const => try fbr.readIleb128(i64),
1351 FORM.implicit_const => try fbr.takeLeb128(i64),
13421352 else => undefined,
13431353 },
13441354 });
......@@ -1359,24 +1369,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table
13591369}
13601370
13611371fn parseDie(
1362 fbr: *FixedBufferReader,
1372 fbr: *Reader,
13631373 attrs_buf: []Die.Attr,
13641374 abbrev_table: *const Abbrev.Table,
13651375 format: Format,
1376 endian: Endian,
13661377) ScanError!?Die {
1367 const abbrev_code = try fbr.readUleb128(u64);
1378 const abbrev_code = try fbr.takeLeb128(u64);
13681379 if (abbrev_code == 0) return null;
13691380 const table_entry = abbrev_table.get(abbrev_code) orelse return bad();
13701381
13711382 const attrs = attrs_buf[0..table_entry.attrs.len];
1372 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = Die.Attr{
1383 for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{
13731384 .id = attr.id,
1374 .value = try parseFormValue(
1375 fbr,
1376 attr.form_id,
1377 format,
1378 attr.payload,
1379 ),
1385 .value = try parseFormValue(fbr, attr.form_id, format, endian, attr.payload),
13801386 };
13811387 return .{
13821388 .tag_id = table_entry.tag_id,
......@@ -1387,26 +1393,24 @@ fn parseDie(
13871393
13881394/// Ensures that addresses in the returned LineTable are monotonically increasing.
13891395fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !CompileUnit.SrcLocCache {
1396 const endian = d.endian;
13901397 const compile_unit_cwd = try compile_unit.die.getAttrString(d, AT.comp_dir, d.section(.debug_line_str), compile_unit.*);
13911398 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);
13921399
1393 var fbr: FixedBufferReader = .{
1394 .buf = d.section(.debug_line).?,
1395 .endian = d.endian,
1396 };
1397 try fbr.seekTo(line_info_offset);
1400 var fbr: Reader = .fixed(d.section(.debug_line).?);
1401 fbr.seek = @intCast(line_info_offset);
13981402
1399 const unit_header = try readUnitHeader(&fbr);
1403 const unit_header = try readUnitHeader(&fbr, endian);
14001404 if (unit_header.unit_length == 0) return missing();
14011405
14021406 const next_offset = unit_header.header_length + unit_header.unit_length;
14031407
1404 const version = try fbr.readInt(u16);
1408 const version = try fbr.takeInt(u16, endian);
14051409 if (version < 2) return bad();
14061410
14071411 const addr_size: u8, const seg_size: u8 = if (version >= 5) .{
1408 try fbr.readByte(),
1409 try fbr.readByte(),
1412 try fbr.takeByte(),
1413 try fbr.takeByte(),
14101414 } else .{
14111415 switch (unit_header.format) {
14121416 .@"32" => 4,
......@@ -1417,26 +1421,26 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
14171421 _ = addr_size;
14181422 _ = seg_size;
14191423
1420 const prologue_length = try fbr.readAddress(unit_header.format);
1421 const prog_start_offset = fbr.pos + prologue_length;
1424 const prologue_length = try readAddress(&fbr, unit_header.format, endian);
1425 const prog_start_offset = fbr.seek + prologue_length;
14221426
1423 const minimum_instruction_length = try fbr.readByte();
1427 const minimum_instruction_length = try fbr.takeByte();
14241428 if (minimum_instruction_length == 0) return bad();
14251429
14261430 if (version >= 4) {
1427 const maximum_operations_per_instruction = try fbr.readByte();
1431 const maximum_operations_per_instruction = try fbr.takeByte();
14281432 _ = maximum_operations_per_instruction;
14291433 }
14301434
1431 const default_is_stmt = (try fbr.readByte()) != 0;
1432 const line_base = try fbr.readByteSigned();
1435 const default_is_stmt = (try fbr.takeByte()) != 0;
1436 const line_base = try fbr.takeByteSigned();
14331437
1434 const line_range = try fbr.readByte();
1438 const line_range = try fbr.takeByte();
14351439 if (line_range == 0) return bad();
14361440
1437 const opcode_base = try fbr.readByte();
1441 const opcode_base = try fbr.takeByte();
14381442
1439 const standard_opcode_lengths = try fbr.readBytes(opcode_base - 1);
1443 const standard_opcode_lengths = try fbr.take(opcode_base - 1);
14401444
14411445 var directories: ArrayList(FileEntry) = .empty;
14421446 defer directories.deinit(gpa);
......@@ -1447,17 +1451,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
14471451 try directories.append(gpa, .{ .path = compile_unit_cwd });
14481452
14491453 while (true) {
1450 const dir = try fbr.readBytesTo(0);
1454 const dir = try fbr.takeSentinel(0);
14511455 if (dir.len == 0) break;
14521456 try directories.append(gpa, .{ .path = dir });
14531457 }
14541458
14551459 while (true) {
1456 const file_name = try fbr.readBytesTo(0);
1460 const file_name = try fbr.takeSentinel(0);
14571461 if (file_name.len == 0) break;
1458 const dir_index = try fbr.readUleb128(u32);
1459 const mtime = try fbr.readUleb128(u64);
1460 const size = try fbr.readUleb128(u64);
1462 const dir_index = try fbr.takeLeb128(u32);
1463 const mtime = try fbr.takeLeb128(u64);
1464 const size = try fbr.takeLeb128(u64);
14611465 try file_entries.append(gpa, .{
14621466 .path = file_name,
14631467 .dir_index = dir_index,
......@@ -1472,26 +1476,21 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
14721476 };
14731477 {
14741478 var dir_ent_fmt_buf: [10]FileEntFmt = undefined;
1475 const directory_entry_format_count = try fbr.readByte();
1479 const directory_entry_format_count = try fbr.takeByte();
14761480 if (directory_entry_format_count > dir_ent_fmt_buf.len) return bad();
14771481 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |*ent_fmt| {
14781482 ent_fmt.* = .{
1479 .content_type_code = try fbr.readUleb128(u8),
1480 .form_code = try fbr.readUleb128(u16),
1483 .content_type_code = try fbr.takeLeb128(u8),
1484 .form_code = try fbr.takeLeb128(u16),
14811485 };
14821486 }
14831487
1484 const directories_count = try fbr.readUleb128(usize);
1488 const directories_count = try fbr.takeLeb128(usize);
14851489
14861490 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
14871491 e.* = .{ .path = &.{} };
14881492 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
1489 const form_value = try parseFormValue(
1490 &fbr,
1491 ent_fmt.form_code,
1492 unit_header.format,
1493 null,
1494 );
1493 const form_value = try parseFormValue(&fbr, ent_fmt.form_code, unit_header.format, endian, null);
14951494 switch (ent_fmt.content_type_code) {
14961495 DW.LNCT.path => e.path = try form_value.getString(d.*),
14971496 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
......@@ -1508,27 +1507,22 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
15081507 }
15091508
15101509 var file_ent_fmt_buf: [10]FileEntFmt = undefined;
1511 const file_name_entry_format_count = try fbr.readByte();
1510 const file_name_entry_format_count = try fbr.takeByte();
15121511 if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad();
15131512 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {
15141513 ent_fmt.* = .{
1515 .content_type_code = try fbr.readUleb128(u16),
1516 .form_code = try fbr.readUleb128(u16),
1514 .content_type_code = try fbr.takeLeb128(u16),
1515 .form_code = try fbr.takeLeb128(u16),
15171516 };
15181517 }
15191518
1520 const file_names_count = try fbr.readUleb128(usize);
1519 const file_names_count = try fbr.takeLeb128(usize);
15211520 try file_entries.ensureUnusedCapacity(gpa, file_names_count);
15221521
15231522 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
15241523 e.* = .{ .path = &.{} };
15251524 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
1526 const form_value = try parseFormValue(
1527 &fbr,
1528 ent_fmt.form_code,
1529 unit_header.format,
1530 null,
1531 );
1525 const form_value = try parseFormValue(&fbr, ent_fmt.form_code, unit_header.format, endian, null);
15321526 switch (ent_fmt.content_type_code) {
15331527 DW.LNCT.path => e.path = try form_value.getString(d.*),
15341528 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),
......@@ -1548,17 +1542,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
15481542 var line_table: CompileUnit.SrcLocCache.LineTable = .{};
15491543 errdefer line_table.deinit(gpa);
15501544
1551 try fbr.seekTo(prog_start_offset);
1545 fbr.seek = @intCast(prog_start_offset);
15521546
15531547 const next_unit_pos = line_info_offset + next_offset;
15541548
1555 while (fbr.pos < next_unit_pos) {
1556 const opcode = try fbr.readByte();
1549 while (fbr.seek < next_unit_pos) {
1550 const opcode = try fbr.takeByte();
15571551
15581552 if (opcode == DW.LNS.extended_op) {
1559 const op_size = try fbr.readUleb128(u64);
1553 const op_size = try fbr.takeLeb128(u64);
15601554 if (op_size < 1) return bad();
1561 const sub_op = try fbr.readByte();
1555 const sub_op = try fbr.takeByte();
15621556 switch (sub_op) {
15631557 DW.LNE.end_sequence => {
15641558 // The row being added here is an "end" address, meaning
......@@ -1577,14 +1571,14 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
15771571 prog.reset();
15781572 },
15791573 DW.LNE.set_address => {
1580 const addr = try fbr.readInt(usize);
1574 const addr = try fbr.takeInt(usize, endian);
15811575 prog.address = addr;
15821576 },
15831577 DW.LNE.define_file => {
1584 const path = try fbr.readBytesTo(0);
1585 const dir_index = try fbr.readUleb128(u32);
1586 const mtime = try fbr.readUleb128(u64);
1587 const size = try fbr.readUleb128(u64);
1578 const path = try fbr.takeSentinel(0);
1579 const dir_index = try fbr.takeLeb128(u32);
1580 const mtime = try fbr.takeLeb128(u64);
1581 const size = try fbr.takeLeb128(u64);
15881582 try file_entries.append(gpa, .{
15891583 .path = path,
15901584 .dir_index = dir_index,
......@@ -1592,7 +1586,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
15921586 .size = size,
15931587 });
15941588 },
1595 else => try fbr.seekForward(op_size - 1),
1589 else => try fbr.discardAll64(op_size - 1),
15961590 }
15971591 } else if (opcode >= opcode_base) {
15981592 // special opcodes
......@@ -1610,19 +1604,19 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
16101604 prog.basic_block = false;
16111605 },
16121606 DW.LNS.advance_pc => {
1613 const arg = try fbr.readUleb128(usize);
1607 const arg = try fbr.takeLeb128(usize);
16141608 prog.address += arg * minimum_instruction_length;
16151609 },
16161610 DW.LNS.advance_line => {
1617 const arg = try fbr.readIleb128(i64);
1611 const arg = try fbr.takeLeb128(i64);
16181612 prog.line += arg;
16191613 },
16201614 DW.LNS.set_file => {
1621 const arg = try fbr.readUleb128(usize);
1615 const arg = try fbr.takeLeb128(usize);
16221616 prog.file = arg;
16231617 },
16241618 DW.LNS.set_column => {
1625 const arg = try fbr.readUleb128(u64);
1619 const arg = try fbr.takeLeb128(u64);
16261620 prog.column = arg;
16271621 },
16281622 DW.LNS.negate_stmt => {
......@@ -1636,13 +1630,13 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
16361630 prog.address += inc_addr;
16371631 },
16381632 DW.LNS.fixed_advance_pc => {
1639 const arg = try fbr.readInt(u16);
1633 const arg = try fbr.takeInt(u16, endian);
16401634 prog.address += arg;
16411635 },
16421636 DW.LNS.set_prologue_end => {},
16431637 else => {
16441638 if (opcode - 1 >= standard_opcode_lengths.len) return bad();
1645 try fbr.seekForward(standard_opcode_lengths[opcode - 1]);
1639 try fbr.discardAll(standard_opcode_lengths[opcode - 1]);
16461640 },
16471641 }
16481642 }
......@@ -1735,38 +1729,40 @@ fn readDebugAddr(di: Dwarf, compile_unit: CompileUnit, index: u64) !u64 {
17351729///
17361730/// See also `scanCieFdeInfo`.
17371731pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
1732 const endian = di.endian;
1733
17381734 if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {
1739 var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian };
1735 var fbr: Reader = .fixed(eh_frame_hdr);
17401736
1741 const version = try fbr.readByte();
1737 const version = try fbr.takeByte();
17421738 if (version != 1) break :blk;
17431739
1744 const eh_frame_ptr_enc = try fbr.readByte();
1740 const eh_frame_ptr_enc = try fbr.takeByte();
17451741 if (eh_frame_ptr_enc == EH.PE.omit) break :blk;
1746 const fde_count_enc = try fbr.readByte();
1742 const fde_count_enc = try fbr.takeByte();
17471743 if (fde_count_enc == EH.PE.omit) break :blk;
1748 const table_enc = try fbr.readByte();
1744 const table_enc = try fbr.takeByte();
17491745 if (table_enc == EH.PE.omit) break :blk;
17501746
17511747 const eh_frame_ptr = cast(usize, try readEhPointer(&fbr, eh_frame_ptr_enc, @sizeOf(usize), .{
1752 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
1748 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.seek]),
17531749 .follow_indirect = true,
1754 }) orelse return bad()) orelse return bad();
1750 }, endian) orelse return bad()) orelse return bad();
17551751
17561752 const fde_count = cast(usize, try readEhPointer(&fbr, fde_count_enc, @sizeOf(usize), .{
1757 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
1753 .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.seek]),
17581754 .follow_indirect = true,
1759 }) orelse return bad()) orelse return bad();
1755 }, endian) orelse return bad()) orelse return bad();
17601756
17611757 const entry_size = try ExceptionFrameHeader.entrySize(table_enc);
17621758 const entries_len = fde_count * entry_size;
1763 if (entries_len > eh_frame_hdr.len - fbr.pos) return bad();
1759 if (entries_len > eh_frame_hdr.len - fbr.seek) return bad();
17641760
17651761 di.eh_frame_hdr = .{
17661762 .eh_frame_ptr = eh_frame_ptr,
17671763 .table_enc = table_enc,
17681764 .fde_count = fde_count,
1769 .entries = eh_frame_hdr[fbr.pos..][0..entries_len],
1765 .entries = eh_frame_hdr[fbr.seek..][0..entries_len],
17701766 };
17711767
17721768 // No need to scan .eh_frame, we have a binary search table already
......@@ -1779,12 +1775,13 @@ pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize)
17791775/// Scan `.eh_frame` and `.debug_frame` and build a sorted list of FDEs for binary searching during
17801776/// unwinding.
17811777pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
1778 const endian = di.endian;
17821779 const frame_sections = [2]Section.Id{ .eh_frame, .debug_frame };
17831780 for (frame_sections) |frame_section| {
17841781 if (di.section(frame_section)) |section_data| {
1785 var fbr: FixedBufferReader = .{ .buf = section_data, .endian = di.endian };
1786 while (fbr.pos < fbr.buf.len) {
1787 const entry_header = try EntryHeader.read(&fbr, frame_section);
1782 var fbr: Reader = .fixed(section_data);
1783 while (fbr.seek < fbr.buffer.len) {
1784 const entry_header = try EntryHeader.read(&fbr, frame_section, endian);
17881785 switch (entry_header.type) {
17891786 .cie => {
17901787 const cie = try CommonInformationEntry.parse(
......@@ -1826,68 +1823,60 @@ pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !vo
18261823}
18271824
18281825fn parseFormValue(
1829 fbr: *FixedBufferReader,
1826 r: *Reader,
18301827 form_id: u64,
18311828 format: Format,
1829 endian: Endian,
18321830 implicit_const: ?i64,
18331831) ScanError!FormValue {
18341832 return switch (form_id) {
1835 FORM.addr => .{ .addr = try fbr.readAddress(switch (@bitSizeOf(usize)) {
1836 32 => .@"32",
1837 64 => .@"64",
1838 else => @compileError("unsupported @sizeOf(usize)"),
1839 }) },
1840 FORM.addrx1 => .{ .addrx = try fbr.readInt(u8) },
1841 FORM.addrx2 => .{ .addrx = try fbr.readInt(u16) },
1842 FORM.addrx3 => .{ .addrx = try fbr.readInt(u24) },
1843 FORM.addrx4 => .{ .addrx = try fbr.readInt(u32) },
1844 FORM.addrx => .{ .addrx = try fbr.readUleb128(usize) },
1845
1846 FORM.block1,
1847 FORM.block2,
1848 FORM.block4,
1849 FORM.block,
1850 => .{ .block = try fbr.readBytes(switch (form_id) {
1851 FORM.block1 => try fbr.readInt(u8),
1852 FORM.block2 => try fbr.readInt(u16),
1853 FORM.block4 => try fbr.readInt(u32),
1854 FORM.block => try fbr.readUleb128(usize),
1855 else => unreachable,
1856 }) },
1857
1858 FORM.data1 => .{ .udata = try fbr.readInt(u8) },
1859 FORM.data2 => .{ .udata = try fbr.readInt(u16) },
1860 FORM.data4 => .{ .udata = try fbr.readInt(u32) },
1861 FORM.data8 => .{ .udata = try fbr.readInt(u64) },
1862 FORM.data16 => .{ .data16 = (try fbr.readBytes(16))[0..16] },
1863 FORM.udata => .{ .udata = try fbr.readUleb128(u64) },
1864 FORM.sdata => .{ .sdata = try fbr.readIleb128(i64) },
1865 FORM.exprloc => .{ .exprloc = try fbr.readBytes(try fbr.readUleb128(usize)) },
1866 FORM.flag => .{ .flag = (try fbr.readByte()) != 0 },
1833 // DWARF5.pdf page 213: the size of this value is encoded in the
1834 // compilation unit header as address size.
1835 FORM.addr => .{ .addr = try readAddress(r, nativeFormat(), endian) },
1836 FORM.addrx1 => .{ .addrx = try r.takeByte() },
1837 FORM.addrx2 => .{ .addrx = try r.takeInt(u16, endian) },
1838 FORM.addrx3 => .{ .addrx = try r.takeInt(u24, endian) },
1839 FORM.addrx4 => .{ .addrx = try r.takeInt(u32, endian) },
1840 FORM.addrx => .{ .addrx = try r.takeLeb128(usize) },
1841
1842 FORM.block1 => .{ .block = try r.take(try r.takeByte()) },
1843 FORM.block2 => .{ .block = try r.take(try r.takeInt(u16, endian)) },
1844 FORM.block4 => .{ .block = try r.take(try r.takeInt(u32, endian)) },
1845 FORM.block => .{ .block = try r.take(try r.takeLeb128(usize)) },
1846
1847 FORM.data1 => .{ .udata = try r.takeByte() },
1848 FORM.data2 => .{ .udata = try r.takeInt(u16, endian) },
1849 FORM.data4 => .{ .udata = try r.takeInt(u32, endian) },
1850 FORM.data8 => .{ .udata = try r.takeInt(u64, endian) },
1851 FORM.data16 => .{ .data16 = try r.takeArray(16) },
1852 FORM.udata => .{ .udata = try r.takeLeb128(u64) },
1853 FORM.sdata => .{ .sdata = try r.takeLeb128(i64) },
1854 FORM.exprloc => .{ .exprloc = try r.take(try r.takeLeb128(usize)) },
1855 FORM.flag => .{ .flag = (try r.takeByte()) != 0 },
18671856 FORM.flag_present => .{ .flag = true },
1868 FORM.sec_offset => .{ .sec_offset = try fbr.readAddress(format) },
1869
1870 FORM.ref1 => .{ .ref = try fbr.readInt(u8) },
1871 FORM.ref2 => .{ .ref = try fbr.readInt(u16) },
1872 FORM.ref4 => .{ .ref = try fbr.readInt(u32) },
1873 FORM.ref8 => .{ .ref = try fbr.readInt(u64) },
1874 FORM.ref_udata => .{ .ref = try fbr.readUleb128(u64) },
1875
1876 FORM.ref_addr => .{ .ref_addr = try fbr.readAddress(format) },
1877 FORM.ref_sig8 => .{ .ref = try fbr.readInt(u64) },
1878
1879 FORM.string => .{ .string = try fbr.readBytesTo(0) },
1880 FORM.strp => .{ .strp = try fbr.readAddress(format) },
1881 FORM.strx1 => .{ .strx = try fbr.readInt(u8) },
1882 FORM.strx2 => .{ .strx = try fbr.readInt(u16) },
1883 FORM.strx3 => .{ .strx = try fbr.readInt(u24) },
1884 FORM.strx4 => .{ .strx = try fbr.readInt(u32) },
1885 FORM.strx => .{ .strx = try fbr.readUleb128(usize) },
1886 FORM.line_strp => .{ .line_strp = try fbr.readAddress(format) },
1887 FORM.indirect => parseFormValue(fbr, try fbr.readUleb128(u64), format, implicit_const),
1857 FORM.sec_offset => .{ .sec_offset = try readAddress(r, format, endian) },
1858
1859 FORM.ref1 => .{ .ref = try r.takeByte() },
1860 FORM.ref2 => .{ .ref = try r.takeInt(u16, endian) },
1861 FORM.ref4 => .{ .ref = try r.takeInt(u32, endian) },
1862 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
1863 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },
1864
1865 FORM.ref_addr => .{ .ref_addr = try readAddress(r, format, endian) },
1866 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
1867
1868 FORM.string => .{ .string = try r.takeSentinel(0) },
1869 FORM.strp => .{ .strp = try readAddress(r, format, endian) },
1870 FORM.strx1 => .{ .strx = try r.takeByte() },
1871 FORM.strx2 => .{ .strx = try r.takeInt(u16, endian) },
1872 FORM.strx3 => .{ .strx = try r.takeInt(u24, endian) },
1873 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
1874 FORM.strx => .{ .strx = try r.takeLeb128(usize) },
1875 FORM.line_strp => .{ .line_strp = try readAddress(r, format, endian) },
1876 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, implicit_const),
18881877 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
1889 FORM.loclistx => .{ .loclistx = try fbr.readUleb128(u64) },
1890 FORM.rnglistx => .{ .rnglistx = try fbr.readUleb128(u64) },
1878 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
1879 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },
18911880 else => {
18921881 //debug.print("unrecognized form id: {x}\n", .{form_id});
18931882 return bad();
......@@ -1957,8 +1946,8 @@ const UnitHeader = struct {
19571946 unit_length: u64,
19581947};
19591948
1960fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {
1961 return switch (try fbr.readInt(u32)) {
1949fn readUnitHeader(r: *Reader, endian: Endian) ScanError!UnitHeader {
1950 return switch (try r.takeInt(u32, endian)) {
19621951 0...0xfffffff0 - 1 => |unit_length| .{
19631952 .format = .@"32",
19641953 .header_length = 4,
......@@ -1968,7 +1957,7 @@ fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {
19681957 0xffffffff => .{
19691958 .format = .@"64",
19701959 .header_length = 12,
1971 .unit_length = try fbr.readInt(u64),
1960 .unit_length = try r.takeInt(u64, endian),
19721961 },
19731962 };
19741963}
......@@ -2026,7 +2015,8 @@ const EhPointerContext = struct {
20262015 text_rel_base: ?u64 = null,
20272016 function_rel_base: ?u64 = null,
20282017};
2029fn readEhPointer(fbr: *FixedBufferReader, enc: u8, addr_size_bytes: u8, ctx: EhPointerContext) !?u64 {
2018
2019fn readEhPointer(fbr: *Reader, enc: u8, addr_size_bytes: u8, ctx: EhPointerContext, endian: Endian) !?u64 {
20302020 if (enc == EH.PE.omit) return null;
20312021
20322022 const value: union(enum) {
......@@ -2035,20 +2025,20 @@ fn readEhPointer(fbr: *FixedBufferReader, enc: u8, addr_size_bytes: u8, ctx: EhP
20352025 } = switch (enc & EH.PE.type_mask) {
20362026 EH.PE.absptr => .{
20372027 .unsigned = switch (addr_size_bytes) {
2038 2 => try fbr.readInt(u16),
2039 4 => try fbr.readInt(u32),
2040 8 => try fbr.readInt(u64),
2028 2 => try fbr.takeInt(u16, endian),
2029 4 => try fbr.takeInt(u32, endian),
2030 8 => try fbr.takeInt(u64, endian),
20412031 else => return error.InvalidAddrSize,
20422032 },
20432033 },
2044 EH.PE.uleb128 => .{ .unsigned = try fbr.readUleb128(u64) },
2045 EH.PE.udata2 => .{ .unsigned = try fbr.readInt(u16) },
2046 EH.PE.udata4 => .{ .unsigned = try fbr.readInt(u32) },
2047 EH.PE.udata8 => .{ .unsigned = try fbr.readInt(u64) },
2048 EH.PE.sleb128 => .{ .signed = try fbr.readIleb128(i64) },
2049 EH.PE.sdata2 => .{ .signed = try fbr.readInt(i16) },
2050 EH.PE.sdata4 => .{ .signed = try fbr.readInt(i32) },
2051 EH.PE.sdata8 => .{ .signed = try fbr.readInt(i64) },
2034 EH.PE.uleb128 => .{ .unsigned = try fbr.takeLeb128(u64) },
2035 EH.PE.udata2 => .{ .unsigned = try fbr.takeInt(u16, endian) },
2036 EH.PE.udata4 => .{ .unsigned = try fbr.takeInt(u32, endian) },
2037 EH.PE.udata8 => .{ .unsigned = try fbr.takeInt(u64, endian) },
2038 EH.PE.sleb128 => .{ .signed = try fbr.takeLeb128(i64) },
2039 EH.PE.sdata2 => .{ .signed = try fbr.takeInt(i16, endian) },
2040 EH.PE.sdata4 => .{ .signed = try fbr.takeInt(i32, endian) },
2041 EH.PE.sdata8 => .{ .signed = try fbr.takeInt(i64, endian) },
20522042 else => return bad(),
20532043 };
20542044
......@@ -2156,7 +2146,7 @@ pub const ElfModule = struct {
21562146 if (!mem.eql(u8, hdr.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
21572147 if (hdr.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;
21582148
2159 const endian: std.builtin.Endian = switch (hdr.e_ident[elf.EI_DATA]) {
2149 const endian: Endian = switch (hdr.e_ident[elf.EI_DATA]) {
21602150 elf.ELFDATA2LSB => .little,
21612151 elf.ELFDATA2MSB => .big,
21622152 else => return error.InvalidElfEndian,
......@@ -2195,7 +2185,7 @@ pub const ElfModule = struct {
21952185 const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);
21962186 const crc_offset = mem.alignForward(usize, debug_filename.len + 1, 4);
21972187 const crc_bytes = gnu_debuglink[crc_offset..][0..4];
2198 separate_debug_crc = mem.readInt(u32, crc_bytes, native_endian);
2188 separate_debug_crc = mem.readInt(u32, crc_bytes, endian);
21992189 separate_debug_filename = debug_filename;
22002190 continue;
22012191 }
......@@ -2209,7 +2199,7 @@ pub const ElfModule = struct {
22092199
22102200 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
22112201 sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: {
2212 var section_reader: std.Io.Reader = .fixed(section_bytes);
2202 var section_reader: Reader = .fixed(section_bytes);
22132203 const chdr = section_reader.takeStruct(elf.Chdr, endian) catch continue;
22142204 if (chdr.ch_type != .ZLIB) continue;
22152205
......@@ -2452,3 +2442,18 @@ pub fn chopSlice(ptr: []const u8, offset: u64, size: u64) error{Overflow}![]cons
24522442 const end = start + (cast(usize, size) orelse return error.Overflow);
24532443 return ptr[start..end];
24542444}
2445
2446fn readAddress(r: *Reader, format: std.dwarf.Format, endian: Endian) !u64 {
2447 return switch (format) {
2448 .@"32" => try r.takeInt(u32, endian),
2449 .@"64" => try r.takeInt(u64, endian),
2450 };
2451}
2452
2453fn nativeFormat() std.dwarf.Format {
2454 return switch (@sizeOf(usize)) {
2455 4 => .@"32",
2456 8 => .@"64",
2457 else => @compileError("unsupported @sizeOf(usize)"),
2458 };
2459}
lib/std/debug/FixedBufferReader.zig deleted-70
......@@ -1,70 +0,0 @@
1//! Optimized for performance in debug builds.
2
3const std = @import("../std.zig");
4
5const FixedBufferReader = @This();
6
7buf: []const u8,
8pos: usize = 0,
9endian: std.builtin.Endian,
10
11pub const Error = error{ EndOfBuffer, Overflow, InvalidBuffer };
12
13pub fn seekTo(fbr: *FixedBufferReader, pos: u64) Error!void {
14 if (pos > fbr.buf.len) return error.EndOfBuffer;
15 fbr.pos = @intCast(pos);
16}
17
18pub fn seekForward(fbr: *FixedBufferReader, amount: u64) Error!void {
19 if (fbr.buf.len - fbr.pos < amount) return error.EndOfBuffer;
20 fbr.pos += @intCast(amount);
21}
22
23pub inline fn readByte(fbr: *FixedBufferReader) Error!u8 {
24 if (fbr.pos >= fbr.buf.len) return error.EndOfBuffer;
25 defer fbr.pos += 1;
26 return fbr.buf[fbr.pos];
27}
28
29pub fn readByteSigned(fbr: *FixedBufferReader) Error!i8 {
30 return @bitCast(try fbr.readByte());
31}
32
33pub fn readInt(fbr: *FixedBufferReader, comptime T: type) Error!T {
34 const size = @divExact(@typeInfo(T).int.bits, 8);
35 if (fbr.buf.len - fbr.pos < size) return error.EndOfBuffer;
36 defer fbr.pos += size;
37 return std.mem.readInt(T, fbr.buf[fbr.pos..][0..size], fbr.endian);
38}
39
40pub fn readUleb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
41 return std.leb.readUleb128(T, fbr);
42}
43
44pub fn readIleb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
45 return std.leb.readIleb128(T, fbr);
46}
47
48pub fn readAddress(fbr: *FixedBufferReader, format: std.dwarf.Format) Error!u64 {
49 return switch (format) {
50 .@"32" => try fbr.readInt(u32),
51 .@"64" => try fbr.readInt(u64),
52 };
53}
54
55pub fn readBytes(fbr: *FixedBufferReader, len: usize) Error![]const u8 {
56 if (fbr.buf.len - fbr.pos < len) return error.EndOfBuffer;
57 defer fbr.pos += len;
58 return fbr.buf[fbr.pos..][0..len];
59}
60
61pub fn readBytesTo(fbr: *FixedBufferReader, comptime sentinel: u8) Error![:sentinel]const u8 {
62 const end = @call(.always_inline, std.mem.indexOfScalarPos, .{
63 u8,
64 fbr.buf,
65 fbr.pos,
66 sentinel,
67 }) orelse return error.EndOfBuffer;
68 defer fbr.pos = end + 1;
69 return fbr.buf[fbr.pos..end :sentinel];
70}
lib/std/debug/SelfInfo.zig+8-9
......@@ -1555,26 +1555,24 @@ pub fn unwindFrameDwarf(
15551555 if (!supports_unwinding) return error.UnsupportedCpuArchitecture;
15561556 if (context.pc == 0) return 0;
15571557
1558 const endian = di.endian;
1559
15581560 // Find the FDE and CIE
15591561 const cie, const fde = if (explicit_fde_offset) |fde_offset| blk: {
15601562 const dwarf_section: Dwarf.Section.Id = .eh_frame;
15611563 const frame_section = di.section(dwarf_section) orelse return error.MissingFDE;
15621564 if (fde_offset >= frame_section.len) return error.MissingFDE;
15631565
1564 var fbr: std.debug.FixedBufferReader = .{
1565 .buf = frame_section,
1566 .pos = fde_offset,
1567 .endian = di.endian,
1568 };
1566 var fbr: std.Io.Reader = .fixed(frame_section);
1567 fbr.seek = fde_offset;
15691568
1570 const fde_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section);
1569 const fde_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section, endian);
15711570 if (fde_entry_header.type != .fde) return error.MissingFDE;
15721571
15731572 const cie_offset = fde_entry_header.type.fde;
1574 try fbr.seekTo(cie_offset);
1573 fbr.seek = @intCast(cie_offset);
15751574
1576 fbr.endian = native_endian;
1577 const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section);
1575 const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section, endian);
15781576 if (cie_entry_header.type != .cie) return Dwarf.bad();
15791577
15801578 const cie = try Dwarf.CommonInformationEntry.parse(
......@@ -1617,6 +1615,7 @@ pub fn unwindFrameDwarf(
16171615 context.pc,
16181616 &cie,
16191617 &fde,
1618 endian,
16201619 ) catch |err| switch (err) {
16211620 error.MissingDebugInfo => {
16221621 // `.eh_frame_hdr` appears to be incomplete, so go ahead and populate `cie_map`