| ... | @@ -20,9 +20,10 @@ const Module = @import("../../Module.zig"); | ... | @@ -20,9 +20,10 @@ const Module = @import("../../Module.zig"); |
| 20 | const StringTable = @import("../strtab.zig").StringTable; | 20 | const StringTable = @import("../strtab.zig").StringTable; |
| 21 | const Type = @import("../../type.zig").Type; | 21 | const Type = @import("../../type.zig").Type; |
| 22 | | 22 | |
| 23 | base: *MachO, | 23 | allocator: Allocator, |
| 24 | dwarf: Dwarf, | 24 | dwarf: Dwarf, |
| 25 | file: fs.File, | 25 | file: fs.File, |
| | 26 | page_size: u16, |
| 26 | | 27 | |
| 27 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, | 28 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, |
| 28 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, | 29 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | @@ -59,21 +60,17 @@ pub const Reloc = struct { | ... | @@ -59,21 +60,17 @@ pub const Reloc = struct { |
| 59 | | 60 | |
| 60 | /// You must call this function *after* `MachO.populateMissingMetadata()` | 61 | /// You must call this function *after* `MachO.populateMissingMetadata()` |
| 61 | /// has been called to get a viable debug symbols output. | 62 | /// has been called to get a viable debug symbols output. |
| 62 | pub fn populateMissingMetadata(self: *DebugSymbols, gpa: Allocator) !void { | 63 | pub fn populateMissingMetadata(self: *DebugSymbols) !void { |
| 63 | if (self.dwarf_segment_cmd_index == null) { | 64 | if (self.dwarf_segment_cmd_index == null) { |
| 64 | self.dwarf_segment_cmd_index = @intCast(u8, self.segments.items.len); | 65 | self.dwarf_segment_cmd_index = @intCast(u8, self.segments.items.len); |
| 65 | | 66 | |
| 66 | const off = @intCast(u64, self.base.page_size); | 67 | const off = @intCast(u64, self.page_size); |
| 67 | const ideal_size: u16 = 200 + 128 + 160 + 250; | 68 | const ideal_size: u16 = 200 + 128 + 160 + 250; |
| 68 | const needed_size = mem.alignForwardGeneric( | 69 | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 69 | u64, | | |
| 70 | padToIdeal(ideal_size), | | |
| 71 | self.base.page_size, | | |
| 72 | ); | | |
| 73 | | 70 | |
| 74 | log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size }); | 71 | log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 75 | | 72 | |
| 76 | try self.segments.append(gpa, .{ | 73 | try self.segments.append(self.allocator, .{ |
| 77 | .segname = makeStaticString("__DWARF"), | 74 | .segname = makeStaticString("__DWARF"), |
| 78 | .vmsize = needed_size, | 75 | .vmsize = needed_size, |
| 79 | .fileoff = off, | 76 | .fileoff = off, |
| ... | @@ -114,7 +111,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, gpa: Allocator) !void { | ... | @@ -114,7 +111,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, gpa: Allocator) !void { |
| 114 | | 111 | |
| 115 | if (self.linkedit_segment_cmd_index == null) { | 112 | if (self.linkedit_segment_cmd_index == null) { |
| 116 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); | 113 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); |
| 117 | try self.segments.append(gpa, .{ | 114 | try self.segments.append(self.allocator, .{ |
| 118 | .segname = makeStaticString("__LINKEDIT"), | 115 | .segname = makeStaticString("__LINKEDIT"), |
| 119 | .maxprot = macho.PROT.READ, | 116 | .maxprot = macho.PROT.READ, |
| 120 | .initprot = macho.PROT.READ, | 117 | .initprot = macho.PROT.READ, |
| ... | @@ -124,8 +121,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, gpa: Allocator) !void { | ... | @@ -124,8 +121,6 @@ pub fn populateMissingMetadata(self: *DebugSymbols, gpa: Allocator) !void { |
| 124 | } | 121 | } |
| 125 | | 122 | |
| 126 | fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u8 { | 123 | fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u8 { |
| 127 | const gpa = self.base.base.allocator; | | |
| 128 | | | |
| 129 | const segment = self.getDwarfSegmentPtr(); | 124 | const segment = self.getDwarfSegmentPtr(); |
| 130 | var sect = macho.section_64{ | 125 | var sect = macho.section_64{ |
| 131 | .sectname = makeStaticString(sectname), | 126 | .sectname = makeStaticString(sectname), |
| ... | @@ -147,7 +142,7 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme | ... | @@ -147,7 +142,7 @@ fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignme |
| 147 | sect.offset = @intCast(u32, off); | 142 | sect.offset = @intCast(u32, off); |
| 148 | | 143 | |
| 149 | const index = @intCast(u8, self.sections.items.len); | 144 | const index = @intCast(u8, self.sections.items.len); |
| 150 | try self.sections.append(gpa, sect); | 145 | try self.sections.append(self.allocator, sect); |
| 151 | segment.cmdsize += @sizeOf(macho.section_64); | 146 | segment.cmdsize += @sizeOf(macho.section_64); |
| 152 | segment.nsects += 1; | 147 | segment.nsects += 1; |
| 153 | | 148 | |
| ... | @@ -175,34 +170,35 @@ pub fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) | ... | @@ -175,34 +170,35 @@ pub fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) |
| 175 | return offset; | 170 | return offset; |
| 176 | } | 171 | } |
| 177 | | 172 | |
| 178 | pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Options) !void { | 173 | pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 179 | // TODO This linker code currently assumes there is only 1 compilation unit and it corresponds to the | 174 | // TODO This linker code currently assumes there is only 1 compilation unit |
| 180 | // Zig source code. | 175 | // and it corresponds to the Zig source code. |
| | 176 | const options = macho_file.base.options; |
| 181 | const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 177 | const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 182 | | 178 | |
| 183 | for (self.relocs.items) |*reloc| { | 179 | for (self.relocs.items) |*reloc| { |
| 184 | const sym = switch (reloc.type) { | 180 | const sym = switch (reloc.type) { |
| 185 | .direct_load => self.base.getSymbol(.{ .sym_index = reloc.target, .file = null }), | 181 | .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target, .file = null }), |
| 186 | .got_load => blk: { | 182 | .got_load => blk: { |
| 187 | const got_index = self.base.got_entries_table.get(.{ | 183 | const got_index = macho_file.got_entries_table.get(.{ |
| 188 | .sym_index = reloc.target, | 184 | .sym_index = reloc.target, |
| 189 | .file = null, | 185 | .file = null, |
| 190 | }).?; | 186 | }).?; |
| 191 | const got_entry = self.base.got_entries.items[got_index]; | 187 | const got_entry = macho_file.got_entries.items[got_index]; |
| 192 | break :blk got_entry.getSymbol(self.base); | 188 | break :blk got_entry.getSymbol(macho_file); |
| 193 | }, | 189 | }, |
| 194 | }; | 190 | }; |
| 195 | if (sym.n_value == reloc.prev_vaddr) continue; | 191 | if (sym.n_value == reloc.prev_vaddr) continue; |
| 196 | | 192 | |
| 197 | const sym_name = switch (reloc.type) { | 193 | const sym_name = switch (reloc.type) { |
| 198 | .direct_load => self.base.getSymbolName(.{ .sym_index = reloc.target, .file = null }), | 194 | .direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target, .file = null }), |
| 199 | .got_load => blk: { | 195 | .got_load => blk: { |
| 200 | const got_index = self.base.got_entries_table.get(.{ | 196 | const got_index = macho_file.got_entries_table.get(.{ |
| 201 | .sym_index = reloc.target, | 197 | .sym_index = reloc.target, |
| 202 | .file = null, | 198 | .file = null, |
| 203 | }).?; | 199 | }).?; |
| 204 | const got_entry = self.base.got_entries.items[got_index]; | 200 | const got_entry = macho_file.got_entries.items[got_index]; |
| 205 | break :blk got_entry.getName(self.base); | 201 | break :blk got_entry.getName(macho_file); |
| 206 | }, | 202 | }, |
| 207 | }; | 203 | }; |
| 208 | const sect = &self.sections.items[self.debug_info_section_index.?]; | 204 | const sect = &self.sections.items[self.debug_info_section_index.?]; |
| ... | @@ -218,30 +214,30 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti | ... | @@ -218,30 +214,30 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti |
| 218 | } | 214 | } |
| 219 | | 215 | |
| 220 | if (self.debug_abbrev_section_dirty) { | 216 | if (self.debug_abbrev_section_dirty) { |
| 221 | try self.dwarf.writeDbgAbbrev(&self.base.base); | 217 | try self.dwarf.writeDbgAbbrev(&macho_file.base); |
| 222 | self.debug_abbrev_section_dirty = false; | 218 | self.debug_abbrev_section_dirty = false; |
| 223 | } | 219 | } |
| 224 | | 220 | |
| 225 | if (self.debug_info_header_dirty) { | 221 | if (self.debug_info_header_dirty) { |
| 226 | // Currently only one compilation unit is supported, so the address range is simply | 222 | // Currently only one compilation unit is supported, so the address range is simply |
| 227 | // identical to the main program header virtual address and memory size. | 223 | // identical to the main program header virtual address and memory size. |
| 228 | const text_section = self.base.sections.items(.header)[self.base.text_section_index.?]; | 224 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; |
| 229 | const low_pc = text_section.addr; | 225 | const low_pc = text_section.addr; |
| 230 | const high_pc = text_section.addr + text_section.size; | 226 | const high_pc = text_section.addr + text_section.size; |
| 231 | try self.dwarf.writeDbgInfoHeader(&self.base.base, module, low_pc, high_pc); | 227 | try self.dwarf.writeDbgInfoHeader(&macho_file.base, module, low_pc, high_pc); |
| 232 | self.debug_info_header_dirty = false; | 228 | self.debug_info_header_dirty = false; |
| 233 | } | 229 | } |
| 234 | | 230 | |
| 235 | if (self.debug_aranges_section_dirty) { | 231 | if (self.debug_aranges_section_dirty) { |
| 236 | // Currently only one compilation unit is supported, so the address range is simply | 232 | // Currently only one compilation unit is supported, so the address range is simply |
| 237 | // identical to the main program header virtual address and memory size. | 233 | // identical to the main program header virtual address and memory size. |
| 238 | const text_section = self.base.sections.items(.header)[self.base.text_section_index.?]; | 234 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; |
| 239 | try self.dwarf.writeDbgAranges(&self.base.base, text_section.addr, text_section.size); | 235 | try self.dwarf.writeDbgAranges(&macho_file.base, text_section.addr, text_section.size); |
| 240 | self.debug_aranges_section_dirty = false; | 236 | self.debug_aranges_section_dirty = false; |
| 241 | } | 237 | } |
| 242 | | 238 | |
| 243 | if (self.debug_line_header_dirty) { | 239 | if (self.debug_line_header_dirty) { |
| 244 | try self.dwarf.writeDbgLineHeader(&self.base.base, module); | 240 | try self.dwarf.writeDbgLineHeader(&macho_file.base, module); |
| 245 | self.debug_line_header_dirty = false; | 241 | self.debug_line_header_dirty = false; |
| 246 | } | 242 | } |
| 247 | | 243 | |
| ... | @@ -270,40 +266,45 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti | ... | @@ -270,40 +266,45 @@ pub fn flushModule(self: *DebugSymbols, allocator: Allocator, options: link.Opti |
| 270 | } | 266 | } |
| 271 | } | 267 | } |
| 272 | | 268 | |
| 273 | var lc_buffer = std.ArrayList(u8).init(allocator); | 269 | var lc_buffer = std.ArrayList(u8).init(self.allocator); |
| 274 | defer lc_buffer.deinit(); | 270 | defer lc_buffer.deinit(); |
| 275 | const lc_writer = lc_buffer.writer(); | 271 | const lc_writer = lc_buffer.writer(); |
| 276 | var ncmds: u32 = 0; | 272 | var ncmds: u32 = 0; |
| 277 | | 273 | |
| 278 | self.finalizeDwarfSegment(); | 274 | self.finalizeDwarfSegment(macho_file); |
| 279 | try self.writeLinkeditSegmentData(&ncmds, lc_writer); | 275 | try self.writeLinkeditSegmentData(macho_file, &ncmds, lc_writer); |
| 280 | | 276 | |
| 281 | { | 277 | { |
| 282 | try lc_writer.writeStruct(self.base.uuid); | 278 | try lc_writer.writeStruct(macho_file.uuid); |
| 283 | ncmds += 1; | 279 | ncmds += 1; |
| 284 | } | 280 | } |
| 285 | | 281 | |
| 286 | var headers_buf = std.ArrayList(u8).init(allocator); | 282 | var headers_buf = std.ArrayList(u8).init(self.allocator); |
| 287 | defer headers_buf.deinit(); | 283 | defer headers_buf.deinit(); |
| 288 | try self.writeSegmentHeaders(&ncmds, headers_buf.writer()); | 284 | try self.writeSegmentHeaders(macho_file, &ncmds, headers_buf.writer()); |
| 289 | | 285 | |
| 290 | try self.file.pwriteAll(headers_buf.items, @sizeOf(macho.mach_header_64)); | 286 | try self.file.pwriteAll(headers_buf.items, @sizeOf(macho.mach_header_64)); |
| 291 | try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64) + headers_buf.items.len); | 287 | try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64) + headers_buf.items.len); |
| 292 | | 288 | |
| 293 | try self.writeHeader(ncmds, @intCast(u32, lc_buffer.items.len + headers_buf.items.len)); | 289 | try self.writeHeader( |
| | 290 | macho_file, |
| | 291 | ncmds, |
| | 292 | @intCast(u32, lc_buffer.items.len + headers_buf.items.len), |
| | 293 | ); |
| 294 | | 294 | |
| 295 | assert(!self.debug_abbrev_section_dirty); | 295 | assert(!self.debug_abbrev_section_dirty); |
| 296 | assert(!self.debug_aranges_section_dirty); | 296 | assert(!self.debug_aranges_section_dirty); |
| 297 | assert(!self.debug_string_table_dirty); | 297 | assert(!self.debug_string_table_dirty); |
| 298 | } | 298 | } |
| 299 | | 299 | |
| 300 | pub fn deinit(self: *DebugSymbols, allocator: Allocator) void { | 300 | pub fn deinit(self: *DebugSymbols) void { |
| | 301 | const gpa = self.allocator; |
| 301 | self.file.close(); | 302 | self.file.close(); |
| 302 | self.segments.deinit(allocator); | 303 | self.segments.deinit(gpa); |
| 303 | self.sections.deinit(allocator); | 304 | self.sections.deinit(gpa); |
| 304 | self.dwarf.deinit(); | 305 | self.dwarf.deinit(); |
| 305 | self.strtab.deinit(allocator); | 306 | self.strtab.deinit(gpa); |
| 306 | self.relocs.deinit(allocator); | 307 | self.relocs.deinit(gpa); |
| 307 | } | 308 | } |
| 308 | | 309 | |
| 309 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { | 310 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { |
| ... | @@ -319,16 +320,22 @@ pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { | ... | @@ -319,16 +320,22 @@ pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { |
| 319 | } | 320 | } |
| 320 | } | 321 | } |
| 321 | | 322 | |
| 322 | fn finalizeDwarfSegment(self: *DebugSymbols) void { | 323 | fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 323 | const base_vmaddr = blk: { | 324 | const base_vmaddr = blk: { |
| 324 | const last_seg = self.base.getLinkeditSegmentPtr(); | 325 | // Note that we purposely take the last VM address of the MachO binary including |
| | 326 | // the binary's LINKEDIT segment. This is in contrast to how dsymutil does it |
| | 327 | // which overwrites the the address space taken by the original MachO binary, |
| | 328 | // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we |
| | 329 | // do not want as we want to be able to incrementally move DWARF sections in the |
| | 330 | // file as we please. |
| | 331 | const last_seg = macho_file.getLinkeditSegmentPtr(); |
| 325 | break :blk last_seg.vmaddr + last_seg.vmsize; | 332 | break :blk last_seg.vmaddr + last_seg.vmsize; |
| 326 | }; | 333 | }; |
| 327 | const dwarf_segment = self.getDwarfSegmentPtr(); | 334 | const dwarf_segment = self.getDwarfSegmentPtr(); |
| 328 | const aligned_size = mem.alignForwardGeneric( | 335 | const aligned_size = mem.alignForwardGeneric( |
| 329 | u64, | 336 | u64, |
| 330 | dwarf_segment.filesize, | 337 | dwarf_segment.filesize, |
| 331 | self.base.page_size, | 338 | self.page_size, |
| 332 | ); | 339 | ); |
| 333 | dwarf_segment.vmaddr = base_vmaddr; | 340 | dwarf_segment.vmaddr = base_vmaddr; |
| 334 | dwarf_segment.filesize = aligned_size; | 341 | dwarf_segment.filesize = aligned_size; |
| ... | @@ -338,21 +345,21 @@ fn finalizeDwarfSegment(self: *DebugSymbols) void { | ... | @@ -338,21 +345,21 @@ fn finalizeDwarfSegment(self: *DebugSymbols) void { |
| 338 | linkedit.vmaddr = mem.alignForwardGeneric( | 345 | linkedit.vmaddr = mem.alignForwardGeneric( |
| 339 | u64, | 346 | u64, |
| 340 | dwarf_segment.vmaddr + aligned_size, | 347 | dwarf_segment.vmaddr + aligned_size, |
| 341 | self.base.page_size, | 348 | self.page_size, |
| 342 | ); | 349 | ); |
| 343 | linkedit.fileoff = mem.alignForwardGeneric( | 350 | linkedit.fileoff = mem.alignForwardGeneric( |
| 344 | u64, | 351 | u64, |
| 345 | dwarf_segment.fileoff + aligned_size, | 352 | dwarf_segment.fileoff + aligned_size, |
| 346 | self.base.page_size, | 353 | self.page_size, |
| 347 | ); | 354 | ); |
| 348 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); | 355 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); |
| 349 | } | 356 | } |
| 350 | | 357 | |
| 351 | fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void { | 358 | fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, ncmds: *u32, writer: anytype) !void { |
| 352 | // Write segment/section headers from the binary file first. | 359 | // Write segment/section headers from the binary file first. |
| 353 | const end = self.base.linkedit_segment_cmd_index.?; | 360 | const end = macho_file.linkedit_segment_cmd_index.?; |
| 354 | for (self.base.segments.items[0..end]) |seg, i| { | 361 | for (macho_file.segments.items[0..end]) |seg, i| { |
| 355 | const indexes = self.base.getSectionIndexes(@intCast(u8, i)); | 362 | const indexes = macho_file.getSectionIndexes(@intCast(u8, i)); |
| 356 | var out_seg = seg; | 363 | var out_seg = seg; |
| 357 | out_seg.fileoff = 0; | 364 | out_seg.fileoff = 0; |
| 358 | out_seg.filesize = 0; | 365 | out_seg.filesize = 0; |
| ... | @@ -361,7 +368,7 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void | ... | @@ -361,7 +368,7 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void |
| 361 | | 368 | |
| 362 | // Update section headers count; any section with size of 0 is excluded | 369 | // Update section headers count; any section with size of 0 is excluded |
| 363 | // since it doesn't have any data in the final binary file. | 370 | // since it doesn't have any data in the final binary file. |
| 364 | for (self.base.sections.items(.header)[indexes.start..indexes.end]) |header| { | 371 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { |
| 365 | if (header.size == 0) continue; | 372 | if (header.size == 0) continue; |
| 366 | out_seg.cmdsize += @sizeOf(macho.section_64); | 373 | out_seg.cmdsize += @sizeOf(macho.section_64); |
| 367 | out_seg.nsects += 1; | 374 | out_seg.nsects += 1; |
| ... | @@ -372,7 +379,7 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void | ... | @@ -372,7 +379,7 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void |
| 372 | mem.eql(u8, out_seg.segName(), "__DATA"))) continue; | 379 | mem.eql(u8, out_seg.segName(), "__DATA"))) continue; |
| 373 | | 380 | |
| 374 | try writer.writeStruct(out_seg); | 381 | try writer.writeStruct(out_seg); |
| 375 | for (self.base.sections.items(.header)[indexes.start..indexes.end]) |header| { | 382 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { |
| 376 | if (header.size == 0) continue; | 383 | if (header.size == 0) continue; |
| 377 | var out_header = header; | 384 | var out_header = header; |
| 378 | out_header.offset = 0; | 385 | out_header.offset = 0; |
| ... | @@ -392,11 +399,11 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void | ... | @@ -392,11 +399,11 @@ fn writeSegmentHeaders(self: *DebugSymbols, ncmds: *u32, writer: anytype) !void |
| 392 | } | 399 | } |
| 393 | } | 400 | } |
| 394 | | 401 | |
| 395 | fn writeHeader(self: *DebugSymbols, ncmds: u32, sizeofcmds: u32) !void { | 402 | fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void { |
| 396 | var header: macho.mach_header_64 = .{}; | 403 | var header: macho.mach_header_64 = .{}; |
| 397 | header.filetype = macho.MH_DSYM; | 404 | header.filetype = macho.MH_DSYM; |
| 398 | | 405 | |
| 399 | switch (self.base.base.options.target.cpu.arch) { | 406 | switch (macho_file.base.options.target.cpu.arch) { |
| 400 | .aarch64 => { | 407 | .aarch64 => { |
| 401 | header.cputype = macho.CPU_TYPE_ARM64; | 408 | header.cputype = macho.CPU_TYPE_ARM64; |
| 402 | header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; | 409 | header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; |
| ... | @@ -427,7 +434,12 @@ pub fn allocatedSize(self: *DebugSymbols, start: u64) u64 { | ... | @@ -427,7 +434,12 @@ pub fn allocatedSize(self: *DebugSymbols, start: u64) u64 { |
| 427 | return min_pos - start; | 434 | return min_pos - start; |
| 428 | } | 435 | } |
| 429 | | 436 | |
| 430 | fn writeLinkeditSegmentData(self: *DebugSymbols, ncmds: *u32, lc_writer: anytype) !void { | 437 | fn writeLinkeditSegmentData( |
| | 438 | self: *DebugSymbols, |
| | 439 | macho_file: *MachO, |
| | 440 | ncmds: *u32, |
| | 441 | lc_writer: anytype, |
| | 442 | ) !void { |
| 431 | const tracy = trace(@src()); | 443 | const tracy = trace(@src()); |
| 432 | defer tracy.end(); | 444 | defer tracy.end(); |
| 433 | | 445 | |
| ... | @@ -438,43 +450,43 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, ncmds: *u32, lc_writer: anytype | ... | @@ -438,43 +450,43 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, ncmds: *u32, lc_writer: anytype |
| 438 | .stroff = 0, | 450 | .stroff = 0, |
| 439 | .strsize = 0, | 451 | .strsize = 0, |
| 440 | }; | 452 | }; |
| 441 | try self.writeSymtab(&symtab_cmd); | 453 | try self.writeSymtab(macho_file, &symtab_cmd); |
| 442 | try self.writeStrtab(&symtab_cmd); | 454 | try self.writeStrtab(&symtab_cmd); |
| 443 | try lc_writer.writeStruct(symtab_cmd); | 455 | try lc_writer.writeStruct(symtab_cmd); |
| 444 | ncmds.* += 1; | 456 | ncmds.* += 1; |
| 445 | | 457 | |
| 446 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 458 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; |
| 447 | const aligned_size = mem.alignForwardGeneric(u64, seg.filesize, self.base.page_size); | 459 | const aligned_size = mem.alignForwardGeneric(u64, seg.filesize, self.page_size); |
| 448 | seg.vmsize = aligned_size; | 460 | seg.vmsize = aligned_size; |
| 449 | } | 461 | } |
| 450 | | 462 | |
| 451 | fn writeSymtab(self: *DebugSymbols, lc: *macho.symtab_command) !void { | 463 | fn writeSymtab(self: *DebugSymbols, macho_file: *MachO, lc: *macho.symtab_command) !void { |
| 452 | const tracy = trace(@src()); | 464 | const tracy = trace(@src()); |
| 453 | defer tracy.end(); | 465 | defer tracy.end(); |
| 454 | | 466 | |
| 455 | const gpa = self.base.base.allocator; | 467 | const gpa = self.allocator; |
| 456 | | 468 | |
| 457 | var locals = std.ArrayList(macho.nlist_64).init(gpa); | 469 | var locals = std.ArrayList(macho.nlist_64).init(gpa); |
| 458 | defer locals.deinit(); | 470 | defer locals.deinit(); |
| 459 | | 471 | |
| 460 | for (self.base.locals.items) |sym, sym_id| { | 472 | for (macho_file.locals.items) |sym, sym_id| { |
| 461 | if (sym.n_strx == 0) continue; // no name, skip | 473 | if (sym.n_strx == 0) continue; // no name, skip |
| 462 | const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null }; | 474 | const sym_loc = MachO.SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null }; |
| 463 | if (self.base.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip | 475 | if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 464 | if (self.base.getGlobal(self.base.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | 476 | if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 465 | var out_sym = sym; | 477 | var out_sym = sym; |
| 466 | out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(sym_loc)); | 478 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc)); |
| 467 | try locals.append(out_sym); | 479 | try locals.append(out_sym); |
| 468 | } | 480 | } |
| 469 | | 481 | |
| 470 | var exports = std.ArrayList(macho.nlist_64).init(gpa); | 482 | var exports = std.ArrayList(macho.nlist_64).init(gpa); |
| 471 | defer exports.deinit(); | 483 | defer exports.deinit(); |
| 472 | | 484 | |
| 473 | for (self.base.globals.items) |global| { | 485 | for (macho_file.globals.items) |global| { |
| 474 | const sym = self.base.getSymbol(global); | 486 | const sym = macho_file.getSymbol(global); |
| 475 | if (sym.undf()) continue; // import, skip | 487 | if (sym.undf()) continue; // import, skip |
| 476 | var out_sym = sym; | 488 | var out_sym = sym; |
| 477 | out_sym.n_strx = try self.strtab.insert(gpa, self.base.getSymbolName(global)); | 489 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global)); |
| 478 | try exports.append(out_sym); | 490 | try exports.append(out_sym); |
| 479 | } | 491 | } |
| 480 | | 492 | |