| author | |
| committer | |
| log | 3e939e61538706f37abb76a97af0ee77c15b24fc |
| tree | 115e68db5a398834f7bf3034275ad5e54a27da04 |
| parent | f93a36c091a151ed02602d2f330f7206eb9f95a3 |
| parent | 78740e55406ebf82371f385bbbf54f224949b8cb |
| signature |
macho: reinstate DWARF in self-hosted x86_64-macho9 files changed, 278 insertions(+), 283 deletions(-)
src/link/Dwarf.zig-1| ... | ... | @@ -1468,7 +1468,6 @@ pub fn commitDeclState( |
| 1468 | 1468 | .target = reloc.target, |
| 1469 | 1469 | .offset = reloc.offset + self.getAtom(.di_atom, di_atom_index).off, |
| 1470 | 1470 | .addend = 0, |
| 1471 | .prev_vaddr = 0, | |
| 1472 | 1471 | }); |
| 1473 | 1472 | }, |
| 1474 | 1473 | .elf => {}, // TODO |
src/link/MachO.zig+45-37| ... | ... | @@ -256,32 +256,39 @@ pub fn createEmpty( |
| 256 | 256 | .program_code_size_hint = options.program_code_size_hint, |
| 257 | 257 | }); |
| 258 | 258 | |
| 259 | // TODO init dwarf | |
| 260 | ||
| 261 | // if (comp.config.debug_format != .strip) { | |
| 262 | // // Create dSYM bundle. | |
| 263 | // log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); | |
| 264 | ||
| 265 | // const d_sym_path = try std.fmt.allocPrint( | |
| 266 | // arena, | |
| 267 | // "{s}.dSYM" ++ fs.path.sep_str ++ "Contents" ++ fs.path.sep_str ++ "Resources" ++ fs.path.sep_str ++ "DWARF", | |
| 268 | // .{emit.sub_path}, | |
| 269 | // ); | |
| 270 | ||
| 271 | // var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); | |
| 272 | // defer d_sym_bundle.close(); | |
| 273 | ||
| 274 | // const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ | |
| 275 | // .truncate = false, | |
| 276 | // .read = true, | |
| 277 | // }); | |
| 278 | ||
| 279 | // self.d_sym = .{ | |
| 280 | // .allocator = gpa, | |
| 281 | // .dwarf = link.File.Dwarf.init(&self.base, .dwarf32), | |
| 282 | // .file = d_sym_file, | |
| 283 | // }; | |
| 284 | // } | |
| 259 | switch (comp.config.debug_format) { | |
| 260 | .strip => {}, | |
| 261 | .dwarf => if (!self.base.isRelocatable()) { | |
| 262 | // Create dSYM bundle. | |
| 263 | log.debug("creating {s}.dSYM bundle", .{emit.sub_path}); | |
| 264 | ||
| 265 | const sep = fs.path.sep_str; | |
| 266 | const d_sym_path = try std.fmt.allocPrint( | |
| 267 | arena, | |
| 268 | "{s}.dSYM" ++ sep ++ "Contents" ++ sep ++ "Resources" ++ sep ++ "DWARF", | |
| 269 | .{emit.sub_path}, | |
| 270 | ); | |
| 271 | ||
| 272 | var d_sym_bundle = try emit.directory.handle.makeOpenPath(d_sym_path, .{}); | |
| 273 | defer d_sym_bundle.close(); | |
| 274 | ||
| 275 | const d_sym_file = try d_sym_bundle.createFile(emit.sub_path, .{ | |
| 276 | .truncate = false, | |
| 277 | .read = true, | |
| 278 | }); | |
| 279 | ||
| 280 | self.d_sym = .{ | |
| 281 | .allocator = gpa, | |
| 282 | .dwarf = link.File.Dwarf.init(&self.base, .dwarf32), | |
| 283 | .file = d_sym_file, | |
| 284 | }; | |
| 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; | |
| 289 | }, | |
| 290 | .code_view => unreachable, | |
| 291 | } | |
| 285 | 292 | } |
| 286 | 293 | } |
| 287 | 294 | |
| ... | ... | @@ -692,6 +699,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 692 | 699 | const ncmds, const sizeofcmds, const uuid_cmd_offset = try self.writeLoadCommands(); |
| 693 | 700 | try self.writeHeader(ncmds, sizeofcmds); |
| 694 | 701 | try self.writeUuid(uuid_cmd_offset, self.requiresCodeSig()); |
| 702 | if (self.getDebugSymbols()) |dsym| try dsym.flushModule(self); | |
| 695 | 703 | |
| 696 | 704 | if (codesig) |*csig| { |
| 697 | 705 | try self.writeCodeSignature(csig); // code signing always comes last |
| ... | ... | @@ -731,9 +739,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 731 | 739 | try argv.append("-r"); |
| 732 | 740 | } |
| 733 | 741 | |
| 734 | try argv.append("-o"); | |
| 735 | try argv.append(full_out_path); | |
| 736 | ||
| 737 | 742 | if (self.base.isRelocatable()) { |
| 738 | 743 | for (comp.objects) |obj| { |
| 739 | 744 | try argv.append(obj.path); |
| ... | ... | @@ -2047,7 +2052,11 @@ pub fn sortSections(self: *MachO) !void { |
| 2047 | 2052 | for (&[_]*?u8{ |
| 2048 | 2053 | &self.data_sect_index, |
| 2049 | 2054 | &self.got_sect_index, |
| 2055 | &self.zig_text_sect_index, | |
| 2050 | 2056 | &self.zig_got_sect_index, |
| 2057 | &self.zig_const_sect_index, | |
| 2058 | &self.zig_data_sect_index, | |
| 2059 | &self.zig_bss_sect_index, | |
| 2051 | 2060 | &self.stubs_sect_index, |
| 2052 | 2061 | &self.stubs_helper_sect_index, |
| 2053 | 2062 | &self.la_symbol_ptr_sect_index, |
| ... | ... | @@ -2901,16 +2910,16 @@ pub fn writeSymtab(self: *MachO, off: u32) !u32 { |
| 2901 | 2910 | try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); |
| 2902 | 2911 | |
| 2903 | 2912 | if (self.getZigObject()) |zo| { |
| 2904 | zo.writeSymtab(self); | |
| 2913 | zo.writeSymtab(self, self); | |
| 2905 | 2914 | } |
| 2906 | 2915 | for (self.objects.items) |index| { |
| 2907 | try self.getFile(index).?.writeSymtab(self); | |
| 2916 | try self.getFile(index).?.writeSymtab(self, self); | |
| 2908 | 2917 | } |
| 2909 | 2918 | for (self.dylibs.items) |index| { |
| 2910 | try self.getFile(index).?.writeSymtab(self); | |
| 2919 | try self.getFile(index).?.writeSymtab(self, self); | |
| 2911 | 2920 | } |
| 2912 | 2921 | if (self.getInternalObject()) |internal| { |
| 2913 | internal.writeSymtab(self); | |
| 2922 | internal.writeSymtab(self, self); | |
| 2914 | 2923 | } |
| 2915 | 2924 | |
| 2916 | 2925 | assert(self.strtab.items.len == cmd.strsize); |
| ... | ... | @@ -3176,7 +3185,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) |
| 3176 | 3185 | |
| 3177 | 3186 | pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void { |
| 3178 | 3187 | if (self.llvm_object) |_| return; |
| 3179 | return self.getZigObject().?.updateDeclLineNumber(module, decl_index); | |
| 3188 | return self.getZigObject().?.updateDeclLineNumber(self, module, decl_index); | |
| 3180 | 3189 | } |
| 3181 | 3190 | |
| 3182 | 3191 | pub fn updateExports( |
| ... | ... | @@ -3909,9 +3918,8 @@ fn reportDuplicates(self: *MachO, dupes: anytype) error{ HasDuplicates, OutOfMem |
| 3909 | 3918 | } |
| 3910 | 3919 | |
| 3911 | 3920 | pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols { |
| 3912 | if (self.d_sym) |*ds| { | |
| 3913 | return ds; | |
| 3914 | } else return null; | |
| 3921 | if (self.d_sym) |*ds| return ds; | |
| 3922 | return null; | |
| 3915 | 3923 | } |
| 3916 | 3924 | |
| 3917 | 3925 | pub fn ptraceAttach(self: *MachO, pid: std.os.pid_t) !void { |
src/link/MachO/DebugSymbols.zig+117-153| ... | ... | @@ -3,6 +3,7 @@ dwarf: Dwarf, |
| 3 | 3 | file: fs.File, |
| 4 | 4 | |
| 5 | 5 | symtab_cmd: macho.symtab_command = .{}, |
| 6 | uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, | |
| 6 | 7 | |
| 7 | 8 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, |
| 8 | 9 | sections: std.ArrayListUnmanaged(macho.section_64) = .{}, |
| ... | ... | @@ -22,9 +23,12 @@ debug_aranges_section_dirty: bool = false, |
| 22 | 23 | debug_info_header_dirty: bool = false, |
| 23 | 24 | debug_line_header_dirty: bool = false, |
| 24 | 25 | |
| 25 | strtab: StringTable = .{}, | |
| 26 | 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 | 32 | pub const Reloc = struct { |
| 29 | 33 | type: enum { |
| 30 | 34 | direct_load, |
| ... | ... | @@ -33,18 +37,17 @@ pub const Reloc = struct { |
| 33 | 37 | target: u32, |
| 34 | 38 | offset: u64, |
| 35 | 39 | addend: u32, |
| 36 | prev_vaddr: u64, | |
| 37 | 40 | }; |
| 38 | 41 | |
| 39 | /// You must call this function *after* `MachO.populateMissingMetadata()` | |
| 42 | /// You must call this function *after* `ZigObject.initMetadata()` | |
| 40 | 43 | /// has been called to get a viable debug symbols output. |
| 41 | pub fn populateMissingMetadata(self: *DebugSymbols, macho_file: *MachO) !void { | |
| 42 | const target = macho_file.base.comp.root_mod.resolved_target.result; | |
| 44 | pub fn initMetadata(self: *DebugSymbols, macho_file: *MachO) !void { | |
| 45 | try self.strtab.append(self.allocator, 0); | |
| 43 | 46 | |
| 44 | 47 | if (self.dwarf_segment_cmd_index == null) { |
| 45 | 48 | self.dwarf_segment_cmd_index = @as(u8, @intCast(self.segments.items.len)); |
| 46 | 49 | |
| 47 | const page_size = MachO.getPageSize(target.cpu.arch); | |
| 50 | const page_size = macho_file.getPageSize(); | |
| 48 | 51 | const off = @as(u64, @intCast(page_size)); |
| 49 | 52 | const ideal_size: u16 = 200 + 128 + 160 + 250; |
| 50 | 53 | const needed_size = mem.alignForward(u64, padToIdeal(ideal_size), page_size); |
| ... | ... | @@ -203,35 +206,24 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 203 | 206 | // and it corresponds to the Zig source code. |
| 204 | 207 | const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 205 | 208 | |
| 209 | try self.dwarf.flushModule(zcu); | |
| 210 | ||
| 206 | 211 | for (self.relocs.items) |*reloc| { |
| 207 | const sym = switch (reloc.type) { | |
| 208 | .direct_load => macho_file.getSymbol(.{ .sym_index = reloc.target }), | |
| 209 | .got_load => blk: { | |
| 210 | const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; | |
| 211 | const got_entry = macho_file.got_table.entries.items[got_index]; | |
| 212 | break :blk macho_file.getSymbol(got_entry); | |
| 213 | }, | |
| 214 | }; | |
| 215 | if (sym.n_value == reloc.prev_vaddr) continue; | |
| 216 | ||
| 217 | const sym_name = switch (reloc.type) { | |
| 218 | .direct_load => macho_file.getSymbolName(.{ .sym_index = reloc.target }), | |
| 219 | .got_load => blk: { | |
| 220 | const got_index = macho_file.got_table.lookup.get(.{ .sym_index = reloc.target }).?; | |
| 221 | const got_entry = macho_file.got_table.entries.items[got_index]; | |
| 222 | break :blk macho_file.getSymbolName(got_entry); | |
| 223 | }, | |
| 212 | const sym = macho_file.getSymbol(reloc.target); | |
| 213 | const sym_name = sym.getName(macho_file); | |
| 214 | const addr = switch (reloc.type) { | |
| 215 | .direct_load => sym.getAddress(.{}, macho_file), | |
| 216 | .got_load => sym.getGotAddress(macho_file), | |
| 224 | 217 | }; |
| 225 | 218 | const sect = &self.sections.items[self.debug_info_section_index.?]; |
| 226 | 219 | const file_offset = sect.offset + reloc.offset; |
| 227 | 220 | log.debug("resolving relocation: {d}@{x} ('{s}') at offset {x}", .{ |
| 228 | 221 | reloc.target, |
| 229 | sym.n_value, | |
| 222 | addr, | |
| 230 | 223 | sym_name, |
| 231 | 224 | file_offset, |
| 232 | 225 | }); |
| 233 | try self.file.pwriteAll(mem.asBytes(&sym.n_value), file_offset); | |
| 234 | reloc.prev_vaddr = sym.n_value; | |
| 226 | try self.file.pwriteAll(mem.asBytes(&addr), file_offset); | |
| 235 | 227 | } |
| 236 | 228 | |
| 237 | 229 | if (self.debug_abbrev_section_dirty) { |
| ... | ... | @@ -242,7 +234,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 242 | 234 | if (self.debug_info_header_dirty) { |
| 243 | 235 | // Currently only one compilation unit is supported, so the address range is simply |
| 244 | 236 | // identical to the main program header virtual address and memory size. |
| 245 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; | |
| 237 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | |
| 246 | 238 | const low_pc = text_section.addr; |
| 247 | 239 | const high_pc = text_section.addr + text_section.size; |
| 248 | 240 | try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc); |
| ... | ... | @@ -252,7 +244,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 252 | 244 | if (self.debug_aranges_section_dirty) { |
| 253 | 245 | // Currently only one compilation unit is supported, so the address range is simply |
| 254 | 246 | // identical to the main program header virtual address and memory size. |
| 255 | const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?]; | |
| 247 | const text_section = macho_file.sections.items(.header)[macho_file.zig_text_sect_index.?]; | |
| 256 | 248 | try self.dwarf.writeDbgAranges(text_section.addr, text_section.size); |
| 257 | 249 | self.debug_aranges_section_dirty = false; |
| 258 | 250 | } |
| ... | ... | @@ -276,17 +268,8 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { |
| 276 | 268 | try self.writeLinkeditSegmentData(macho_file); |
| 277 | 269 | |
| 278 | 270 | // Write load commands |
| 279 | var lc_buffer = std.ArrayList(u8).init(self.allocator); | |
| 280 | defer lc_buffer.deinit(); | |
| 281 | const lc_writer = lc_buffer.writer(); | |
| 282 | ||
| 283 | try self.writeSegmentHeaders(macho_file, lc_writer); | |
| 284 | try lc_writer.writeStruct(self.symtab_cmd); | |
| 285 | try lc_writer.writeStruct(macho_file.uuid_cmd); | |
| 286 | ||
| 287 | const ncmds = load_commands.calcNumOfLCs(lc_buffer.items); | |
| 288 | try self.file.pwriteAll(lc_buffer.items, @sizeOf(macho.mach_header_64)); | |
| 289 | try self.writeHeader(macho_file, ncmds, @as(u32, @intCast(lc_buffer.items.len))); | |
| 271 | const ncmds, const sizeofcmds = try self.writeLoadCommands(macho_file); | |
| 272 | try self.writeHeader(macho_file, ncmds, sizeofcmds); | |
| 290 | 273 | |
| 291 | 274 | assert(!self.debug_abbrev_section_dirty); |
| 292 | 275 | assert(!self.debug_aranges_section_dirty); |
| ... | ... | @@ -299,8 +282,9 @@ pub fn deinit(self: *DebugSymbols) void { |
| 299 | 282 | self.segments.deinit(gpa); |
| 300 | 283 | self.sections.deinit(gpa); |
| 301 | 284 | self.dwarf.deinit(); |
| 302 | self.strtab.deinit(gpa); | |
| 303 | 285 | self.relocs.deinit(gpa); |
| 286 | self.symtab.deinit(gpa); | |
| 287 | self.strtab.deinit(gpa); | |
| 304 | 288 | } |
| 305 | 289 | |
| 306 | 290 | pub fn swapRemoveRelocs(self: *DebugSymbols, target: u32) void { |
| ... | ... | @@ -324,7 +308,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 324 | 308 | // however at the cost of having LINKEDIT preceed DWARF in dSYM binary which we |
| 325 | 309 | // do not want as we want to be able to incrementally move DWARF sections in the |
| 326 | 310 | // file as we please. |
| 327 | const last_seg = macho_file.getLinkeditSegmentPtr(); | |
| 311 | const last_seg = macho_file.getLinkeditSegment(); | |
| 328 | 312 | break :blk last_seg.vmaddr + last_seg.vmsize; |
| 329 | 313 | }; |
| 330 | 314 | const dwarf_segment = self.getDwarfSegmentPtr(); |
| ... | ... | @@ -334,8 +318,7 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 334 | 318 | file_size = @max(file_size, header.offset + header.size); |
| 335 | 319 | } |
| 336 | 320 | |
| 337 | const target = macho_file.base.comp.root_mod.resolved_target.result; | |
| 338 | const page_size = MachO.getPageSize(target.cpu.arch); | |
| 321 | const page_size = macho_file.getPageSize(); | |
| 339 | 322 | const aligned_size = mem.alignForward(u64, file_size, page_size); |
| 340 | 323 | dwarf_segment.vmaddr = base_vmaddr; |
| 341 | 324 | dwarf_segment.filesize = aligned_size; |
| ... | ... | @@ -355,54 +338,70 @@ fn finalizeDwarfSegment(self: *DebugSymbols, macho_file: *MachO) void { |
| 355 | 338 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{linkedit.fileoff}); |
| 356 | 339 | } |
| 357 | 340 | |
| 358 | fn writeSegmentHeaders(self: *DebugSymbols, macho_file: *MachO, writer: anytype) !void { | |
| 359 | // Write segment/section headers from the binary file first. | |
| 360 | const end = macho_file.linkedit_segment_cmd_index.?; | |
| 361 | for (macho_file.segments.items[0..end], 0..) |seg, i| { | |
| 362 | const indexes = macho_file.getSectionIndexes(@as(u8, @intCast(i))); | |
| 363 | var out_seg = seg; | |
| 364 | out_seg.fileoff = 0; | |
| 365 | out_seg.filesize = 0; | |
| 366 | out_seg.cmdsize = @sizeOf(macho.segment_command_64); | |
| 367 | out_seg.nsects = 0; | |
| 368 | ||
| 369 | // Update section headers count; any section with size of 0 is excluded | |
| 370 | // since it doesn't have any data in the final binary file. | |
| 371 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { | |
| 372 | if (header.size == 0) continue; | |
| 373 | out_seg.cmdsize += @sizeOf(macho.section_64); | |
| 374 | out_seg.nsects += 1; | |
| 375 | } | |
| 341 | fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, usize } { | |
| 342 | const gpa = self.allocator; | |
| 343 | const needed_size = load_commands.calcLoadCommandsSizeDsym(macho_file, self); | |
| 344 | const buffer = try gpa.alloc(u8, needed_size); | |
| 345 | defer gpa.free(buffer); | |
| 346 | ||
| 347 | var stream = std.io.fixedBufferStream(buffer); | |
| 348 | var cwriter = std.io.countingWriter(stream.writer()); | |
| 349 | const writer = cwriter.writer(); | |
| 376 | 350 | |
| 377 | if (out_seg.nsects == 0 and | |
| 378 | (mem.eql(u8, out_seg.segName(), "__DATA_CONST") or | |
| 379 | mem.eql(u8, out_seg.segName(), "__DATA"))) continue; | |
| 351 | var ncmds: usize = 0; | |
| 380 | 352 | |
| 381 | try writer.writeStruct(out_seg); | |
| 382 | for (macho_file.sections.items(.header)[indexes.start..indexes.end]) |header| { | |
| 383 | if (header.size == 0) continue; | |
| 384 | var out_header = header; | |
| 385 | out_header.offset = 0; | |
| 386 | try writer.writeStruct(out_header); | |
| 353 | // UUID comes first presumably to speed up lookup by the consumer like lldb. | |
| 354 | @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); | |
| 355 | try writer.writeStruct(self.uuid_cmd); | |
| 356 | ncmds += 1; | |
| 357 | ||
| 358 | // Segment and section load commands | |
| 359 | { | |
| 360 | // Write segment/section headers from the binary file first. | |
| 361 | const slice = macho_file.sections.slice(); | |
| 362 | var sect_id: usize = 0; | |
| 363 | for (macho_file.segments.items, 0..) |seg, seg_id| { | |
| 364 | if (seg_id == macho_file.linkedit_seg_index.?) break; | |
| 365 | var out_seg = seg; | |
| 366 | out_seg.fileoff = 0; | |
| 367 | out_seg.filesize = 0; | |
| 368 | try writer.writeStruct(out_seg); | |
| 369 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { | |
| 370 | var out_header = header; | |
| 371 | out_header.offset = 0; | |
| 372 | try writer.writeStruct(out_header); | |
| 373 | } | |
| 374 | sect_id += seg.nsects; | |
| 387 | 375 | } |
| 388 | } | |
| 389 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. | |
| 390 | for (self.segments.items, 0..) |seg, i| { | |
| 391 | const indexes = self.getSectionIndexes(@as(u8, @intCast(i))); | |
| 392 | try writer.writeStruct(seg); | |
| 393 | for (self.sections.items[indexes.start..indexes.end]) |header| { | |
| 394 | try writer.writeStruct(header); | |
| 376 | ncmds += macho_file.segments.items.len - 1; | |
| 377 | ||
| 378 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. | |
| 379 | sect_id = 0; | |
| 380 | for (self.segments.items) |seg| { | |
| 381 | try writer.writeStruct(seg); | |
| 382 | for (self.sections.items[sect_id..][0..seg.nsects]) |header| { | |
| 383 | try writer.writeStruct(header); | |
| 384 | } | |
| 385 | sect_id += seg.nsects; | |
| 395 | 386 | } |
| 387 | ncmds += self.segments.items.len; | |
| 396 | 388 | } |
| 397 | } | |
| 398 | 389 | |
| 399 | fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: u32) !void { | |
| 400 | const target = macho_file.base.comp.root_mod.resolved_target.result; | |
| 390 | try writer.writeStruct(self.symtab_cmd); | |
| 391 | ncmds += 1; | |
| 392 | ||
| 393 | assert(cwriter.bytes_written == needed_size); | |
| 401 | 394 | |
| 395 | try self.file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); | |
| 396 | ||
| 397 | return .{ ncmds, buffer.len }; | |
| 398 | } | |
| 399 | ||
| 400 | fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: usize, sizeofcmds: usize) !void { | |
| 402 | 401 | var header: macho.mach_header_64 = .{}; |
| 403 | 402 | header.filetype = macho.MH_DSYM; |
| 404 | 403 | |
| 405 | switch (target.cpu.arch) { | |
| 404 | switch (macho_file.getTarget().cpu.arch) { | |
| 406 | 405 | .aarch64 => { |
| 407 | 406 | header.cputype = macho.CPU_TYPE_ARM64; |
| 408 | 407 | header.cpusubtype = macho.CPU_SUBTYPE_ARM_ALL; |
| ... | ... | @@ -414,8 +413,8 @@ fn writeHeader(self: *DebugSymbols, macho_file: *MachO, ncmds: u32, sizeofcmds: |
| 414 | 413 | else => return error.UnsupportedCpuArchitecture, |
| 415 | 414 | } |
| 416 | 415 | |
| 417 | header.ncmds = ncmds; | |
| 418 | header.sizeofcmds = sizeofcmds; | |
| 416 | header.ncmds = @intCast(ncmds); | |
| 417 | header.sizeofcmds = @intCast(sizeofcmds); | |
| 419 | 418 | |
| 420 | 419 | log.debug("writing Mach-O header {}", .{header}); |
| 421 | 420 | |
| ... | ... | @@ -437,91 +436,56 @@ fn writeLinkeditSegmentData(self: *DebugSymbols, macho_file: *MachO) !void { |
| 437 | 436 | const tracy = trace(@src()); |
| 438 | 437 | defer tracy.end(); |
| 439 | 438 | |
| 440 | try self.writeSymtab(macho_file); | |
| 441 | try self.writeStrtab(); | |
| 442 | ||
| 443 | const target = macho_file.base.comp.root_mod.resolved_target.result; | |
| 444 | const page_size = MachO.getPageSize(target.cpu.arch); | |
| 439 | const page_size = macho_file.getPageSize(); | |
| 445 | 440 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; |
| 441 | ||
| 442 | var off = math.cast(u32, seg.fileoff) orelse return error.Overflow; | |
| 443 | off = try self.writeSymtab(off, macho_file); | |
| 444 | off = mem.alignForward(u32, off, @alignOf(u64)); | |
| 445 | off = try self.writeStrtab(off); | |
| 446 | seg.filesize = off - seg.fileoff; | |
| 447 | ||
| 446 | 448 | const aligned_size = mem.alignForward(u64, seg.filesize, page_size); |
| 447 | 449 | seg.vmsize = aligned_size; |
| 448 | 450 | } |
| 449 | 451 | |
| 450 | fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void { | |
| 452 | pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { | |
| 451 | 453 | const tracy = trace(@src()); |
| 452 | 454 | defer tracy.end(); |
| 453 | ||
| 454 | 455 | const gpa = self.allocator; |
| 456 | const cmd = &self.symtab_cmd; | |
| 457 | cmd.nsyms = macho_file.symtab_cmd.nsyms; | |
| 458 | cmd.strsize = macho_file.symtab_cmd.strsize; | |
| 459 | cmd.symoff = off; | |
| 455 | 460 | |
| 456 | var locals = std.ArrayList(macho.nlist_64).init(gpa); | |
| 457 | defer locals.deinit(); | |
| 458 | ||
| 459 | for (macho_file.locals.items, 0..) |sym, sym_id| { | |
| 460 | if (sym.n_strx == 0) continue; // no name, skip | |
| 461 | const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) }; | |
| 462 | if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip | |
| 463 | if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip | |
| 464 | var out_sym = sym; | |
| 465 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(sym_loc)); | |
| 466 | try locals.append(out_sym); | |
| 467 | } | |
| 461 | try self.symtab.resize(gpa, cmd.nsyms); | |
| 462 | try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); | |
| 468 | 463 | |
| 469 | var exports = std.ArrayList(macho.nlist_64).init(gpa); | |
| 470 | defer exports.deinit(); | |
| 471 | ||
| 472 | for (macho_file.globals.items) |global| { | |
| 473 | const sym = macho_file.getSymbol(global); | |
| 474 | if (sym.undf()) continue; // import, skip | |
| 475 | var out_sym = sym; | |
| 476 | out_sym.n_strx = try self.strtab.insert(gpa, macho_file.getSymbolName(global)); | |
| 477 | try exports.append(out_sym); | |
| 464 | if (macho_file.getZigObject()) |zo| { | |
| 465 | zo.writeSymtab(macho_file, self); | |
| 466 | } | |
| 467 | for (macho_file.objects.items) |index| { | |
| 468 | try macho_file.getFile(index).?.writeSymtab(macho_file, self); | |
| 469 | } | |
| 470 | for (macho_file.dylibs.items) |index| { | |
| 471 | try macho_file.getFile(index).?.writeSymtab(macho_file, self); | |
| 472 | } | |
| 473 | if (macho_file.getInternalObject()) |internal| { | |
| 474 | internal.writeSymtab(macho_file, self); | |
| 478 | 475 | } |
| 479 | 476 | |
| 480 | const nlocals = locals.items.len; | |
| 481 | const nexports = exports.items.len; | |
| 482 | const nsyms = nlocals + nexports; | |
| 483 | ||
| 484 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | |
| 485 | const offset = mem.alignForward(u64, seg.fileoff, @alignOf(macho.nlist_64)); | |
| 486 | const needed_size = nsyms * @sizeOf(macho.nlist_64); | |
| 487 | seg.filesize = offset + needed_size - seg.fileoff; | |
| 488 | ||
| 489 | self.symtab_cmd.symoff = @as(u32, @intCast(offset)); | |
| 490 | self.symtab_cmd.nsyms = @as(u32, @intCast(nsyms)); | |
| 491 | ||
| 492 | const locals_off = @as(u32, @intCast(offset)); | |
| 493 | const locals_size = nlocals * @sizeOf(macho.nlist_64); | |
| 494 | const exports_off = locals_off + locals_size; | |
| 495 | const exports_size = nexports * @sizeOf(macho.nlist_64); | |
| 477 | assert(self.strtab.items.len == cmd.strsize); | |
| 496 | 478 | |
| 497 | log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); | |
| 498 | try self.file.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); | |
| 479 | try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); | |
| 499 | 480 | |
| 500 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); | |
| 501 | try self.file.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); | |
| 481 | return off + cmd.nsyms * @sizeOf(macho.nlist_64); | |
| 502 | 482 | } |
| 503 | 483 | |
| 504 | fn writeStrtab(self: *DebugSymbols) !void { | |
| 505 | const tracy = trace(@src()); | |
| 506 | defer tracy.end(); | |
| 507 | ||
| 508 | const seg = &self.segments.items[self.linkedit_segment_cmd_index.?]; | |
| 509 | const symtab_size = @as(u32, @intCast(self.symtab_cmd.nsyms * @sizeOf(macho.nlist_64))); | |
| 510 | const offset = mem.alignForward(u64, self.symtab_cmd.symoff + symtab_size, @alignOf(u64)); | |
| 511 | const needed_size = mem.alignForward(u64, self.strtab.buffer.items.len, @alignOf(u64)); | |
| 512 | ||
| 513 | seg.filesize = offset + needed_size - seg.fileoff; | |
| 514 | self.symtab_cmd.stroff = @as(u32, @intCast(offset)); | |
| 515 | self.symtab_cmd.strsize = @as(u32, @intCast(needed_size)); | |
| 516 | ||
| 517 | log.debug("writing string table from 0x{x} to 0x{x}", .{ offset, offset + needed_size }); | |
| 518 | ||
| 519 | try self.file.pwriteAll(self.strtab.buffer.items, offset); | |
| 520 | ||
| 521 | if (self.strtab.buffer.items.len < needed_size) { | |
| 522 | // Ensure we are always padded to the actual length of the file. | |
| 523 | try self.file.pwriteAll(&[_]u8{0}, offset + needed_size); | |
| 524 | } | |
| 484 | pub fn writeStrtab(self: *DebugSymbols, off: u32) !u32 { | |
| 485 | const cmd = &self.symtab_cmd; | |
| 486 | cmd.stroff = off; | |
| 487 | try self.file.pwriteAll(self.strtab.items, cmd.stroff); | |
| 488 | return off + cmd.strsize; | |
| 525 | 489 | } |
| 526 | 490 | |
| 527 | 491 | pub fn getSectionIndexes(self: *DebugSymbols, segment_index: u8) struct { start: u8, end: u8 } { |
| ... | ... | @@ -561,7 +525,7 @@ const assert = std.debug.assert; |
| 561 | 525 | const fs = std.fs; |
| 562 | 526 | const link = @import("../../link.zig"); |
| 563 | 527 | const load_commands = @import("load_commands.zig"); |
| 564 | const log = std.log.scoped(.dsym); | |
| 528 | const log = std.log.scoped(.link_dsym); | |
| 565 | 529 | const macho = std.macho; |
| 566 | 530 | const makeStaticString = MachO.makeStaticString; |
| 567 | 531 | 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 | 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 | 580 | const tracy = trace(@src()); |
| 581 | 581 | defer tracy.end(); |
| 582 | 582 | |
| ... | ... | @@ -585,10 +585,10 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { |
| 585 | 585 | const file = global.getFile(macho_file) orelse continue; |
| 586 | 586 | if (file.getIndex() != self.index) continue; |
| 587 | 587 | const idx = global.getOutputSymtabIndex(macho_file) orelse continue; |
| 588 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 589 | macho_file.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); | |
| 590 | macho_file.strtab.appendAssumeCapacity(0); | |
| 591 | const out_sym = &macho_file.symtab.items[idx]; | |
| 588 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 589 | ctx.strtab.appendSliceAssumeCapacity(global.getName(macho_file)); | |
| 590 | ctx.strtab.appendAssumeCapacity(0); | |
| 591 | const out_sym = &ctx.symtab.items[idx]; | |
| 592 | 592 | out_sym.n_strx = n_strx; |
| 593 | 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 | 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 | 143 | for (self.symbols.items) |sym_index| { |
| 144 | 144 | const sym = macho_file.getSymbol(sym_index); |
| 145 | 145 | if (sym.getFile(macho_file)) |file| if (file.getIndex() != self.index) continue; |
| 146 | 146 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 147 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 148 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 149 | macho_file.strtab.appendAssumeCapacity(0); | |
| 150 | const out_sym = &macho_file.symtab.items[idx]; | |
| 147 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 148 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 149 | ctx.strtab.appendAssumeCapacity(0); | |
| 150 | const out_sym = &ctx.symtab.items[idx]; | |
| 151 | 151 | out_sym.n_strx = n_strx; |
| 152 | 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 | 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 | 1324 | const tracy = trace(@src()); |
| 1325 | 1325 | defer tracy.end(); |
| 1326 | 1326 | |
| ... | ... | @@ -1329,19 +1329,19 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) error{Overflow}!void { |
| 1329 | 1329 | const file = sym.getFile(macho_file) orelse continue; |
| 1330 | 1330 | if (file.getIndex() != self.index) continue; |
| 1331 | 1331 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 1332 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1333 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 1334 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1335 | const out_sym = &macho_file.symtab.items[idx]; | |
| 1332 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1333 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 1334 | ctx.strtab.appendAssumeCapacity(0); | |
| 1335 | const out_sym = &ctx.symtab.items[idx]; | |
| 1336 | 1336 | out_sym.n_strx = n_strx; |
| 1337 | 1337 | sym.setOutputSym(macho_file, out_sym); |
| 1338 | 1338 | } |
| 1339 | 1339 | |
| 1340 | 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 | 1345 | const writeFuncStab = struct { |
| 1346 | 1346 | inline fn writeFuncStab( |
| 1347 | 1347 | n_strx: u32, |
| ... | ... | @@ -1349,30 +1349,30 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1349 | 1349 | n_value: u64, |
| 1350 | 1350 | size: u64, |
| 1351 | 1351 | index: u32, |
| 1352 | ctx: *MachO, | |
| 1352 | context: anytype, | |
| 1353 | 1353 | ) void { |
| 1354 | ctx.symtab.items[index] = .{ | |
| 1354 | context.symtab.items[index] = .{ | |
| 1355 | 1355 | .n_strx = 0, |
| 1356 | 1356 | .n_type = macho.N_BNSYM, |
| 1357 | 1357 | .n_sect = n_sect, |
| 1358 | 1358 | .n_desc = 0, |
| 1359 | 1359 | .n_value = n_value, |
| 1360 | 1360 | }; |
| 1361 | ctx.symtab.items[index + 1] = .{ | |
| 1361 | context.symtab.items[index + 1] = .{ | |
| 1362 | 1362 | .n_strx = n_strx, |
| 1363 | 1363 | .n_type = macho.N_FUN, |
| 1364 | 1364 | .n_sect = n_sect, |
| 1365 | 1365 | .n_desc = 0, |
| 1366 | 1366 | .n_value = n_value, |
| 1367 | 1367 | }; |
| 1368 | ctx.symtab.items[index + 2] = .{ | |
| 1368 | context.symtab.items[index + 2] = .{ | |
| 1369 | 1369 | .n_strx = 0, |
| 1370 | 1370 | .n_type = macho.N_FUN, |
| 1371 | 1371 | .n_sect = 0, |
| 1372 | 1372 | .n_desc = 0, |
| 1373 | 1373 | .n_value = size, |
| 1374 | 1374 | }; |
| 1375 | ctx.symtab.items[index + 3] = .{ | |
| 1375 | context.symtab.items[index + 3] = .{ | |
| 1376 | 1376 | .n_strx = 0, |
| 1377 | 1377 | .n_type = macho.N_ENSYM, |
| 1378 | 1378 | .n_sect = n_sect, |
| ... | ... | @@ -1392,10 +1392,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1392 | 1392 | |
| 1393 | 1393 | // Open scope |
| 1394 | 1394 | // N_SO comp_dir |
| 1395 | var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1396 | macho_file.strtab.appendSliceAssumeCapacity(comp_dir); | |
| 1397 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1398 | macho_file.symtab.items[index] = .{ | |
| 1395 | var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1396 | ctx.strtab.appendSliceAssumeCapacity(comp_dir); | |
| 1397 | ctx.strtab.appendAssumeCapacity(0); | |
| 1398 | ctx.symtab.items[index] = .{ | |
| 1399 | 1399 | .n_strx = n_strx, |
| 1400 | 1400 | .n_type = macho.N_SO, |
| 1401 | 1401 | .n_sect = 0, |
| ... | ... | @@ -1404,10 +1404,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1404 | 1404 | }; |
| 1405 | 1405 | index += 1; |
| 1406 | 1406 | // N_SO tu_name |
| 1407 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1408 | macho_file.strtab.appendSliceAssumeCapacity(tu_name); | |
| 1409 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1410 | macho_file.symtab.items[index] = .{ | |
| 1407 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1408 | ctx.strtab.appendSliceAssumeCapacity(tu_name); | |
| 1409 | ctx.strtab.appendAssumeCapacity(0); | |
| 1410 | ctx.symtab.items[index] = .{ | |
| 1411 | 1411 | .n_strx = n_strx, |
| 1412 | 1412 | .n_type = macho.N_SO, |
| 1413 | 1413 | .n_sect = 0, |
| ... | ... | @@ -1416,18 +1416,18 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1416 | 1416 | }; |
| 1417 | 1417 | index += 1; |
| 1418 | 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 | 1420 | if (self.archive) |ar| { |
| 1421 | macho_file.strtab.appendSliceAssumeCapacity(ar.path); | |
| 1422 | macho_file.strtab.appendAssumeCapacity('('); | |
| 1423 | macho_file.strtab.appendSliceAssumeCapacity(self.path); | |
| 1424 | macho_file.strtab.appendAssumeCapacity(')'); | |
| 1425 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1421 | ctx.strtab.appendSliceAssumeCapacity(ar.path); | |
| 1422 | ctx.strtab.appendAssumeCapacity('('); | |
| 1423 | ctx.strtab.appendSliceAssumeCapacity(self.path); | |
| 1424 | ctx.strtab.appendAssumeCapacity(')'); | |
| 1425 | ctx.strtab.appendAssumeCapacity(0); | |
| 1426 | 1426 | } else { |
| 1427 | macho_file.strtab.appendSliceAssumeCapacity(self.path); | |
| 1428 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1427 | ctx.strtab.appendSliceAssumeCapacity(self.path); | |
| 1428 | ctx.strtab.appendAssumeCapacity(0); | |
| 1429 | 1429 | } |
| 1430 | macho_file.symtab.items[index] = .{ | |
| 1430 | ctx.symtab.items[index] = .{ | |
| 1431 | 1431 | .n_strx = n_strx, |
| 1432 | 1432 | .n_type = macho.N_OSO, |
| 1433 | 1433 | .n_sect = 0, |
| ... | ... | @@ -1448,17 +1448,17 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1448 | 1448 | const sect = macho_file.sections.items(.header)[sym.out_n_sect]; |
| 1449 | 1449 | const sym_n_strx = n_strx: { |
| 1450 | 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 | 1452 | break :n_strx osym.n_strx; |
| 1453 | 1453 | }; |
| 1454 | 1454 | const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.out_n_sect + 1) else 0; |
| 1455 | 1455 | const sym_n_value = sym.getAddress(.{}, macho_file); |
| 1456 | 1456 | const sym_size = sym.getSize(macho_file); |
| 1457 | 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 | 1459 | index += 4; |
| 1460 | 1460 | } else if (sym.visibility == .global) { |
| 1461 | macho_file.symtab.items[index] = .{ | |
| 1461 | ctx.symtab.items[index] = .{ | |
| 1462 | 1462 | .n_strx = sym_n_strx, |
| 1463 | 1463 | .n_type = macho.N_GSYM, |
| 1464 | 1464 | .n_sect = sym_n_sect, |
| ... | ... | @@ -1467,7 +1467,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1467 | 1467 | }; |
| 1468 | 1468 | index += 1; |
| 1469 | 1469 | } else { |
| 1470 | macho_file.symtab.items[index] = .{ | |
| 1470 | ctx.symtab.items[index] = .{ | |
| 1471 | 1471 | .n_strx = sym_n_strx, |
| 1472 | 1472 | .n_type = macho.N_STSYM, |
| 1473 | 1473 | .n_sect = sym_n_sect, |
| ... | ... | @@ -1480,7 +1480,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1480 | 1480 | |
| 1481 | 1481 | // Close scope |
| 1482 | 1482 | // N_SO |
| 1483 | macho_file.symtab.items[index] = .{ | |
| 1483 | ctx.symtab.items[index] = .{ | |
| 1484 | 1484 | .n_strx = 0, |
| 1485 | 1485 | .n_type = macho.N_SO, |
| 1486 | 1486 | .n_sect = 0, |
| ... | ... | @@ -1493,10 +1493,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1493 | 1493 | for (self.stab_files.items) |sf| { |
| 1494 | 1494 | // Open scope |
| 1495 | 1495 | // N_SO comp_dir |
| 1496 | var n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1497 | macho_file.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); | |
| 1498 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1499 | macho_file.symtab.items[index] = .{ | |
| 1496 | var n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1497 | ctx.strtab.appendSliceAssumeCapacity(sf.getCompDir(self)); | |
| 1498 | ctx.strtab.appendAssumeCapacity(0); | |
| 1499 | ctx.symtab.items[index] = .{ | |
| 1500 | 1500 | .n_strx = n_strx, |
| 1501 | 1501 | .n_type = macho.N_SO, |
| 1502 | 1502 | .n_sect = 0, |
| ... | ... | @@ -1505,10 +1505,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1505 | 1505 | }; |
| 1506 | 1506 | index += 1; |
| 1507 | 1507 | // N_SO tu_name |
| 1508 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1509 | macho_file.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); | |
| 1510 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1511 | macho_file.symtab.items[index] = .{ | |
| 1508 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1509 | ctx.strtab.appendSliceAssumeCapacity(sf.getTuName(self)); | |
| 1510 | ctx.strtab.appendAssumeCapacity(0); | |
| 1511 | ctx.symtab.items[index] = .{ | |
| 1512 | 1512 | .n_strx = n_strx, |
| 1513 | 1513 | .n_type = macho.N_SO, |
| 1514 | 1514 | .n_sect = 0, |
| ... | ... | @@ -1517,10 +1517,10 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1517 | 1517 | }; |
| 1518 | 1518 | index += 1; |
| 1519 | 1519 | // N_OSO path |
| 1520 | n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 1521 | macho_file.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); | |
| 1522 | macho_file.strtab.appendAssumeCapacity(0); | |
| 1523 | macho_file.symtab.items[index] = .{ | |
| 1520 | n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 1521 | ctx.strtab.appendSliceAssumeCapacity(sf.getOsoPath(self)); | |
| 1522 | ctx.strtab.appendAssumeCapacity(0); | |
| 1523 | ctx.symtab.items[index] = .{ | |
| 1524 | 1524 | .n_strx = n_strx, |
| 1525 | 1525 | .n_type = macho.N_OSO, |
| 1526 | 1526 | .n_sect = 0, |
| ... | ... | @@ -1536,7 +1536,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1536 | 1536 | if (!sym.flags.output_symtab) continue; |
| 1537 | 1537 | const sym_n_strx = n_strx: { |
| 1538 | 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 | 1540 | break :n_strx osym.n_strx; |
| 1541 | 1541 | }; |
| 1542 | 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 | 1544 | const sym_size = sym.getSize(macho_file); |
| 1545 | 1545 | switch (stab.tag) { |
| 1546 | 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 | 1548 | index += 4; |
| 1549 | 1549 | }, |
| 1550 | 1550 | .global => { |
| 1551 | macho_file.symtab.items[index] = .{ | |
| 1551 | ctx.symtab.items[index] = .{ | |
| 1552 | 1552 | .n_strx = sym_n_strx, |
| 1553 | 1553 | .n_type = macho.N_GSYM, |
| 1554 | 1554 | .n_sect = sym_n_sect, |
| ... | ... | @@ -1558,7 +1558,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1558 | 1558 | index += 1; |
| 1559 | 1559 | }, |
| 1560 | 1560 | .static => { |
| 1561 | macho_file.symtab.items[index] = .{ | |
| 1561 | ctx.symtab.items[index] = .{ | |
| 1562 | 1562 | .n_strx = sym_n_strx, |
| 1563 | 1563 | .n_type = macho.N_STSYM, |
| 1564 | 1564 | .n_sect = sym_n_sect, |
| ... | ... | @@ -1572,7 +1572,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) error{Overflow}!void |
| 1572 | 1572 | |
| 1573 | 1573 | // Close scope |
| 1574 | 1574 | // N_SO |
| 1575 | macho_file.symtab.items[index] = .{ | |
| 1575 | ctx.symtab.items[index] = .{ | |
| 1576 | 1576 | .n_strx = 0, |
| 1577 | 1577 | .n_type = macho.N_SO, |
| 1578 | 1578 | .n_sect = 0, |
src/link/MachO/ZigObject.zig+31-29| ... | ... | @@ -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 | 314 | const tracy = trace(@src()); |
| 315 | 315 | defer tracy.end(); |
| 316 | 316 | |
| ... | ... | @@ -319,10 +319,10 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { |
| 319 | 319 | const file = sym.getFile(macho_file) orelse continue; |
| 320 | 320 | if (file.getIndex() != self.index) continue; |
| 321 | 321 | const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; |
| 322 | const n_strx = @as(u32, @intCast(macho_file.strtab.items.len)); | |
| 323 | macho_file.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 324 | macho_file.strtab.appendAssumeCapacity(0); | |
| 325 | const out_sym = &macho_file.symtab.items[idx]; | |
| 322 | const n_strx = @as(u32, @intCast(ctx.strtab.items.len)); | |
| 323 | ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file)); | |
| 324 | ctx.strtab.appendAssumeCapacity(0); | |
| 325 | const out_sym = &ctx.symtab.items[idx]; | |
| 326 | 326 | out_sym.n_strx = n_strx; |
| 327 | 327 | sym.setOutputSym(macho_file, out_sym); |
| 328 | 328 | } |
| ... | ... | @@ -531,7 +531,7 @@ pub fn updateFunc( |
| 531 | 531 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 532 | 532 | defer code_buffer.deinit(); |
| 533 | 533 | |
| 534 | var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf | |
| 534 | var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null; | |
| 535 | 535 | defer if (decl_state) |*ds| ds.deinit(); |
| 536 | 536 | |
| 537 | 537 | const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; |
| ... | ... | @@ -557,16 +557,16 @@ pub fn updateFunc( |
| 557 | 557 | const sect_index = try self.getDeclOutputSection(macho_file, decl, code); |
| 558 | 558 | try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code); |
| 559 | 559 | |
| 560 | // if (decl_state) |*ds| { | |
| 561 | // const sym = elf_file.symbol(sym_index); | |
| 562 | // try self.dwarf.?.commitDeclState( | |
| 563 | // mod, | |
| 564 | // decl_index, | |
| 565 | // sym.value, | |
| 566 | // sym.atom(elf_file).?.size, | |
| 567 | // ds, | |
| 568 | // ); | |
| 569 | // } | |
| 560 | if (decl_state) |*ds| { | |
| 561 | const sym = macho_file.getSymbol(sym_index); | |
| 562 | try macho_file.getDebugSymbols().?.dwarf.commitDeclState( | |
| 563 | mod, | |
| 564 | decl_index, | |
| 565 | sym.getAddress(.{}, macho_file), | |
| 566 | sym.getAtom(macho_file).?.size, | |
| 567 | ds, | |
| 568 | ); | |
| 569 | } | |
| 570 | 570 | |
| 571 | 571 | // Since we updated the vaddr and the size, each corresponding export |
| 572 | 572 | // symbol also needs to be updated. |
| ... | ... | @@ -606,7 +606,7 @@ pub fn updateDecl( |
| 606 | 606 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 607 | 607 | defer code_buffer.deinit(); |
| 608 | 608 | |
| 609 | var decl_state: ?Dwarf.DeclState = null; // TODO: Dwarf | |
| 609 | var decl_state: ?Dwarf.DeclState = if (macho_file.getDebugSymbols()) |d_sym| try d_sym.dwarf.initDeclState(mod, decl_index) else null; | |
| 610 | 610 | defer if (decl_state) |*ds| ds.deinit(); |
| 611 | 611 | |
| 612 | 612 | const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; |
| ... | ... | @@ -638,15 +638,16 @@ pub fn updateDecl( |
| 638 | 638 | try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code); |
| 639 | 639 | } |
| 640 | 640 | |
| 641 | // if (decl_state) |*ds| { | |
| 642 | // try self.d_sym.?.dwarf.commitDeclState( | |
| 643 | // mod, | |
| 644 | // decl_index, | |
| 645 | // addr, | |
| 646 | // self.getAtom(atom_index).size, | |
| 647 | // ds, | |
| 648 | // ); | |
| 649 | // } | |
| 641 | if (decl_state) |*ds| { | |
| 642 | const sym = macho_file.getSymbol(sym_index); | |
| 643 | try macho_file.getDebugSymbols().?.dwarf.commitDeclState( | |
| 644 | mod, | |
| 645 | decl_index, | |
| 646 | sym.getAddress(.{}, macho_file), | |
| 647 | sym.getAtom(macho_file).?.size, | |
| 648 | ds, | |
| 649 | ); | |
| 650 | } | |
| 650 | 651 | |
| 651 | 652 | // Since we updated the vaddr and the size, each corresponding export symbol also |
| 652 | 653 | // needs to be updated. |
| ... | ... | @@ -1220,13 +1221,14 @@ fn updateLazySymbol( |
| 1220 | 1221 | /// Must be called only after a successful call to `updateDecl`. |
| 1221 | 1222 | pub fn updateDeclLineNumber( |
| 1222 | 1223 | self: *ZigObject, |
| 1224 | macho_file: *MachO, | |
| 1223 | 1225 | mod: *Module, |
| 1224 | 1226 | decl_index: InternPool.DeclIndex, |
| 1225 | 1227 | ) !void { |
| 1226 | 1228 | _ = self; |
| 1227 | _ = mod; | |
| 1228 | _ = decl_index; | |
| 1229 | // TODO: Dwarf | |
| 1229 | if (macho_file.getDebugSymbols()) |d_sym| { | |
| 1230 | try d_sym.dwarf.updateDeclLineNumber(mod, decl_index); | |
| 1231 | } | |
| 1230 | 1232 | } |
| 1231 | 1233 | |
| 1232 | 1234 | pub fn deleteDeclExport( |
src/link/MachO/file.zig+2-2| ... | ... | @@ -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 | 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 | 5 | const mem = std.mem; |
| 6 | 6 | |
| 7 | 7 | const Allocator = mem.Allocator; |
| 8 | const DebugSymbols = @import("DebugSymbols.zig"); | |
| 8 | 9 | const Dylib = @import("Dylib.zig"); |
| 9 | 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 | 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 | 122 | pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { |
| 101 | 123 | var sizeofcmds: u64 = 0; |
| 102 | 124 |