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;...@@ -14,7 +14,6 @@ const native_os = builtin.os.tag;
14const native_endian = native_arch.endian();14const native_endian = native_arch.endian();
15const Writer = std.io.Writer;15const Writer = std.io.Writer;
1616
17pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
18pub const Dwarf = @import("debug/Dwarf.zig");17pub const Dwarf = @import("debug/Dwarf.zig");
19pub const Pdb = @import("debug/Pdb.zig");18pub const Pdb = @import("debug/Pdb.zig");
20pub const SelfInfo = @import("debug/SelfInfo.zig");19pub const SelfInfo = @import("debug/SelfInfo.zig");
...@@ -1773,7 +1772,6 @@ pub inline fn inValgrind() bool {...@@ -1773,7 +1772,6 @@ pub inline fn inValgrind() bool {
17731772
1774test {1773test {
1775 _ = &Dwarf;1774 _ = &Dwarf;
1776 _ = &FixedBufferReader;
1777 _ = &Pdb;1775 _ = &Pdb;
1778 _ = &SelfInfo;1776 _ = &SelfInfo;
1779 _ = &dumpHex;1777 _ = &dumpHex;
lib/std/debug/Dwarf.zig+287-282
...@@ -25,8 +25,9 @@ const assert = std.debug.assert;...@@ -25,8 +25,9 @@ const assert = std.debug.assert;
25const cast = std.math.cast;25const cast = std.math.cast;
26const maxInt = std.math.maxInt;26const maxInt = std.math.maxInt;
27const Path = std.Build.Cache.Path;27const Path = std.Build.Cache.Path;
28const FixedBufferReader = std.debug.FixedBufferReader;
29const ArrayList = std.ArrayList;28const ArrayList = std.ArrayList;
29const Endian = std.builtin.Endian;
30const Reader = std.Io.Reader;
3031
31const Dwarf = @This();32const Dwarf = @This();
3233
...@@ -37,7 +38,7 @@ pub const call_frame = @import("Dwarf/call_frame.zig");...@@ -37,7 +38,7 @@ pub const call_frame = @import("Dwarf/call_frame.zig");
37/// Useful to temporarily enable while working on this file.38/// Useful to temporarily enable while working on this file.
38const debug_debug_mode = false;39const debug_debug_mode = false;
3940
40endian: std.builtin.Endian,41endian: Endian,
41sections: SectionArray = null_section_array,42sections: SectionArray = null_section_array,
42is_macho: bool,43is_macho: bool,
4344
...@@ -355,23 +356,23 @@ pub const ExceptionFrameHeader = struct {...@@ -355,23 +356,23 @@ pub const ExceptionFrameHeader = struct {
355 pc: usize,356 pc: usize,
356 cie: *CommonInformationEntry,357 cie: *CommonInformationEntry,
357 fde: *FrameDescriptionEntry,358 fde: *FrameDescriptionEntry,
359 endian: Endian,
358 ) !void {360 ) !void {
359 const entry_size = try entrySize(self.table_enc);361 const entry_size = try entrySize(self.table_enc);
360362
361 var left: usize = 0;363 var left: usize = 0;
362 var len: usize = self.fde_count;364 var len: usize = self.fde_count;
363365 var fbr: Reader = .fixed(self.entries);
364 var fbr: FixedBufferReader = .{ .buf = self.entries, .endian = native_endian };
365366
366 while (len > 1) {367 while (len > 1) {
367 const mid = left + len / 2;368 const mid = left + len / 2;
368369
369 fbr.pos = mid * entry_size;370 fbr.seek = mid * entry_size;
370 const pc_begin = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{371 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]),
372 .follow_indirect = true,373 .follow_indirect = true,
373 .data_rel_base = eh_frame_hdr_ptr,374 .data_rel_base = eh_frame_hdr_ptr,
374 }) orelse return bad();375 }, endian) orelse return bad();
375376
376 if (pc < pc_begin) {377 if (pc < pc_begin) {
377 len /= 2;378 len /= 2;
...@@ -383,39 +384,36 @@ pub const ExceptionFrameHeader = struct {...@@ -383,39 +384,36 @@ pub const ExceptionFrameHeader = struct {
383 }384 }
384385
385 if (len == 0) return missing();386 if (len == 0) return missing();
386 fbr.pos = left * entry_size;387 fbr.seek = left * entry_size;
387388
388 // Read past the pc_begin field of the entry389 // Read past the pc_begin field of the entry
389 _ = try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{390 _ = 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]),
391 .follow_indirect = true,392 .follow_indirect = true,
392 .data_rel_base = eh_frame_hdr_ptr,393 .data_rel_base = eh_frame_hdr_ptr,
393 }) orelse return bad();394 }, endian) orelse return bad();
394395
395 const fde_ptr = cast(usize, try readEhPointer(&fbr, self.table_enc, @sizeOf(usize), .{396 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]),
397 .follow_indirect = true,398 .follow_indirect = true,
398 .data_rel_base = eh_frame_hdr_ptr,399 .data_rel_base = eh_frame_hdr_ptr,
399 }) orelse return bad()) orelse return bad();400 }, endian) orelse return bad()) orelse return bad();
400401
401 if (fde_ptr < self.eh_frame_ptr) return bad();402 if (fde_ptr < self.eh_frame_ptr) return bad();
402403
403 const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0..eh_frame_len];404 const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0..eh_frame_len];
404405
405 const fde_offset = fde_ptr - self.eh_frame_ptr;406 const fde_offset = fde_ptr - self.eh_frame_ptr;
406 var eh_frame_fbr: FixedBufferReader = .{407 var eh_frame_fbr: Reader = .fixed(eh_frame);
407 .buf = eh_frame,408 eh_frame_fbr.seek = fde_offset;
408 .pos = fde_offset,
409 .endian = native_endian,
410 };
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);
413 if (fde_entry_header.type != .fde) return bad();411 if (fde_entry_header.type != .fde) return bad();
414412
415 // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable413 // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable
416 const cie_offset = fde_entry_header.type.fde;414 const cie_offset = fde_entry_header.type.fde;
417 try eh_frame_fbr.seekTo(cie_offset);415 eh_frame_fbr.seek = @intCast(cie_offset);
418 const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);416 const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame, endian);
419 if (cie_entry_header.type != .cie) return bad();417 if (cie_entry_header.type != .cie) return bad();
420418
421 cie.* = try CommonInformationEntry.parse(419 cie.* = try CommonInformationEntry.parse(
...@@ -426,7 +424,7 @@ pub const ExceptionFrameHeader = struct {...@@ -426,7 +424,7 @@ pub const ExceptionFrameHeader = struct {
426 .eh_frame,424 .eh_frame,
427 cie_entry_header.length_offset,425 cie_entry_header.length_offset,
428 @sizeOf(usize),426 @sizeOf(usize),
429 native_endian,427 endian,
430 );428 );
431429
432 fde.* = try FrameDescriptionEntry.parse(430 fde.* = try FrameDescriptionEntry.parse(
...@@ -435,7 +433,7 @@ pub const ExceptionFrameHeader = struct {...@@ -435,7 +433,7 @@ pub const ExceptionFrameHeader = struct {
435 true,433 true,
436 cie.*,434 cie.*,
437 @sizeOf(usize),435 @sizeOf(usize),
438 native_endian,436 endian,
439 );437 );
440438
441 if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return missing();439 if (pc < fde.pc_begin or pc >= fde.pc_begin + fde.pc_range) return missing();
...@@ -460,13 +458,18 @@ pub const EntryHeader = struct {...@@ -460,13 +458,18 @@ pub const EntryHeader = struct {
460 return self.entry_bytes.len + @as(u8, if (self.format == .@"64") 8 else 4);458 return self.entry_bytes.len + @as(u8, if (self.format == .@"64") 8 else 4);
461 }459 }
462460
463 /// Reads a header for either an FDE or a CIE, then advances the fbr to the position after the trailing structure.461 /// Reads a header for either an FDE or a CIE, then advances the fbr to the
464 /// `fbr` must be a FixedBufferReader backed by either the .eh_frame or .debug_frame sections.462 /// position after the trailing structure.
465 pub fn read(fbr: *FixedBufferReader, dwarf_section: Section.Id) !EntryHeader {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 {
466 assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);469 assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);
467470
468 const length_offset = fbr.pos;471 const length_offset = fbr.seek;
469 const unit_header = try readUnitHeader(fbr);472 const unit_header = try readUnitHeader(fbr, endian);
470 const unit_length = cast(usize, unit_header.unit_length) orelse return bad();473 const unit_length = cast(usize, unit_header.unit_length) orelse return bad();
471 if (unit_length == 0) return .{474 if (unit_length == 0) return .{
472 .length_offset = length_offset,475 .length_offset = length_offset,
...@@ -474,12 +477,12 @@ pub const EntryHeader = struct {...@@ -474,12 +477,12 @@ pub const EntryHeader = struct {
474 .type = .terminator,477 .type = .terminator,
475 .entry_bytes = &.{},478 .entry_bytes = &.{},
476 };479 };
477 const start_offset = fbr.pos;480 const start_offset = fbr.seek;
478 const end_offset = start_offset + unit_length;481 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);484 const id = try readAddress(fbr, unit_header.format, endian);
482 const entry_bytes = fbr.buf[fbr.pos..end_offset];485 const entry_bytes = fbr.buffer[fbr.seek..end_offset];
483 const cie_id: u64 = switch (dwarf_section) {486 const cie_id: u64 = switch (dwarf_section) {
484 .eh_frame => CommonInformationEntry.eh_id,487 .eh_frame => CommonInformationEntry.eh_id,
485 .debug_frame => switch (unit_header.format) {488 .debug_frame => switch (unit_header.format) {
...@@ -565,13 +568,13 @@ pub const CommonInformationEntry = struct {...@@ -565,13 +568,13 @@ pub const CommonInformationEntry = struct {
565 dwarf_section: Section.Id,568 dwarf_section: Section.Id,
566 length_offset: u64,569 length_offset: u64,
567 addr_size_bytes: u8,570 addr_size_bytes: u8,
568 endian: std.builtin.Endian,571 endian: Endian,
569 ) !CommonInformationEntry {572 ) !CommonInformationEntry {
570 if (addr_size_bytes > 8) return error.UnsupportedAddrSize;573 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();
575 switch (dwarf_section) {578 switch (dwarf_section) {
576 .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,579 .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
577 .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,580 .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
...@@ -582,9 +585,9 @@ pub const CommonInformationEntry = struct {...@@ -582,9 +585,9 @@ pub const CommonInformationEntry = struct {
582 var has_aug_data = false;585 var has_aug_data = false;
583586
584 var aug_str_len: usize = 0;587 var aug_str_len: usize = 0;
585 const aug_str_start = fbr.pos;588 const aug_str_start = fbr.seek;
586 var aug_byte = try fbr.readByte();589 var aug_byte = try fbr.takeByte();
587 while (aug_byte != 0) : (aug_byte = try fbr.readByte()) {590 while (aug_byte != 0) : (aug_byte = try fbr.takeByte()) {
588 switch (aug_byte) {591 switch (aug_byte) {
589 'z' => {592 'z' => {
590 if (aug_str_len != 0) return bad();593 if (aug_str_len != 0) return bad();
...@@ -592,7 +595,7 @@ pub const CommonInformationEntry = struct {...@@ -592,7 +595,7 @@ pub const CommonInformationEntry = struct {
592 },595 },
593 'e' => {596 'e' => {
594 if (has_aug_data or aug_str_len != 0) return bad();597 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();
596 has_eh_data = true;599 has_eh_data = true;
597 },600 },
598 else => if (has_eh_data) return bad(),601 else => if (has_eh_data) return bad(),
...@@ -603,15 +606,15 @@ pub const CommonInformationEntry = struct {...@@ -603,15 +606,15 @@ pub const CommonInformationEntry = struct {
603606
604 if (has_eh_data) {607 if (has_eh_data) {
605 // legacy data created by older versions of gcc - unsupported here608 // 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();
607 }610 }
608611
609 const address_size = if (version == 4) try fbr.readByte() else addr_size_bytes;612 const address_size = if (version == 4) try fbr.takeByte() else addr_size_bytes;
610 const segment_selector_size = if (version == 4) try fbr.readByte() else null;613 const segment_selector_size = if (version == 4) try fbr.takeByte() else null;
611614
612 const code_alignment_factor = try fbr.readUleb128(u32);615 const code_alignment_factor = try fbr.takeLeb128(u32);
613 const data_alignment_factor = try fbr.readIleb128(i32);616 const data_alignment_factor = try fbr.takeLeb128(i32);
614 const return_address_register = if (version == 1) try fbr.readByte() else try fbr.readUleb128(u8);617 const return_address_register = if (version == 1) try fbr.takeByte() else try fbr.takeLeb128(u8);
615618
616 var lsda_pointer_enc: u8 = EH.PE.omit;619 var lsda_pointer_enc: u8 = EH.PE.omit;
617 var personality_enc: ?u8 = null;620 var personality_enc: ?u8 = null;
...@@ -620,25 +623,25 @@ pub const CommonInformationEntry = struct {...@@ -620,25 +623,25 @@ pub const CommonInformationEntry = struct {
620623
621 var aug_data: []const u8 = &[_]u8{};624 var aug_data: []const u8 = &[_]u8{};
622 const aug_str = if (has_aug_data) blk: {625 const aug_str = if (has_aug_data) blk: {
623 const aug_data_len = try fbr.readUleb128(usize);626 const aug_data_len = try fbr.takeLeb128(usize);
624 const aug_data_start = fbr.pos;627 const aug_data_start = fbr.seek;
625 aug_data = cie_bytes[aug_data_start..][0..aug_data_len];628 aug_data = cie_bytes[aug_data_start..][0..aug_data_len];
626629
627 const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];630 const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];
628 for (aug_str[1..]) |byte| {631 for (aug_str[1..]) |byte| {
629 switch (byte) {632 switch (byte) {
630 'L' => {633 'L' => {
631 lsda_pointer_enc = try fbr.readByte();634 lsda_pointer_enc = try fbr.takeByte();
632 },635 },
633 'P' => {636 'P' => {
634 personality_enc = try fbr.readByte();637 personality_enc = try fbr.takeByte();
635 personality_routine_pointer = try readEhPointer(&fbr, personality_enc.?, addr_size_bytes, .{638 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),
637 .follow_indirect = is_runtime,640 .follow_indirect = is_runtime,
638 });641 }, endian);
639 },642 },
640 'R' => {643 'R' => {
641 fde_pointer_enc = try fbr.readByte();644 fde_pointer_enc = try fbr.takeByte();
642 },645 },
643 'S', 'B', 'G' => {},646 'S', 'B', 'G' => {},
644 else => return bad(),647 else => return bad(),
...@@ -646,11 +649,11 @@ pub const CommonInformationEntry = struct {...@@ -646,11 +649,11 @@ pub const CommonInformationEntry = struct {
646 }649 }
647650
648 // aug_data_len can include padding so the CIE ends on an address boundary651 // 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;
650 break :blk aug_str;653 break :blk aug_str;
651 } else &[_]u8{};654 } else &[_]u8{};
652655
653 const initial_instructions = cie_bytes[fbr.pos..];656 const initial_instructions = cie_bytes[fbr.seek..];
654 return .{657 return .{
655 .length_offset = length_offset,658 .length_offset = length_offset,
656 .version = version,659 .version = version,
...@@ -699,41 +702,41 @@ pub const FrameDescriptionEntry = struct {...@@ -699,41 +702,41 @@ pub const FrameDescriptionEntry = struct {
699 is_runtime: bool,702 is_runtime: bool,
700 cie: CommonInformationEntry,703 cie: CommonInformationEntry,
701 addr_size_bytes: u8,704 addr_size_bytes: u8,
702 endian: std.builtin.Endian,705 endian: Endian,
703 ) !FrameDescriptionEntry {706 ) !FrameDescriptionEntry {
704 if (addr_size_bytes > 8) return error.InvalidAddrSize;707 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
708 const pc_begin = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{711 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),
710 .follow_indirect = is_runtime,713 .follow_indirect = is_runtime,
711 }) orelse return bad();714 }, endian) orelse return bad();
712715
713 const pc_range = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{716 const pc_range = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
714 .pc_rel_base = 0,717 .pc_rel_base = 0,
715 .follow_indirect = false,718 .follow_indirect = false,
716 }) orelse return bad();719 }, endian) orelse return bad();
717720
718 var aug_data: []const u8 = &[_]u8{};721 var aug_data: []const u8 = &[_]u8{};
719 const lsda_pointer = if (cie.aug_str.len > 0) blk: {722 const lsda_pointer = if (cie.aug_str.len > 0) blk: {
720 const aug_data_len = try fbr.readUleb128(usize);723 const aug_data_len = try fbr.takeLeb128(usize);
721 const aug_data_start = fbr.pos;724 const aug_data_start = fbr.seek;
722 aug_data = fde_bytes[aug_data_start..][0..aug_data_len];725 aug_data = fde_bytes[aug_data_start..][0..aug_data_len];
723726
724 const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)727 const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)
725 try readEhPointer(&fbr, cie.lsda_pointer_enc, addr_size_bytes, .{728 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),
727 .follow_indirect = is_runtime,730 .follow_indirect = is_runtime,
728 })731 }, endian)
729 else732 else
730 null;733 null;
731734
732 fbr.pos = aug_data_start + aug_data_len;735 fbr.seek = aug_data_start + aug_data_len;
733 break :blk lsda_pointer;736 break :blk lsda_pointer;
734 } else null;737 } else null;
735738
736 const instructions = fde_bytes[fbr.pos..];739 const instructions = fde_bytes[fbr.seek..];
737 return .{740 return .{
738 .cie_length_offset = cie.length_offset,741 .cie_length_offset = cie.length_offset,
739 .pc_begin = pc_begin,742 .pc_begin = pc_begin,
...@@ -816,32 +819,37 @@ pub fn getSymbolName(di: *Dwarf, address: u64) ?[]const u8 {...@@ -816,32 +819,37 @@ pub fn getSymbolName(di: *Dwarf, address: u64) ?[]const u8 {
816pub const ScanError = error{819pub const ScanError = error{
817 InvalidDebugInfo,820 InvalidDebugInfo,
818 MissingDebugInfo,821 MissingDebugInfo,
819} || Allocator.Error || std.debug.FixedBufferReader.Error;822 ReadFailed,
823 EndOfStream,
824 Overflow,
825 StreamTooLong,
826} || Allocator.Error;
820827
821fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {828fn 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).?);
823 var this_unit_offset: u64 = 0;831 var this_unit_offset: u64 = 0;
824832
825 while (this_unit_offset < fbr.buf.len) {833 while (this_unit_offset < fbr.buffer.len) {
826 try fbr.seekTo(this_unit_offset);834 fbr.seek = @intCast(this_unit_offset);
827835
828 const unit_header = try readUnitHeader(&fbr);836 const unit_header = try readUnitHeader(&fbr, endian);
829 if (unit_header.unit_length == 0) return;837 if (unit_header.unit_length == 0) return;
830 const next_offset = unit_header.header_length + unit_header.unit_length;838 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);
833 if (version < 2 or version > 5) return bad();841 if (version < 2 or version > 5) return bad();
834842
835 var address_size: u8 = undefined;843 var address_size: u8 = undefined;
836 var debug_abbrev_offset: u64 = undefined;844 var debug_abbrev_offset: u64 = undefined;
837 if (version >= 5) {845 if (version >= 5) {
838 const unit_type = try fbr.readInt(u8);846 const unit_type = try fbr.takeByte();
839 if (unit_type != DW.UT.compile) return bad();847 if (unit_type != DW.UT.compile) return bad();
840 address_size = try fbr.readByte();848 address_size = try fbr.takeByte();
841 debug_abbrev_offset = try fbr.readAddress(unit_header.format);849 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
842 } else {850 } else {
843 debug_abbrev_offset = try fbr.readAddress(unit_header.format);851 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
844 address_size = try fbr.readByte();852 address_size = try fbr.takeByte();
845 }853 }
846 if (address_size != @sizeOf(usize)) return bad();854 if (address_size != @sizeOf(usize)) return bad();
847855
...@@ -882,15 +890,16 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {...@@ -882,15 +890,16 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
882 };890 };
883891
884 while (true) {892 while (true) {
885 fbr.pos = std.mem.indexOfNonePos(u8, fbr.buf, fbr.pos, &.{893 fbr.seek = std.mem.indexOfNonePos(u8, fbr.buffer, fbr.seek, &.{
886 zig_padding_abbrev_code, 0,894 zig_padding_abbrev_code, 0,
887 }) orelse fbr.buf.len;895 }) orelse fbr.buffer.len;
888 if (fbr.pos >= next_unit_pos) break;896 if (fbr.seek >= next_unit_pos) break;
889 var die_obj = (try parseDie(897 var die_obj = (try parseDie(
890 &fbr,898 &fbr,
891 attrs_bufs[0],899 attrs_bufs[0],
892 abbrev_table,900 abbrev_table,
893 unit_header.format,901 unit_header.format,
902 endian,
894 )) orelse continue;903 )) orelse continue;
895904
896 switch (die_obj.tag_id) {905 switch (die_obj.tag_id) {
...@@ -913,30 +922,32 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {...@@ -913,30 +922,32 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
913 if (this_die_obj.getAttr(AT.name)) |_| {922 if (this_die_obj.getAttr(AT.name)) |_| {
914 break :x try this_die_obj.getAttrString(di, AT.name, di.section(.debug_str), compile_unit);923 break :x try this_die_obj.getAttrString(di, AT.name, di.section(.debug_str), compile_unit);
915 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {924 } else if (this_die_obj.getAttr(AT.abstract_origin)) |_| {
916 const after_die_offset = fbr.pos;925 const after_die_offset = fbr.seek;
917 defer fbr.pos = after_die_offset;926 defer fbr.seek = after_die_offset;
918927
919 // Follow the DIE it points to and repeat928 // Follow the DIE it points to and repeat
920 const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin, this_unit_offset, next_offset);929 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);
922 this_die_obj = (try parseDie(931 this_die_obj = (try parseDie(
923 &fbr,932 &fbr,
924 attrs_bufs[2],933 attrs_bufs[2],
925 abbrev_table, // wrong abbrev table for different cu934 abbrev_table, // wrong abbrev table for different cu
926 unit_header.format,935 unit_header.format,
936 endian,
927 )) orelse return bad();937 )) orelse return bad();
928 } else if (this_die_obj.getAttr(AT.specification)) |_| {938 } else if (this_die_obj.getAttr(AT.specification)) |_| {
929 const after_die_offset = fbr.pos;939 const after_die_offset = fbr.seek;
930 defer fbr.pos = after_die_offset;940 defer fbr.seek = after_die_offset;
931941
932 // Follow the DIE it points to and repeat942 // Follow the DIE it points to and repeat
933 const ref_offset = try this_die_obj.getAttrRef(AT.specification, this_unit_offset, next_offset);943 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);
935 this_die_obj = (try parseDie(945 this_die_obj = (try parseDie(
936 &fbr,946 &fbr,
937 attrs_bufs[2],947 attrs_bufs[2],
938 abbrev_table, // wrong abbrev table for different cu948 abbrev_table, // wrong abbrev table for different cu
939 unit_header.format,949 unit_header.format,
950 endian,
940 )) orelse return bad();951 )) orelse return bad();
941 } else {952 } else {
942 break :x null;953 break :x null;
...@@ -1005,32 +1016,33 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {...@@ -1005,32 +1016,33 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
1005}1016}
10061017
1007fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {1018fn 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).?);
1009 var this_unit_offset: u64 = 0;1021 var this_unit_offset: u64 = 0;
10101022
1011 var attrs_buf = std.array_list.Managed(Die.Attr).init(allocator);1023 var attrs_buf = std.array_list.Managed(Die.Attr).init(allocator);
1012 defer attrs_buf.deinit();1024 defer attrs_buf.deinit();
10131025
1014 while (this_unit_offset < fbr.buf.len) {1026 while (this_unit_offset < fbr.buffer.len) {
1015 try fbr.seekTo(this_unit_offset);1027 fbr.seek = @intCast(this_unit_offset);
10161028
1017 const unit_header = try readUnitHeader(&fbr);1029 const unit_header = try readUnitHeader(&fbr, endian);
1018 if (unit_header.unit_length == 0) return;1030 if (unit_header.unit_length == 0) return;
1019 const next_offset = unit_header.header_length + unit_header.unit_length;1031 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);
1022 if (version < 2 or version > 5) return bad();1034 if (version < 2 or version > 5) return bad();
10231035
1024 var address_size: u8 = undefined;1036 var address_size: u8 = undefined;
1025 var debug_abbrev_offset: u64 = undefined;1037 var debug_abbrev_offset: u64 = undefined;
1026 if (version >= 5) {1038 if (version >= 5) {
1027 const unit_type = try fbr.readInt(u8);1039 const unit_type = try fbr.takeByte();
1028 if (unit_type != UT.compile) return bad();1040 if (unit_type != UT.compile) return bad();
1029 address_size = try fbr.readByte();1041 address_size = try fbr.takeByte();
1030 debug_abbrev_offset = try fbr.readAddress(unit_header.format);1042 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
1031 } else {1043 } else {
1032 debug_abbrev_offset = try fbr.readAddress(unit_header.format);1044 debug_abbrev_offset = try readAddress(&fbr, unit_header.format, endian);
1033 address_size = try fbr.readByte();1045 address_size = try fbr.takeByte();
1034 }1046 }
1035 if (address_size != @sizeOf(usize)) return bad();1047 if (address_size != @sizeOf(usize)) return bad();
10361048
...@@ -1047,6 +1059,7 @@ fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {...@@ -1047,6 +1059,7 @@ fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {
1047 attrs_buf.items,1059 attrs_buf.items,
1048 abbrev_table,1060 abbrev_table,
1049 unit_header.format,1061 unit_header.format,
1062 endian,
1050 )) orelse return bad();1063 )) orelse return bad();
10511064
1052 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();1065 if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad();
...@@ -1132,7 +1145,7 @@ const DebugRangeIterator = struct {...@@ -1132,7 +1145,7 @@ const DebugRangeIterator = struct {
1132 section_type: Section.Id,1145 section_type: Section.Id,
1133 di: *const Dwarf,1146 di: *const Dwarf,
1134 compile_unit: *const CompileUnit,1147 compile_unit: *const CompileUnit,
1135 fbr: FixedBufferReader,1148 fbr: Reader,
11361149
1137 pub fn init(ranges_value: *const FormValue, di: *const Dwarf, compile_unit: *const CompileUnit) !@This() {1150 pub fn init(ranges_value: *const FormValue, di: *const Dwarf, compile_unit: *const CompileUnit) !@This() {
1138 const section_type = if (compile_unit.version >= 5) Section.Id.debug_rnglists else Section.Id.debug_ranges;1151 const section_type = if (compile_unit.version >= 5) Section.Id.debug_rnglists else Section.Id.debug_ranges;
...@@ -1168,36 +1181,36 @@ const DebugRangeIterator = struct {...@@ -1168,36 +1181,36 @@ const DebugRangeIterator = struct {
1168 else => return err,1181 else => return err,
1169 };1182 };
11701183
1184 var fbr: Reader = .fixed(debug_ranges);
1185 fbr.seek = cast(usize, ranges_offset) orelse return bad();
1186
1171 return .{1187 return .{
1172 .base_address = base_address,1188 .base_address = base_address,
1173 .section_type = section_type,1189 .section_type = section_type,
1174 .di = di,1190 .di = di,
1175 .compile_unit = compile_unit,1191 .compile_unit = compile_unit,
1176 .fbr = .{1192 .fbr = fbr,
1177 .buf = debug_ranges,
1178 .pos = cast(usize, ranges_offset) orelse return bad(),
1179 .endian = di.endian,
1180 },
1181 };1193 };
1182 }1194 }
11831195
1184 // Returns the next range in the list, or null if the end was reached.1196 // Returns the next range in the list, or null if the end was reached.
1185 pub fn next(self: *@This()) !?PcRange {1197 pub fn next(self: *@This()) !?PcRange {
1198 const endian = self.di.endian;
1186 switch (self.section_type) {1199 switch (self.section_type) {
1187 .debug_rnglists => {1200 .debug_rnglists => {
1188 const kind = try self.fbr.readByte();1201 const kind = try self.fbr.takeByte();
1189 switch (kind) {1202 switch (kind) {
1190 RLE.end_of_list => return null,1203 RLE.end_of_list => return null,
1191 RLE.base_addressx => {1204 RLE.base_addressx => {
1192 const index = try self.fbr.readUleb128(usize);1205 const index = try self.fbr.takeLeb128(usize);
1193 self.base_address = try self.di.readDebugAddr(self.compile_unit.*, index);1206 self.base_address = try self.di.readDebugAddr(self.compile_unit.*, index);
1194 return try self.next();1207 return try self.next();
1195 },1208 },
1196 RLE.startx_endx => {1209 RLE.startx_endx => {
1197 const start_index = try self.fbr.readUleb128(usize);1210 const start_index = try self.fbr.takeLeb128(usize);
1198 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);1211 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);
1201 const end_addr = try self.di.readDebugAddr(self.compile_unit.*, end_index);1214 const end_addr = try self.di.readDebugAddr(self.compile_unit.*, end_index);
12021215
1203 return .{1216 return .{
...@@ -1206,10 +1219,10 @@ const DebugRangeIterator = struct {...@@ -1206,10 +1219,10 @@ const DebugRangeIterator = struct {
1206 };1219 };
1207 },1220 },
1208 RLE.startx_length => {1221 RLE.startx_length => {
1209 const start_index = try self.fbr.readUleb128(usize);1222 const start_index = try self.fbr.takeLeb128(usize);
1210 const start_addr = try self.di.readDebugAddr(self.compile_unit.*, start_index);1223 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);
1213 const end_addr = start_addr + len;1226 const end_addr = start_addr + len;
12141227
1215 return .{1228 return .{
...@@ -1218,8 +1231,8 @@ const DebugRangeIterator = struct {...@@ -1218,8 +1231,8 @@ const DebugRangeIterator = struct {
1218 };1231 };
1219 },1232 },
1220 RLE.offset_pair => {1233 RLE.offset_pair => {
1221 const start_addr = try self.fbr.readUleb128(usize);1234 const start_addr = try self.fbr.takeLeb128(usize);
1222 const end_addr = try self.fbr.readUleb128(usize);1235 const end_addr = try self.fbr.takeLeb128(usize);
12231236
1224 // This is the only kind that uses the base address1237 // This is the only kind that uses the base address
1225 return .{1238 return .{
...@@ -1228,12 +1241,12 @@ const DebugRangeIterator = struct {...@@ -1228,12 +1241,12 @@ const DebugRangeIterator = struct {
1228 };1241 };
1229 },1242 },
1230 RLE.base_address => {1243 RLE.base_address => {
1231 self.base_address = try self.fbr.readInt(usize);1244 self.base_address = try self.fbr.takeInt(usize, endian);
1232 return try self.next();1245 return try self.next();
1233 },1246 },
1234 RLE.start_end => {1247 RLE.start_end => {
1235 const start_addr = try self.fbr.readInt(usize);1248 const start_addr = try self.fbr.takeInt(usize, endian);
1236 const end_addr = try self.fbr.readInt(usize);1249 const end_addr = try self.fbr.takeInt(usize, endian);
12371250
1238 return .{1251 return .{
1239 .start = start_addr,1252 .start = start_addr,
...@@ -1241,8 +1254,8 @@ const DebugRangeIterator = struct {...@@ -1241,8 +1254,8 @@ const DebugRangeIterator = struct {
1241 };1254 };
1242 },1255 },
1243 RLE.start_length => {1256 RLE.start_length => {
1244 const start_addr = try self.fbr.readInt(usize);1257 const start_addr = try self.fbr.takeInt(usize, endian);
1245 const len = try self.fbr.readUleb128(usize);1258 const len = try self.fbr.takeLeb128(usize);
1246 const end_addr = start_addr + len;1259 const end_addr = start_addr + len;
12471260
1248 return .{1261 return .{
...@@ -1254,8 +1267,8 @@ const DebugRangeIterator = struct {...@@ -1254,8 +1267,8 @@ const DebugRangeIterator = struct {
1254 }1267 }
1255 },1268 },
1256 .debug_ranges => {1269 .debug_ranges => {
1257 const start_addr = try self.fbr.readInt(usize);1270 const start_addr = try self.fbr.takeInt(usize, endian);
1258 const end_addr = try self.fbr.readInt(usize);1271 const end_addr = try self.fbr.takeInt(usize, endian);
1259 if (start_addr == 0 and end_addr == 0) return null;1272 if (start_addr == 0 and end_addr == 0) return null;
12601273
1261 // This entry selects a new value for the base address1274 // This entry selects a new value for the base address
...@@ -1307,11 +1320,8 @@ fn getAbbrevTable(di: *Dwarf, allocator: Allocator, abbrev_offset: u64) !*const...@@ -1307,11 +1320,8 @@ fn getAbbrevTable(di: *Dwarf, allocator: Allocator, abbrev_offset: u64) !*const
1307}1320}
13081321
1309fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table {1322fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table {
1310 var fbr: FixedBufferReader = .{1323 var fbr: Reader = .fixed(di.section(.debug_abbrev).?);
1311 .buf = di.section(.debug_abbrev).?,1324 fbr.seek = cast(usize, offset) orelse return bad();
1312 .pos = cast(usize, offset) orelse return bad(),
1313 .endian = di.endian,
1314 };
13151325
1316 var abbrevs = std.array_list.Managed(Abbrev).init(allocator);1326 var abbrevs = std.array_list.Managed(Abbrev).init(allocator);
1317 defer {1327 defer {
...@@ -1325,20 +1335,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table...@@ -1325,20 +1335,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table
1325 defer attrs.deinit();1335 defer attrs.deinit();
13261336
1327 while (true) {1337 while (true) {
1328 const code = try fbr.readUleb128(u64);1338 const code = try fbr.takeLeb128(u64);
1329 if (code == 0) break;1339 if (code == 0) break;
1330 const tag_id = try fbr.readUleb128(u64);1340 const tag_id = try fbr.takeLeb128(u64);
1331 const has_children = (try fbr.readByte()) == DW.CHILDREN.yes;1341 const has_children = (try fbr.takeByte()) == DW.CHILDREN.yes;
13321342
1333 while (true) {1343 while (true) {
1334 const attr_id = try fbr.readUleb128(u64);1344 const attr_id = try fbr.takeLeb128(u64);
1335 const form_id = try fbr.readUleb128(u64);1345 const form_id = try fbr.takeLeb128(u64);
1336 if (attr_id == 0 and form_id == 0) break;1346 if (attr_id == 0 and form_id == 0) break;
1337 try attrs.append(.{1347 try attrs.append(.{
1338 .id = attr_id,1348 .id = attr_id,
1339 .form_id = form_id,1349 .form_id = form_id,
1340 .payload = switch (form_id) {1350 .payload = switch (form_id) {
1341 FORM.implicit_const => try fbr.readIleb128(i64),1351 FORM.implicit_const => try fbr.takeLeb128(i64),
1342 else => undefined,1352 else => undefined,
1343 },1353 },
1344 });1354 });
...@@ -1359,24 +1369,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table...@@ -1359,24 +1369,20 @@ fn parseAbbrevTable(di: *Dwarf, allocator: Allocator, offset: u64) !Abbrev.Table
1359}1369}
13601370
1361fn parseDie(1371fn parseDie(
1362 fbr: *FixedBufferReader,1372 fbr: *Reader,
1363 attrs_buf: []Die.Attr,1373 attrs_buf: []Die.Attr,
1364 abbrev_table: *const Abbrev.Table,1374 abbrev_table: *const Abbrev.Table,
1365 format: Format,1375 format: Format,
1376 endian: Endian,
1366) ScanError!?Die {1377) ScanError!?Die {
1367 const abbrev_code = try fbr.readUleb128(u64);1378 const abbrev_code = try fbr.takeLeb128(u64);
1368 if (abbrev_code == 0) return null;1379 if (abbrev_code == 0) return null;
1369 const table_entry = abbrev_table.get(abbrev_code) orelse return bad();1380 const table_entry = abbrev_table.get(abbrev_code) orelse return bad();
13701381
1371 const attrs = attrs_buf[0..table_entry.attrs.len];1382 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.* = .{
1373 .id = attr.id,1384 .id = attr.id,
1374 .value = try parseFormValue(1385 .value = try parseFormValue(fbr, attr.form_id, format, endian, attr.payload),
1375 fbr,
1376 attr.form_id,
1377 format,
1378 attr.payload,
1379 ),
1380 };1386 };
1381 return .{1387 return .{
1382 .tag_id = table_entry.tag_id,1388 .tag_id = table_entry.tag_id,
...@@ -1387,26 +1393,24 @@ fn parseDie(...@@ -1387,26 +1393,24 @@ fn parseDie(
13871393
1388/// Ensures that addresses in the returned LineTable are monotonically increasing.1394/// Ensures that addresses in the returned LineTable are monotonically increasing.
1389fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !CompileUnit.SrcLocCache {1395fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !CompileUnit.SrcLocCache {
1396 const endian = d.endian;
1390 const compile_unit_cwd = try compile_unit.die.getAttrString(d, AT.comp_dir, d.section(.debug_line_str), compile_unit.*);1397 const compile_unit_cwd = try compile_unit.die.getAttrString(d, AT.comp_dir, d.section(.debug_line_str), compile_unit.*);
1391 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);1398 const line_info_offset = try compile_unit.die.getAttrSecOffset(AT.stmt_list);
13921399
1393 var fbr: FixedBufferReader = .{1400 var fbr: Reader = .fixed(d.section(.debug_line).?);
1394 .buf = d.section(.debug_line).?,1401 fbr.seek = @intCast(line_info_offset);
1395 .endian = d.endian,
1396 };
1397 try fbr.seekTo(line_info_offset);
13981402
1399 const unit_header = try readUnitHeader(&fbr);1403 const unit_header = try readUnitHeader(&fbr, endian);
1400 if (unit_header.unit_length == 0) return missing();1404 if (unit_header.unit_length == 0) return missing();
14011405
1402 const next_offset = unit_header.header_length + unit_header.unit_length;1406 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);
1405 if (version < 2) return bad();1409 if (version < 2) return bad();
14061410
1407 const addr_size: u8, const seg_size: u8 = if (version >= 5) .{1411 const addr_size: u8, const seg_size: u8 = if (version >= 5) .{
1408 try fbr.readByte(),1412 try fbr.takeByte(),
1409 try fbr.readByte(),1413 try fbr.takeByte(),
1410 } else .{1414 } else .{
1411 switch (unit_header.format) {1415 switch (unit_header.format) {
1412 .@"32" => 4,1416 .@"32" => 4,
...@@ -1417,26 +1421,26 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1417,26 +1421,26 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1417 _ = addr_size;1421 _ = addr_size;
1418 _ = seg_size;1422 _ = seg_size;
14191423
1420 const prologue_length = try fbr.readAddress(unit_header.format);1424 const prologue_length = try readAddress(&fbr, unit_header.format, endian);
1421 const prog_start_offset = fbr.pos + prologue_length;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();
1424 if (minimum_instruction_length == 0) return bad();1428 if (minimum_instruction_length == 0) return bad();
14251429
1426 if (version >= 4) {1430 if (version >= 4) {
1427 const maximum_operations_per_instruction = try fbr.readByte();1431 const maximum_operations_per_instruction = try fbr.takeByte();
1428 _ = maximum_operations_per_instruction;1432 _ = maximum_operations_per_instruction;
1429 }1433 }
14301434
1431 const default_is_stmt = (try fbr.readByte()) != 0;1435 const default_is_stmt = (try fbr.takeByte()) != 0;
1432 const line_base = try fbr.readByteSigned();1436 const line_base = try fbr.takeByteSigned();
14331437
1434 const line_range = try fbr.readByte();1438 const line_range = try fbr.takeByte();
1435 if (line_range == 0) return bad();1439 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
1441 var directories: ArrayList(FileEntry) = .empty;1445 var directories: ArrayList(FileEntry) = .empty;
1442 defer directories.deinit(gpa);1446 defer directories.deinit(gpa);
...@@ -1447,17 +1451,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1447,17 +1451,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1447 try directories.append(gpa, .{ .path = compile_unit_cwd });1451 try directories.append(gpa, .{ .path = compile_unit_cwd });
14481452
1449 while (true) {1453 while (true) {
1450 const dir = try fbr.readBytesTo(0);1454 const dir = try fbr.takeSentinel(0);
1451 if (dir.len == 0) break;1455 if (dir.len == 0) break;
1452 try directories.append(gpa, .{ .path = dir });1456 try directories.append(gpa, .{ .path = dir });
1453 }1457 }
14541458
1455 while (true) {1459 while (true) {
1456 const file_name = try fbr.readBytesTo(0);1460 const file_name = try fbr.takeSentinel(0);
1457 if (file_name.len == 0) break;1461 if (file_name.len == 0) break;
1458 const dir_index = try fbr.readUleb128(u32);1462 const dir_index = try fbr.takeLeb128(u32);
1459 const mtime = try fbr.readUleb128(u64);1463 const mtime = try fbr.takeLeb128(u64);
1460 const size = try fbr.readUleb128(u64);1464 const size = try fbr.takeLeb128(u64);
1461 try file_entries.append(gpa, .{1465 try file_entries.append(gpa, .{
1462 .path = file_name,1466 .path = file_name,
1463 .dir_index = dir_index,1467 .dir_index = dir_index,
...@@ -1472,26 +1476,21 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1472,26 +1476,21 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1472 };1476 };
1473 {1477 {
1474 var dir_ent_fmt_buf: [10]FileEntFmt = undefined;1478 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();
1476 if (directory_entry_format_count > dir_ent_fmt_buf.len) return bad();1480 if (directory_entry_format_count > dir_ent_fmt_buf.len) return bad();
1477 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |*ent_fmt| {1481 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |*ent_fmt| {
1478 ent_fmt.* = .{1482 ent_fmt.* = .{
1479 .content_type_code = try fbr.readUleb128(u8),1483 .content_type_code = try fbr.takeLeb128(u8),
1480 .form_code = try fbr.readUleb128(u16),1484 .form_code = try fbr.takeLeb128(u16),
1481 };1485 };
1482 }1486 }
14831487
1484 const directories_count = try fbr.readUleb128(usize);1488 const directories_count = try fbr.takeLeb128(usize);
14851489
1486 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {1490 for (try directories.addManyAsSlice(gpa, directories_count)) |*e| {
1487 e.* = .{ .path = &.{} };1491 e.* = .{ .path = &.{} };
1488 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {1492 for (dir_ent_fmt_buf[0..directory_entry_format_count]) |ent_fmt| {
1489 const form_value = try parseFormValue(1493 const form_value = try parseFormValue(&fbr, ent_fmt.form_code, unit_header.format, endian, null);
1490 &fbr,
1491 ent_fmt.form_code,
1492 unit_header.format,
1493 null,
1494 );
1495 switch (ent_fmt.content_type_code) {1494 switch (ent_fmt.content_type_code) {
1496 DW.LNCT.path => e.path = try form_value.getString(d.*),1495 DW.LNCT.path => e.path = try form_value.getString(d.*),
1497 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1496 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) !...@@ -1508,27 +1507,22 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1508 }1507 }
15091508
1510 var file_ent_fmt_buf: [10]FileEntFmt = undefined;1509 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();
1512 if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad();1511 if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad();
1513 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {1512 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| {
1514 ent_fmt.* = .{1513 ent_fmt.* = .{
1515 .content_type_code = try fbr.readUleb128(u16),1514 .content_type_code = try fbr.takeLeb128(u16),
1516 .form_code = try fbr.readUleb128(u16),1515 .form_code = try fbr.takeLeb128(u16),
1517 };1516 };
1518 }1517 }
15191518
1520 const file_names_count = try fbr.readUleb128(usize);1519 const file_names_count = try fbr.takeLeb128(usize);
1521 try file_entries.ensureUnusedCapacity(gpa, file_names_count);1520 try file_entries.ensureUnusedCapacity(gpa, file_names_count);
15221521
1523 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {1522 for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| {
1524 e.* = .{ .path = &.{} };1523 e.* = .{ .path = &.{} };
1525 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {1524 for (file_ent_fmt_buf[0..file_name_entry_format_count]) |ent_fmt| {
1526 const form_value = try parseFormValue(1525 const form_value = try parseFormValue(&fbr, ent_fmt.form_code, unit_header.format, endian, null);
1527 &fbr,
1528 ent_fmt.form_code,
1529 unit_header.format,
1530 null,
1531 );
1532 switch (ent_fmt.content_type_code) {1526 switch (ent_fmt.content_type_code) {
1533 DW.LNCT.path => e.path = try form_value.getString(d.*),1527 DW.LNCT.path => e.path = try form_value.getString(d.*),
1534 DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32),1528 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) !...@@ -1548,17 +1542,17 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1548 var line_table: CompileUnit.SrcLocCache.LineTable = .{};1542 var line_table: CompileUnit.SrcLocCache.LineTable = .{};
1549 errdefer line_table.deinit(gpa);1543 errdefer line_table.deinit(gpa);
15501544
1551 try fbr.seekTo(prog_start_offset);1545 fbr.seek = @intCast(prog_start_offset);
15521546
1553 const next_unit_pos = line_info_offset + next_offset;1547 const next_unit_pos = line_info_offset + next_offset;
15541548
1555 while (fbr.pos < next_unit_pos) {1549 while (fbr.seek < next_unit_pos) {
1556 const opcode = try fbr.readByte();1550 const opcode = try fbr.takeByte();
15571551
1558 if (opcode == DW.LNS.extended_op) {1552 if (opcode == DW.LNS.extended_op) {
1559 const op_size = try fbr.readUleb128(u64);1553 const op_size = try fbr.takeLeb128(u64);
1560 if (op_size < 1) return bad();1554 if (op_size < 1) return bad();
1561 const sub_op = try fbr.readByte();1555 const sub_op = try fbr.takeByte();
1562 switch (sub_op) {1556 switch (sub_op) {
1563 DW.LNE.end_sequence => {1557 DW.LNE.end_sequence => {
1564 // The row being added here is an "end" address, meaning1558 // The row being added here is an "end" address, meaning
...@@ -1577,14 +1571,14 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1577,14 +1571,14 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1577 prog.reset();1571 prog.reset();
1578 },1572 },
1579 DW.LNE.set_address => {1573 DW.LNE.set_address => {
1580 const addr = try fbr.readInt(usize);1574 const addr = try fbr.takeInt(usize, endian);
1581 prog.address = addr;1575 prog.address = addr;
1582 },1576 },
1583 DW.LNE.define_file => {1577 DW.LNE.define_file => {
1584 const path = try fbr.readBytesTo(0);1578 const path = try fbr.takeSentinel(0);
1585 const dir_index = try fbr.readUleb128(u32);1579 const dir_index = try fbr.takeLeb128(u32);
1586 const mtime = try fbr.readUleb128(u64);1580 const mtime = try fbr.takeLeb128(u64);
1587 const size = try fbr.readUleb128(u64);1581 const size = try fbr.takeLeb128(u64);
1588 try file_entries.append(gpa, .{1582 try file_entries.append(gpa, .{
1589 .path = path,1583 .path = path,
1590 .dir_index = dir_index,1584 .dir_index = dir_index,
...@@ -1592,7 +1586,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1592,7 +1586,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1592 .size = size,1586 .size = size,
1593 });1587 });
1594 },1588 },
1595 else => try fbr.seekForward(op_size - 1),1589 else => try fbr.discardAll64(op_size - 1),
1596 }1590 }
1597 } else if (opcode >= opcode_base) {1591 } else if (opcode >= opcode_base) {
1598 // special opcodes1592 // special opcodes
...@@ -1610,19 +1604,19 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1610,19 +1604,19 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1610 prog.basic_block = false;1604 prog.basic_block = false;
1611 },1605 },
1612 DW.LNS.advance_pc => {1606 DW.LNS.advance_pc => {
1613 const arg = try fbr.readUleb128(usize);1607 const arg = try fbr.takeLeb128(usize);
1614 prog.address += arg * minimum_instruction_length;1608 prog.address += arg * minimum_instruction_length;
1615 },1609 },
1616 DW.LNS.advance_line => {1610 DW.LNS.advance_line => {
1617 const arg = try fbr.readIleb128(i64);1611 const arg = try fbr.takeLeb128(i64);
1618 prog.line += arg;1612 prog.line += arg;
1619 },1613 },
1620 DW.LNS.set_file => {1614 DW.LNS.set_file => {
1621 const arg = try fbr.readUleb128(usize);1615 const arg = try fbr.takeLeb128(usize);
1622 prog.file = arg;1616 prog.file = arg;
1623 },1617 },
1624 DW.LNS.set_column => {1618 DW.LNS.set_column => {
1625 const arg = try fbr.readUleb128(u64);1619 const arg = try fbr.takeLeb128(u64);
1626 prog.column = arg;1620 prog.column = arg;
1627 },1621 },
1628 DW.LNS.negate_stmt => {1622 DW.LNS.negate_stmt => {
...@@ -1636,13 +1630,13 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !...@@ -1636,13 +1630,13 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
1636 prog.address += inc_addr;1630 prog.address += inc_addr;
1637 },1631 },
1638 DW.LNS.fixed_advance_pc => {1632 DW.LNS.fixed_advance_pc => {
1639 const arg = try fbr.readInt(u16);1633 const arg = try fbr.takeInt(u16, endian);
1640 prog.address += arg;1634 prog.address += arg;
1641 },1635 },
1642 DW.LNS.set_prologue_end => {},1636 DW.LNS.set_prologue_end => {},
1643 else => {1637 else => {
1644 if (opcode - 1 >= standard_opcode_lengths.len) return bad();1638 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]);
1646 },1640 },
1647 }1641 }
1648 }1642 }
...@@ -1735,38 +1729,40 @@ fn readDebugAddr(di: Dwarf, compile_unit: CompileUnit, index: u64) !u64 {...@@ -1735,38 +1729,40 @@ fn readDebugAddr(di: Dwarf, compile_unit: CompileUnit, index: u64) !u64 {
1735///1729///
1736/// See also `scanCieFdeInfo`.1730/// See also `scanCieFdeInfo`.
1737pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {1731pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
1732 const endian = di.endian;
1733
1738 if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {1734 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();
1742 if (version != 1) break :blk;1738 if (version != 1) break :blk;
17431739
1744 const eh_frame_ptr_enc = try fbr.readByte();1740 const eh_frame_ptr_enc = try fbr.takeByte();
1745 if (eh_frame_ptr_enc == EH.PE.omit) break :blk;1741 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();
1747 if (fde_count_enc == EH.PE.omit) break :blk;1743 if (fde_count_enc == EH.PE.omit) break :blk;
1748 const table_enc = try fbr.readByte();1744 const table_enc = try fbr.takeByte();
1749 if (table_enc == EH.PE.omit) break :blk;1745 if (table_enc == EH.PE.omit) break :blk;
17501746
1751 const eh_frame_ptr = cast(usize, try readEhPointer(&fbr, eh_frame_ptr_enc, @sizeOf(usize), .{1747 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]),
1753 .follow_indirect = true,1749 .follow_indirect = true,
1754 }) orelse return bad()) orelse return bad();1750 }, endian) orelse return bad()) orelse return bad();
17551751
1756 const fde_count = cast(usize, try readEhPointer(&fbr, fde_count_enc, @sizeOf(usize), .{1752 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]),
1758 .follow_indirect = true,1754 .follow_indirect = true,
1759 }) orelse return bad()) orelse return bad();1755 }, endian) orelse return bad()) orelse return bad();
17601756
1761 const entry_size = try ExceptionFrameHeader.entrySize(table_enc);1757 const entry_size = try ExceptionFrameHeader.entrySize(table_enc);
1762 const entries_len = fde_count * entry_size;1758 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
1765 di.eh_frame_hdr = .{1761 di.eh_frame_hdr = .{
1766 .eh_frame_ptr = eh_frame_ptr,1762 .eh_frame_ptr = eh_frame_ptr,
1767 .table_enc = table_enc,1763 .table_enc = table_enc,
1768 .fde_count = fde_count,1764 .fde_count = fde_count,
1769 .entries = eh_frame_hdr[fbr.pos..][0..entries_len],1765 .entries = eh_frame_hdr[fbr.seek..][0..entries_len],
1770 };1766 };
17711767
1772 // No need to scan .eh_frame, we have a binary search table already1768 // 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)...@@ -1779,12 +1775,13 @@ pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize)
1779/// Scan `.eh_frame` and `.debug_frame` and build a sorted list of FDEs for binary searching during1775/// Scan `.eh_frame` and `.debug_frame` and build a sorted list of FDEs for binary searching during
1780/// unwinding.1776/// unwinding.
1781pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {1777pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
1778 const endian = di.endian;
1782 const frame_sections = [2]Section.Id{ .eh_frame, .debug_frame };1779 const frame_sections = [2]Section.Id{ .eh_frame, .debug_frame };
1783 for (frame_sections) |frame_section| {1780 for (frame_sections) |frame_section| {
1784 if (di.section(frame_section)) |section_data| {1781 if (di.section(frame_section)) |section_data| {
1785 var fbr: FixedBufferReader = .{ .buf = section_data, .endian = di.endian };1782 var fbr: Reader = .fixed(section_data);
1786 while (fbr.pos < fbr.buf.len) {1783 while (fbr.seek < fbr.buffer.len) {
1787 const entry_header = try EntryHeader.read(&fbr, frame_section);1784 const entry_header = try EntryHeader.read(&fbr, frame_section, endian);
1788 switch (entry_header.type) {1785 switch (entry_header.type) {
1789 .cie => {1786 .cie => {
1790 const cie = try CommonInformationEntry.parse(1787 const cie = try CommonInformationEntry.parse(
...@@ -1826,68 +1823,60 @@ pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !vo...@@ -1826,68 +1823,60 @@ pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !vo
1826}1823}
18271824
1828fn parseFormValue(1825fn parseFormValue(
1829 fbr: *FixedBufferReader,1826 r: *Reader,
1830 form_id: u64,1827 form_id: u64,
1831 format: Format,1828 format: Format,
1829 endian: Endian,
1832 implicit_const: ?i64,1830 implicit_const: ?i64,
1833) ScanError!FormValue {1831) ScanError!FormValue {
1834 return switch (form_id) {1832 return switch (form_id) {
1835 FORM.addr => .{ .addr = try fbr.readAddress(switch (@bitSizeOf(usize)) {1833 // DWARF5.pdf page 213: the size of this value is encoded in the
1836 32 => .@"32",1834 // compilation unit header as address size.
1837 64 => .@"64",1835 FORM.addr => .{ .addr = try readAddress(r, nativeFormat(), endian) },
1838 else => @compileError("unsupported @sizeOf(usize)"),1836 FORM.addrx1 => .{ .addrx = try r.takeByte() },
1839 }) },1837 FORM.addrx2 => .{ .addrx = try r.takeInt(u16, endian) },
1840 FORM.addrx1 => .{ .addrx = try fbr.readInt(u8) },1838 FORM.addrx3 => .{ .addrx = try r.takeInt(u24, endian) },
1841 FORM.addrx2 => .{ .addrx = try fbr.readInt(u16) },1839 FORM.addrx4 => .{ .addrx = try r.takeInt(u32, endian) },
1842 FORM.addrx3 => .{ .addrx = try fbr.readInt(u24) },1840 FORM.addrx => .{ .addrx = try r.takeLeb128(usize) },
1843 FORM.addrx4 => .{ .addrx = try fbr.readInt(u32) },1841
1844 FORM.addrx => .{ .addrx = try fbr.readUleb128(usize) },1842 FORM.block1 => .{ .block = try r.take(try r.takeByte()) },
18451843 FORM.block2 => .{ .block = try r.take(try r.takeInt(u16, endian)) },
1846 FORM.block1,1844 FORM.block4 => .{ .block = try r.take(try r.takeInt(u32, endian)) },
1847 FORM.block2,1845 FORM.block => .{ .block = try r.take(try r.takeLeb128(usize)) },
1848 FORM.block4,1846
1849 FORM.block,1847 FORM.data1 => .{ .udata = try r.takeByte() },
1850 => .{ .block = try fbr.readBytes(switch (form_id) {1848 FORM.data2 => .{ .udata = try r.takeInt(u16, endian) },
1851 FORM.block1 => try fbr.readInt(u8),1849 FORM.data4 => .{ .udata = try r.takeInt(u32, endian) },
1852 FORM.block2 => try fbr.readInt(u16),1850 FORM.data8 => .{ .udata = try r.takeInt(u64, endian) },
1853 FORM.block4 => try fbr.readInt(u32),1851 FORM.data16 => .{ .data16 = try r.takeArray(16) },
1854 FORM.block => try fbr.readUleb128(usize),1852 FORM.udata => .{ .udata = try r.takeLeb128(u64) },
1855 else => unreachable,1853 FORM.sdata => .{ .sdata = try r.takeLeb128(i64) },
1856 }) },1854 FORM.exprloc => .{ .exprloc = try r.take(try r.takeLeb128(usize)) },
18571855 FORM.flag => .{ .flag = (try r.takeByte()) != 0 },
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 },
1867 FORM.flag_present => .{ .flag = true },1856 FORM.flag_present => .{ .flag = true },
1868 FORM.sec_offset => .{ .sec_offset = try fbr.readAddress(format) },1857 FORM.sec_offset => .{ .sec_offset = try readAddress(r, format, endian) },
18691858
1870 FORM.ref1 => .{ .ref = try fbr.readInt(u8) },1859 FORM.ref1 => .{ .ref = try r.takeByte() },
1871 FORM.ref2 => .{ .ref = try fbr.readInt(u16) },1860 FORM.ref2 => .{ .ref = try r.takeInt(u16, endian) },
1872 FORM.ref4 => .{ .ref = try fbr.readInt(u32) },1861 FORM.ref4 => .{ .ref = try r.takeInt(u32, endian) },
1873 FORM.ref8 => .{ .ref = try fbr.readInt(u64) },1862 FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) },
1874 FORM.ref_udata => .{ .ref = try fbr.readUleb128(u64) },1863 FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) },
18751864
1876 FORM.ref_addr => .{ .ref_addr = try fbr.readAddress(format) },1865 FORM.ref_addr => .{ .ref_addr = try readAddress(r, format, endian) },
1877 FORM.ref_sig8 => .{ .ref = try fbr.readInt(u64) },1866 FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) },
18781867
1879 FORM.string => .{ .string = try fbr.readBytesTo(0) },1868 FORM.string => .{ .string = try r.takeSentinel(0) },
1880 FORM.strp => .{ .strp = try fbr.readAddress(format) },1869 FORM.strp => .{ .strp = try readAddress(r, format, endian) },
1881 FORM.strx1 => .{ .strx = try fbr.readInt(u8) },1870 FORM.strx1 => .{ .strx = try r.takeByte() },
1882 FORM.strx2 => .{ .strx = try fbr.readInt(u16) },1871 FORM.strx2 => .{ .strx = try r.takeInt(u16, endian) },
1883 FORM.strx3 => .{ .strx = try fbr.readInt(u24) },1872 FORM.strx3 => .{ .strx = try r.takeInt(u24, endian) },
1884 FORM.strx4 => .{ .strx = try fbr.readInt(u32) },1873 FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) },
1885 FORM.strx => .{ .strx = try fbr.readUleb128(usize) },1874 FORM.strx => .{ .strx = try r.takeLeb128(usize) },
1886 FORM.line_strp => .{ .line_strp = try fbr.readAddress(format) },1875 FORM.line_strp => .{ .line_strp = try readAddress(r, format, endian) },
1887 FORM.indirect => parseFormValue(fbr, try fbr.readUleb128(u64), format, implicit_const),1876 FORM.indirect => parseFormValue(r, try r.takeLeb128(u64), format, endian, implicit_const),
1888 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },1877 FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() },
1889 FORM.loclistx => .{ .loclistx = try fbr.readUleb128(u64) },1878 FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) },
1890 FORM.rnglistx => .{ .rnglistx = try fbr.readUleb128(u64) },1879 FORM.rnglistx => .{ .rnglistx = try r.takeLeb128(u64) },
1891 else => {1880 else => {
1892 //debug.print("unrecognized form id: {x}\n", .{form_id});1881 //debug.print("unrecognized form id: {x}\n", .{form_id});
1893 return bad();1882 return bad();
...@@ -1957,8 +1946,8 @@ const UnitHeader = struct {...@@ -1957,8 +1946,8 @@ const UnitHeader = struct {
1957 unit_length: u64,1946 unit_length: u64,
1958};1947};
19591948
1960fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {1949fn readUnitHeader(r: *Reader, endian: Endian) ScanError!UnitHeader {
1961 return switch (try fbr.readInt(u32)) {1950 return switch (try r.takeInt(u32, endian)) {
1962 0...0xfffffff0 - 1 => |unit_length| .{1951 0...0xfffffff0 - 1 => |unit_length| .{
1963 .format = .@"32",1952 .format = .@"32",
1964 .header_length = 4,1953 .header_length = 4,
...@@ -1968,7 +1957,7 @@ fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {...@@ -1968,7 +1957,7 @@ fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {
1968 0xffffffff => .{1957 0xffffffff => .{
1969 .format = .@"64",1958 .format = .@"64",
1970 .header_length = 12,1959 .header_length = 12,
1971 .unit_length = try fbr.readInt(u64),1960 .unit_length = try r.takeInt(u64, endian),
1972 },1961 },
1973 };1962 };
1974}1963}
...@@ -2026,7 +2015,8 @@ const EhPointerContext = struct {...@@ -2026,7 +2015,8 @@ const EhPointerContext = struct {
2026 text_rel_base: ?u64 = null,2015 text_rel_base: ?u64 = null,
2027 function_rel_base: ?u64 = null,2016 function_rel_base: ?u64 = null,
2028};2017};
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 {
2030 if (enc == EH.PE.omit) return null;2020 if (enc == EH.PE.omit) return null;
20312021
2032 const value: union(enum) {2022 const value: union(enum) {
...@@ -2035,20 +2025,20 @@ fn readEhPointer(fbr: *FixedBufferReader, enc: u8, addr_size_bytes: u8, ctx: EhP...@@ -2035,20 +2025,20 @@ fn readEhPointer(fbr: *FixedBufferReader, enc: u8, addr_size_bytes: u8, ctx: EhP
2035 } = switch (enc & EH.PE.type_mask) {2025 } = switch (enc & EH.PE.type_mask) {
2036 EH.PE.absptr => .{2026 EH.PE.absptr => .{
2037 .unsigned = switch (addr_size_bytes) {2027 .unsigned = switch (addr_size_bytes) {
2038 2 => try fbr.readInt(u16),2028 2 => try fbr.takeInt(u16, endian),
2039 4 => try fbr.readInt(u32),2029 4 => try fbr.takeInt(u32, endian),
2040 8 => try fbr.readInt(u64),2030 8 => try fbr.takeInt(u64, endian),
2041 else => return error.InvalidAddrSize,2031 else => return error.InvalidAddrSize,
2042 },2032 },
2043 },2033 },
2044 EH.PE.uleb128 => .{ .unsigned = try fbr.readUleb128(u64) },2034 EH.PE.uleb128 => .{ .unsigned = try fbr.takeLeb128(u64) },
2045 EH.PE.udata2 => .{ .unsigned = try fbr.readInt(u16) },2035 EH.PE.udata2 => .{ .unsigned = try fbr.takeInt(u16, endian) },
2046 EH.PE.udata4 => .{ .unsigned = try fbr.readInt(u32) },2036 EH.PE.udata4 => .{ .unsigned = try fbr.takeInt(u32, endian) },
2047 EH.PE.udata8 => .{ .unsigned = try fbr.readInt(u64) },2037 EH.PE.udata8 => .{ .unsigned = try fbr.takeInt(u64, endian) },
2048 EH.PE.sleb128 => .{ .signed = try fbr.readIleb128(i64) },2038 EH.PE.sleb128 => .{ .signed = try fbr.takeLeb128(i64) },
2049 EH.PE.sdata2 => .{ .signed = try fbr.readInt(i16) },2039 EH.PE.sdata2 => .{ .signed = try fbr.takeInt(i16, endian) },
2050 EH.PE.sdata4 => .{ .signed = try fbr.readInt(i32) },2040 EH.PE.sdata4 => .{ .signed = try fbr.takeInt(i32, endian) },
2051 EH.PE.sdata8 => .{ .signed = try fbr.readInt(i64) },2041 EH.PE.sdata8 => .{ .signed = try fbr.takeInt(i64, endian) },
2052 else => return bad(),2042 else => return bad(),
2053 };2043 };
20542044
...@@ -2156,7 +2146,7 @@ pub const ElfModule = struct {...@@ -2156,7 +2146,7 @@ pub const ElfModule = struct {
2156 if (!mem.eql(u8, hdr.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;2146 if (!mem.eql(u8, hdr.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
2157 if (hdr.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;2147 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]) {
2160 elf.ELFDATA2LSB => .little,2150 elf.ELFDATA2LSB => .little,
2161 elf.ELFDATA2MSB => .big,2151 elf.ELFDATA2MSB => .big,
2162 else => return error.InvalidElfEndian,2152 else => return error.InvalidElfEndian,
...@@ -2195,7 +2185,7 @@ pub const ElfModule = struct {...@@ -2195,7 +2185,7 @@ pub const ElfModule = struct {
2195 const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);2185 const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);
2196 const crc_offset = mem.alignForward(usize, debug_filename.len + 1, 4);2186 const crc_offset = mem.alignForward(usize, debug_filename.len + 1, 4);
2197 const crc_bytes = gnu_debuglink[crc_offset..][0..4];2187 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);
2199 separate_debug_filename = debug_filename;2189 separate_debug_filename = debug_filename;
2200 continue;2190 continue;
2201 }2191 }
...@@ -2209,7 +2199,7 @@ pub const ElfModule = struct {...@@ -2209,7 +2199,7 @@ pub const ElfModule = struct {
22092199
2210 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);2200 const section_bytes = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
2211 sections[section_index.?] = if ((shdr.sh_flags & elf.SHF_COMPRESSED) > 0) blk: {2201 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);
2213 const chdr = section_reader.takeStruct(elf.Chdr, endian) catch continue;2203 const chdr = section_reader.takeStruct(elf.Chdr, endian) catch continue;
2214 if (chdr.ch_type != .ZLIB) continue;2204 if (chdr.ch_type != .ZLIB) continue;
22152205
...@@ -2452,3 +2442,18 @@ pub fn chopSlice(ptr: []const u8, offset: u64, size: u64) error{Overflow}![]cons...@@ -2452,3 +2442,18 @@ pub fn chopSlice(ptr: []const u8, offset: u64, size: u64) error{Overflow}![]cons
2452 const end = start + (cast(usize, size) orelse return error.Overflow);2442 const end = start + (cast(usize, size) orelse return error.Overflow);
2453 return ptr[start..end];2443 return ptr[start..end];
2454}2444}
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(...@@ -1555,26 +1555,24 @@ pub fn unwindFrameDwarf(
1555 if (!supports_unwinding) return error.UnsupportedCpuArchitecture;1555 if (!supports_unwinding) return error.UnsupportedCpuArchitecture;
1556 if (context.pc == 0) return 0;1556 if (context.pc == 0) return 0;
15571557
1558 const endian = di.endian;
1559
1558 // Find the FDE and CIE1560 // Find the FDE and CIE
1559 const cie, const fde = if (explicit_fde_offset) |fde_offset| blk: {1561 const cie, const fde = if (explicit_fde_offset) |fde_offset| blk: {
1560 const dwarf_section: Dwarf.Section.Id = .eh_frame;1562 const dwarf_section: Dwarf.Section.Id = .eh_frame;
1561 const frame_section = di.section(dwarf_section) orelse return error.MissingFDE;1563 const frame_section = di.section(dwarf_section) orelse return error.MissingFDE;
1562 if (fde_offset >= frame_section.len) return error.MissingFDE;1564 if (fde_offset >= frame_section.len) return error.MissingFDE;
15631565
1564 var fbr: std.debug.FixedBufferReader = .{1566 var fbr: std.Io.Reader = .fixed(frame_section);
1565 .buf = frame_section,1567 fbr.seek = fde_offset;
1566 .pos = fde_offset,
1567 .endian = di.endian,
1568 };
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);
1571 if (fde_entry_header.type != .fde) return error.MissingFDE;1570 if (fde_entry_header.type != .fde) return error.MissingFDE;
15721571
1573 const cie_offset = fde_entry_header.type.fde;1572 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;1575 const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section, endian);
1577 const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section);
1578 if (cie_entry_header.type != .cie) return Dwarf.bad();1576 if (cie_entry_header.type != .cie) return Dwarf.bad();
15791577
1580 const cie = try Dwarf.CommonInformationEntry.parse(1578 const cie = try Dwarf.CommonInformationEntry.parse(
...@@ -1617,6 +1615,7 @@ pub fn unwindFrameDwarf(...@@ -1617,6 +1615,7 @@ pub fn unwindFrameDwarf(
1617 context.pc,1615 context.pc,
1618 &cie,1616 &cie,
1619 &fde,1617 &fde,
1618 endian,
1620 ) catch |err| switch (err) {1619 ) catch |err| switch (err) {
1621 error.MissingDebugInfo => {1620 error.MissingDebugInfo => {
1622 // `.eh_frame_hdr` appears to be incomplete, so go ahead and populate `cie_map`1621 // `.eh_frame_hdr` appears to be incomplete, so go ahead and populate `cie_map`