| ... | @@ -60,14 +60,20 @@ globals_lookup: []i64 = undefined, | ... | @@ -60,14 +60,20 @@ globals_lookup: []i64 = undefined, |
| 60 | /// Can be undefined as set together with in_symtab. | 60 | /// Can be undefined as set together with in_symtab. |
| 61 | relocs_lookup: []RelocEntry = undefined, | 61 | relocs_lookup: []RelocEntry = undefined, |
| 62 | | 62 | |
| | 63 | /// All relocations sorted and flatened. |
| | 64 | relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{}, |
| | 65 | /// Beginning index to the relocations array for each input section |
| | 66 | /// defined within this Object file. |
| | 67 | section_relocs_lookup: std.ArrayListUnmanaged(u32) = .{}, |
| | 68 | |
| 63 | atoms: std.ArrayListUnmanaged(AtomIndex) = .{}, | 69 | atoms: std.ArrayListUnmanaged(AtomIndex) = .{}, |
| 64 | exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{}, | 70 | exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{}, |
| 65 | | 71 | |
| 66 | eh_frame_sect: ?macho.section_64 = null, | 72 | eh_frame_sect_id: ?u8 = null, |
| 67 | eh_frame_relocs_lookup: std.AutoArrayHashMapUnmanaged(u32, Record) = .{}, | 73 | eh_frame_relocs_lookup: std.AutoArrayHashMapUnmanaged(u32, Record) = .{}, |
| 68 | eh_frame_records_lookup: std.AutoArrayHashMapUnmanaged(AtomIndex, u32) = .{}, | 74 | eh_frame_records_lookup: std.AutoArrayHashMapUnmanaged(AtomIndex, u32) = .{}, |
| 69 | | 75 | |
| 70 | unwind_info_sect: ?macho.section_64 = null, | 76 | unwind_info_sect_id: ?u8 = null, |
| 71 | unwind_relocs_lookup: []Record = undefined, | 77 | unwind_relocs_lookup: []Record = undefined, |
| 72 | unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{}, | 78 | unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{}, |
| 73 | | 79 | |
| ... | @@ -100,6 +106,8 @@ pub fn deinit(self: *Object, gpa: Allocator) void { | ... | @@ -100,6 +106,8 @@ pub fn deinit(self: *Object, gpa: Allocator) void { |
| 100 | gpa.free(self.unwind_relocs_lookup); | 106 | gpa.free(self.unwind_relocs_lookup); |
| 101 | } | 107 | } |
| 102 | self.unwind_records_lookup.deinit(gpa); | 108 | self.unwind_records_lookup.deinit(gpa); |
| | 109 | self.relocations.deinit(gpa); |
| | 110 | self.section_relocs_lookup.deinit(gpa); |
| 103 | } | 111 | } |
| 104 | | 112 | |
| 105 | pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void { | 113 | pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void { |
| ... | @@ -137,15 +145,18 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -137,15 +145,18 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 137 | .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds], | 145 | .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds], |
| 138 | }; | 146 | }; |
| 139 | const nsects = self.getSourceSections().len; | 147 | const nsects = self.getSourceSections().len; |
| | 148 | |
| | 149 | // Prepopulate relocations per section lookup table. |
| | 150 | try self.section_relocs_lookup.resize(allocator, nsects); |
| | 151 | mem.set(u32, self.section_relocs_lookup.items, 0); |
| | 152 | |
| | 153 | // Parse symtab. |
| 140 | const symtab = while (it.next()) |cmd| switch (cmd.cmd()) { | 154 | const symtab = while (it.next()) |cmd| switch (cmd.cmd()) { |
| 141 | .SYMTAB => break cmd.cast(macho.symtab_command).?, | 155 | .SYMTAB => break cmd.cast(macho.symtab_command).?, |
| 142 | else => {}, | 156 | else => {}, |
| 143 | } else return; | 157 | } else return; |
| 144 | | 158 | |
| 145 | self.in_symtab = @ptrCast( | 159 | self.in_symtab = @ptrCast([*]align(1) const macho.nlist_64, self.contents.ptr + symtab.symoff)[0..symtab.nsyms]; |
| 146 | [*]const macho.nlist_64, | | |
| 147 | @alignCast(@alignOf(macho.nlist_64), &self.contents[symtab.symoff]), | | |
| 148 | )[0..symtab.nsyms]; | | |
| 149 | self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize]; | 160 | self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize]; |
| 150 | | 161 | |
| 151 | self.symtab = try allocator.alloc(macho.nlist_64, self.in_symtab.?.len + nsects); | 162 | self.symtab = try allocator.alloc(macho.nlist_64, self.in_symtab.?.len + nsects); |
| ... | @@ -212,10 +223,10 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) | ... | @@ -212,10 +223,10 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) |
| 212 | } | 223 | } |
| 213 | | 224 | |
| 214 | // Parse __TEXT,__eh_frame header if one exists | 225 | // Parse __TEXT,__eh_frame header if one exists |
| 215 | self.eh_frame_sect = self.getSourceSectionByName("__TEXT", "__eh_frame"); | 226 | self.eh_frame_sect_id = self.getSourceSectionIndexByName("__TEXT", "__eh_frame"); |
| 216 | | 227 | |
| 217 | // Parse __LD,__compact_unwind header if one exists | 228 | // Parse __LD,__compact_unwind header if one exists |
| 218 | self.unwind_info_sect = self.getSourceSectionByName("__LD", "__compact_unwind"); | 229 | self.unwind_info_sect_id = self.getSourceSectionIndexByName("__LD", "__compact_unwind"); |
| 219 | if (self.hasUnwindRecords()) { | 230 | if (self.hasUnwindRecords()) { |
| 220 | self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len); | 231 | self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len); |
| 221 | mem.set(Record, self.unwind_relocs_lookup, .{ | 232 | mem.set(Record, self.unwind_relocs_lookup, .{ |
| ... | @@ -452,6 +463,8 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -452,6 +463,8 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void { |
| 452 | zld.sections.items(.header)[out_sect_id].sectName(), | 463 | zld.sections.items(.header)[out_sect_id].sectName(), |
| 453 | }); | 464 | }); |
| 454 | | 465 | |
| | 466 | try self.parseRelocs(gpa, section.id); |
| | 467 | |
| 455 | const cpu_arch = zld.options.target.cpu.arch; | 468 | const cpu_arch = zld.options.target.cpu.arch; |
| 456 | const sect_loc = filterSymbolsBySection(symtab[sect_sym_index..], sect_id + 1); | 469 | const sect_loc = filterSymbolsBySection(symtab[sect_sym_index..], sect_id + 1); |
| 457 | const sect_start_index = sect_sym_index + sect_loc.index; | 470 | const sect_start_index = sect_sym_index + sect_loc.index; |
| ... | @@ -623,25 +636,36 @@ fn filterRelocs( | ... | @@ -623,25 +636,36 @@ fn filterRelocs( |
| 623 | return .{ .start = @intCast(u32, start), .len = @intCast(u32, len) }; | 636 | return .{ .start = @intCast(u32, start), .len = @intCast(u32, len) }; |
| 624 | } | 637 | } |
| 625 | | 638 | |
| | 639 | /// Parse all relocs for the input section, and sort in descending order. |
| | 640 | /// Previously, I have wrongly assumed the compilers output relocations for each |
| | 641 | /// section in a sorted manner which is simply not true. |
| | 642 | fn parseRelocs(self: *Object, gpa: Allocator, sect_id: u8) !void { |
| | 643 | const section = self.getSourceSection(sect_id); |
| | 644 | const start = @intCast(u32, self.relocations.items.len); |
| | 645 | if (self.getSourceRelocs(section)) |relocs| { |
| | 646 | try self.relocations.ensureUnusedCapacity(gpa, relocs.len); |
| | 647 | self.relocations.appendUnalignedSliceAssumeCapacity(relocs); |
| | 648 | std.sort.sort(macho.relocation_info, self.relocations.items[start..], {}, relocGreaterThan); |
| | 649 | } |
| | 650 | self.section_relocs_lookup.items[sect_id] = start; |
| | 651 | } |
| | 652 | |
| 626 | fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void { | 653 | fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void { |
| 627 | const atom = zld.getAtom(atom_index); | 654 | const atom = zld.getAtom(atom_index); |
| 628 | | 655 | |
| 629 | const source_sect = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: { | 656 | const source_sect_id = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: { |
| 630 | const source_sect = self.getSourceSection(source_sym.n_sect - 1); | 657 | break :blk source_sym.n_sect - 1; |
| 631 | assert(!source_sect.isZerofill()); | | |
| 632 | break :blk source_sect; | | |
| 633 | } else blk: { | 658 | } else blk: { |
| 634 | // If there was no matching symbol present in the source symtab, this means | 659 | // If there was no matching symbol present in the source symtab, this means |
| 635 | // we are dealing with either an entire section, or part of it, but also | 660 | // we are dealing with either an entire section, or part of it, but also |
| 636 | // starting at the beginning. | 661 | // starting at the beginning. |
| 637 | const nbase = @intCast(u32, self.in_symtab.?.len); | 662 | const nbase = @intCast(u32, self.in_symtab.?.len); |
| 638 | const sect_id = @intCast(u16, atom.sym_index - nbase); | 663 | const sect_id = @intCast(u8, atom.sym_index - nbase); |
| 639 | const source_sect = self.getSourceSection(sect_id); | 664 | break :blk sect_id; |
| 640 | assert(!source_sect.isZerofill()); | | |
| 641 | break :blk source_sect; | | |
| 642 | }; | 665 | }; |
| 643 | | 666 | const source_sect = self.getSourceSection(source_sect_id); |
| 644 | const relocs = self.getRelocs(source_sect); | 667 | assert(!source_sect.isZerofill()); |
| | 668 | const relocs = self.getRelocs(source_sect_id); |
| 645 | | 669 | |
| 646 | self.relocs_lookup[atom.sym_index] = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: { | 670 | self.relocs_lookup[atom.sym_index] = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: { |
| 647 | const offset = source_sym.n_value - source_sect.addr; | 671 | const offset = source_sym.n_value - source_sect.addr; |
| ... | @@ -649,8 +673,14 @@ fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void { | ... | @@ -649,8 +673,14 @@ fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void { |
| 649 | } else filterRelocs(relocs, 0, atom.size); | 673 | } else filterRelocs(relocs, 0, atom.size); |
| 650 | } | 674 | } |
| 651 | | 675 | |
| | 676 | fn relocGreaterThan(ctx: void, lhs: macho.relocation_info, rhs: macho.relocation_info) bool { |
| | 677 | _ = ctx; |
| | 678 | return lhs.r_address > rhs.r_address; |
| | 679 | } |
| | 680 | |
| 652 | fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | 681 | fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 653 | const sect = self.eh_frame_sect orelse return; | 682 | const sect_id = self.eh_frame_sect_id orelse return; |
| | 683 | const sect = self.getSourceSection(sect_id); |
| 654 | | 684 | |
| 655 | log.debug("parsing __TEXT,__eh_frame section", .{}); | 685 | log.debug("parsing __TEXT,__eh_frame section", .{}); |
| 656 | | 686 | |
| ... | @@ -660,7 +690,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -660,7 +690,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 660 | | 690 | |
| 661 | const gpa = zld.gpa; | 691 | const gpa = zld.gpa; |
| 662 | const cpu_arch = zld.options.target.cpu.arch; | 692 | const cpu_arch = zld.options.target.cpu.arch; |
| 663 | const relocs = self.getRelocs(sect); | 693 | try self.parseRelocs(gpa, sect_id); |
| | 694 | const relocs = self.getRelocs(sect_id); |
| 664 | | 695 | |
| 665 | var it = self.getEhFrameRecordsIterator(); | 696 | var it = self.getEhFrameRecordsIterator(); |
| 666 | var record_count: u32 = 0; | 697 | var record_count: u32 = 0; |
| ... | @@ -728,12 +759,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -728,12 +759,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 728 | } | 759 | } |
| 729 | | 760 | |
| 730 | fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { | 761 | fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 731 | const sect = self.unwind_info_sect orelse { | 762 | const sect_id = self.unwind_info_sect_id orelse { |
| 732 | // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`, | 763 | // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`, |
| 733 | // we will try fully synthesising unwind info records to somewhat match Apple ld's | 764 | // we will try fully synthesising unwind info records to somewhat match Apple ld's |
| 734 | // approach. However, we will only synthesise DWARF records and nothing more. For this reason, | 765 | // approach. However, we will only synthesise DWARF records and nothing more. For this reason, |
| 735 | // we still create the output `__TEXT,__unwind_info` section. | 766 | // we still create the output `__TEXT,__unwind_info` section. |
| 736 | if (self.eh_frame_sect != null) { | 767 | if (self.hasEhFrameRecords()) { |
| 737 | if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { | 768 | if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { |
| 738 | _ = try zld.initSection("__TEXT", "__unwind_info", .{}); | 769 | _ = try zld.initSection("__TEXT", "__unwind_info", .{}); |
| 739 | } | 770 | } |
| ... | @@ -758,15 +789,15 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -758,15 +789,15 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 758 | if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true; | 789 | if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true; |
| 759 | } else false; | 790 | } else false; |
| 760 | | 791 | |
| 761 | if (needs_eh_frame) { | 792 | if (needs_eh_frame and !self.hasEhFrameRecords()) { |
| 762 | if (self.eh_frame_sect == null) { | 793 | log.err("missing __TEXT,__eh_frame section", .{}); |
| 763 | log.err("missing __TEXT,__eh_frame section", .{}); | 794 | log.err(" in object {s}", .{self.name}); |
| 764 | log.err(" in object {s}", .{self.name}); | 795 | return error.MissingSection; |
| 765 | return error.MissingSection; | | |
| 766 | } | | |
| 767 | } | 796 | } |
| 768 | | 797 | |
| 769 | const relocs = self.getRelocs(sect); | 798 | try self.parseRelocs(gpa, sect_id); |
| | 799 | const relocs = self.getRelocs(sect_id); |
| | 800 | |
| 770 | for (unwind_records) |record, record_id| { | 801 | for (unwind_records) |record, record_id| { |
| 771 | const offset = record_id * @sizeOf(macho.compact_unwind_entry); | 802 | const offset = record_id * @sizeOf(macho.compact_unwind_entry); |
| 772 | const rel_pos = filterRelocs( | 803 | const rel_pos = filterRelocs( |
| ... | @@ -806,25 +837,23 @@ pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 { | ... | @@ -806,25 +837,23 @@ pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 { |
| 806 | return symtab[mapped_index]; | 837 | return symtab[mapped_index]; |
| 807 | } | 838 | } |
| 808 | | 839 | |
| 809 | pub fn getSourceSection(self: Object, index: u16) macho.section_64 { | 840 | pub fn getSourceSection(self: Object, index: u8) macho.section_64 { |
| 810 | const sections = self.getSourceSections(); | 841 | const sections = self.getSourceSections(); |
| 811 | assert(index < sections.len); | 842 | assert(index < sections.len); |
| 812 | return sections[index]; | 843 | return sections[index]; |
| 813 | } | 844 | } |
| 814 | | 845 | |
| 815 | pub fn getSourceSectionByName(self: Object, segname: []const u8, sectname: []const u8) ?macho.section_64 { | 846 | pub fn getSourceSectionByName(self: Object, segname: []const u8, sectname: []const u8) ?macho.section_64 { |
| | 847 | const index = self.getSourceSectionIndexByName(segname, sectname) orelse return null; |
| 816 | const sections = self.getSourceSections(); | 848 | const sections = self.getSourceSections(); |
| 817 | for (sections) |sect| { | 849 | return sections[index]; |
| 818 | if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName())) | | |
| 819 | return sect; | | |
| 820 | } else return null; | | |
| 821 | } | 850 | } |
| 822 | | 851 | |
| 823 | pub fn getSourceSectionIndexByName(self: Object, segname: []const u8, sectname: []const u8) ?u8 { | 852 | pub fn getSourceSectionIndexByName(self: Object, segname: []const u8, sectname: []const u8) ?u8 { |
| 824 | const sections = self.getSourceSections(); | 853 | const sections = self.getSourceSections(); |
| 825 | for (sections) |sect, i| { | 854 | for (sections) |sect, i| { |
| 826 | if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName())) | 855 | if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName())) |
| 827 | return @intCast(u8, i + 1); | 856 | return @intCast(u8, i); |
| 828 | } else return null; | 857 | } else return null; |
| 829 | } | 858 | } |
| 830 | | 859 | |
| ... | @@ -914,11 +943,18 @@ pub fn getSectionAliasSymbolPtr(self: *Object, sect_id: u8) *macho.nlist_64 { | ... | @@ -914,11 +943,18 @@ pub fn getSectionAliasSymbolPtr(self: *Object, sect_id: u8) *macho.nlist_64 { |
| 914 | return &self.symtab[self.getSectionAliasSymbolIndex(sect_id)]; | 943 | return &self.symtab[self.getSectionAliasSymbolIndex(sect_id)]; |
| 915 | } | 944 | } |
| 916 | | 945 | |
| 917 | pub fn getRelocs(self: Object, sect: macho.section_64) []align(1) const macho.relocation_info { | 946 | fn getSourceRelocs(self: Object, sect: macho.section_64) ?[]align(1) const macho.relocation_info { |
| 918 | if (sect.nreloc == 0) return &[0]macho.relocation_info{}; | 947 | if (sect.nreloc == 0) return null; |
| 919 | return @ptrCast([*]align(1) const macho.relocation_info, self.contents.ptr + sect.reloff)[0..sect.nreloc]; | 948 | return @ptrCast([*]align(1) const macho.relocation_info, self.contents.ptr + sect.reloff)[0..sect.nreloc]; |
| 920 | } | 949 | } |
| 921 | | 950 | |
| | 951 | pub fn getRelocs(self: Object, sect_id: u8) []const macho.relocation_info { |
| | 952 | const sect = self.getSourceSection(sect_id); |
| | 953 | const start = self.section_relocs_lookup.items[sect_id]; |
| | 954 | const len = sect.nreloc; |
| | 955 | return self.relocations.items[start..][0..len]; |
| | 956 | } |
| | 957 | |
| 922 | pub fn getSymbolName(self: Object, index: u32) []const u8 { | 958 | pub fn getSymbolName(self: Object, index: u32) []const u8 { |
| 923 | const strtab = self.in_strtab.?; | 959 | const strtab = self.in_strtab.?; |
| 924 | const sym = self.symtab[index]; | 960 | const sym = self.symtab[index]; |
| ... | @@ -976,22 +1012,24 @@ pub fn getAtomIndexForSymbol(self: Object, sym_index: u32) ?AtomIndex { | ... | @@ -976,22 +1012,24 @@ pub fn getAtomIndexForSymbol(self: Object, sym_index: u32) ?AtomIndex { |
| 976 | } | 1012 | } |
| 977 | | 1013 | |
| 978 | pub fn hasUnwindRecords(self: Object) bool { | 1014 | pub fn hasUnwindRecords(self: Object) bool { |
| 979 | return self.unwind_info_sect != null; | 1015 | return self.unwind_info_sect_id != null; |
| 980 | } | 1016 | } |
| 981 | | 1017 | |
| 982 | pub fn getUnwindRecords(self: Object) []align(1) const macho.compact_unwind_entry { | 1018 | pub fn getUnwindRecords(self: Object) []align(1) const macho.compact_unwind_entry { |
| 983 | const sect = self.unwind_info_sect orelse return &[0]macho.compact_unwind_entry{}; | 1019 | const sect_id = self.unwind_info_sect_id orelse return &[0]macho.compact_unwind_entry{}; |
| | 1020 | const sect = self.getSourceSection(sect_id); |
| 984 | const data = self.getSectionContents(sect); | 1021 | const data = self.getSectionContents(sect); |
| 985 | const num_entries = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); | 1022 | const num_entries = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); |
| 986 | return @ptrCast([*]align(1) const macho.compact_unwind_entry, data)[0..num_entries]; | 1023 | return @ptrCast([*]align(1) const macho.compact_unwind_entry, data)[0..num_entries]; |
| 987 | } | 1024 | } |
| 988 | | 1025 | |
| 989 | pub fn hasEhFrameRecords(self: Object) bool { | 1026 | pub fn hasEhFrameRecords(self: Object) bool { |
| 990 | return self.eh_frame_sect != null; | 1027 | return self.eh_frame_sect_id != null; |
| 991 | } | 1028 | } |
| 992 | | 1029 | |
| 993 | pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator { | 1030 | pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator { |
| 994 | const sect = self.eh_frame_sect orelse return .{ .data = &[0]u8{} }; | 1031 | const sect_id = self.eh_frame_sect_id orelse return .{ .data = &[0]u8{} }; |
| | 1032 | const sect = self.getSourceSection(sect_id); |
| 995 | const data = self.getSectionContents(sect); | 1033 | const data = self.getSectionContents(sect); |
| 996 | return .{ .data = data }; | 1034 | return .{ .data = data }; |
| 997 | } | 1035 | } |