| ... | ... | @@ -26,17 +26,20 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 26 | 26 | pagezero_segment_cmd_index: ?u16 = null, |
| 27 | 27 | /// __TEXT segment |
| 28 | 28 | text_segment_cmd_index: ?u16 = null, |
| 29 | | /// __DWARF segment |
| 30 | | dwarf_segment_cmd_index: ?u16 = null, |
| 31 | 29 | /// __DATA segment |
| 32 | 30 | data_segment_cmd_index: ?u16 = null, |
| 33 | 31 | /// __LINKEDIT segment |
| 34 | 32 | linkedit_segment_cmd_index: ?u16 = null, |
| 33 | /// __DWARF segment |
| 34 | dwarf_segment_cmd_index: ?u16 = null, |
| 35 | 35 | /// Symbol table |
| 36 | 36 | symtab_cmd_index: ?u16 = null, |
| 37 | 37 | /// UUID load command |
| 38 | 38 | uuid_cmd_index: ?u16 = null, |
| 39 | 39 | |
| 40 | /// Index into __TEXT,__text section. |
| 41 | text_section_index: ?u16 = null, |
| 42 | |
| 40 | 43 | header_dirty: bool = false, |
| 41 | 44 | load_commands_dirty: bool = false, |
| 42 | 45 | |
| ... | ... | @@ -58,6 +61,22 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void |
| 58 | 61 | self.header = header; |
| 59 | 62 | self.header_dirty = true; |
| 60 | 63 | } |
| 64 | if (self.pagezero_segment_cmd_index == null) { |
| 65 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 66 | const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment; |
| 67 | try self.copySegmentCommand(allocator, base_cmd); |
| 68 | } |
| 69 | if (self.text_segment_cmd_index == null) { |
| 70 | self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 71 | const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment; |
| 72 | try self.copySegmentCommand(allocator, base_cmd); |
| 73 | } |
| 74 | if (self.data_segment_cmd_index == null) outer: { |
| 75 | if (self.base.data_segment_cmd_index == null) break :outer; // __DATA is optional |
| 76 | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 77 | const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment; |
| 78 | try self.copySegmentCommand(allocator, base_cmd); |
| 79 | } |
| 61 | 80 | if (self.uuid_cmd_index == null) { |
| 62 | 81 | const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?]; |
| 63 | 82 | self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len); |
| ... | ... | @@ -81,6 +100,53 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void { |
| 81 | 100 | self.file.close(); |
| 82 | 101 | } |
| 83 | 102 | |
| 103 | fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !void { |
| 104 | var cmd = SegmentCommand.empty(.{ |
| 105 | .cmd = macho.LC_SEGMENT_64, |
| 106 | .cmdsize = base_cmd.inner.cmdsize, |
| 107 | .segname = undefined, |
| 108 | .vmaddr = base_cmd.inner.vmaddr, |
| 109 | .vmsize = base_cmd.inner.vmsize, |
| 110 | .fileoff = 0, |
| 111 | .filesize = 0, |
| 112 | .maxprot = base_cmd.inner.maxprot, |
| 113 | .initprot = base_cmd.inner.initprot, |
| 114 | .nsects = base_cmd.inner.nsects, |
| 115 | .flags = base_cmd.inner.flags, |
| 116 | }); |
| 117 | mem.copy(u8, &cmd.inner.segname, &base_cmd.inner.segname); |
| 118 | |
| 119 | try cmd.sections.ensureCapacity(allocator, cmd.inner.nsects); |
| 120 | for (base_cmd.sections.items) |base_sect, i| { |
| 121 | var sect = macho.section_64{ |
| 122 | .sectname = undefined, |
| 123 | .segname = undefined, |
| 124 | .addr = base_sect.addr, |
| 125 | .size = base_sect.size, |
| 126 | .offset = 0, |
| 127 | .@"align" = base_sect.@"align", |
| 128 | .reloff = 0, |
| 129 | .nreloc = 0, |
| 130 | .flags = base_sect.flags, |
| 131 | .reserved1 = base_sect.reserved1, |
| 132 | .reserved2 = base_sect.reserved2, |
| 133 | .reserved3 = base_sect.reserved3, |
| 134 | }; |
| 135 | mem.copy(u8, &sect.sectname, &base_sect.sectname); |
| 136 | mem.copy(u8, &sect.segname, &base_sect.segname); |
| 137 | |
| 138 | if (self.base.text_section_index.? == i) { |
| 139 | self.text_section_index = @intCast(u16, i); |
| 140 | } |
| 141 | |
| 142 | cmd.sections.appendAssumeCapacity(sect); |
| 143 | } |
| 144 | |
| 145 | try self.load_commands.append(allocator, .{ .Segment = cmd }); |
| 146 | self.header_dirty = true; |
| 147 | self.load_commands_dirty = true; |
| 148 | } |
| 149 | |
| 84 | 150 | /// Writes all load commands and section headers. |
| 85 | 151 | fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void { |
| 86 | 152 | if (!self.load_commands_dirty) return; |