| author | |
| committer | |
| log | f2214e43715d1094a2d933c3fe1b6f461391915b |
| tree | fef3b2025f353c4be81eeda7d87fbcc314019525 |
| parent | d53cb284de0486fbb31f6377d3b86d8de5f93cd0 |
9 files changed, 212 insertions(+), 223 deletions(-)
src/link/Dwarf.zig-1| ... | @@ -1468,7 +1468,6 @@ pub fn commitDeclState( | ... | @@ -1468,7 +1468,6 @@ pub fn commitDeclState( |
| 1468 | .target = reloc.target, | 1468 | .target = reloc.target, |
| 1469 | .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, | 1469 | .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, |
| 1470 | .addend = 0, | 1470 | .addend = 0, |
| 1471 | .prev_vaddr = 0, | ||
| 1472 | }); | 1471 | }); |
| 1473 | }, | 1472 | }, |
| 1474 | .elf => {}, // TODO | 1473 | .elf => {}, // TODO |
src/link/MachO.zig+9-5| ... | @@ -258,7 +258,7 @@ pub fn createEmpty( | ... | @@ -258,7 +258,7 @@ pub fn createEmpty( |
| 258 | 258 | ||
| 259 | switch (comp.config.debug_format) { | 259 | switch (comp.config.debug_format) { |
| 260 | .strip => {}, | 260 | .strip => {}, |
| 261 | .dwarf => { | 261 | .dwarf => if (!self.base.isRelocatable()) { |
| 262 | // Create dSYM bundle. | 262 | // Create dSYM bundle. |
| 263 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); | 263 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); |
| 264 | 264 | ||
| ... | @@ -283,6 +283,9 @@ pub fn createEmpty( | ... | @@ -283,6 +283,9 @@ pub fn createEmpty( |
| 283 | .file = d_sym_file, | 283 | .file = d_sym_file, |
| 284 | }; | 284 | }; |
| 285 | try self.d_sym.?.initMetadata(self); | 285 | try self.d_sym.?.initMetadata(self); |
| 286 | } else { | ||
| 287 | try self.reportUnexpectedError("TODO: implement generating and emitting __DWARF in .o file", .{}); | ||
| 288 | return error.Unexpected; | ||
| 286 | }, | 289 | }, |
| 287 | .code_view => unreachable, | 290 | .code_view => unreachable, |
| 288 | } | 291 | } |
| ... | @@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -696,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 696 | const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands(); | 699 | const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands(); |
| 697 | try self.writeHeader(ncmds, sizeofcmds); | 700 | try self.writeHeader(ncmds, sizeofcmds); |
| 698 | try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()); | 701 | try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()); |
| 702 | if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self); | ||
| 699 | 703 | ||
| 700 | if (codesig) |*csig| { | 704 | if (codesig) |*csig| { |
| 701 | try self.writeCodeSignature(csig); // code signing always comes last | 705 | try self.writeCodeSignature(csig); // code signing always comes last |
| ... | @@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 { | ... | @@ -2902,16 +2906,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 { |
| 2902 | try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); | 2906 | try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); |
| 2903 | 2907 | ||
| 2904 | if (self.getZigObject()) |zo| { | 2908 | if (self.getZigObject()) |zo| { |
| 2905 | zo.writeSymtab(self); | 2909 | zo.writeSymtab(self, self); |
| 2906 | } | 2910 | } |
| 2907 | for (self.objects.items) |index| { | 2911 | for (self.objects.items) |index| { |
| 2908 | try self.getFile(index).?.writeSymtab(self); | 2912 | try self.getFile(index).?.writeSymtab(self, self); |
| 2909 | } | 2913 | } |
| 2910 | for (self.dylibs.items) |index| { | 2914 | for (self.dylibs.items) |index| { |
| 2911 | try self.getFile(index).?.writeSymtab(self); | 2915 | try self.getFile(index).?.writeSymtab(self, self); |
| 2912 | } | 2916 | } |
| 2913 | if (self.getInternalObject()) |internal| { | 2917 | if (self.getInternalObject()) |internal| { |
| 2914 | internal.writeSymtab(self); | 2918 | internal.writeSymtab(self, self); |
| 2915 | } | 2919 | } |
| 2916 | 2920 | ||
| 2917 | assert(self.strtab.items.len == cmd.strsize); | 2921 | assert(self.strtab.items.len == cmd.strsize); |
src/link/MachO/DebugSymbols.zig+113-149| ... | @@ -3,6 +3,7 @@ dwarf: Dwarf, | ... | @@ -3,6 +3,7 @@ dwarf: Dwarf, |
| 3 | file: fs.File, | 3 | file: fs.File, |
| 4 | 4 | ||
| 5 | symtab_cmd: macho.symtab_command = .{}, | 5 | symtab_cmd: macho.symtab_command = .{}, |
| 6 | uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, | ||
| 6 | 7 | ||
| 7 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, | 8 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, |
| 8 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, | 9 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | @@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false, | ... | @@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false, |
| 22 | debug_info_header_dirty: bool = false, | 23 | debug_info_header_dirty: bool = false, |
| 23 | debug_line_header_dirty: bool = false, | 24 | debug_line_header_dirty: bool = false, |
| 24 | 25 | ||
| 25 | strtab: StringTable = .{}, | ||
| 26 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, | 26 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, |
| 27 | 27 | ||
| 28 | /// Output synthetic sections | ||
| 29 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | ||
| 30 | strtab: std.ArrayListUnmanaged(u8) = .{}, | ||
| 31 | |||
| 28 | pub const Reloc = struct { | 32 | pub const Reloc = struct { |
| 29 | type: enum { | 33 | type: enum { |
| 30 | direct_load, | 34 | direct_load, |
| ... | @@ -33,12 +37,13 @@ pub const Reloc = struct { | ... | @@ -33,12 +37,13 @@ pub const Reloc = struct { |
| 33 | target: u32, | 37 | target: u32, |
| 34 | offset: u64, | 38 | offset: u64, |
| 35 | addend: u32, | 39 | addend: u32, |
| 36 | prev_vaddr: u64, | ||
| 37 | }; | 40 | }; |
| 38 | 41 | ||
| 39 | /// You must call this function *after* `ZigObject.initMetadata()` | 42 | /// You must call this function *after* `ZigObject.initMetadata()` |
| 40 | /// has been called to get a viable debug symbols output. | 43 | /// has been called to get a viable debug symbols output. |
| 41 | pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { | 44 | pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { |
| 45 | try self.strtab.append(self.allocator, 0); | ||
| 46 | |||
| 42 | if (self.dwarf_segment_cmd_index == null) { | 47 | if (self.dwarf_segment_cmd_index == null) { |
| 43 | self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); | 48 | self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); |
| 44 | 49 | ||
| ... | @@ -202,34 +207,21 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -202,34 +207,21 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 202 | const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 207 | const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 203 | 208 | ||
| 204 | for (self.relocs.items) |*reloc| { | 209 | for (self.relocs.items) |*reloc| { |
| 205 | const sym = switch (reloc.type) { | 210 | const sym = macho_file.getSymbol(reloc.target); |
| 206 | .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }), | 211 | const sym_name = sym.getName(macho_file); |
| 207 | .got_load => blk: { | 212 | const addr = switch (reloc.type) { |
| 208 | const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; | 213 | .direct_load => sym.getAddress(.{}, macho_file), |
| 209 | const got_entry = macho_file.got_table.entries.items[got_index]; | 214 | .got_load => sym.getGotAddress(macho_file), |
| 210 | break :blk macho_file.getSymbol(got_entry); | ||
| 211 | }, | ||
| 212 | }; | ||
| 213 | if (sym.n_value == reloc.prev_vaddr) continue; | ||
| 214 | |||
| 215 | const sym_name = switch (reloc.type) { | ||
| 216 | .direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }), | ||
| 217 | .got_load => blk: { | ||
| 218 | const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; | ||
| 219 | const got_entry = macho_file.got_table.entries.items[got_index]; | ||
| 220 | break :blk macho_file.getSymbolName(got_entry); | ||
| 221 | }, | ||
| 222 | }; | 215 | }; |
| 223 | const sect = &self.sections.items[self.debug_info_section_index.?]; | 216 | const sect = &self.sections.items[self.debug_info_section_index.?]; |
| 224 | const file_offset = sect.offset + reloc.offset; | 217 | const file_offset = sect.offset + reloc.offset; |
| 225 | log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ | 218 | log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ |
| 226 | reloc.target, | 219 | reloc.target, |
| 227 | sym.n_value, | 220 | addr, |
| 228 | sym_name, | 221 | sym_name, |
| 229 | file_offset, | 222 | file_offset, |
| 230 | }); | 223 | }); |
| 231 | try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset); | 224 | try self.file.pwriteAll(mem.asBytes(&addr), file_offset); |
| 232 | reloc.prev_vaddr = sym.n_value; | ||
| 233 | } | 225 | } |
| 234 | 226 | ||
| 235 | if (self.debug_abbrev_section_dirty) { | 227 | if (self.debug_abbrev_section_dirty) { |
| ... | @@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -240,7 +232,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 240 | if (self.debug_info_header_dirty) { | 232 | if (self.debug_info_header_dirty) { |
| 241 | // Currently only one compilation unit is supported, so the address range is simply | 233 | // Currently only one compilation unit is supported, so the address range is simply |
| 242 | // identical to the main program header virtual address and memory size. | 234 | // identical to the main program header virtual address and memory size. |
| 243 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; | 235 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; |
| 244 | const low_pc = text_section.addr; | 236 | const low_pc = text_section.addr; |
| 245 | const high_pc = text_section.addr + text_section.size; | 237 | const high_pc = text_section.addr + text_section.size; |
| 246 | try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); | 238 | try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); |
| ... | @@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -250,7 +242,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 250 | if (self.debug_aranges_section_dirty) { | 242 | if (self.debug_aranges_section_dirty) { |
| 251 | // Currently only one compilation unit is supported, so the address range is simply | 243 | // Currently only one compilation unit is supported, so the address range is simply |
| 252 | // identical to the main program header virtual address and memory size. | 244 | // identical to the main program header virtual address and memory size. |
| 253 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; | 245 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; |
| 254 | try self.dwarf.writeDbgAranges(text_section.addr, text_section.size); | 246 | try self.dwarf.writeDbgAranges(text_section.addr, text_section.size); |
| 255 | self.debug_aranges_section_dirty = false; | 247 | self.debug_aranges_section_dirty = false; |
| 256 | } | 248 | } |
| ... | @@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -274,17 +266,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 274 | try self.writeLinkeditSegmentData(macho_file); | 266 | try self.writeLinkeditSegmentData(macho_file); |
| 275 | 267 | ||
| 276 | // Write load commands | 268 | // Write load commands |
| 277 | var lc_buffer = std.ArrayList(u8).init(self.allocator); | 269 | const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file); |
| 278 | defer lc_buffer.deinit(); | 270 | try self.writeHeader(macho_file, ncmds, sizeofcmds); |
| 279 | const lc_writer = lc_buffer.writer(); | ||
| 280 | |||
| 281 | try self.writeSegmentHeaders(macho_file, lc_writer); | ||
| 282 | try lc_writer.writeStruct(self.symtab_cmd); | ||
| 283 | try lc_writer.writeStruct(macho_file.uuid_cmd); | ||
| 284 | |||
| 285 | const ncmds = load_commands.calcNumOfLCs(lc_buffer.items); | ||
| 286 | try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); | ||
| 287 | try self.writeHeader(macho_file, ncmds, @as(u32, @intCast(lc_buffer.items.len))); | ||
| 288 | 271 | ||
| 289 | assert(!self.debug_abbrev_section_dirty); | 272 | assert(!self.debug_abbrev_section_dirty); |
| 290 | assert(!self.debug_aranges_section_dirty); | 273 | assert(!self.debug_aranges_section_dirty); |
| ... | @@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void { | ... | @@ -297,8 +280,9 @@ pub fn deinit(self: *DebugSymbols) void { |
| 297 | self.segments.deinit(gpa); | 280 | self.segments.deinit(gpa); |
| 298 | self.sections.deinit(gpa); | 281 | self.sections.deinit(gpa); |
| 299 | self.dwarf.deinit(); | 282 | self.dwarf.deinit(); |
| 300 | self.strtab.deinit(gpa); | ||
| 301 | self.relocs.deinit(gpa); | 283 | self.relocs.deinit(gpa); |
| 284 | self.symtab.deinit(gpa); | ||
| 285 | self.strtab.deinit(gpa); | ||
| 302 | } | 286 | } |
| 303 | 287 | ||
| 304 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { | 288 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { |
| ... | @@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { | ... | @@ -322,7 +306,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 322 | // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we | 306 | // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we |
| 323 | // do not want as we want to be able to incrementally move DWARF sections in the | 307 | // do not want as we want to be able to incrementally move DWARF sections in the |
| 324 | // file as we please. | 308 | // file as we please. |
| 325 | const last_seg = macho_file.getLinkeditSegmentPtr(); | 309 | const last_seg = macho_file.getLinkeditSegment(); |
| 326 | break :blk last_seg.vmaddr + last_seg.vmsize; | 310 | break :blk last_seg.vmaddr + last_seg.vmsize; |
| 327 | }; | 311 | }; |
| 328 | const dwarf_segment = self.getDwarfSegmentPtr(); | 312 | const dwarf_segment = self.getDwarfSegmentPtr(); |
| ... | @@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { | ... | @@ -332,8 +316,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 332 | file_size = @max(file_size, header.offset + header.size); | 316 | file_size = @max(file_size, header.offset + header.size); |
| 333 | } | 317 | } |
| 334 | 318 | ||
| 335 | const target = macho_file.base.comp.root_mod.resolved_target.result; | 319 | const page_size = macho_file.getPageSize(); |
| 336 | const page_size = MachO.getPageSize(target.cpu.arch); | ||
| 337 | const aligned_size = mem.alignForward(u64, file_size, page_size); | 320 | const aligned_size = mem.alignForward(u64, file_size, page_size); |
| 338 | dwarf_segment.vmaddr = base_vmaddr; | 321 | dwarf_segment.vmaddr = base_vmaddr; |
| 339 | dwarf_segment.filesize = aligned_size; | 322 | dwarf_segment.filesize = aligned_size; |
| ... | @@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { | ... | @@ -353,54 +336,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 353 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); | 336 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); |
| 354 | } | 337 | } |
| 355 | 338 | ||
| 356 | fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void { | 339 | fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } { |
| 357 | // Write segment/section headers from the binary file first. | 340 | const gpa = self.allocator; |
| 358 | const end = macho_file.linkedit_segment_cmd_index.?; | 341 | const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self); |
| 359 | for (macho_file.segments.items[0..end], 0..) |seg, i| { | 342 | const buffer = try gpa.alloc(u8, needed_size); |
| 360 | const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i))); | 343 | defer gpa.free(buffer); |
| 361 | var out_seg = seg; | 344 | |
| 362 | out_seg.fileoff = 0; | 345 | var stream = std.io.fixedBufferStream(buffer); |
| 363 | out_seg.filesize = 0; | 346 | var cwriter = std.io.countingWriter(stream.writer()); |
| 364 | out_seg.cmdsize = @sizeOf(macho.segment_command_64); | 347 | const writer = cwriter.writer(); |
| 365 | out_seg.nsects = 0; | ||
| 366 | |||
| 367 | // Update section headers count; any section with size of 0 is excluded | ||
| 368 | // since it doesn't have any data in the final binary file. | ||
| 369 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { | ||
| 370 | if (header.size == 0) continue; | ||
| 371 | out_seg.cmdsize += @sizeOf(macho.section_64); | ||
| 372 | out_seg.nsects += 1; | ||
| 373 | } | ||
| 374 | 348 | ||
| 375 | if (out_seg.nsects == 0 and | 349 | var ncmds: usize = 0; |
| 376 | (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or | ||
| 377 | mem.eql(u8, out_seg.segName(), "__DATA"))) continue; | ||
| 378 | 350 | ||
| 379 | try writer.writeStruct(out_seg); | 351 | // UUID comes first presumably to speed up lookup by the consumer like lldb. |
| 380 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { | 352 | @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); |
| 381 | if (header.size == 0) continue; | 353 | try writer.writeStruct(self.uuid_cmd); |
| 382 | var out_header = header; | 354 | ncmds += 1; |
| 383 | out_header.offset = 0; | 355 | |
| 384 | try writer.writeStruct(out_header); | 356 | // Segment and section load commands |
| 357 | { | ||
| 358 | // Write segment/section headers from the binary file first. | ||
| 359 | const slice = macho_file.sections.slice(); | ||
| 360 | var sect_id: usize = 0; | ||
| 361 | for (macho_file.segments.items, 0..) |seg, seg_id| { | ||
| 362 | if (seg_id == macho_file.linkedit_seg_index.?) break; | ||
| 363 | var out_seg = seg; | ||
| 364 | out_seg.fileoff = 0; | ||
| 365 | out_seg.filesize = 0; | ||
| 366 | try writer.writeStruct(out_seg); | ||
| 367 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { | ||
| 368 | var out_header = header; | ||
| 369 | out_header.offset = 0; | ||
| 370 | try writer.writeStruct(out_header); | ||
| 371 | } | ||
| 372 | sect_id += seg.nsects; | ||
| 385 | } | 373 | } |
| 386 | } | 374 | ncmds += macho_file.segments.items.len - 1; |
| 387 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. | 375 | |
| 388 | for (self.segments.items, 0..) |seg, i| { | 376 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. |
| 389 | const indexes = self.getSectionIndexes(@as(u8, @intCast(i))); | 377 | sect_id = 0; |
| 390 | try writer.writeStruct(seg); | 378 | for (self.segments.items) |seg| { |
| 391 | for (self.sections.items[indexes.start..indexes.end]) |header| { | 379 | try writer.writeStruct(seg); |
| 392 | try writer.writeStruct(header); | 380 | for (self.sections.items[sect_id..][0..seg.nsects]) |header| { |
| 381 | try writer.writeStruct(header); | ||
| 382 | } | ||
| 383 | sect_id += seg.nsects; | ||
| 393 | } | 384 | } |
| 385 | ncmds += self.segments.items.len; | ||
| 394 | } | 386 | } |
| 395 | } | ||
| 396 | 387 | ||
| 397 | fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void { | 388 | try writer.writeStruct(self.symtab_cmd); |
| 398 | const target = macho_file.base.comp.root_mod.resolved_target.result; | 389 | ncmds += 1; |
| 390 | |||
| 391 | assert(cwriter.bytes_written == needed_size); | ||
| 399 | 392 | ||
| 393 | try self.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); | ||
| 394 | |||
| 395 | return .{ ncmds, buffer.len }; | ||
| 396 | } | ||
| 397 | |||
| 398 | fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { | ||
| 400 | var header: macho.mach_header_64 = .{}; | 399 | var header: macho.mach_header_64 = .{}; |
| 401 | header.filetype = macho.MH_DSYM; | 400 | header.filetype = macho.MH_DSYM; |
| 402 | 401 | ||
| 403 | switch (target.cpu.arch) { | 402 | switch (macho_file.getTarget().cpu.arch) { |
| 404 | .aarch64 => { | 403 | .aarch64 => { |
| 405 | header.cputype = macho.CPU_TYPE_ARM64; | 404 | header.cputype = macho.CPU_TYPE_ARM64; |
| 406 | header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; | 405 | header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; |
| ... | @@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: | ... | @@ -412,8 +411,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: |
| 412 | else => return error.UnsupportedCpuArchitecture, | 411 | else => return error.UnsupportedCpuArchitecture, |
| 413 | } | 412 | } |
| 414 | 413 | ||
| 415 | header.ncmds = ncmds; | 414 | header.ncmds = @intCast(ncmds); |
| 416 | header.sizeofcmds = sizeofcmds; | 415 | header.sizeofcmds = @intCast(sizeofcmds); |
| 417 | 416 | ||
| 418 | log.debug("writing Mach-O header {}", .{header}); | 417 | log.debug("writing Mach-O header {}", .{header}); |
| 419 | 418 | ||
| ... | @@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { | ... | @@ -435,91 +434,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { |
| 435 | const tracy = trace(@src()); | 434 | const tracy = trace(@src()); |
| 436 | defer tracy.end(); | 435 | defer tracy.end(); |
| 437 | 436 | ||
| 438 | try self.writeSymtab(macho_file); | 437 | const page_size = macho_file.getPageSize(); |
| 439 | try self.writeStrtab(); | ||
| 440 | |||
| 441 | const target = macho_file.base.comp.root_mod.resolved_target.result; | ||
| 442 | const page_size = MachO.getPageSize(target.cpu.arch); | ||
| 443 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 438 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; |
| 439 | |||
| 440 | var off = math.cast(u32, seg.fileoff) orelse return error.Overflow; | ||
| 441 | off = try self.writeSymtab(off, macho_file); | ||
| 442 | off = mem.alignForward(u32, off, @alignOf(u64)); | ||
| 443 | off = try self.writeStrtab(off); | ||
| 444 | seg.filesize = off - seg.fileoff; | ||
| 445 | |||
| 444 | const aligned_size = mem.alignForward(u64, seg.filesize, page_size); | 446 | const aligned_size = mem.alignForward(u64, seg.filesize, page_size); |
| 445 | seg.vmsize = aligned_size; | 447 | seg.vmsize = aligned_size; |
| 446 | } | 448 | } |
| 447 | 449 | ||
| 448 | fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void { | 450 | pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { |
| 449 | const tracy = trace(@src()); | 451 | const tracy = trace(@src()); |
| 450 | defer tracy.end(); | 452 | defer tracy.end(); |
| 451 | |||
| 452 | const gpa = self.allocator; | 453 | const gpa = self.allocator; |
| 454 | const cmd = &self.symtab_cmd; | ||
| 455 | cmd.nsyms = macho_file.symtab_cmd.nsyms; | ||
| 456 | cmd.strsize = macho_file.symtab_cmd.strsize; | ||
| 457 | cmd.symoff = off; | ||
| 453 | 458 | ||
| 454 | var locals = std.ArrayList(macho.nlist_64).init(gpa); | 459 | try self.symtab.resize(gpa, cmd.nsyms); |
| 455 | defer locals.deinit(); | 460 | try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); |
| 456 | |||
| 457 | for (macho_file.locals.items, 0..) |sym, sym_id| { | ||
| 458 | if (sym.n_strx == 0) continue; // no name, skip | ||
| 459 | const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) }; | ||
| 460 | if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip | ||
| 461 | if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | ||
| 462 | var out_sym = sym; | ||
| 463 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc)); | ||
| 464 | try locals.append(out_sym); | ||
| 465 | } | ||
| 466 | 461 | ||
| 467 | var exports = std.ArrayList(macho.nlist_64).init(gpa); | 462 | if (macho_file.getZigObject()) |zo| { |
| 468 | defer exports.deinit(); | 463 | zo.writeSymtab(macho_file, self); |
| 469 | 464 | } | |
| 470 | for (macho_file.globals.items) |global| { | 465 | for (macho_file.objects.items) |index| { |
| 471 | const sym = macho_file.getSymbol(global); | 466 | try macho_file.getFile(index).?.writeSymtab(macho_file, self); |
| 472 | if (sym.undf()) continue; // import, skip | 467 | } |
| 473 | var out_sym = sym; | 468 | for (macho_file.dylibs.items) |index| { |
| 474 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global)); | 469 | try macho_file.getFile(index).?.writeSymtab(macho_file, self); |
| 475 | try exports.append(out_sym); | 470 | } |
| 471 | if (macho_file.getInternalObject()) |internal| { | ||
| 472 | internal.writeSymtab(macho_file, self); | ||
| 476 | } | 473 | } |
| 477 | 474 | ||
| 478 | const nlocals = locals.items.len; | 475 | assert(self.strtab.items.len == cmd.strsize); |
| 479 | const nexports = exports.items.len; | ||
| 480 | const nsyms = nlocals + nexports; | ||
| 481 | |||
| 482 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | ||
| 483 | const offset = mem.alignForward(u64, seg.fileoff, @alignOf(macho.nlist_64)); | ||
| 484 | const needed_size = nsyms * @sizeOf(macho.nlist_64); | ||
| 485 | seg.filesize = offset + needed_size - seg.fileoff; | ||
| 486 | |||
| 487 | self.symtab_cmd.symoff = @as(u32, @intCast(offset)); | ||
| 488 | self.symtab_cmd.nsyms = @as(u32, @intCast(nsyms)); | ||
| 489 | |||
| 490 | const locals_off = @as(u32, @intCast(offset)); | ||
| 491 | const locals_size = nlocals * @sizeOf(macho.nlist_64); | ||
| 492 | const exports_off = locals_off + locals_size; | ||
| 493 | const exports_size = nexports * @sizeOf(macho.nlist_64); | ||
| 494 | 476 | ||
| 495 | log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); | 477 | try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); |
| 496 | try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); | ||
| 497 | 478 | ||
| 498 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); | 479 | return off + cmd.nsyms * @sizeOf(macho.nlist_64); |
| 499 | try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); | ||
| 500 | } | 480 | } |
| 501 | 481 | ||
| 502 | fn writeStrtab(self: *DebugSymbols) !void { | 482 | pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 { |
| 503 | const tracy = trace(@src()); | 483 | const cmd = &self.symtab_cmd; |
| 504 | defer tracy.end(); | 484 | cmd.stroff = off; |
| 505 | 485 | try self.file.pwriteAll(self.strtab.items, cmd.stroff); | |
| 506 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | 486 | return off + cmd.strsize; |
| 507 | const symtab_size = @as(u32, @intCast(self.symtab_cmd.nsyms * @sizeOf(macho.nlist_64))); | ||
| 508 | const offset = mem.alignForward(u64, self.symtab_cmd.symoff + symtab_size, @alignOf(u64)); | ||
| 509 | const needed_size = mem.alignForward(u64, self.strtab.buffer.items.len, @alignOf(u64)); | ||
| 510 | |||
| 511 | seg.filesize = offset + needed_size - seg.fileoff; | ||
| 512 | self.symtab_cmd.stroff = @as(u32, @intCast(offset)); | ||
| 513 | self.symtab_cmd.strsize = @as(u32, @intCast(needed_size)); | ||
| 514 | |||
| 515 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | ||
| 516 | |||
| 517 | try self.file.pwriteAll(self.strtab.buffer.items, offset); | ||
| 518 | |||
| 519 | if (self.strtab.buffer.items.len < needed_size) { | ||
| 520 | // Ensure we are always padded to the actual length of the file. | ||
| 521 | try self.file.pwriteAll(&[_]u8{0}, offset + needed_size); | ||
| 522 | } | ||
| 523 | } | 487 | } |
| 524 | 488 | ||
| 525 | pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } { | 489 | pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } { |
| ... | @@ -559,7 +523,7 @@ const assert = std.debug.assert; | ... | @@ -559,7 +523,7 @@ const assert = std.debug.assert; |
| 559 | const fs = std.fs; | 523 | const fs = std.fs; |
| 560 | const link = @import("../../link.zig"); | 524 | const link = @import("../../link.zig"); |
| 561 | const load_commands = @import("load_commands.zig"); | 525 | const load_commands = @import("load_commands.zig"); |
| 562 | const log = std.log.scoped(.dsym); | 526 | const log = std.log.scoped(.link_dsym); |
| 563 | const macho = std.macho; | 527 | const macho = std.macho; |
| 564 | const makeStaticString = MachO.makeStaticString; | 528 | const makeStaticString = MachO.makeStaticString; |
| 565 | const math = std.math; | 529 | const math = std.math; |
src/link/MachO/Dylib.zig+5-5| ... | @@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void { | ... | @@ -576,7 +576,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) !void { |
| 576 | } | 576 | } |
| 577 | } | 577 | } |
| 578 | 578 | ||
| 579 | pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { | 579 | pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void { |
| 580 | const tracy = trace(@src()); | 580 | const tracy = trace(@src()); |
| 581 | defer tracy.end(); | 581 | defer tracy.end(); |
| 582 | 582 | ||
| ... | @@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { | ... | @@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { |
| 585 | const file = global.getFile(macho_file) orelse continue; | 585 | const file = global.getFile(macho_file) orelse continue; |
| 586 | if (file.getIndex() != self.index) continue; | 586 | if (file.getIndex() != self.index) continue; |
| 587 | const idx = global.getOutputSymtabIndex(macho_file) orelse continue; | 587 | const idx = global.getOutputSymtabIndex(macho_file) orelse continue; |
| 588 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 588 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 589 | macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); | 589 | ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); |
| 590 | macho_file.strtab.appendAssumeCapacity(0); | 590 | ctx.strtab.appendAssumeCapacity(0); |
| 591 | const out_sym = &macho_file.symtab.items[idx]; | 591 | const out_sym = &ctx.symtab.items[idx]; |
| 592 | out_sym.n_strx = n_strx; | 592 | out_sym.n_strx = n_strx; |
| 593 | global.setOutputSym(macho_file, out_sym); | 593 | global.setOutputSym(macho_file, out_sym); |
| 594 | } | 594 | } |
src/link/MachO/InternalObject.zig+5-5| ... | @@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void { | ... | @@ -139,15 +139,15 @@ pub fn calcSymtabSize(self: *InternalObject, macho_file: *MachO) !void { |
| 139 | } | 139 | } |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void { | 142 | pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void { |
| 143 | for (self.symbols.items) |sym_index| { | 143 | for (self.symbols.items) |sym_index| { |
| 144 | const sym = macho_file.getSymbol(sym_index); | 144 | const sym = macho_file.getSymbol(sym_index); |
| 145 | if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue; | 145 | if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue; |
| 146 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; | 146 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 147 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 147 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 148 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | 148 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); |
| 149 | macho_file.strtab.appendAssumeCapacity(0); | 149 | ctx.strtab.appendAssumeCapacity(0); |
| 150 | const out_sym = &macho_file.symtab.items[idx]; | 150 | const out_sym = &ctx.symtab.items[idx]; |
| 151 | out_sym.n_strx = n_strx; | 151 | out_sym.n_strx = n_strx; |
| 152 | sym.setOutputSym(macho_file, out_sym); | 152 | sym.setOutputSym(macho_file, out_sym); |
| 153 | } | 153 | } |
src/link/MachO/Object.zig+51-51| ... | @@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { | ... | @@ -1320,7 +1320,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { |
| 1320 | } | 1320 | } |
| 1321 | } | 1321 | } |
| 1322 | 1322 | ||
| 1323 | pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { | 1323 | pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void { |
| 1324 | const tracy = trace(@src()); | 1324 | const tracy = trace(@src()); |
| 1325 | defer tracy.end(); | 1325 | defer tracy.end(); |
| 1326 | 1326 | ||
| ... | @@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { | ... | @@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { |
| 1329 | const file = sym.getFile(macho_file) orelse continue; | 1329 | const file = sym.getFile(macho_file) orelse continue; |
| 1330 | if (file.getIndex() != self.index) continue; | 1330 | if (file.getIndex() != self.index) continue; |
| 1331 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; | 1331 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 1332 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1332 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1333 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | 1333 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); |
| 1334 | macho_file.strtab.appendAssumeCapacity(0); | 1334 | ctx.strtab.appendAssumeCapacity(0); |
| 1335 | const out_sym = &macho_file.symtab.items[idx]; | 1335 | const out_sym = &ctx.symtab.items[idx]; |
| 1336 | out_sym.n_strx = n_strx; | 1336 | out_sym.n_strx = n_strx; |
| 1337 | sym.setOutputSym(macho_file, out_sym); | 1337 | sym.setOutputSym(macho_file, out_sym); |
| 1338 | } | 1338 | } |
| 1339 | 1339 | ||
| 1340 | if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo()) | 1340 | if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo()) |
| 1341 | try self.writeStabs(macho_file); | 1341 | try self.writeStabs(macho_file, ctx); |
| 1342 | } | 1342 | } |
| 1343 | 1343 | ||
| 1344 | pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void { | 1344 | pub fn writeStabs(self: *const Object, macho_file: *MachO, ctx: anytype) error{Overflow}!void { |
| 1345 | const writeFuncStab = struct { | 1345 | const writeFuncStab = struct { |
| 1346 | inline fn writeFuncStab( | 1346 | inline fn writeFuncStab( |
| 1347 | n_strx: u32, | 1347 | n_strx: u32, |
| ... | @@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1349 | n_value: u64, | 1349 | n_value: u64, |
| 1350 | size: u64, | 1350 | size: u64, |
| 1351 | index: u32, | 1351 | index: u32, |
| 1352 | ctx: *MachO, | 1352 | context: anytype, |
| 1353 | ) void { | 1353 | ) void { |
| 1354 | ctx.symtab.items[index] = .{ | 1354 | context.symtab.items[index] = .{ |
| 1355 | .n_strx = 0, | 1355 | .n_strx = 0, |
| 1356 | .n_type = macho.N_BNSYM, | 1356 | .n_type = macho.N_BNSYM, |
| 1357 | .n_sect = n_sect, | 1357 | .n_sect = n_sect, |
| 1358 | .n_desc = 0, | 1358 | .n_desc = 0, |
| 1359 | .n_value = n_value, | 1359 | .n_value = n_value, |
| 1360 | }; | 1360 | }; |
| 1361 | ctx.symtab.items[index + 1] = .{ | 1361 | context.symtab.items[index + 1] = .{ |
| 1362 | .n_strx = n_strx, | 1362 | .n_strx = n_strx, |
| 1363 | .n_type = macho.N_FUN, | 1363 | .n_type = macho.N_FUN, |
| 1364 | .n_sect = n_sect, | 1364 | .n_sect = n_sect, |
| 1365 | .n_desc = 0, | 1365 | .n_desc = 0, |
| 1366 | .n_value = n_value, | 1366 | .n_value = n_value, |
| 1367 | }; | 1367 | }; |
| 1368 | ctx.symtab.items[index + 2] = .{ | 1368 | context.symtab.items[index + 2] = .{ |
| 1369 | .n_strx = 0, | 1369 | .n_strx = 0, |
| 1370 | .n_type = macho.N_FUN, | 1370 | .n_type = macho.N_FUN, |
| 1371 | .n_sect = 0, | 1371 | .n_sect = 0, |
| 1372 | .n_desc = 0, | 1372 | .n_desc = 0, |
| 1373 | .n_value = size, | 1373 | .n_value = size, |
| 1374 | }; | 1374 | }; |
| 1375 | ctx.symtab.items[index + 3] = .{ | 1375 | context.symtab.items[index + 3] = .{ |
| 1376 | .n_strx = 0, | 1376 | .n_strx = 0, |
| 1377 | .n_type = macho.N_ENSYM, | 1377 | .n_type = macho.N_ENSYM, |
| 1378 | .n_sect = n_sect, | 1378 | .n_sect = n_sect, |
| ... | @@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1392 | 1392 | ||
| 1393 | // Open scope | 1393 | // Open scope |
| 1394 | // N_SO comp_dir | 1394 | // N_SO comp_dir |
| 1395 | var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1395 | var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1396 | macho_file.strtab.appendSliceAssumeCapacity(comp_dir); | 1396 | ctx.strtab.appendSliceAssumeCapacity(comp_dir); |
| 1397 | macho_file.strtab.appendAssumeCapacity(0); | 1397 | ctx.strtab.appendAssumeCapacity(0); |
| 1398 | macho_file.symtab.items[index] = .{ | 1398 | ctx.symtab.items[index] = .{ |
| 1399 | .n_strx = n_strx, | 1399 | .n_strx = n_strx, |
| 1400 | .n_type = macho.N_SO, | 1400 | .n_type = macho.N_SO, |
| 1401 | .n_sect = 0, | 1401 | .n_sect = 0, |
| ... | @@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1404 | }; | 1404 | }; |
| 1405 | index += 1; | 1405 | index += 1; |
| 1406 | // N_SO tu_name | 1406 | // N_SO tu_name |
| 1407 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1407 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1408 | macho_file.strtab.appendSliceAssumeCapacity(tu_name); | 1408 | ctx.strtab.appendSliceAssumeCapacity(tu_name); |
| 1409 | macho_file.strtab.appendAssumeCapacity(0); | 1409 | ctx.strtab.appendAssumeCapacity(0); |
| 1410 | macho_file.symtab.items[index] = .{ | 1410 | ctx.symtab.items[index] = .{ |
| 1411 | .n_strx = n_strx, | 1411 | .n_strx = n_strx, |
| 1412 | .n_type = macho.N_SO, | 1412 | .n_type = macho.N_SO, |
| 1413 | .n_sect = 0, | 1413 | .n_sect = 0, |
| ... | @@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1416 | }; | 1416 | }; |
| 1417 | index += 1; | 1417 | index += 1; |
| 1418 | // N_OSO path | 1418 | // N_OSO path |
| 1419 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1419 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1420 | if (self.archive) |ar| { | 1420 | if (self.archive) |ar| { |
| 1421 | macho_file.strtab.appendSliceAssumeCapacity(ar.path); | 1421 | ctx.strtab.appendSliceAssumeCapacity(ar.path); |
| 1422 | macho_file.strtab.appendAssumeCapacity('('); | 1422 | ctx.strtab.appendAssumeCapacity('('); |
| 1423 | macho_file.strtab.appendSliceAssumeCapacity(self.path); | 1423 | ctx.strtab.appendSliceAssumeCapacity(self.path); |
| 1424 | macho_file.strtab.appendAssumeCapacity(')'); | 1424 | ctx.strtab.appendAssumeCapacity(')'); |
| 1425 | macho_file.strtab.appendAssumeCapacity(0); | 1425 | ctx.strtab.appendAssumeCapacity(0); |
| 1426 | } else { | 1426 | } else { |
| 1427 | macho_file.strtab.appendSliceAssumeCapacity(self.path); | 1427 | ctx.strtab.appendSliceAssumeCapacity(self.path); |
| 1428 | macho_file.strtab.appendAssumeCapacity(0); | 1428 | ctx.strtab.appendAssumeCapacity(0); |
| 1429 | } | 1429 | } |
| 1430 | macho_file.symtab.items[index] = .{ | 1430 | ctx.symtab.items[index] = .{ |
| 1431 | .n_strx = n_strx, | 1431 | .n_strx = n_strx, |
| 1432 | .n_type = macho.N_OSO, | 1432 | .n_type = macho.N_OSO, |
| 1433 | .n_sect = 0, | 1433 | .n_sect = 0, |
| ... | @@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1448 | const sect = macho_file.sections.items(.header)[sym.out_n_sect]; | 1448 | const sect = macho_file.sections.items(.header)[sym.out_n_sect]; |
| 1449 | const sym_n_strx = n_strx: { | 1449 | const sym_n_strx = n_strx: { |
| 1450 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; | 1450 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; |
| 1451 | const osym = macho_file.symtab.items[symtab_index]; | 1451 | const osym = ctx.symtab.items[symtab_index]; |
| 1452 | break :n_strx osym.n_strx; | 1452 | break :n_strx osym.n_strx; |
| 1453 | }; | 1453 | }; |
| 1454 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; | 1454 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; |
| 1455 | const sym_n_value = sym.getAddress(.{}, macho_file); | 1455 | const sym_n_value = sym.getAddress(.{}, macho_file); |
| 1456 | const sym_size = sym.getSize(macho_file); | 1456 | const sym_size = sym.getSize(macho_file); |
| 1457 | if (sect.isCode()) { | 1457 | if (sect.isCode()) { |
| 1458 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); | 1458 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); |
| 1459 | index += 4; | 1459 | index += 4; |
| 1460 | } else if (sym.visibility == .global) { | 1460 | } else if (sym.visibility == .global) { |
| 1461 | macho_file.symtab.items[index] = .{ | 1461 | ctx.symtab.items[index] = .{ |
| 1462 | .n_strx = sym_n_strx, | 1462 | .n_strx = sym_n_strx, |
| 1463 | .n_type = macho.N_GSYM, | 1463 | .n_type = macho.N_GSYM, |
| 1464 | .n_sect = sym_n_sect, | 1464 | .n_sect = sym_n_sect, |
| ... | @@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1467 | }; | 1467 | }; |
| 1468 | index += 1; | 1468 | index += 1; |
| 1469 | } else { | 1469 | } else { |
| 1470 | macho_file.symtab.items[index] = .{ | 1470 | ctx.symtab.items[index] = .{ |
| 1471 | .n_strx = sym_n_strx, | 1471 | .n_strx = sym_n_strx, |
| 1472 | .n_type = macho.N_STSYM, | 1472 | .n_type = macho.N_STSYM, |
| 1473 | .n_sect = sym_n_sect, | 1473 | .n_sect = sym_n_sect, |
| ... | @@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1480 | 1480 | ||
| 1481 | // Close scope | 1481 | // Close scope |
| 1482 | // N_SO | 1482 | // N_SO |
| 1483 | macho_file.symtab.items[index] = .{ | 1483 | ctx.symtab.items[index] = .{ |
| 1484 | .n_strx = 0, | 1484 | .n_strx = 0, |
| 1485 | .n_type = macho.N_SO, | 1485 | .n_type = macho.N_SO, |
| 1486 | .n_sect = 0, | 1486 | .n_sect = 0, |
| ... | @@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1493 | for (self.stab_files.items) |sf| { | 1493 | for (self.stab_files.items) |sf| { |
| 1494 | // Open scope | 1494 | // Open scope |
| 1495 | // N_SO comp_dir | 1495 | // N_SO comp_dir |
| 1496 | var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1496 | var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1497 | macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); | 1497 | ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); |
| 1498 | macho_file.strtab.appendAssumeCapacity(0); | 1498 | ctx.strtab.appendAssumeCapacity(0); |
| 1499 | macho_file.symtab.items[index] = .{ | 1499 | ctx.symtab.items[index] = .{ |
| 1500 | .n_strx = n_strx, | 1500 | .n_strx = n_strx, |
| 1501 | .n_type = macho.N_SO, | 1501 | .n_type = macho.N_SO, |
| 1502 | .n_sect = 0, | 1502 | .n_sect = 0, |
| ... | @@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1505 | }; | 1505 | }; |
| 1506 | index += 1; | 1506 | index += 1; |
| 1507 | // N_SO tu_name | 1507 | // N_SO tu_name |
| 1508 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1508 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1509 | macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); | 1509 | ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); |
| 1510 | macho_file.strtab.appendAssumeCapacity(0); | 1510 | ctx.strtab.appendAssumeCapacity(0); |
| 1511 | macho_file.symtab.items[index] = .{ | 1511 | ctx.symtab.items[index] = .{ |
| 1512 | .n_strx = n_strx, | 1512 | .n_strx = n_strx, |
| 1513 | .n_type = macho.N_SO, | 1513 | .n_type = macho.N_SO, |
| 1514 | .n_sect = 0, | 1514 | .n_sect = 0, |
| ... | @@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1517 | }; | 1517 | }; |
| 1518 | index += 1; | 1518 | index += 1; |
| 1519 | // N_OSO path | 1519 | // N_OSO path |
| 1520 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 1520 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 1521 | macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); | 1521 | ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); |
| 1522 | macho_file.strtab.appendAssumeCapacity(0); | 1522 | ctx.strtab.appendAssumeCapacity(0); |
| 1523 | macho_file.symtab.items[index] = .{ | 1523 | ctx.symtab.items[index] = .{ |
| 1524 | .n_strx = n_strx, | 1524 | .n_strx = n_strx, |
| 1525 | .n_type = macho.N_OSO, | 1525 | .n_type = macho.N_OSO, |
| 1526 | .n_sect = 0, | 1526 | .n_sect = 0, |
| ... | @@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1536 | if (!sym.flags.output_symtab) continue; | 1536 | if (!sym.flags.output_symtab) continue; |
| 1537 | const sym_n_strx = n_strx: { | 1537 | const sym_n_strx = n_strx: { |
| 1538 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; | 1538 | const symtab_index = sym.getOutputSymtabIndex(macho_file).?; |
| 1539 | const osym = macho_file.symtab.items[symtab_index]; | 1539 | const osym = ctx.symtab.items[symtab_index]; |
| 1540 | break :n_strx osym.n_strx; | 1540 | break :n_strx osym.n_strx; |
| 1541 | }; | 1541 | }; |
| 1542 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; | 1542 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; |
| ... | @@ -1544,11 +1544,11 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1544,11 +1544,11 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1544 | const sym_size = sym.getSize(macho_file); | 1544 | const sym_size = sym.getSize(macho_file); |
| 1545 | switch (stab.tag) { | 1545 | switch (stab.tag) { |
| 1546 | .func => { | 1546 | .func => { |
| 1547 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); | 1547 | writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); |
| 1548 | index += 4; | 1548 | index += 4; |
| 1549 | }, | 1549 | }, |
| 1550 | .global => { | 1550 | .global => { |
| 1551 | macho_file.symtab.items[index] = .{ | 1551 | ctx.symtab.items[index] = .{ |
| 1552 | .n_strx = sym_n_strx, | 1552 | .n_strx = sym_n_strx, |
| 1553 | .n_type = macho.N_GSYM, | 1553 | .n_type = macho.N_GSYM, |
| 1554 | .n_sect = sym_n_sect, | 1554 | .n_sect = sym_n_sect, |
| ... | @@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1558 | index += 1; | 1558 | index += 1; |
| 1559 | }, | 1559 | }, |
| 1560 | .static => { | 1560 | .static => { |
| 1561 | macho_file.symtab.items[index] = .{ | 1561 | ctx.symtab.items[index] = .{ |
| 1562 | .n_strx = sym_n_strx, | 1562 | .n_strx = sym_n_strx, |
| 1563 | .n_type = macho.N_STSYM, | 1563 | .n_type = macho.N_STSYM, |
| 1564 | .n_sect = sym_n_sect, | 1564 | .n_sect = sym_n_sect, |
| ... | @@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void | ... | @@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1572 | 1572 | ||
| 1573 | // Close scope | 1573 | // Close scope |
| 1574 | // N_SO | 1574 | // N_SO |
| 1575 | macho_file.symtab.items[index] = .{ | 1575 | ctx.symtab.items[index] = .{ |
| 1576 | .n_strx = 0, | 1576 | .n_strx = 0, |
| 1577 | .n_type = macho.N_SO, | 1577 | .n_type = macho.N_SO, |
| 1578 | .n_sect = 0, | 1578 | .n_sect = 0, |
src/link/MachO/ZigObject.zig+5-5| ... | @@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void { | ... | @@ -310,7 +310,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void { |
| 310 | } | 310 | } |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { | 313 | pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void { |
| 314 | const tracy = trace(@src()); | 314 | const tracy = trace(@src()); |
| 315 | defer tracy.end(); | 315 | defer tracy.end(); |
| 316 | 316 | ||
| ... | @@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { | ... | @@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { |
| 319 | const file = sym.getFile(macho_file) orelse continue; | 319 | const file = sym.getFile(macho_file) orelse continue; |
| 320 | if (file.getIndex() != self.index) continue; | 320 | if (file.getIndex() != self.index) continue; |
| 321 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; | 321 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 322 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | 322 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); |
| 323 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | 323 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); |
| 324 | macho_file.strtab.appendAssumeCapacity(0); | 324 | ctx.strtab.appendAssumeCapacity(0); |
| 325 | const out_sym = &macho_file.symtab.items[idx]; | 325 | const out_sym = &ctx.symtab.items[idx]; |
| 326 | out_sym.n_strx = n_strx; | 326 | out_sym.n_strx = n_strx; |
| 327 | sym.setOutputSym(macho_file, out_sym); | 327 | sym.setOutputSym(macho_file, out_sym); |
| 328 | } | 328 | } |
src/link/MachO/file.zig+2-2| ... | @@ -90,9 +90,9 @@ pub const File = union(enum) { | ... | @@ -90,9 +90,9 @@ pub const File = union(enum) { |
| 90 | }; | 90 | }; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | pub fn writeSymtab(file: File, macho_file: *MachO) !void { | 93 | pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void { |
| 94 | return switch (file) { | 94 | return switch (file) { |
| 95 | inline else => |x| x.writeSymtab(macho_file), | 95 | inline else => |x| x.writeSymtab(macho_file, ctx), |
| 96 | }; | 96 | }; |
| 97 | } | 97 | } |
| 98 | 98 |
src/link/MachO/load_commands.zig+22| ... | @@ -5,6 +5,7 @@ const macho = std.macho; | ... | @@ -5,6 +5,7 @@ const macho = std.macho; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | 6 | ||
| 7 | const Allocator = mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| 8 | const DebugSymbols = @import("DebugSymbols.zig"); | ||
| 8 | const Dylib = @import("Dylib.zig"); | 9 | const Dylib = @import("Dylib.zig"); |
| 9 | const MachO = @import("../MachO.zig"); | 10 | const MachO = @import("../MachO.zig"); |
| 10 | 11 | ||
| ... | @@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 { | ... | @@ -97,6 +98,27 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) u32 { |
| 97 | return @as(u32, @intCast(sizeofcmds)); | 98 | return @as(u32, @intCast(sizeofcmds)); |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 101 | pub fn calcLoadCommandsSizeDsym(macho_file: *MachO, dsym: *const DebugSymbols) u32 { | ||
| 102 | var sizeofcmds: u64 = 0; | ||
| 103 | |||
| 104 | // LC_SEGMENT_64 | ||
| 105 | sizeofcmds += @sizeOf(macho.segment_command_64) * (macho_file.segments.items.len - 1); | ||
| 106 | for (macho_file.segments.items) |seg| { | ||
| 107 | sizeofcmds += seg.nsects * @sizeOf(macho.section_64); | ||
| 108 | } | ||
| 109 | sizeofcmds += @sizeOf(macho.segment_command_64) * dsym.segments.items.len; | ||
| 110 | for (dsym.segments.items) |seg| { | ||
| 111 | sizeofcmds += seg.nsects * @sizeOf(macho.section_64); | ||
| 112 | } | ||
| 113 | |||
| 114 | // LC_SYMTAB | ||
| 115 | sizeofcmds += @sizeOf(macho.symtab_command); | ||
| 116 | // LC_UUID | ||
| 117 | sizeofcmds += @sizeOf(macho.uuid_command); | ||
| 118 | |||
| 119 | return @as(u32, @intCast(sizeofcmds)); | ||
| 120 | } | ||
| 121 | |||
| 100 | pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { | 122 | pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { |
| 101 | var sizeofcmds: u64 = 0; | 123 | var sizeofcmds: u64 = 0; |
| 102 | 124 |