| author | |
| committer | |
| log | 0c171afab003f7d7dfde8491141e00cac7e99c21 |
| tree | 4873f24bd6468489045beada751540f82c5d956f |
| parent | 7588eeccea02b155f934a453cc47d8641686ab22 |
8 files changed, 797 insertions(+), 431 deletions(-)
src/link/MachO.zig+630-305| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | base: File, | 1 | base: link.File, |
| 2 | 2 | ||
| 3 | /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. | 3 | /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. |
| 4 | llvm_object: ?*LlvmObject = null, | 4 | llvm_object: ?*LlvmObject = null, |
| ... | @@ -6,6 +6,27 @@ llvm_object: ?*LlvmObject = null, | ... | @@ -6,6 +6,27 @@ llvm_object: ?*LlvmObject = null, |
| 6 | /// Debug symbols bundle (or dSym). | 6 | /// Debug symbols bundle (or dSym). |
| 7 | d_sym: ?DebugSymbols = null, | 7 | d_sym: ?DebugSymbols = null, |
| 8 | 8 | ||
| 9 | /// A list of all input files. | ||
| 10 | /// Index of each input file also encodes the priority or precedence of one input file | ||
| 11 | /// over another. | ||
| 12 | files: std.MultiArrayList(File.Entry) = .{}, | ||
| 13 | internal_object: ?File.Index = null, | ||
| 14 | objects: std.ArrayListUnmanaged(File.Index) = .{}, | ||
| 15 | dylibs: std.ArrayListUnmanaged(File.Index) = .{}, | ||
| 16 | |||
| 17 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, | ||
| 18 | sections: std.MultiArrayList(Section) = .{}, | ||
| 19 | |||
| 20 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, | ||
| 21 | symbols_extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 22 | globals: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{}, | ||
| 23 | /// This table will be populated after `scanRelocs` has run. | ||
| 24 | /// Key is symbol index. | ||
| 25 | undefs: std.AutoHashMapUnmanaged(Symbol.Index, std.ArrayListUnmanaged(Atom.Index)) = .{}, | ||
| 26 | /// Global symbols we need to resolve for the link to succeed. | ||
| 27 | undefined_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 28 | boundary_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ||
| 29 | |||
| 9 | dyld_info_cmd: macho.dyld_info_command = .{}, | 30 | dyld_info_cmd: macho.dyld_info_command = .{}, |
| 10 | symtab_cmd: macho.symtab_command = .{}, | 31 | symtab_cmd: macho.symtab_command = .{}, |
| 11 | dysymtab_cmd: macho.dysymtab_command = .{}, | 32 | dysymtab_cmd: macho.dysymtab_command = .{}, |
| ... | @@ -14,36 +35,46 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE }, | ... | @@ -14,36 +35,46 @@ data_in_code_cmd: macho.linkedit_data_command = .{ .cmd = .DATA_IN_CODE }, |
| 14 | uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, | 35 | uuid_cmd: macho.uuid_command = .{ .uuid = [_]u8{0} ** 16 }, |
| 15 | codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE }, | 36 | codesig_cmd: macho.linkedit_data_command = .{ .cmd = .CODE_SIGNATURE }, |
| 16 | 37 | ||
| 17 | segments: std.ArrayListUnmanaged(macho.segment_command_64) = .{}, | 38 | pagezero_seg_index: ?u8 = null, |
| 18 | sections: std.MultiArrayList(Section) = .{}, | 39 | text_seg_index: ?u8 = null, |
| 19 | 40 | linkedit_seg_index: ?u8 = null, | |
| 20 | pagezero_segment_cmd_index: ?u8 = null, | 41 | data_sect_index: ?u8 = null, |
| 21 | header_segment_cmd_index: ?u8 = null, | 42 | got_sect_index: ?u8 = null, |
| 22 | text_segment_cmd_index: ?u8 = null, | 43 | stubs_sect_index: ?u8 = null, |
| 23 | data_const_segment_cmd_index: ?u8 = null, | 44 | stubs_helper_sect_index: ?u8 = null, |
| 24 | data_segment_cmd_index: ?u8 = null, | 45 | la_symbol_ptr_sect_index: ?u8 = null, |
| 25 | linkedit_segment_cmd_index: ?u8 = null, | 46 | tlv_ptr_sect_index: ?u8 = null, |
| 26 | 47 | eh_frame_sect_index: ?u8 = null, | |
| 27 | text_section_index: ?u8 = null, | 48 | unwind_info_sect_index: ?u8 = null, |
| 28 | data_const_section_index: ?u8 = null, | 49 | objc_stubs_sect_index: ?u8 = null, |
| 29 | data_section_index: ?u8 = null, | ||
| 30 | bss_section_index: ?u8 = null, | ||
| 31 | thread_vars_section_index: ?u8 = null, | ||
| 32 | thread_data_section_index: ?u8 = null, | ||
| 33 | thread_bss_section_index: ?u8 = null, | ||
| 34 | eh_frame_section_index: ?u8 = null, | ||
| 35 | unwind_info_section_index: ?u8 = null, | ||
| 36 | stubs_section_index: ?u8 = null, | ||
| 37 | stub_helper_section_index: ?u8 = null, | ||
| 38 | got_section_index: ?u8 = null, | ||
| 39 | la_symbol_ptr_section_index: ?u8 = null, | ||
| 40 | tlv_ptr_section_index: ?u8 = null, | ||
| 41 | |||
| 42 | strtab: StringTable = .{}, | ||
| 43 | 50 | ||
| 44 | /// List of atoms that are either synthetic or map directly to the Zig source program. | 51 | /// List of atoms that are either synthetic or map directly to the Zig source program. |
| 45 | atoms: std.ArrayListUnmanaged(Atom) = .{}, | 52 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 46 | 53 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, | |
| 54 | unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record) = .{}, | ||
| 55 | |||
| 56 | /// String interning table | ||
| 57 | strings: StringTable = .{}, | ||
| 58 | |||
| 59 | /// Output synthetic sections | ||
| 60 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | ||
| 61 | strtab: std.ArrayListUnmanaged(u8) = .{}, | ||
| 62 | indsymtab: Indsymtab = .{}, | ||
| 63 | got: GotSection = .{}, | ||
| 64 | stubs: StubsSection = .{}, | ||
| 65 | stubs_helper: StubsHelperSection = .{}, | ||
| 66 | objc_stubs: ObjcStubsSection = .{}, | ||
| 67 | la_symbol_ptr: LaSymbolPtrSection = .{}, | ||
| 68 | tlv_ptr: TlvPtrSection = .{}, | ||
| 69 | rebase: RebaseSection = .{}, | ||
| 70 | bind: BindSection = .{}, | ||
| 71 | weak_bind: WeakBindSection = .{}, | ||
| 72 | lazy_bind: LazyBindSection = .{}, | ||
| 73 | export_trie: ExportTrieSection = .{}, | ||
| 74 | unwind_info: UnwindInfo = .{}, | ||
| 75 | |||
| 76 | /// Options | ||
| 77 | /// SDK layout | ||
| 47 | sdk_layout: ?SdkLayout, | 78 | sdk_layout: ?SdkLayout, |
| 48 | /// Size of the __PAGEZERO segment. | 79 | /// Size of the __PAGEZERO segment. |
| 49 | pagezero_vmsize: ?u64, | 80 | pagezero_vmsize: ?u64, |
| ... | @@ -62,6 +93,8 @@ entitlements: ?[]const u8, | ... | @@ -62,6 +93,8 @@ entitlements: ?[]const u8, |
| 62 | compatibility_version: ?std.SemanticVersion, | 93 | compatibility_version: ?std.SemanticVersion, |
| 63 | /// Entry name | 94 | /// Entry name |
| 64 | entry_name: ?[]const u8, | 95 | entry_name: ?[]const u8, |
| 96 | platform: Platform, | ||
| 97 | sdk_version: ?std.SemanticVersion, | ||
| 65 | 98 | ||
| 66 | /// Hot-code swapping state. | 99 | /// Hot-code swapping state. |
| 67 | hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, | 100 | hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{}, |
| ... | @@ -144,6 +177,8 @@ pub fn createEmpty( | ... | @@ -144,6 +177,8 @@ pub fn createEmpty( |
| 144 | .enabled => default_entry_symbol_name, | 177 | .enabled => default_entry_symbol_name, |
| 145 | .named => |name| name, | 178 | .named => |name| name, |
| 146 | }, | 179 | }, |
| 180 | .platform = Platform.fromTarget(target), | ||
| 181 | .sdk_version = if (options.darwin_sdk_layout) |layout| inferSdkVersion(comp, layout) else null, | ||
| 147 | }; | 182 | }; |
| 148 | if (use_llvm and comp.config.have_zcu) { | 183 | if (use_llvm and comp.config.have_zcu) { |
| 149 | self.llvm_object = try LlvmObject.create(arena, comp); | 184 | self.llvm_object = try LlvmObject.create(arena, comp); |
| ... | @@ -156,9 +191,16 @@ pub fn createEmpty( | ... | @@ -156,9 +191,16 @@ pub fn createEmpty( |
| 156 | .mode = link.File.determineMode(false, output_mode, link_mode), | 191 | .mode = link.File.determineMode(false, output_mode, link_mode), |
| 157 | }); | 192 | }); |
| 158 | 193 | ||
| 159 | // Index 0 is always a null symbol. | 194 | // Append null file |
| 160 | // try self.locals.append(gpa, null_sym); | 195 | try self.files.append(gpa, .null); |
| 161 | try self.strtab.buffer.append(gpa, 0); | 196 | // Atom at index 0 is reserved as null atom |
| 197 | try self.atoms.append(gpa, .{}); | ||
| 198 | // Append empty string to string tables | ||
| 199 | try self.strings.buffer.append(gpa, 0); | ||
| 200 | try self.strtab.append(gpa, 0); | ||
| 201 | // Append null symbols | ||
| 202 | try self.symbols.append(gpa, .{}); | ||
| 203 | try self.symbols_extra.append(gpa, 0); | ||
| 162 | 204 | ||
| 163 | // TODO: init | 205 | // TODO: init |
| 164 | 206 | ||
| ... | @@ -208,8 +250,71 @@ pub fn open( | ... | @@ -208,8 +250,71 @@ pub fn open( |
| 208 | return createEmpty(arena, comp, emit, options); | 250 | return createEmpty(arena, comp, emit, options); |
| 209 | } | 251 | } |
| 210 | 252 | ||
| 253 | pub fn deinit(self: *MachO) void { | ||
| 254 | const gpa = self.base.comp.gpa; | ||
| 255 | |||
| 256 | if (self.llvm_object) |llvm_object| llvm_object.deinit(); | ||
| 257 | |||
| 258 | if (self.d_sym) |*d_sym| { | ||
| 259 | d_sym.deinit(); | ||
| 260 | } | ||
| 261 | |||
| 262 | for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) { | ||
| 263 | .null => {}, | ||
| 264 | .internal => data.internal.deinit(gpa), | ||
| 265 | .object => data.object.deinit(gpa), | ||
| 266 | .dylib => data.dylib.deinit(gpa), | ||
| 267 | }; | ||
| 268 | self.files.deinit(gpa); | ||
| 269 | self.objects.deinit(gpa); | ||
| 270 | self.dylibs.deinit(gpa); | ||
| 271 | |||
| 272 | self.segments.deinit(gpa); | ||
| 273 | for (self.sections.items(.atoms)) |*list| { | ||
| 274 | list.deinit(gpa); | ||
| 275 | } | ||
| 276 | self.sections.deinit(gpa); | ||
| 277 | |||
| 278 | self.symbols.deinit(gpa); | ||
| 279 | self.symbols_extra.deinit(gpa); | ||
| 280 | self.globals.deinit(gpa); | ||
| 281 | { | ||
| 282 | var it = self.undefs.iterator(); | ||
| 283 | while (it.next()) |entry| { | ||
| 284 | entry.value_ptr.deinit(gpa); | ||
| 285 | } | ||
| 286 | self.undefs.deinit(gpa); | ||
| 287 | } | ||
| 288 | self.undefined_symbols.deinit(gpa); | ||
| 289 | self.boundary_symbols.deinit(gpa); | ||
| 290 | |||
| 291 | self.strings.deinit(gpa); | ||
| 292 | self.symtab.deinit(gpa); | ||
| 293 | self.strtab.deinit(gpa); | ||
| 294 | self.got.deinit(gpa); | ||
| 295 | self.stubs.deinit(gpa); | ||
| 296 | self.objc_stubs.deinit(gpa); | ||
| 297 | self.tlv_ptr.deinit(gpa); | ||
| 298 | self.rebase.deinit(gpa); | ||
| 299 | self.bind.deinit(gpa); | ||
| 300 | self.weak_bind.deinit(gpa); | ||
| 301 | self.lazy_bind.deinit(gpa); | ||
| 302 | self.export_trie.deinit(gpa); | ||
| 303 | self.unwind_info.deinit(gpa); | ||
| 304 | |||
| 305 | self.atoms.deinit(gpa); | ||
| 306 | for (self.thunks.items) |*thunk| { | ||
| 307 | thunk.deinit(gpa); | ||
| 308 | } | ||
| 309 | self.thunks.deinit(gpa); | ||
| 310 | self.unwind_records.deinit(gpa); | ||
| 311 | } | ||
| 312 | |||
| 211 | pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { | 313 | pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 212 | // TODO: what else should we do in flush? Is it actually needed at all? | 314 | // TODO: I think this is just a temp and can be removed once we can emit static archives |
| 315 | if (self.base.isStaticLib() and build_options.have_llvm) { | ||
| 316 | return self.base.linkAsArchive(arena, prog_node); | ||
| 317 | } | ||
| 213 | try self.flushModule(arena, prog_node); | 318 | try self.flushModule(arena, prog_node); |
| 214 | } | 319 | } |
| 215 | 320 | ||
| ... | @@ -219,10 +324,11 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -219,10 +324,11 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 219 | 324 | ||
| 220 | const comp = self.base.comp; | 325 | const comp = self.base.comp; |
| 221 | const gpa = comp.gpa; | 326 | const gpa = comp.gpa; |
| 222 | _ = gpa; | ||
| 223 | 327 | ||
| 224 | if (self.llvm_object) |llvm_object| { | 328 | if (self.llvm_object) |llvm_object| { |
| 225 | try self.base.emitLlvmObject(arena, llvm_object, prog_node); | 329 | try self.base.emitLlvmObject(arena, llvm_object, prog_node); |
| 330 | // TODO: I think this is just a temp and can be removed once we can emit static archives | ||
| 331 | if (self.base.isStaticLib() and build_options.have_llvm) return; | ||
| 226 | } | 332 | } |
| 227 | 333 | ||
| 228 | var sub_prog_node = prog_node.start("MachO Flush", 0); | 334 | var sub_prog_node = prog_node.start("MachO Flush", 0); |
| ... | @@ -240,11 +346,55 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -240,11 +346,55 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 240 | break :blk path; | 346 | break :blk path; |
| 241 | } | 347 | } |
| 242 | } else null; | 348 | } else null; |
| 243 | _ = module_obj_path; | ||
| 244 | 349 | ||
| 245 | // --verbose-link | 350 | // --verbose-link |
| 246 | if (comp.verbose_link) try self.dumpArgv(comp); | 351 | if (comp.verbose_link) try self.dumpArgv(comp); |
| 247 | 352 | ||
| 353 | if (self.base.isStaticLib()) return self.flushStaticLib(comp, module_obj_path); | ||
| 354 | if (self.base.isObject()) return self.flushObject(comp, module_obj_path); | ||
| 355 | |||
| 356 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | ||
| 357 | defer positionals.deinit(); | ||
| 358 | |||
| 359 | try positionals.ensureUnusedCapacity(comp.objects.len); | ||
| 360 | positionals.appendSliceAssumeCapacity(comp.objects); | ||
| 361 | |||
| 362 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | ||
| 363 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | ||
| 364 | // in this set. | ||
| 365 | try positionals.ensureUnusedCapacity(comp.c_object_table.keys().len); | ||
| 366 | for (comp.c_object_table.keys()) |key| { | ||
| 367 | positionals.appendAssumeCapacity(.{ .path = key.status.success.object_path }); | ||
| 368 | } | ||
| 369 | |||
| 370 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | ||
| 371 | |||
| 372 | // rpaths | ||
| 373 | var rpath_table = std.StringArrayHashMap(void).init(gpa); | ||
| 374 | defer rpath_table.deinit(); | ||
| 375 | try rpath_table.ensureUnusedCapacity(self.base.rpath_list.len); | ||
| 376 | |||
| 377 | for (self.base.rpath_list) |rpath| { | ||
| 378 | _ = rpath_table.putAssumeCapacity(rpath, {}); | ||
| 379 | } | ||
| 380 | |||
| 381 | for (positionals.items) |obj| { | ||
| 382 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | ||
| 383 | error.MalformedObject, | ||
| 384 | error.MalformedArchive, | ||
| 385 | error.InvalidCpuArch, | ||
| 386 | error.InvalidTarget, | ||
| 387 | => continue, // already reported | ||
| 388 | else => |e| try self.reportParseError( | ||
| 389 | obj.path, | ||
| 390 | "unexpected error: parsing input file failed with error {s}", | ||
| 391 | .{@errorName(e)}, | ||
| 392 | ), | ||
| 393 | }; | ||
| 394 | } | ||
| 395 | |||
| 396 | state_log.debug("{}", .{self.dumpState()}); | ||
| 397 | |||
| 248 | @panic("TODO"); | 398 | @panic("TODO"); |
| 249 | } | 399 | } |
| 250 | 400 | ||
| ... | @@ -255,7 +405,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -255,7 +405,6 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 255 | defer arena_allocator.deinit(); | 405 | defer arena_allocator.deinit(); |
| 256 | const arena = arena_allocator.allocator(); | 406 | const arena = arena_allocator.allocator(); |
| 257 | 407 | ||
| 258 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 259 | const directory = self.base.emit.directory; | 408 | const directory = self.base.emit.directory; |
| 260 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | 409 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| 261 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { | 410 | const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: { |
| ... | @@ -309,18 +458,14 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -309,18 +458,14 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 309 | } | 458 | } |
| 310 | } | 459 | } |
| 311 | 460 | ||
| 312 | { | 461 | try argv.append("-platform_version"); |
| 313 | const platform = Platform.fromTarget(target); | 462 | try argv.append(@tagName(self.platform.os_tag)); |
| 314 | try argv.append("-platform_version"); | 463 | try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version})); |
| 315 | try argv.append(@tagName(platform.os_tag)); | 464 | |
| 316 | try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); | 465 | if (self.sdk_version) |ver| { |
| 317 | 466 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); | |
| 318 | const sdk_version: ?std.SemanticVersion = self.inferSdkVersion(); | 467 | } else { |
| 319 | if (sdk_version) |ver| { | 468 | try argv.append(try std.fmt.allocPrint(arena, "{}", .{self.platform.version})); |
| 320 | try argv.append(try std.fmt.allocPrint(arena, "{d}.{d}", .{ ver.major, ver.minor })); | ||
| 321 | } else { | ||
| 322 | try argv.append(try std.fmt.allocPrint(arena, "{}", .{platform.version})); | ||
| 323 | } | ||
| 324 | } | 469 | } |
| 325 | 470 | ||
| 326 | if (comp.sysroot) |syslibroot| { | 471 | if (comp.sysroot) |syslibroot| { |
| ... | @@ -419,6 +564,26 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { | ... | @@ -419,6 +564,26 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void { |
| 419 | Compilation.dump_argv(argv.items); | 564 | Compilation.dump_argv(argv.items); |
| 420 | } | 565 | } |
| 421 | 566 | ||
| 567 | fn flushStaticLib(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | ||
| 568 | _ = comp; | ||
| 569 | _ = module_obj_path; | ||
| 570 | |||
| 571 | var err = try self.addErrorWithNotes(0); | ||
| 572 | try err.addMsg(self, "TODO implement flushStaticLib", .{}); | ||
| 573 | |||
| 574 | return error.FlushFailure; | ||
| 575 | } | ||
| 576 | |||
| 577 | fn flushObject(self: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | ||
| 578 | _ = comp; | ||
| 579 | _ = module_obj_path; | ||
| 580 | |||
| 581 | var err = try self.addErrorWithNotes(0); | ||
| 582 | try err.addMsg(self, "TODO implement flushObject", .{}); | ||
| 583 | |||
| 584 | return error.FlushFailure; | ||
| 585 | } | ||
| 586 | |||
| 422 | /// XNU starting with Big Sur running on arm64 is caching inodes of running binaries. | 587 | /// XNU starting with Big Sur running on arm64 is caching inodes of running binaries. |
| 423 | /// Any change to the binary will effectively invalidate the kernel's cache | 588 | /// Any change to the binary will effectively invalidate the kernel's cache |
| 424 | /// resulting in a SIGKILL on each subsequent run. Since when doing incremental | 589 | /// resulting in a SIGKILL on each subsequent run. Since when doing incremental |
| ... | @@ -518,132 +683,60 @@ fn accessLibPath( | ... | @@ -518,132 +683,60 @@ fn accessLibPath( |
| 518 | } | 683 | } |
| 519 | 684 | ||
| 520 | const ParseError = error{ | 685 | const ParseError = error{ |
| 521 | UnknownFileType, | 686 | MalformedObject, |
| 687 | MalformedArchive, | ||
| 688 | NotLibStub, | ||
| 689 | InvalidCpuArch, | ||
| 522 | InvalidTarget, | 690 | InvalidTarget, |
| 523 | InvalidTargetFatLibrary, | 691 | InvalidTargetFatLibrary, |
| 524 | DylibAlreadyExists, | ||
| 525 | IncompatibleDylibVersion, | 692 | IncompatibleDylibVersion, |
| 526 | OutOfMemory, | 693 | OutOfMemory, |
| 527 | Overflow, | 694 | Overflow, |
| 528 | InputOutput, | 695 | InputOutput, |
| 529 | MalformedArchive, | ||
| 530 | NotLibStub, | ||
| 531 | EndOfStream, | 696 | EndOfStream, |
| 532 | FileSystem, | 697 | FileSystem, |
| 533 | NotSupported, | 698 | NotSupported, |
| 534 | } || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError; | 699 | } || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError || tapi.TapiError; |
| 535 | 700 | ||
| 536 | pub fn parsePositional( | 701 | fn parsePositional(self: *MachO, path: []const u8, must_link: bool) ParseError!void { |
| 537 | self: *MachO, | ||
| 538 | file: std.fs.File, | ||
| 539 | path: []const u8, | ||
| 540 | must_link: bool, | ||
| 541 | dependent_libs: anytype, | ||
| 542 | ctx: *ParseErrorCtx, | ||
| 543 | ) ParseError!void { | ||
| 544 | const tracy = trace(@src()); | 702 | const tracy = trace(@src()); |
| 545 | defer tracy.end(); | 703 | defer tracy.end(); |
| 704 | if (try Object.isObject(path)) { | ||
| 705 | try self.parseObject(path); | ||
| 706 | } else { | ||
| 707 | try self.parseLibrary(.{ .path = path }, must_link); | ||
| 708 | } | ||
| 709 | } | ||
| 546 | 710 | ||
| 711 | fn parseLibrary(self: *MachO, lib: SystemLib, must_link: bool) ParseError!void { | ||
| 547 | _ = self; | 712 | _ = self; |
| 548 | _ = file; | 713 | _ = lib; |
| 549 | _ = path; | ||
| 550 | _ = must_link; | 714 | _ = must_link; |
| 551 | _ = dependent_libs; | ||
| 552 | _ = ctx; | ||
| 553 | } | 715 | } |
| 554 | 716 | ||
| 555 | pub fn deinit(self: *MachO) void { | 717 | fn parseObject(self: *MachO, path: []const u8) ParseError!void { |
| 556 | const gpa = self.base.comp.gpa; | 718 | const tracy = trace(@src()); |
| 557 | 719 | defer tracy.end(); | |
| 558 | if (self.llvm_object) |llvm_object| llvm_object.deinit(); | ||
| 559 | |||
| 560 | if (self.d_sym) |*d_sym| { | ||
| 561 | d_sym.deinit(); | ||
| 562 | } | ||
| 563 | |||
| 564 | self.strtab.deinit(gpa); | ||
| 565 | |||
| 566 | self.segments.deinit(gpa); | ||
| 567 | |||
| 568 | for (self.sections.items(.free_list)) |*list| { | ||
| 569 | list.deinit(gpa); | ||
| 570 | } | ||
| 571 | self.sections.deinit(gpa); | ||
| 572 | } | ||
| 573 | 720 | ||
| 574 | fn freeAtom(self: *MachO, atom_index: Atom.Index) void { | ||
| 575 | const gpa = self.base.comp.gpa; | 721 | const gpa = self.base.comp.gpa; |
| 576 | log.debug("freeAtom {d}", .{atom_index}); | 722 | const file = try std.fs.cwd().openFile(path, .{}); |
| 577 | 723 | defer file.close(); | |
| 578 | // Remove any relocs and base relocs associated with this Atom | 724 | const mtime: u64 = mtime: { |
| 579 | Atom.freeRelocations(self, atom_index); | 725 | const stat = file.stat() catch break :mtime 0; |
| 580 | 726 | break :mtime @as(u64, @intCast(@divFloor(stat.mtime, 1_000_000_000))); | |
| 581 | const atom = self.getAtom(atom_index); | 727 | }; |
| 582 | const sect_id = atom.getSymbol(self).n_sect - 1; | 728 | const data = try file.readToEndAlloc(gpa, std.math.maxInt(u32)); |
| 583 | const free_list = &self.sections.items(.free_list)[sect_id]; | 729 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 584 | var already_have_free_list_node = false; | 730 | self.files.set(index, .{ .object = .{ |
| 585 | { | 731 | .path = try gpa.dupe(u8, path), |
| 586 | var i: usize = 0; | 732 | .mtime = mtime, |
| 587 | // TODO turn free_list into a hash map | 733 | .data = data, |
| 588 | while (i < free_list.items.len) { | 734 | .index = index, |
| 589 | if (free_list.items[i] == atom_index) { | 735 | } }); |
| 590 | _ = free_list.swapRemove(i); | 736 | try self.objects.append(gpa, index); |
| 591 | continue; | 737 | |
| 592 | } | 738 | const object = self.getFile(index).?.object; |
| 593 | if (free_list.items[i] == atom.prev_index) { | 739 | try object.parse(self); |
| 594 | already_have_free_list_node = true; | ||
| 595 | } | ||
| 596 | i += 1; | ||
| 597 | } | ||
| 598 | } | ||
| 599 | |||
| 600 | const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id]; | ||
| 601 | if (maybe_last_atom_index.*) |last_atom_index| { | ||
| 602 | if (last_atom_index == atom_index) { | ||
| 603 | if (atom.prev_index) |prev_index| { | ||
| 604 | // TODO shrink the section size here | ||
| 605 | maybe_last_atom_index.* = prev_index; | ||
| 606 | } else { | ||
| 607 | maybe_last_atom_index.* = null; | ||
| 608 | } | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 612 | if (atom.prev_index) |prev_index| { | ||
| 613 | const prev = self.getAtomPtr(prev_index); | ||
| 614 | prev.next_index = atom.next_index; | ||
| 615 | |||
| 616 | if (!already_have_free_list_node and prev.*.freeListEligible(self)) { | ||
| 617 | // The free list is heuristics, it doesn't have to be perfect, so we can ignore | ||
| 618 | // the OOM here. | ||
| 619 | free_list.append(gpa, prev_index) catch {}; | ||
| 620 | } | ||
| 621 | } else { | ||
| 622 | self.getAtomPtr(atom_index).prev_index = null; | ||
| 623 | } | ||
| 624 | |||
| 625 | if (atom.next_index) |next_index| { | ||
| 626 | self.getAtomPtr(next_index).prev_index = atom.prev_index; | ||
| 627 | } else { | ||
| 628 | self.getAtomPtr(atom_index).next_index = null; | ||
| 629 | } | ||
| 630 | |||
| 631 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | ||
| 632 | const sym_index = atom.getSymbolIndex().?; | ||
| 633 | |||
| 634 | self.locals_free_list.append(gpa, sym_index) catch {}; | ||
| 635 | |||
| 636 | // Try freeing GOT atom if this decl had one | ||
| 637 | self.got_table.freeEntry(gpa, .{ .sym_index = sym_index }); | ||
| 638 | |||
| 639 | if (self.d_sym) |*d_sym| { | ||
| 640 | d_sym.swapRemoveRelocs(sym_index); | ||
| 641 | } | ||
| 642 | |||
| 643 | self.locals.items[sym_index].n_type = 0; | ||
| 644 | _ = self.atom_by_index_table.remove(sym_index); | ||
| 645 | log.debug(" adding local symbol index {d} to free list", .{sym_index}); | ||
| 646 | self.getAtomPtr(atom_index).sym_index = 0; | ||
| 647 | } | 740 | } |
| 648 | 741 | ||
| 649 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { | 742 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { |
| ... | @@ -716,7 +809,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) | ... | @@ -716,7 +809,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) |
| 716 | 809 | ||
| 717 | fn updateLazySymbolAtom( | 810 | fn updateLazySymbolAtom( |
| 718 | self: *MachO, | 811 | self: *MachO, |
| 719 | sym: File.LazySymbol, | 812 | sym: link.File.LazySymbol, |
| 720 | atom_index: Atom.Index, | 813 | atom_index: Atom.Index, |
| 721 | section_index: u8, | 814 | section_index: u8, |
| 722 | ) !void { | 815 | ) !void { |
| ... | @@ -727,7 +820,7 @@ fn updateLazySymbolAtom( | ... | @@ -727,7 +820,7 @@ fn updateLazySymbolAtom( |
| 727 | @panic("TODO updateLazySymbolAtom"); | 820 | @panic("TODO updateLazySymbolAtom"); |
| 728 | } | 821 | } |
| 729 | 822 | ||
| 730 | pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index { | 823 | pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: link.File.LazySymbol) !Atom.Index { |
| 731 | _ = self; | 824 | _ = self; |
| 732 | _ = sym; | 825 | _ = sym; |
| 733 | @panic("TODO getOrCreateAtomForLazySymbol"); | 826 | @panic("TODO getOrCreateAtomForLazySymbol"); |
| ... | @@ -763,7 +856,7 @@ pub fn updateExports( | ... | @@ -763,7 +856,7 @@ pub fn updateExports( |
| 763 | mod: *Module, | 856 | mod: *Module, |
| 764 | exported: Module.Exported, | 857 | exported: Module.Exported, |
| 765 | exports: []const *Module.Export, | 858 | exports: []const *Module.Export, |
| 766 | ) File.UpdateExportsError!void { | 859 | ) link.File.UpdateExportsError!void { |
| 767 | if (build_options.skip_non_native and builtin.object_format != .macho) { | 860 | if (build_options.skip_non_native and builtin.object_format != .macho) { |
| 768 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 861 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 769 | } | 862 | } |
| ... | @@ -795,7 +888,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { | ... | @@ -795,7 +888,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { |
| 795 | @panic("TODO freeDecl"); | 888 | @panic("TODO freeDecl"); |
| 796 | } | 889 | } |
| 797 | 890 | ||
| 798 | pub fn getDeclVAddr(self: *MachO, decl_index: InternPool.DeclIndex, reloc_info: File.RelocInfo) !u64 { | 891 | pub fn getDeclVAddr(self: *MachO, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 { |
| 799 | assert(self.llvm_object == null); | 892 | assert(self.llvm_object == null); |
| 800 | _ = decl_index; | 893 | _ = decl_index; |
| 801 | _ = reloc_info; | 894 | _ = reloc_info; |
| ... | @@ -872,94 +965,224 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { | ... | @@ -872,94 +965,224 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { |
| 872 | return start; | 965 | return start; |
| 873 | } | 966 | } |
| 874 | 967 | ||
| 968 | pub fn getTarget(self: MachO) std.Target { | ||
| 969 | return self.base.comp.root_mod.resolved_target.result; | ||
| 970 | } | ||
| 971 | |||
| 875 | pub fn makeStaticString(bytes: []const u8) [16]u8 { | 972 | pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 876 | var buf = [_]u8{0} ** 16; | 973 | var buf = [_]u8{0} ** 16; |
| 877 | @memcpy(buf[0..bytes.len], bytes); | 974 | @memcpy(buf[0..bytes.len], bytes); |
| 878 | return buf; | 975 | return buf; |
| 879 | } | 976 | } |
| 880 | 977 | ||
| 881 | pub const ParseErrorCtx = struct { | 978 | pub fn getFile(self: *MachO, index: File.Index) ?File { |
| 882 | arena_allocator: std.heap.ArenaAllocator, | 979 | const tag = self.files.items(.tags)[index]; |
| 883 | detected_dylib_id: struct { | 980 | return switch (tag) { |
| 884 | parent: u16, | 981 | .null => null, |
| 885 | required_version: u32, | 982 | .internal => .{ .internal = &self.files.items(.data)[index].internal }, |
| 886 | found_version: u32, | 983 | .object => .{ .object = &self.files.items(.data)[index].object }, |
| 887 | }, | 984 | .dylib => .{ .dylib = &self.files.items(.data)[index].dylib }, |
| 888 | detected_targets: std.ArrayList([]const u8), | 985 | }; |
| 986 | } | ||
| 889 | 987 | ||
| 890 | pub fn init(gpa: Allocator) ParseErrorCtx { | 988 | pub fn getInternalObject(self: *MachO) ?*InternalObject { |
| 891 | return .{ | 989 | const index = self.internal_object orelse return null; |
| 892 | .arena_allocator = std.heap.ArenaAllocator.init(gpa), | 990 | return self.getFile(index).?.internal; |
| 893 | .detected_dylib_id = undefined, | 991 | } |
| 894 | .detected_targets = std.ArrayList([]const u8).init(gpa), | 992 | |
| 993 | pub fn addAtom(self: *MachO) error{OutOfMemory}!Atom.Index { | ||
| 994 | const index = @as(Atom.Index, @intCast(self.atoms.items.len)); | ||
| 995 | const atom = try self.atoms.addOne(self.base.comp.gpa); | ||
| 996 | atom.* = .{}; | ||
| 997 | return index; | ||
| 998 | } | ||
| 999 | |||
| 1000 | pub fn getAtom(self: *MachO, index: Atom.Index) ?*Atom { | ||
| 1001 | if (index == 0) return null; | ||
| 1002 | assert(index < self.atoms.items.len); | ||
| 1003 | return &self.atoms.items[index]; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | pub fn addSymbol(self: *MachO) !Symbol.Index { | ||
| 1007 | const index = @as(Symbol.Index, @intCast(self.symbols.items.len)); | ||
| 1008 | const symbol = try self.symbols.addOne(self.base.comp.gpa); | ||
| 1009 | symbol.* = .{}; | ||
| 1010 | return index; | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | pub fn getSymbol(self: *MachO, index: Symbol.Index) *Symbol { | ||
| 1014 | assert(index < self.symbols.items.len); | ||
| 1015 | return &self.symbols.items[index]; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | pub fn addSymbolExtra(self: *MachO, extra: Symbol.Extra) !u32 { | ||
| 1019 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | ||
| 1020 | try self.symbols_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len); | ||
| 1021 | return self.addSymbolExtraAssumeCapacity(extra); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | pub fn addSymbolExtraAssumeCapacity(self: *MachO, extra: Symbol.Extra) u32 { | ||
| 1025 | const index = @as(u32, @intCast(self.symbols_extra.items.len)); | ||
| 1026 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | ||
| 1027 | inline for (fields) |field| { | ||
| 1028 | self.symbols_extra.appendAssumeCapacity(switch (field.type) { | ||
| 1029 | u32 => @field(extra, field.name), | ||
| 1030 | else => @compileError("bad field type"), | ||
| 1031 | }); | ||
| 1032 | } | ||
| 1033 | return index; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | pub fn getSymbolExtra(self: MachO, index: u32) ?Symbol.Extra { | ||
| 1037 | if (index == 0) return null; | ||
| 1038 | const fields = @typeInfo(Symbol.Extra).Struct.fields; | ||
| 1039 | var i: usize = index; | ||
| 1040 | var result: Symbol.Extra = undefined; | ||
| 1041 | inline for (fields) |field| { | ||
| 1042 | @field(result, field.name) = switch (field.type) { | ||
| 1043 | u32 => self.symbols_extra.items[i], | ||
| 1044 | else => @compileError("bad field type"), | ||
| 895 | }; | 1045 | }; |
| 1046 | i += 1; | ||
| 896 | } | 1047 | } |
| 1048 | return result; | ||
| 1049 | } | ||
| 897 | 1050 | ||
| 898 | pub fn deinit(ctx: *ParseErrorCtx) void { | 1051 | pub fn setSymbolExtra(self: *MachO, index: u32, extra: Symbol.Extra) void { |
| 899 | ctx.arena_allocator.deinit(); | 1052 | assert(index > 0); |
| 900 | ctx.detected_targets.deinit(); | 1053 | const fields = @typeInfo(Symbol.Extra).Struct.fields; |
| 1054 | inline for (fields, 0..) |field, i| { | ||
| 1055 | self.symbols_extra.items[index + i] = switch (field.type) { | ||
| 1056 | u32 => @field(extra, field.name), | ||
| 1057 | else => @compileError("bad field type"), | ||
| 1058 | }; | ||
| 901 | } | 1059 | } |
| 1060 | } | ||
| 1061 | |||
| 1062 | const GetOrCreateGlobalResult = struct { | ||
| 1063 | found_existing: bool, | ||
| 1064 | index: Symbol.Index, | ||
| 1065 | }; | ||
| 902 | 1066 | ||
| 903 | pub fn arena(ctx: *ParseErrorCtx) Allocator { | 1067 | pub fn getOrCreateGlobal(self: *MachO, off: u32) !GetOrCreateGlobalResult { |
| 904 | return ctx.arena_allocator.allocator(); | 1068 | const gpa = self.base.comp.gpa; |
| 1069 | const gop = try self.globals.getOrPut(gpa, off); | ||
| 1070 | if (!gop.found_existing) { | ||
| 1071 | const index = try self.addSymbol(); | ||
| 1072 | const global = self.getSymbol(index); | ||
| 1073 | global.name = off; | ||
| 1074 | gop.value_ptr.* = index; | ||
| 1075 | } | ||
| 1076 | return .{ | ||
| 1077 | .found_existing = gop.found_existing, | ||
| 1078 | .index = gop.value_ptr.*, | ||
| 1079 | }; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | pub fn getGlobalByName(self: *MachO, name: []const u8) ?Symbol.Index { | ||
| 1083 | const off = self.strings.getOffset(name) orelse return null; | ||
| 1084 | return self.globals.get(off); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | pub fn addUnwindRecord(self: *MachO) !UnwindInfo.Record.Index { | ||
| 1088 | const index = @as(UnwindInfo.Record.Index, @intCast(self.unwind_records.items.len)); | ||
| 1089 | const rec = try self.unwind_records.addOne(self.base.comp.gpa); | ||
| 1090 | rec.* = .{}; | ||
| 1091 | return index; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | pub fn getUnwindRecord(self: *MachO, index: UnwindInfo.Record.Index) *UnwindInfo.Record { | ||
| 1095 | assert(index < self.unwind_records.items.len); | ||
| 1096 | return &self.unwind_records.items[index]; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | pub fn addThunk(self: *MachO) !Thunk.Index { | ||
| 1100 | const index = @as(Thunk.Index, @intCast(self.thunks.items.len)); | ||
| 1101 | const thunk = try self.thunks.addOne(self.base.comp.gpa); | ||
| 1102 | thunk.* = .{}; | ||
| 1103 | return index; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | pub fn getThunk(self: *MachO, index: Thunk.Index) *Thunk { | ||
| 1107 | assert(index < self.thunks.items.len); | ||
| 1108 | return &self.thunks.items[index]; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | pub fn eatPrefix(path: []const u8, prefix: []const u8) ?[]const u8 { | ||
| 1112 | if (mem.startsWith(u8, path, prefix)) return path[prefix.len..]; | ||
| 1113 | return null; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | const ErrorWithNotes = struct { | ||
| 1117 | /// Allocated index in comp.link_errors array. | ||
| 1118 | index: usize, | ||
| 1119 | |||
| 1120 | /// Next available note slot. | ||
| 1121 | note_slot: usize = 0, | ||
| 1122 | |||
| 1123 | pub fn addMsg( | ||
| 1124 | err: ErrorWithNotes, | ||
| 1125 | macho_file: *MachO, | ||
| 1126 | comptime format: []const u8, | ||
| 1127 | args: anytype, | ||
| 1128 | ) error{OutOfMemory}!void { | ||
| 1129 | const comp = macho_file.base.comp; | ||
| 1130 | const gpa = comp.gpa; | ||
| 1131 | const err_msg = &comp.link_errors.items[err.index]; | ||
| 1132 | err_msg.msg = try std.fmt.allocPrint(gpa, format, args); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | pub fn addNote( | ||
| 1136 | err: *ErrorWithNotes, | ||
| 1137 | macho_file: *MachO, | ||
| 1138 | comptime format: []const u8, | ||
| 1139 | args: anytype, | ||
| 1140 | ) error{OutOfMemory}!void { | ||
| 1141 | const comp = macho_file.base.comp; | ||
| 1142 | const gpa = comp.gpa; | ||
| 1143 | const err_msg = &comp.link_errors.items[err.index]; | ||
| 1144 | assert(err.note_slot < err_msg.notes.len); | ||
| 1145 | err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; | ||
| 1146 | err.note_slot += 1; | ||
| 905 | } | 1147 | } |
| 906 | }; | 1148 | }; |
| 907 | 1149 | ||
| 908 | pub fn handleAndReportParseError( | 1150 | pub fn addErrorWithNotes(self: *MachO, note_count: usize) error{OutOfMemory}!ErrorWithNotes { |
| 1151 | const comp = self.base.comp; | ||
| 1152 | const gpa = comp.gpa; | ||
| 1153 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); | ||
| 1154 | return self.addErrorWithNotesAssumeCapacity(note_count); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | fn addErrorWithNotesAssumeCapacity(self: *MachO, note_count: usize) error{OutOfMemory}!ErrorWithNotes { | ||
| 1158 | const comp = self.base.comp; | ||
| 1159 | const gpa = comp.gpa; | ||
| 1160 | const index = comp.link_errors.items.len; | ||
| 1161 | const err = comp.link_errors.addOneAssumeCapacity(); | ||
| 1162 | err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; | ||
| 1163 | return .{ .index = index }; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | pub fn reportParseError( | ||
| 909 | self: *MachO, | 1167 | self: *MachO, |
| 910 | path: []const u8, | 1168 | path: []const u8, |
| 911 | err: ParseError, | 1169 | comptime format: []const u8, |
| 912 | ctx: *const ParseErrorCtx, | 1170 | args: anytype, |
| 913 | ) error{OutOfMemory}!void { | 1171 | ) error{OutOfMemory}!void { |
| 914 | const target = self.base.comp.root_mod.resolved_target.result; | 1172 | var err = try self.addErrorWithNotes(1); |
| 915 | const gpa = self.base.comp.gpa; | 1173 | try err.addMsg(self, format, args); |
| 916 | const cpu_arch = target.cpu.arch; | 1174 | try err.addNote(self, "while parsing {s}", .{path}); |
| 917 | switch (err) { | 1175 | } |
| 918 | error.DylibAlreadyExists => {}, | ||
| 919 | error.IncompatibleDylibVersion => { | ||
| 920 | const parent = &self.dylibs.items[ctx.detected_dylib_id.parent]; | ||
| 921 | try self.reportDependencyError( | ||
| 922 | if (parent.id) |id| id.name else parent.path, | ||
| 923 | path, | ||
| 924 | "incompatible dylib version: expected at least '{}', but found '{}'", | ||
| 925 | .{ | ||
| 926 | load_commands.appleVersionToSemanticVersion(ctx.detected_dylib_id.required_version), | ||
| 927 | load_commands.appleVersionToSemanticVersion(ctx.detected_dylib_id.found_version), | ||
| 928 | }, | ||
| 929 | ); | ||
| 930 | }, | ||
| 931 | error.UnknownFileType => try self.reportParseError(path, "unknown file type", .{}), | ||
| 932 | error.InvalidTarget, error.InvalidTargetFatLibrary => { | ||
| 933 | var targets_string = std.ArrayList(u8).init(gpa); | ||
| 934 | defer targets_string.deinit(); | ||
| 935 | |||
| 936 | if (ctx.detected_targets.items.len > 1) { | ||
| 937 | try targets_string.writer().writeAll("("); | ||
| 938 | for (ctx.detected_targets.items) |t| { | ||
| 939 | try targets_string.writer().print("{s}, ", .{t}); | ||
| 940 | } | ||
| 941 | try targets_string.resize(targets_string.items.len - 2); | ||
| 942 | try targets_string.writer().writeAll(")"); | ||
| 943 | } else { | ||
| 944 | try targets_string.writer().writeAll(ctx.detected_targets.items[0]); | ||
| 945 | } | ||
| 946 | 1176 | ||
| 947 | switch (err) { | 1177 | pub fn reportParseError2( |
| 948 | error.InvalidTarget => try self.reportParseError( | 1178 | self: *MachO, |
| 949 | path, | 1179 | file_index: File.Index, |
| 950 | "invalid target: expected '{}', but found '{s}'", | 1180 | comptime format: []const u8, |
| 951 | .{ Platform.fromTarget(target).fmtTarget(cpu_arch), targets_string.items }, | 1181 | args: anytype, |
| 952 | ), | 1182 | ) error{OutOfMemory}!void { |
| 953 | error.InvalidTargetFatLibrary => try self.reportParseError( | 1183 | var err = try self.addErrorWithNotes(1); |
| 954 | path, | 1184 | try err.addMsg(self, format, args); |
| 955 | "invalid architecture in universal library: expected '{s}', but found '{s}'", | 1185 | try err.addNote(self, "while parsing {}", .{self.getFile(file_index).?.fmtPath()}); |
| 956 | .{ @tagName(cpu_arch), targets_string.items }, | ||
| 957 | ), | ||
| 958 | else => unreachable, | ||
| 959 | } | ||
| 960 | }, | ||
| 961 | else => |e| try self.reportParseError(path, "{s}: parsing object failed", .{@errorName(e)}), | ||
| 962 | } | ||
| 963 | } | 1186 | } |
| 964 | 1187 | ||
| 965 | fn reportMissingLibraryError( | 1188 | fn reportMissingLibraryError( |
| ... | @@ -968,18 +1191,11 @@ fn reportMissingLibraryError( | ... | @@ -968,18 +1191,11 @@ fn reportMissingLibraryError( |
| 968 | comptime format: []const u8, | 1191 | comptime format: []const u8, |
| 969 | args: anytype, | 1192 | args: anytype, |
| 970 | ) error{OutOfMemory}!void { | 1193 | ) error{OutOfMemory}!void { |
| 971 | const comp = self.base.comp; | 1194 | var err = try self.addErrorWithNotes(checked_paths.len); |
| 972 | const gpa = comp.gpa; | 1195 | try err.addMsg(self, format, args); |
| 973 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); | 1196 | for (checked_paths) |path| { |
| 974 | const notes = try gpa.alloc(File.ErrorMsg, checked_paths.len); | 1197 | try err.addNote(self, "tried {s}", .{path}); |
| 975 | errdefer gpa.free(notes); | ||
| 976 | for (checked_paths, notes) |path, *note| { | ||
| 977 | note.* = .{ .msg = try std.fmt.allocPrint(gpa, "tried {s}", .{path}) }; | ||
| 978 | } | 1198 | } |
| 979 | comp.link_errors.appendAssumeCapacity(.{ | ||
| 980 | .msg = try std.fmt.allocPrint(gpa, format, args), | ||
| 981 | .notes = notes, | ||
| 982 | }); | ||
| 983 | } | 1199 | } |
| 984 | 1200 | ||
| 985 | fn reportDependencyError( | 1201 | fn reportDependencyError( |
| ... | @@ -992,7 +1208,7 @@ fn reportDependencyError( | ... | @@ -992,7 +1208,7 @@ fn reportDependencyError( |
| 992 | const comp = self.base.comp; | 1208 | const comp = self.base.comp; |
| 993 | const gpa = comp.gpa; | 1209 | const gpa = comp.gpa; |
| 994 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); | 1210 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); |
| 995 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 2); | 1211 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, 2); |
| 996 | defer notes.deinit(); | 1212 | defer notes.deinit(); |
| 997 | if (path) |p| { | 1213 | if (path) |p| { |
| 998 | notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) }); | 1214 | notes.appendAssumeCapacity(.{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{p}) }); |
| ... | @@ -1004,42 +1220,6 @@ fn reportDependencyError( | ... | @@ -1004,42 +1220,6 @@ fn reportDependencyError( |
| 1004 | }); | 1220 | }); |
| 1005 | } | 1221 | } |
| 1006 | 1222 | ||
| 1007 | pub fn reportParseError( | ||
| 1008 | self: *MachO, | ||
| 1009 | path: []const u8, | ||
| 1010 | comptime format: []const u8, | ||
| 1011 | args: anytype, | ||
| 1012 | ) error{OutOfMemory}!void { | ||
| 1013 | const comp = self.base.comp; | ||
| 1014 | const gpa = comp.gpa; | ||
| 1015 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); | ||
| 1016 | var notes = try gpa.alloc(File.ErrorMsg, 1); | ||
| 1017 | errdefer gpa.free(notes); | ||
| 1018 | notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while parsing {s}", .{path}) }; | ||
| 1019 | comp.link_errors.appendAssumeCapacity(.{ | ||
| 1020 | .msg = try std.fmt.allocPrint(gpa, format, args), | ||
| 1021 | .notes = notes, | ||
| 1022 | }); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | pub fn reportUnresolvedBoundarySymbol( | ||
| 1026 | self: *MachO, | ||
| 1027 | sym_name: []const u8, | ||
| 1028 | comptime format: []const u8, | ||
| 1029 | args: anytype, | ||
| 1030 | ) error{OutOfMemory}!void { | ||
| 1031 | const comp = self.base.comp; | ||
| 1032 | const gpa = comp.gpa; | ||
| 1033 | try comp.link_errors.ensureUnusedCapacity(gpa, 1); | ||
| 1034 | var notes = try gpa.alloc(File.ErrorMsg, 1); | ||
| 1035 | errdefer gpa.free(notes); | ||
| 1036 | notes[0] = .{ .msg = try std.fmt.allocPrint(gpa, "while resolving {s}", .{sym_name}) }; | ||
| 1037 | comp.link_errors.appendAssumeCapacity(.{ | ||
| 1038 | .msg = try std.fmt.allocPrint(gpa, format, args), | ||
| 1039 | .notes = notes, | ||
| 1040 | }); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { | 1223 | pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 1044 | const comp = self.base.comp; | 1224 | const comp = self.base.comp; |
| 1045 | const gpa = comp.gpa; | 1225 | const gpa = comp.gpa; |
| ... | @@ -1050,7 +1230,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { | ... | @@ -1050,7 +1230,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 1050 | const global = self.globals.items[global_index]; | 1230 | const global = self.globals.items[global_index]; |
| 1051 | const sym_name = self.getSymbolName(global); | 1231 | const sym_name = self.getSymbolName(global); |
| 1052 | 1232 | ||
| 1053 | var notes = try std.ArrayList(File.ErrorMsg).initCapacity(gpa, 1); | 1233 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, 1); |
| 1054 | defer notes.deinit(); | 1234 | defer notes.deinit(); |
| 1055 | 1235 | ||
| 1056 | if (global.getFile()) |file| { | 1236 | if (global.getFile()) |file| { |
| ... | @@ -1060,7 +1240,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { | ... | @@ -1060,7 +1240,7 @@ pub fn reportUndefined(self: *MachO) error{OutOfMemory}!void { |
| 1060 | notes.appendAssumeCapacity(.{ .msg = note }); | 1240 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 1061 | } | 1241 | } |
| 1062 | 1242 | ||
| 1063 | var err_msg = File.ErrorMsg{ | 1243 | var err_msg = link.File.ErrorMsg{ |
| 1064 | .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}), | 1244 | .msg = try std.fmt.allocPrint(gpa, "undefined reference to symbol {s}", .{sym_name}), |
| 1065 | }; | 1245 | }; |
| 1066 | err_msg.notes = try notes.toOwnedSlice(); | 1246 | err_msg.notes = try notes.toOwnedSlice(); |
| ... | @@ -1164,6 +1344,145 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { | ... | @@ -1164,6 +1344,145 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { |
| 1164 | self.hot_state.mach_task = null; | 1344 | self.hot_state.mach_task = null; |
| 1165 | } | 1345 | } |
| 1166 | 1346 | ||
| 1347 | pub fn dumpState(self: *MachO) std.fmt.Formatter(fmtDumpState) { | ||
| 1348 | return .{ .data = self }; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | fn fmtDumpState( | ||
| 1352 | self: *MachO, | ||
| 1353 | comptime unused_fmt_string: []const u8, | ||
| 1354 | options: std.fmt.FormatOptions, | ||
| 1355 | writer: anytype, | ||
| 1356 | ) !void { | ||
| 1357 | _ = options; | ||
| 1358 | _ = unused_fmt_string; | ||
| 1359 | for (self.objects.items) |index| { | ||
| 1360 | const object = self.getFile(index).?.object; | ||
| 1361 | try writer.print("object({d}) : {} : has_debug({})", .{ | ||
| 1362 | index, | ||
| 1363 | object.fmtPath(), | ||
| 1364 | object.hasDebugInfo(), | ||
| 1365 | }); | ||
| 1366 | if (!object.alive) try writer.writeAll(" : ([*])"); | ||
| 1367 | try writer.writeByte('\n'); | ||
| 1368 | try writer.print("{}{}{}{}{}\n", .{ | ||
| 1369 | object.fmtAtoms(self), | ||
| 1370 | object.fmtCies(self), | ||
| 1371 | object.fmtFdes(self), | ||
| 1372 | object.fmtUnwindRecords(self), | ||
| 1373 | object.fmtSymtab(self), | ||
| 1374 | }); | ||
| 1375 | } | ||
| 1376 | // for (self.dylibs.items) |index| { | ||
| 1377 | // const dylib = self.getFile(index).?.dylib; | ||
| 1378 | // try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ | ||
| 1379 | // index, | ||
| 1380 | // dylib.path, | ||
| 1381 | // dylib.needed, | ||
| 1382 | // dylib.weak, | ||
| 1383 | // }); | ||
| 1384 | // if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); | ||
| 1385 | // try writer.writeByte('\n'); | ||
| 1386 | // try writer.print("{}\n", .{dylib.fmtSymtab(self)}); | ||
| 1387 | // } | ||
| 1388 | if (self.getInternalObject()) |internal| { | ||
| 1389 | try writer.print("internal({d}) : internal\n", .{internal.index}); | ||
| 1390 | try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) }); | ||
| 1391 | } | ||
| 1392 | try writer.writeAll("thunks\n"); | ||
| 1393 | for (self.thunks.items, 0..) |thunk, index| { | ||
| 1394 | try writer.print("thunk({d}) : {}\n", .{ index, thunk.fmt(self) }); | ||
| 1395 | } | ||
| 1396 | try writer.print("stubs\n{}\n", .{self.stubs.fmt(self)}); | ||
| 1397 | try writer.print("objc_stubs\n{}\n", .{self.objc_stubs.fmt(self)}); | ||
| 1398 | try writer.print("got\n{}\n", .{self.got.fmt(self)}); | ||
| 1399 | try writer.print("tlv_ptr\n{}\n", .{self.tlv_ptr.fmt(self)}); | ||
| 1400 | try writer.writeByte('\n'); | ||
| 1401 | try writer.print("sections\n{}\n", .{self.fmtSections()}); | ||
| 1402 | try writer.print("segments\n{}\n", .{self.fmtSegments()}); | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | fn fmtSections(self: *MachO) std.fmt.Formatter(formatSections) { | ||
| 1406 | return .{ .data = self }; | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | fn formatSections( | ||
| 1410 | self: *MachO, | ||
| 1411 | comptime unused_fmt_string: []const u8, | ||
| 1412 | options: std.fmt.FormatOptions, | ||
| 1413 | writer: anytype, | ||
| 1414 | ) !void { | ||
| 1415 | _ = options; | ||
| 1416 | _ = unused_fmt_string; | ||
| 1417 | const slice = self.sections.slice(); | ||
| 1418 | for (slice.items(.header), slice.items(.segment_id), 0..) |header, seg_id, i| { | ||
| 1419 | try writer.print("sect({d}) : seg({d}) : {s},{s} : @{x} ({x}) : align({x}) : size({x})\n", .{ | ||
| 1420 | i, seg_id, header.segName(), header.sectName(), header.offset, header.addr, | ||
| 1421 | header.@"align", header.size, | ||
| 1422 | }); | ||
| 1423 | } | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | fn fmtSegments(self: *MachO) std.fmt.Formatter(formatSegments) { | ||
| 1427 | return .{ .data = self }; | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | fn formatSegments( | ||
| 1431 | self: *MachO, | ||
| 1432 | comptime unused_fmt_string: []const u8, | ||
| 1433 | options: std.fmt.FormatOptions, | ||
| 1434 | writer: anytype, | ||
| 1435 | ) !void { | ||
| 1436 | _ = options; | ||
| 1437 | _ = unused_fmt_string; | ||
| 1438 | for (self.segments.items, 0..) |seg, i| { | ||
| 1439 | try writer.print("seg({d}) : {s} : @{x}-{x} ({x}-{x})\n", .{ | ||
| 1440 | i, seg.segName(), seg.vmaddr, seg.vmaddr + seg.vmsize, | ||
| 1441 | seg.fileoff, seg.fileoff + seg.filesize, | ||
| 1442 | }); | ||
| 1443 | } | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | pub fn fmtSectType(tt: u8) std.fmt.Formatter(formatSectType) { | ||
| 1447 | return .{ .data = tt }; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | fn formatSectType( | ||
| 1451 | tt: u8, | ||
| 1452 | comptime unused_fmt_string: []const u8, | ||
| 1453 | options: std.fmt.FormatOptions, | ||
| 1454 | writer: anytype, | ||
| 1455 | ) !void { | ||
| 1456 | _ = options; | ||
| 1457 | _ = unused_fmt_string; | ||
| 1458 | const name = switch (tt) { | ||
| 1459 | macho.S_REGULAR => "REGULAR", | ||
| 1460 | macho.S_ZEROFILL => "ZEROFILL", | ||
| 1461 | macho.S_CSTRING_LITERALS => "CSTRING_LITERALS", | ||
| 1462 | macho.S_4BYTE_LITERALS => "4BYTE_LITERALS", | ||
| 1463 | macho.S_8BYTE_LITERALS => "8BYTE_LITERALS", | ||
| 1464 | macho.S_16BYTE_LITERALS => "16BYTE_LITERALS", | ||
| 1465 | macho.S_LITERAL_POINTERS => "LITERAL_POINTERS", | ||
| 1466 | macho.S_NON_LAZY_SYMBOL_POINTERS => "NON_LAZY_SYMBOL_POINTERS", | ||
| 1467 | macho.S_LAZY_SYMBOL_POINTERS => "LAZY_SYMBOL_POINTERS", | ||
| 1468 | macho.S_SYMBOL_STUBS => "SYMBOL_STUBS", | ||
| 1469 | macho.S_MOD_INIT_FUNC_POINTERS => "MOD_INIT_FUNC_POINTERS", | ||
| 1470 | macho.S_MOD_TERM_FUNC_POINTERS => "MOD_TERM_FUNC_POINTERS", | ||
| 1471 | macho.S_COALESCED => "COALESCED", | ||
| 1472 | macho.S_GB_ZEROFILL => "GB_ZEROFILL", | ||
| 1473 | macho.S_INTERPOSING => "INTERPOSING", | ||
| 1474 | macho.S_DTRACE_DOF => "DTRACE_DOF", | ||
| 1475 | macho.S_THREAD_LOCAL_REGULAR => "THREAD_LOCAL_REGULAR", | ||
| 1476 | macho.S_THREAD_LOCAL_ZEROFILL => "THREAD_LOCAL_ZEROFILL", | ||
| 1477 | macho.S_THREAD_LOCAL_VARIABLES => "THREAD_LOCAL_VARIABLES", | ||
| 1478 | macho.S_THREAD_LOCAL_VARIABLE_POINTERS => "THREAD_LOCAL_VARIABLE_POINTERS", | ||
| 1479 | macho.S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => "THREAD_LOCAL_INIT_FUNCTION_POINTERS", | ||
| 1480 | macho.S_INIT_FUNC_OFFSETS => "INIT_FUNC_OFFSETS", | ||
| 1481 | else => |x| return writer.print("UNKNOWN({x})", .{x}), | ||
| 1482 | }; | ||
| 1483 | try writer.print("{s}", .{name}); | ||
| 1484 | } | ||
| 1485 | |||
| 1167 | const is_hot_update_compatible = switch (builtin.target.os.tag) { | 1486 | const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| 1168 | .macos => true, | 1487 | .macos => true, |
| 1169 | else => false, | 1488 | else => false, |
| ... | @@ -1171,32 +1490,14 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) { | ... | @@ -1171,32 +1490,14 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| 1171 | 1490 | ||
| 1172 | const default_entry_symbol_name = "_main"; | 1491 | const default_entry_symbol_name = "_main"; |
| 1173 | 1492 | ||
| 1174 | pub const base_tag: File.Tag = File.Tag.macho; | 1493 | pub const base_tag: link.File.Tag = link.File.Tag.macho; |
| 1175 | pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1))); | 1494 | pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1))); |
| 1176 | pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2))); | 1495 | pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2))); |
| 1177 | 1496 | ||
| 1178 | pub const Section = struct { | 1497 | const Section = struct { |
| 1179 | header: macho.section_64, | 1498 | header: macho.section_64, |
| 1180 | segment_index: u8, | 1499 | segment_id: u8, |
| 1181 | first_atom_index: ?Atom.Index = null, | 1500 | atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 1182 | last_atom_index: ?Atom.Index = null, | ||
| 1183 | |||
| 1184 | /// A list of atoms that have surplus capacity. This list can have false | ||
| 1185 | /// positives, as functions grow and shrink over time, only sometimes being added | ||
| 1186 | /// or removed from the freelist. | ||
| 1187 | /// | ||
| 1188 | /// An atom has surplus capacity when its overcapacity value is greater than | ||
| 1189 | /// padToIdeal(minimum_atom_size). That is, when it has so | ||
| 1190 | /// much extra capacity, that we could fit a small new symbol in it, itself with | ||
| 1191 | /// ideal_capacity or more. | ||
| 1192 | /// | ||
| 1193 | /// Ideal capacity is defined by size + (size / ideal_factor). | ||
| 1194 | /// | ||
| 1195 | /// Overcapacity is measured by actual_capacity - ideal_capacity. Note that | ||
| 1196 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | ||
| 1197 | /// allocate a fresh atom, which will have ideal capacity, and then grow it | ||
| 1198 | /// by 1 byte. It will then have -1 overcapacity. | ||
| 1199 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, | ||
| 1200 | }; | 1501 | }; |
| 1201 | 1502 | ||
| 1202 | const HotUpdateState = struct { | 1503 | const HotUpdateState = struct { |
| ... | @@ -1385,15 +1686,13 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { | ... | @@ -1385,15 +1686,13 @@ pub inline fn appleVersionToSemanticVersion(version: u32) std.SemanticVersion { |
| 1385 | }; | 1686 | }; |
| 1386 | } | 1687 | } |
| 1387 | 1688 | ||
| 1388 | fn inferSdkVersion(self: *MachO) ?std.SemanticVersion { | 1689 | fn inferSdkVersion(comp: *Compilation, sdk_layout: SdkLayout) ?std.SemanticVersion { |
| 1389 | const comp = self.base.comp; | ||
| 1390 | const gpa = comp.gpa; | 1690 | const gpa = comp.gpa; |
| 1391 | 1691 | ||
| 1392 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | 1692 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); |
| 1393 | defer arena_allocator.deinit(); | 1693 | defer arena_allocator.deinit(); |
| 1394 | const arena = arena_allocator.allocator(); | 1694 | const arena = arena_allocator.allocator(); |
| 1395 | 1695 | ||
| 1396 | const sdk_layout = self.sdk_layout orelse return null; | ||
| 1397 | const sdk_dir = switch (sdk_layout) { | 1696 | const sdk_dir = switch (sdk_layout) { |
| 1398 | .sdk => comp.sysroot.?, | 1697 | .sdk => comp.sysroot.?, |
| 1399 | .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null, | 1698 | .vendored => std.fs.path.join(arena, &.{ comp.zig_lib_directory.path.?, "libc", "darwin" }) catch return null, |
| ... | @@ -1402,6 +1701,7 @@ fn inferSdkVersion(self: *MachO) ?std.SemanticVersion { | ... | @@ -1402,6 +1701,7 @@ fn inferSdkVersion(self: *MachO) ?std.SemanticVersion { |
| 1402 | return parseSdkVersion(ver); | 1701 | return parseSdkVersion(ver); |
| 1403 | } else |_| { | 1702 | } else |_| { |
| 1404 | // Read from settings should always succeed when vendored. | 1703 | // Read from settings should always succeed when vendored. |
| 1704 | // TODO: convert to fatal linker error | ||
| 1405 | if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version"); | 1705 | if (sdk_layout == .vendored) @panic("zig installation bug: unable to parse SDK version"); |
| 1406 | } | 1706 | } |
| 1407 | 1707 | ||
| ... | @@ -1470,6 +1770,15 @@ pub const default_pagezero_vmsize: u64 = 0x100000000; | ... | @@ -1470,6 +1770,15 @@ pub const default_pagezero_vmsize: u64 = 0x100000000; |
| 1470 | /// potential future extensions. | 1770 | /// potential future extensions. |
| 1471 | pub const default_headerpad_size: u32 = 0x1000; | 1771 | pub const default_headerpad_size: u32 = 0x1000; |
| 1472 | 1772 | ||
| 1773 | const SystemLib = struct { | ||
| 1774 | path: []const u8, | ||
| 1775 | needed: bool = false, | ||
| 1776 | weak: bool = false, | ||
| 1777 | hidden: bool = false, | ||
| 1778 | reexport: bool = false, | ||
| 1779 | must_link: bool = false, | ||
| 1780 | }; | ||
| 1781 | |||
| 1473 | const MachO = @This(); | 1782 | const MachO = @This(); |
| 1474 | 1783 | ||
| 1475 | const std = @import("std"); | 1784 | const std = @import("std"); |
| ... | @@ -1479,6 +1788,7 @@ const assert = std.debug.assert; | ... | @@ -1479,6 +1788,7 @@ const assert = std.debug.assert; |
| 1479 | const dwarf = std.dwarf; | 1788 | const dwarf = std.dwarf; |
| 1480 | const fs = std.fs; | 1789 | const fs = std.fs; |
| 1481 | const log = std.log.scoped(.link); | 1790 | const log = std.log.scoped(.link); |
| 1791 | const state_log = std.log.scoped(.link_state); | ||
| 1482 | const macho = std.macho; | 1792 | const macho = std.macho; |
| 1483 | const math = std.math; | 1793 | const math = std.math; |
| 1484 | const mem = std.mem; | 1794 | const mem = std.mem; |
| ... | @@ -1488,6 +1798,7 @@ const aarch64 = @import("../arch/aarch64/bits.zig"); | ... | @@ -1488,6 +1798,7 @@ const aarch64 = @import("../arch/aarch64/bits.zig"); |
| 1488 | const calcUuid = @import("MachO/uuid.zig").calcUuid; | 1798 | const calcUuid = @import("MachO/uuid.zig").calcUuid; |
| 1489 | const codegen = @import("../codegen.zig"); | 1799 | const codegen = @import("../codegen.zig"); |
| 1490 | const dead_strip = @import("MachO/dead_strip.zig"); | 1800 | const dead_strip = @import("MachO/dead_strip.zig"); |
| 1801 | const eh_frame = @import("MachO/eh_frame.zig"); | ||
| 1491 | const fat = @import("MachO/fat.zig"); | 1802 | const fat = @import("MachO/fat.zig"); |
| 1492 | const link = @import("../link.zig"); | 1803 | const link = @import("../link.zig"); |
| 1493 | const llvm_backend = @import("../codegen/llvm.zig"); | 1804 | const llvm_backend = @import("../codegen/llvm.zig"); |
| ... | @@ -1496,12 +1807,14 @@ const tapi = @import("tapi.zig"); | ... | @@ -1496,12 +1807,14 @@ const tapi = @import("tapi.zig"); |
| 1496 | const target_util = @import("../target.zig"); | 1807 | const target_util = @import("../target.zig"); |
| 1497 | const thunks = @import("MachO/thunks.zig"); | 1808 | const thunks = @import("MachO/thunks.zig"); |
| 1498 | const trace = @import("../tracy.zig").trace; | 1809 | const trace = @import("../tracy.zig").trace; |
| 1810 | const synthetic = @import("MachO/synthetic.zig"); | ||
| 1499 | 1811 | ||
| 1500 | const Air = @import("../Air.zig"); | 1812 | const Air = @import("../Air.zig"); |
| 1501 | const Alignment = Atom.Alignment; | 1813 | const Alignment = Atom.Alignment; |
| 1502 | const Allocator = mem.Allocator; | 1814 | const Allocator = mem.Allocator; |
| 1503 | const Archive = @import("MachO/Archive.zig"); | 1815 | const Archive = @import("MachO/Archive.zig"); |
| 1504 | pub const Atom = @import("MachO/Atom.zig"); | 1816 | pub const Atom = @import("MachO/Atom.zig"); |
| 1817 | const BindSection = synthetic.BindSection; | ||
| 1505 | const Cache = std.Build.Cache; | 1818 | const Cache = std.Build.Cache; |
| 1506 | const CodeSignature = @import("MachO/CodeSignature.zig"); | 1819 | const CodeSignature = @import("MachO/CodeSignature.zig"); |
| 1507 | const Compilation = @import("../Compilation.zig"); | 1820 | const Compilation = @import("../Compilation.zig"); |
| ... | @@ -1509,17 +1822,29 @@ pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); | ... | @@ -1509,17 +1822,29 @@ pub const DebugSymbols = @import("MachO/DebugSymbols.zig"); |
| 1509 | const Dwarf = File.Dwarf; | 1822 | const Dwarf = File.Dwarf; |
| 1510 | const DwarfInfo = @import("MachO/DwarfInfo.zig"); | 1823 | const DwarfInfo = @import("MachO/DwarfInfo.zig"); |
| 1511 | const Dylib = @import("MachO/Dylib.zig"); | 1824 | const Dylib = @import("MachO/Dylib.zig"); |
| 1512 | const File = link.File; | 1825 | const ExportTrieSection = synthetic.ExportTrieSection; |
| 1826 | const File = @import("MachO/file.zig").File; | ||
| 1827 | const GotSection = synthetic.GotSection; | ||
| 1828 | const Indsymtab = synthetic.Indsymtab; | ||
| 1829 | const InternalObject = @import("MachO/InternalObject.zig"); | ||
| 1830 | const ObjcStubsSection = synthetic.ObjcStubsSection; | ||
| 1513 | const Object = @import("MachO/Object.zig"); | 1831 | const Object = @import("MachO/Object.zig"); |
| 1832 | const LazyBindSection = synthetic.LazyBindSection; | ||
| 1833 | const LaSymbolPtrSection = synthetic.LaSymbolPtrSection; | ||
| 1514 | const LibStub = tapi.LibStub; | 1834 | const LibStub = tapi.LibStub; |
| 1515 | const Liveness = @import("../Liveness.zig"); | 1835 | const Liveness = @import("../Liveness.zig"); |
| 1516 | const LlvmObject = @import("../codegen/llvm.zig").Object; | 1836 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 1517 | const Md5 = std.crypto.hash.Md5; | 1837 | const Md5 = std.crypto.hash.Md5; |
| 1518 | const Module = @import("../Module.zig"); | 1838 | const Module = @import("../Module.zig"); |
| 1519 | const InternPool = @import("../InternPool.zig"); | 1839 | const InternPool = @import("../InternPool.zig"); |
| 1840 | const RebaseSection = synthetic.RebaseSection; | ||
| 1520 | const Relocation = @import("MachO/Relocation.zig"); | 1841 | const Relocation = @import("MachO/Relocation.zig"); |
| 1521 | const StringTable = @import("StringTable.zig"); | 1842 | const StringTable = @import("StringTable.zig"); |
| 1522 | const TableSection = @import("table_section.zig").TableSection; | 1843 | const StubsSection = synthetic.StubsSection; |
| 1523 | const Type = @import("../type.zig").Type; | 1844 | const StubsHelperSection = synthetic.StubsHelperSection; |
| 1845 | const Symbol = @import("MachO/Symbol.zig"); | ||
| 1846 | const Thunk = thunks.Thunk; | ||
| 1847 | const TlvPtrSection = synthetic.TlvPtrSection; | ||
| 1524 | const TypedValue = @import("../TypedValue.zig"); | 1848 | const TypedValue = @import("../TypedValue.zig"); |
| 1525 | const Value = @import("../value.zig").Value; | 1849 | const UnwindInfo = @import("MachO/UnwindInfo.zig"); |
| 1850 | const WeakBindSection = synthetic.WeakBindSection; |
src/link/MachO/Atom.zig+1-1| ... | @@ -38,7 +38,7 @@ unwind_records: Loc = .{}, | ... | @@ -38,7 +38,7 @@ unwind_records: Loc = .{}, |
| 38 | flags: Flags = .{}, | 38 | flags: Flags = .{}, |
| 39 | 39 | ||
| 40 | pub fn getName(self: Atom, macho_file: *MachO) [:0]const u8 { | 40 | pub fn getName(self: Atom, macho_file: *MachO) [:0]const u8 { |
| 41 | return macho_file.string_intern.getAssumeExists(self.name); | 41 | return macho_file.strings.getAssumeExists(self.name); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | pub fn getFile(self: Atom, macho_file: *MachO) File { | 44 | pub fn getFile(self: Atom, macho_file: *MachO) File { |
src/link/MachO/Dylib.zig+1-1| ... | @@ -431,7 +431,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void { | ... | @@ -431,7 +431,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void { |
| 431 | 431 | ||
| 432 | for (self.exports.items(.name)) |noff| { | 432 | for (self.exports.items(.name)) |noff| { |
| 433 | const name = self.getString(noff); | 433 | const name = self.getString(noff); |
| 434 | const off = try macho_file.string_intern.insert(gpa, name); | 434 | const off = try macho_file.strings.insert(gpa, name); |
| 435 | const gop = try macho_file.getOrCreateGlobal(off); | 435 | const gop = try macho_file.getOrCreateGlobal(off); |
| 436 | self.symbols.addOneAssumeCapacity().* = gop.index; | 436 | self.symbols.addOneAssumeCapacity().* = gop.index; |
| 437 | } | 437 | } |
src/link/MachO/Object.zig+138-96| ... | @@ -31,6 +31,14 @@ num_weak_bind_relocs: u32 = 0, | ... | @@ -31,6 +31,14 @@ num_weak_bind_relocs: u32 = 0, |
| 31 | 31 | ||
| 32 | output_symtab_ctx: MachO.SymtabCtx = .{}, | 32 | output_symtab_ctx: MachO.SymtabCtx = .{}, |
| 33 | 33 | ||
| 34 | pub fn isObject(path: []const u8) !bool { | ||
| 35 | const file = try std.fs.cwd().openFile(path, .{}); | ||
| 36 | defer file.close(); | ||
| 37 | const reader = file.reader(); | ||
| 38 | const header = reader.readStruct(macho.mach_header_64) catch return false; | ||
| 39 | return header.filetype == macho.MH_OBJECT; | ||
| 40 | } | ||
| 41 | |||
| 34 | pub fn deinit(self: *Object, allocator: Allocator) void { | 42 | pub fn deinit(self: *Object, allocator: Allocator) void { |
| 35 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { | 43 | for (self.sections.items(.relocs), self.sections.items(.subsections)) |*relocs, *sub| { |
| 36 | relocs.deinit(allocator); | 44 | relocs.deinit(allocator); |
| ... | @@ -55,12 +63,25 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { | ... | @@ -55,12 +63,25 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 55 | const tracy = trace(@src()); | 63 | const tracy = trace(@src()); |
| 56 | defer tracy.end(); | 64 | defer tracy.end(); |
| 57 | 65 | ||
| 58 | const gpa = macho_file.base.allocator; | 66 | const gpa = macho_file.base.comp.gpa; |
| 59 | var stream = std.io.fixedBufferStream(self.data); | 67 | var stream = std.io.fixedBufferStream(self.data); |
| 60 | const reader = stream.reader(); | 68 | const reader = stream.reader(); |
| 61 | 69 | ||
| 62 | self.header = try reader.readStruct(macho.mach_header_64); | 70 | self.header = try reader.readStruct(macho.mach_header_64); |
| 63 | 71 | ||
| 72 | const this_cpu_arch: std.Target.Cpu.Arch = switch (self.header.?.cputype) { | ||
| 73 | macho.CPU_TYPE_ARM64 => .aarch64, | ||
| 74 | macho.CPU_TYPE_X86_64 => .x86_64, | ||
| 75 | else => |x| { | ||
| 76 | try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x}); | ||
| 77 | return error.InvalidCpuArch; | ||
| 78 | }, | ||
| 79 | }; | ||
| 80 | if (macho_file.getTarget().cpu.arch != this_cpu_arch) { | ||
| 81 | try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)}); | ||
| 82 | return error.InvalidCpuArch; | ||
| 83 | } | ||
| 84 | |||
| 64 | if (self.getLoadCommand(.SEGMENT_64)) |lc| { | 85 | if (self.getLoadCommand(.SEGMENT_64)) |lc| { |
| 65 | const sections = lc.getSections(); | 86 | const sections = lc.getSections(); |
| 66 | try self.sections.ensureUnusedCapacity(gpa, sections.len); | 87 | try self.sections.ensureUnusedCapacity(gpa, sections.len); |
| ... | @@ -146,6 +167,20 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { | ... | @@ -146,6 +167,20 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { |
| 146 | } | 167 | } |
| 147 | 168 | ||
| 148 | self.initPlatform(); | 169 | self.initPlatform(); |
| 170 | |||
| 171 | if (self.platform) |platform| { | ||
| 172 | if (!macho_file.platform.eqlTarget(platform)) { | ||
| 173 | try macho_file.reportParseError2(self.index, "invalid platform: {}", .{ | ||
| 174 | platform.fmtTarget(macho_file.getTarget().cpu.arch), | ||
| 175 | }); | ||
| 176 | return error.InvalidTarget; | ||
| 177 | } | ||
| 178 | if (macho_file.platform.version.order(platform.version) != .lt) { | ||
| 179 | try macho_file.reportParseError2(self.index, "object file built for newer platform: {}", .{platform}); | ||
| 180 | return error.InvalidTarget; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 149 | try self.initDwarfInfo(macho_file); | 184 | try self.initDwarfInfo(macho_file); |
| 150 | 185 | ||
| 151 | for (self.atoms.items) |atom_index| { | 186 | for (self.atoms.items) |atom_index| { |
| ... | @@ -175,7 +210,7 @@ inline fn isLiteral(sect: macho.section_64) bool { | ... | @@ -175,7 +210,7 @@ inline fn isLiteral(sect: macho.section_64) bool { |
| 175 | fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void { | 210 | fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 176 | const tracy = trace(@src()); | 211 | const tracy = trace(@src()); |
| 177 | defer tracy.end(); | 212 | defer tracy.end(); |
| 178 | const gpa = macho_file.base.allocator; | 213 | const gpa = macho_file.base.comp.gpa; |
| 179 | const slice = self.sections.slice(); | 214 | const slice = self.sections.slice(); |
| 180 | for (slice.items(.header), slice.items(.subsections), 0..) |sect, *subsections, n_sect| { | 215 | for (slice.items(.header), slice.items(.subsections), 0..) |sect, *subsections, n_sect| { |
| 181 | if (isLiteral(sect)) continue; | 216 | if (isLiteral(sect)) continue; |
| ... | @@ -243,7 +278,7 @@ fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -243,7 +278,7 @@ fn initSubsections(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 243 | fn initSections(self: *Object, nlists: anytype, macho_file: *MachO) !void { | 278 | fn initSections(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 244 | const tracy = trace(@src()); | 279 | const tracy = trace(@src()); |
| 245 | defer tracy.end(); | 280 | defer tracy.end(); |
| 246 | const gpa = macho_file.base.allocator; | 281 | const gpa = macho_file.base.comp.gpa; |
| 247 | const slice = self.sections.slice(); | 282 | const slice = self.sections.slice(); |
| 248 | 283 | ||
| 249 | try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len); | 284 | try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len); |
| ... | @@ -299,12 +334,12 @@ const AddAtomArgs = struct { | ... | @@ -299,12 +334,12 @@ const AddAtomArgs = struct { |
| 299 | }; | 334 | }; |
| 300 | 335 | ||
| 301 | fn addAtom(self: *Object, args: AddAtomArgs, macho_file: *MachO) !Atom.Index { | 336 | fn addAtom(self: *Object, args: AddAtomArgs, macho_file: *MachO) !Atom.Index { |
| 302 | const gpa = macho_file.base.allocator; | 337 | const gpa = macho_file.base.comp.gpa; |
| 303 | const atom_index = try macho_file.addAtom(); | 338 | const atom_index = try macho_file.addAtom(); |
| 304 | const atom = macho_file.getAtom(atom_index).?; | 339 | const atom = macho_file.getAtom(atom_index).?; |
| 305 | atom.file = self.index; | 340 | atom.file = self.index; |
| 306 | atom.atom_index = atom_index; | 341 | atom.atom_index = atom_index; |
| 307 | atom.name = try macho_file.string_intern.insert(gpa, args.name); | 342 | atom.name = try macho_file.strings.insert(gpa, args.name); |
| 308 | atom.n_sect = args.n_sect; | 343 | atom.n_sect = args.n_sect; |
| 309 | atom.size = args.size; | 344 | atom.size = args.size; |
| 310 | atom.alignment = args.alignment; | 345 | atom.alignment = args.alignment; |
| ... | @@ -319,7 +354,7 @@ fn initLiteralSections(self: *Object, macho_file: *MachO) !void { | ... | @@ -319,7 +354,7 @@ fn initLiteralSections(self: *Object, macho_file: *MachO) !void { |
| 319 | // TODO here we should split into equal-sized records, hash the contents, and then | 354 | // TODO here we should split into equal-sized records, hash the contents, and then |
| 320 | // deduplicate - ICF. | 355 | // deduplicate - ICF. |
| 321 | // For now, we simply cover each literal section with one large atom. | 356 | // For now, we simply cover each literal section with one large atom. |
| 322 | const gpa = macho_file.base.allocator; | 357 | const gpa = macho_file.base.comp.gpa; |
| 323 | const slice = self.sections.slice(); | 358 | const slice = self.sections.slice(); |
| 324 | 359 | ||
| 325 | try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len); | 360 | try self.atoms.ensureUnusedCapacity(gpa, self.sections.items(.header).len); |
| ... | @@ -401,10 +436,10 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void { | ... | @@ -401,10 +436,10 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void { |
| 401 | if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| { | 436 | if (self.findAtomInSection(nlist.n_value, nlist.n_sect - 1)) |atom_index| { |
| 402 | atom.* = atom_index; | 437 | atom.* = atom_index; |
| 403 | } else { | 438 | } else { |
| 404 | macho_file.base.fatal("{}: symbol {s} not attached to any (sub)section", .{ | 439 | try macho_file.reportParseError2(self.index, "symbol {s} not attached to any (sub)section", .{ |
| 405 | self.fmtPath(), self.getString(nlist.n_strx), | 440 | self.getString(nlist.n_strx), |
| 406 | }); | 441 | }); |
| 407 | return error.ParseFailed; | 442 | return error.MalformedObject; |
| 408 | } | 443 | } |
| 409 | } | 444 | } |
| 410 | } | 445 | } |
| ... | @@ -413,7 +448,7 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void { | ... | @@ -413,7 +448,7 @@ fn linkNlistToAtom(self: *Object, macho_file: *MachO) !void { |
| 413 | fn initSymbols(self: *Object, macho_file: *MachO) !void { | 448 | fn initSymbols(self: *Object, macho_file: *MachO) !void { |
| 414 | const tracy = trace(@src()); | 449 | const tracy = trace(@src()); |
| 415 | defer tracy.end(); | 450 | defer tracy.end(); |
| 416 | const gpa = macho_file.base.allocator; | 451 | const gpa = macho_file.base.comp.gpa; |
| 417 | const slice = self.symtab.slice(); | 452 | const slice = self.symtab.slice(); |
| 418 | 453 | ||
| 419 | try self.symbols.ensureUnusedCapacity(gpa, slice.items(.nlist).len); | 454 | try self.symbols.ensureUnusedCapacity(gpa, slice.items(.nlist).len); |
| ... | @@ -421,7 +456,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void { | ... | @@ -421,7 +456,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void { |
| 421 | for (slice.items(.nlist), slice.items(.atom), 0..) |nlist, atom_index, i| { | 456 | for (slice.items(.nlist), slice.items(.atom), 0..) |nlist, atom_index, i| { |
| 422 | if (nlist.ext()) { | 457 | if (nlist.ext()) { |
| 423 | const name = self.getString(nlist.n_strx); | 458 | const name = self.getString(nlist.n_strx); |
| 424 | const off = try macho_file.string_intern.insert(gpa, name); | 459 | const off = try macho_file.strings.insert(gpa, name); |
| 425 | const gop = try macho_file.getOrCreateGlobal(off); | 460 | const gop = try macho_file.getOrCreateGlobal(off); |
| 426 | self.symbols.addOneAssumeCapacity().* = gop.index; | 461 | self.symbols.addOneAssumeCapacity().* = gop.index; |
| 427 | continue; | 462 | continue; |
| ... | @@ -433,7 +468,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void { | ... | @@ -433,7 +468,7 @@ fn initSymbols(self: *Object, macho_file: *MachO) !void { |
| 433 | const name = self.getString(nlist.n_strx); | 468 | const name = self.getString(nlist.n_strx); |
| 434 | symbol.* = .{ | 469 | symbol.* = .{ |
| 435 | .value = nlist.n_value, | 470 | .value = nlist.n_value, |
| 436 | .name = try macho_file.string_intern.insert(gpa, name), | 471 | .name = try macho_file.strings.insert(gpa, name), |
| 437 | .nlist_idx = @intCast(i), | 472 | .nlist_idx = @intCast(i), |
| 438 | .atom = 0, | 473 | .atom = 0, |
| 439 | .file = self.index, | 474 | .file = self.index, |
| ... | @@ -482,7 +517,7 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -482,7 +517,7 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 482 | 517 | ||
| 483 | if (start == end) return; | 518 | if (start == end) return; |
| 484 | 519 | ||
| 485 | const gpa = macho_file.base.allocator; | 520 | const gpa = macho_file.base.comp.gpa; |
| 486 | const syms = self.symtab.items(.nlist); | 521 | const syms = self.symtab.items(.nlist); |
| 487 | const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists }; | 522 | const sym_lookup = SymbolLookup{ .ctx = self, .entries = nlists }; |
| 488 | 523 | ||
| ... | @@ -490,11 +525,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -490,11 +525,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 490 | while (i < end) : (i += 1) { | 525 | while (i < end) : (i += 1) { |
| 491 | const open = syms[i]; | 526 | const open = syms[i]; |
| 492 | if (open.n_type != macho.N_SO) { | 527 | if (open.n_type != macho.N_SO) { |
| 493 | macho_file.base.fatal("{}: unexpected symbol stab type 0x{x} as the first entry", .{ | 528 | try macho_file.reportParseError2(self.index, "unexpected symbol stab type 0x{x} as the first entry", .{ |
| 494 | self.fmtPath(), | ||
| 495 | open.n_type, | 529 | open.n_type, |
| 496 | }); | 530 | }); |
| 497 | return error.ParseFailed; | 531 | return error.MalformedObject; |
| 498 | } | 532 | } |
| 499 | 533 | ||
| 500 | while (i < end and syms[i].n_type == macho.N_SO and syms[i].n_sect != 0) : (i += 1) {} | 534 | while (i < end and syms[i].n_type == macho.N_SO and syms[i].n_sect != 0) : (i += 1) {} |
| ... | @@ -522,11 +556,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { | ... | @@ -522,11 +556,10 @@ fn initSymbolStabs(self: *Object, nlists: anytype, macho_file: *MachO) !void { |
| 522 | stab.symbol = sym_lookup.find(nlist.n_value); | 556 | stab.symbol = sym_lookup.find(nlist.n_value); |
| 523 | }, | 557 | }, |
| 524 | else => { | 558 | else => { |
| 525 | macho_file.base.fatal("{}: unhandled symbol stab type 0x{x}", .{ | 559 | try macho_file.reportParseError2(self.index, "unhandled symbol stab type 0x{x}", .{ |
| 526 | self.fmtPath(), | ||
| 527 | nlist.n_type, | 560 | nlist.n_type, |
| 528 | }); | 561 | }); |
| 529 | return error.ParseFailed; | 562 | return error.MalformedObject; |
| 530 | }, | 563 | }, |
| 531 | } | 564 | } |
| 532 | try sf.stabs.append(gpa, stab); | 565 | try sf.stabs.append(gpa, stab); |
| ... | @@ -548,7 +581,7 @@ fn sortAtoms(self: *Object, macho_file: *MachO) !void { | ... | @@ -548,7 +581,7 @@ fn sortAtoms(self: *Object, macho_file: *MachO) !void { |
| 548 | fn initRelocs(self: *Object, macho_file: *MachO) !void { | 581 | fn initRelocs(self: *Object, macho_file: *MachO) !void { |
| 549 | const tracy = trace(@src()); | 582 | const tracy = trace(@src()); |
| 550 | defer tracy.end(); | 583 | defer tracy.end(); |
| 551 | const cpu_arch = macho_file.options.cpu_arch.?; | 584 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 552 | const slice = self.sections.slice(); | 585 | const slice = self.sections.slice(); |
| 553 | 586 | ||
| 554 | for (slice.items(.header), slice.items(.relocs), 0..) |sect, *out, n_sect| { | 587 | for (slice.items(.header), slice.items(.relocs), 0..) |sect, *out, n_sect| { |
| ... | @@ -589,7 +622,7 @@ fn initRelocs(self: *Object, macho_file: *MachO) !void { | ... | @@ -589,7 +622,7 @@ fn initRelocs(self: *Object, macho_file: *MachO) !void { |
| 589 | fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | 622 | fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 590 | const tracy = trace(@src()); | 623 | const tracy = trace(@src()); |
| 591 | defer tracy.end(); | 624 | defer tracy.end(); |
| 592 | const gpa = macho_file.base.allocator; | 625 | const gpa = macho_file.base.comp.gpa; |
| 593 | const nlists = self.symtab.items(.nlist); | 626 | const nlists = self.symtab.items(.nlist); |
| 594 | const slice = self.sections.slice(); | 627 | const slice = self.sections.slice(); |
| 595 | const sect = slice.items(.header)[sect_id]; | 628 | const sect = slice.items(.header)[sect_id]; |
| ... | @@ -667,10 +700,10 @@ fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -667,10 +700,10 @@ fn initEhFrameRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 667 | const cie = for (self.cies.items) |*cie| { | 700 | const cie = for (self.cies.items) |*cie| { |
| 668 | if (cie.offset <= rel.offset and rel.offset < cie.offset + cie.getSize()) break cie; | 701 | if (cie.offset <= rel.offset and rel.offset < cie.offset + cie.getSize()) break cie; |
| 669 | } else { | 702 | } else { |
| 670 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 703 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 671 | self.fmtPath(), sect.segName(), sect.sectName(), rel.offset, | 704 | sect.segName(), sect.sectName(), rel.offset, |
| 672 | }); | 705 | }); |
| 673 | return error.ParseFailed; | 706 | return error.MalformedObject; |
| 674 | }; | 707 | }; |
| 675 | cie.personality = .{ .index = @intCast(rel.target), .offset = rel.offset - cie.offset }; | 708 | cie.personality = .{ .index = @intCast(rel.target), .offset = rel.offset - cie.offset }; |
| 676 | }, | 709 | }, |
| ... | @@ -695,7 +728,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -695,7 +728,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 695 | } | 728 | } |
| 696 | }; | 729 | }; |
| 697 | 730 | ||
| 698 | const gpa = macho_file.base.allocator; | 731 | const gpa = macho_file.base.comp.gpa; |
| 699 | const data = self.getSectionData(sect_id); | 732 | const data = self.getSectionData(sect_id); |
| 700 | const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); | 733 | const nrecs = @divExact(data.len, @sizeOf(macho.compact_unwind_entry)); |
| 701 | const recs = @as([*]align(1) const macho.compact_unwind_entry, @ptrCast(data.ptr))[0..nrecs]; | 734 | const recs = @as([*]align(1) const macho.compact_unwind_entry, @ptrCast(data.ptr))[0..nrecs]; |
| ... | @@ -722,10 +755,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -722,10 +755,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 722 | 755 | ||
| 723 | for (relocs[reloc_start..reloc_idx]) |rel| { | 756 | for (relocs[reloc_start..reloc_idx]) |rel| { |
| 724 | if (rel.type != .unsigned or rel.meta.length != 3) { | 757 | if (rel.type != .unsigned or rel.meta.length != 3) { |
| 725 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 758 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 726 | self.fmtPath(), header.segName(), header.sectName(), rel.offset, | 759 | header.segName(), header.sectName(), rel.offset, |
| 727 | }); | 760 | }); |
| 728 | return error.ParseFailed; | 761 | return error.MalformedObject; |
| 729 | } | 762 | } |
| 730 | assert(rel.type == .unsigned and rel.meta.length == 3); // TODO error | 763 | assert(rel.type == .unsigned and rel.meta.length == 3); // TODO error |
| 731 | const offset = rel.offset - rec_start; | 764 | const offset = rel.offset - rec_start; |
| ... | @@ -740,10 +773,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -740,10 +773,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 740 | const atom = out.getAtom(macho_file); | 773 | const atom = out.getAtom(macho_file); |
| 741 | out.atom_offset = @intCast(rec.rangeStart - atom.getInputAddress(macho_file)); | 774 | out.atom_offset = @intCast(rec.rangeStart - atom.getInputAddress(macho_file)); |
| 742 | } else { | 775 | } else { |
| 743 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 776 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 744 | self.fmtPath(), header.segName(), header.sectName(), rel.offset, | 777 | header.segName(), header.sectName(), rel.offset, |
| 745 | }); | 778 | }); |
| 746 | return error.ParseFailed; | 779 | return error.MalformedObject; |
| 747 | }, | 780 | }, |
| 748 | }, | 781 | }, |
| 749 | 16 => switch (rel.tag) { // personality function | 782 | 16 => switch (rel.tag) { // personality function |
| ... | @@ -753,10 +786,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -753,10 +786,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 753 | .local => if (sym_lookup.find(rec.personalityFunction)) |sym_index| { | 786 | .local => if (sym_lookup.find(rec.personalityFunction)) |sym_index| { |
| 754 | out.personality = sym_index; | 787 | out.personality = sym_index; |
| 755 | } else { | 788 | } else { |
| 756 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 789 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 757 | self.fmtPath(), header.segName(), header.sectName(), rel.offset, | 790 | header.segName(), header.sectName(), rel.offset, |
| 758 | }); | 791 | }); |
| 759 | return error.ParseFailed; | 792 | return error.MalformedObject; |
| 760 | }, | 793 | }, |
| 761 | }, | 794 | }, |
| 762 | 24 => switch (rel.tag) { // lsda | 795 | 24 => switch (rel.tag) { // lsda |
| ... | @@ -769,10 +802,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -769,10 +802,10 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 769 | const atom = out.getLsdaAtom(macho_file).?; | 802 | const atom = out.getLsdaAtom(macho_file).?; |
| 770 | out.lsda_offset = @intCast(rec.lsda - atom.getInputAddress(macho_file)); | 803 | out.lsda_offset = @intCast(rec.lsda - atom.getInputAddress(macho_file)); |
| 771 | } else { | 804 | } else { |
| 772 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 805 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 773 | self.fmtPath(), header.segName(), header.sectName(), rel.offset, | 806 | header.segName(), header.sectName(), rel.offset, |
| 774 | }); | 807 | }); |
| 775 | return error.ParseFailed; | 808 | return error.MalformedObject; |
| 776 | }, | 809 | }, |
| 777 | }, | 810 | }, |
| 778 | else => {}, | 811 | else => {}, |
| ... | @@ -780,7 +813,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { | ... | @@ -780,7 +813,7 @@ fn initUnwindRecords(self: *Object, sect_id: u8, macho_file: *MachO) !void { |
| 780 | } | 813 | } |
| 781 | } | 814 | } |
| 782 | 815 | ||
| 783 | if (!macho_file.options.relocatable) try self.synthesiseNullUnwindRecords(macho_file); | 816 | if (!macho_file.base.isObject()) try self.synthesiseNullUnwindRecords(macho_file); |
| 784 | 817 | ||
| 785 | const sortFn = struct { | 818 | const sortFn = struct { |
| 786 | fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { | 819 | fn sortFn(ctx: *MachO, lhs_index: UnwindInfo.Record.Index, rhs_index: UnwindInfo.Record.Index) bool { |
| ... | @@ -818,7 +851,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { | ... | @@ -818,7 +851,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 818 | 851 | ||
| 819 | const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null }; | 852 | const Superposition = struct { atom: Atom.Index, size: u64, cu: ?UnwindInfo.Record.Index = null, fde: ?Fde.Index = null }; |
| 820 | 853 | ||
| 821 | const gpa = macho_file.base.allocator; | 854 | const gpa = macho_file.base.comp.gpa; |
| 822 | var superposition = std.AutoArrayHashMap(u64, Superposition).init(gpa); | 855 | var superposition = std.AutoArrayHashMap(u64, Superposition).init(gpa); |
| 823 | defer superposition.deinit(); | 856 | defer superposition.deinit(); |
| 824 | 857 | ||
| ... | @@ -875,7 +908,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { | ... | @@ -875,7 +908,7 @@ fn synthesiseNullUnwindRecords(self: *Object, macho_file: *MachO) !void { |
| 875 | rec.atom_offset = fde.atom_offset; | 908 | rec.atom_offset = fde.atom_offset; |
| 876 | rec.fde = fde_index; | 909 | rec.fde = fde_index; |
| 877 | rec.file = fde.file; | 910 | rec.file = fde.file; |
| 878 | switch (macho_file.options.cpu_arch.?) { | 911 | switch (macho_file.getTarget().cpu.arch) { |
| 879 | .x86_64 => rec.enc.setMode(macho.UNWIND_X86_64_MODE.DWARF), | 912 | .x86_64 => rec.enc.setMode(macho.UNWIND_X86_64_MODE.DWARF), |
| 880 | .aarch64 => rec.enc.setMode(macho.UNWIND_ARM64_MODE.DWARF), | 913 | .aarch64 => rec.enc.setMode(macho.UNWIND_ARM64_MODE.DWARF), |
| 881 | else => unreachable, | 914 | else => unreachable, |
| ... | @@ -907,7 +940,7 @@ fn initPlatform(self: *Object) void { | ... | @@ -907,7 +940,7 @@ fn initPlatform(self: *Object) void { |
| 907 | .VERSION_MIN_IPHONEOS, | 940 | .VERSION_MIN_IPHONEOS, |
| 908 | .VERSION_MIN_TVOS, | 941 | .VERSION_MIN_TVOS, |
| 909 | .VERSION_MIN_WATCHOS, | 942 | .VERSION_MIN_WATCHOS, |
| 910 | => break MachO.Options.Platform.fromLoadCommand(cmd), | 943 | => break MachO.Platform.fromLoadCommand(cmd), |
| 911 | else => {}, | 944 | else => {}, |
| 912 | } | 945 | } |
| 913 | } else null; | 946 | } else null; |
| ... | @@ -921,7 +954,7 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void { | ... | @@ -921,7 +954,7 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void { |
| 921 | const tracy = trace(@src()); | 954 | const tracy = trace(@src()); |
| 922 | defer tracy.end(); | 955 | defer tracy.end(); |
| 923 | 956 | ||
| 924 | const gpa = macho_file.base.allocator; | 957 | const gpa = macho_file.base.comp.gpa; |
| 925 | 958 | ||
| 926 | var debug_info_index: ?usize = null; | 959 | var debug_info_index: ?usize = null; |
| 927 | var debug_abbrev_index: ?usize = null; | 960 | var debug_abbrev_index: ?usize = null; |
| ... | @@ -942,8 +975,8 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void { | ... | @@ -942,8 +975,8 @@ fn initDwarfInfo(self: *Object, macho_file: *MachO) !void { |
| 942 | .debug_str = if (debug_str_index) |index| self.getSectionData(@intCast(index)) else "", | 975 | .debug_str = if (debug_str_index) |index| self.getSectionData(@intCast(index)) else "", |
| 943 | }; | 976 | }; |
| 944 | dwarf_info.init(gpa) catch { | 977 | dwarf_info.init(gpa) catch { |
| 945 | macho_file.base.fatal("{}: invalid __DWARF info found", .{self.fmtPath()}); | 978 | try macho_file.reportParseError2(self.index, "invalid __DWARF info found", .{}); |
| 946 | return error.ParseFailed; | 979 | return error.MalformedObject; |
| 947 | }; | 980 | }; |
| 948 | self.dwarf_info = dwarf_info; | 981 | self.dwarf_info = dwarf_info; |
| 949 | } | 982 | } |
| ... | @@ -1060,7 +1093,7 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void { | ... | @@ -1060,7 +1093,7 @@ pub fn scanRelocs(self: Object, macho_file: *MachO) !void { |
| 1060 | pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void { | 1093 | pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void { |
| 1061 | const tracy = trace(@src()); | 1094 | const tracy = trace(@src()); |
| 1062 | defer tracy.end(); | 1095 | defer tracy.end(); |
| 1063 | const gpa = macho_file.base.allocator; | 1096 | const gpa = macho_file.base.comp.gpa; |
| 1064 | 1097 | ||
| 1065 | for (self.symbols.items, 0..) |index, i| { | 1098 | for (self.symbols.items, 0..) |index, i| { |
| 1066 | const sym = macho_file.getSymbol(index); | 1099 | const sym = macho_file.getSymbol(index); |
| ... | @@ -1079,7 +1112,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void { | ... | @@ -1079,7 +1112,7 @@ pub fn convertTentativeDefinitions(self: *Object, macho_file: *MachO) !void { |
| 1079 | defer gpa.free(name); | 1112 | defer gpa.free(name); |
| 1080 | const atom = macho_file.getAtom(atom_index).?; | 1113 | const atom = macho_file.getAtom(atom_index).?; |
| 1081 | atom.atom_index = atom_index; | 1114 | atom.atom_index = atom_index; |
| 1082 | atom.name = try macho_file.string_intern.insert(gpa, name); | 1115 | atom.name = try macho_file.strings.insert(gpa, name); |
| 1083 | atom.file = self.index; | 1116 | atom.file = self.index; |
| 1084 | atom.size = nlist.n_value; | 1117 | atom.size = nlist.n_value; |
| 1085 | atom.alignment = (nlist.n_desc >> 8) & 0x0f; | 1118 | atom.alignment = (nlist.n_desc >> 8) & 0x0f; |
| ... | @@ -1130,7 +1163,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void { | ... | @@ -1130,7 +1163,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void { |
| 1130 | const name = sym.getName(macho_file); | 1163 | const name = sym.getName(macho_file); |
| 1131 | // TODO in -r mode, we actually want to merge symbol names and emit only one | 1164 | // TODO in -r mode, we actually want to merge symbol names and emit only one |
| 1132 | // work it out when emitting relocs | 1165 | // work it out when emitting relocs |
| 1133 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l') and !macho_file.options.relocatable) continue; | 1166 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l') and !macho_file.base.isObject()) continue; |
| 1134 | sym.flags.output_symtab = true; | 1167 | sym.flags.output_symtab = true; |
| 1135 | if (sym.isLocal()) { | 1168 | if (sym.isLocal()) { |
| 1136 | try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file); | 1169 | try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file); |
| ... | @@ -1171,7 +1204,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { | ... | @@ -1171,7 +1204,7 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { |
| 1171 | const file = sym.getFile(macho_file) orelse continue; | 1204 | const file = sym.getFile(macho_file) orelse continue; |
| 1172 | if (file.getIndex() != self.index) continue; | 1205 | if (file.getIndex() != self.index) continue; |
| 1173 | if (!sym.flags.output_symtab) continue; | 1206 | if (!sym.flags.output_symtab) continue; |
| 1174 | if (macho_file.options.relocatable) { | 1207 | if (macho_file.base.isObject()) { |
| 1175 | const name = sym.getName(macho_file); | 1208 | const name = sym.getName(macho_file); |
| 1176 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; | 1209 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; |
| 1177 | } | 1210 | } |
| ... | @@ -1329,7 +1362,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) void { | ... | @@ -1329,7 +1362,7 @@ pub fn writeStabs(self: *const Object, macho_file: *MachO) void { |
| 1329 | const file = sym.getFile(macho_file) orelse continue; | 1362 | const file = sym.getFile(macho_file) orelse continue; |
| 1330 | if (file.getIndex() != self.index) continue; | 1363 | if (file.getIndex() != self.index) continue; |
| 1331 | if (!sym.flags.output_symtab) continue; | 1364 | if (!sym.flags.output_symtab) continue; |
| 1332 | if (macho_file.options.relocatable) { | 1365 | if (macho_file.base.isObject()) { |
| 1333 | const name = sym.getName(macho_file); | 1366 | const name = sym.getName(macho_file); |
| 1334 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; | 1367 | if (name.len > 0 and (name[0] == 'L' or name[0] == 'l')) continue; |
| 1335 | } | 1368 | } |
| ... | @@ -1747,7 +1780,7 @@ const x86_64 = struct { | ... | @@ -1747,7 +1780,7 @@ const x86_64 = struct { |
| 1747 | out: *std.ArrayListUnmanaged(Relocation), | 1780 | out: *std.ArrayListUnmanaged(Relocation), |
| 1748 | macho_file: *MachO, | 1781 | macho_file: *MachO, |
| 1749 | ) !void { | 1782 | ) !void { |
| 1750 | const gpa = macho_file.base.allocator; | 1783 | const gpa = macho_file.base.comp.gpa; |
| 1751 | 1784 | ||
| 1752 | const relocs = @as( | 1785 | const relocs = @as( |
| 1753 | [*]align(1) const macho.relocation_info, | 1786 | [*]align(1) const macho.relocation_info, |
| ... | @@ -1783,10 +1816,10 @@ const x86_64 = struct { | ... | @@ -1783,10 +1816,10 @@ const x86_64 = struct { |
| 1783 | else | 1816 | else |
| 1784 | addend; | 1817 | addend; |
| 1785 | const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse { | 1818 | const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse { |
| 1786 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 1819 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 1787 | self.fmtPath(), sect.segName(), sect.sectName(), rel.r_address, | 1820 | sect.segName(), sect.sectName(), rel.r_address, |
| 1788 | }); | 1821 | }); |
| 1789 | return error.ParseFailed; | 1822 | return error.MalformedObject; |
| 1790 | }; | 1823 | }; |
| 1791 | addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); | 1824 | addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); |
| 1792 | break :blk target; | 1825 | break :blk target; |
| ... | @@ -1796,34 +1829,38 @@ const x86_64 = struct { | ... | @@ -1796,34 +1829,38 @@ const x86_64 = struct { |
| 1796 | @as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR) | 1829 | @as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR) |
| 1797 | blk: { | 1830 | blk: { |
| 1798 | if (rel_type != .X86_64_RELOC_UNSIGNED) { | 1831 | if (rel_type != .X86_64_RELOC_UNSIGNED) { |
| 1799 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: X86_64_RELOC_SUBTRACTOR followed by {s}", .{ | 1832 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: X86_64_RELOC_SUBTRACTOR followed by {s}", .{ |
| 1800 | self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type), | 1833 | sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type), |
| 1801 | }); | 1834 | }); |
| 1802 | return error.ParseFailed; | 1835 | return error.MalformedObject; |
| 1803 | } | 1836 | } |
| 1804 | break :blk true; | 1837 | break :blk true; |
| 1805 | } else false; | 1838 | } else false; |
| 1806 | 1839 | ||
| 1807 | const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { | 1840 | const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { |
| 1808 | switch (err) { | 1841 | switch (err) { |
| 1809 | error.Pcrel => macho_file.base.fatal( | 1842 | error.Pcrel => try macho_file.reportParseError2( |
| 1810 | "{}: {s},{s}: 0x{x}: PC-relative {s} relocation", | 1843 | self.index, |
| 1811 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 1844 | "{s},{s}: 0x{x}: PC-relative {s} relocation", |
| 1845 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1812 | ), | 1846 | ), |
| 1813 | error.NonPcrel => macho_file.base.fatal( | 1847 | error.NonPcrel => try macho_file.reportParseError2( |
| 1814 | "{}: {s},{s}: 0x{x}: non-PC-relative {s} relocation", | 1848 | self.index, |
| 1815 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 1849 | "{s},{s}: 0x{x}: non-PC-relative {s} relocation", |
| 1850 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1816 | ), | 1851 | ), |
| 1817 | error.InvalidLength => macho_file.base.fatal( | 1852 | error.InvalidLength => try macho_file.reportParseError2( |
| 1818 | "{}: {s},{s}: 0x{x}: invalid length of {d} in {s} relocation", | 1853 | self.index, |
| 1819 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) }, | 1854 | "{s},{s}: 0x{x}: invalid length of {d} in {s} relocation", |
| 1855 | .{ sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) }, | ||
| 1820 | ), | 1856 | ), |
| 1821 | error.NonExtern => macho_file.base.fatal( | 1857 | error.NonExtern => try macho_file.reportParseError2( |
| 1822 | "{}: {s},{s}: 0x{x}: non-extern target in {s} relocation", | 1858 | self.index, |
| 1823 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 1859 | "{s},{s}: 0x{x}: non-extern target in {s} relocation", |
| 1860 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1824 | ), | 1861 | ), |
| 1825 | } | 1862 | } |
| 1826 | return error.ParseFailed; | 1863 | return error.MalformedObject; |
| 1827 | }; | 1864 | }; |
| 1828 | 1865 | ||
| 1829 | out.appendAssumeCapacity(.{ | 1866 | out.appendAssumeCapacity(.{ |
| ... | @@ -1899,7 +1936,7 @@ const aarch64 = struct { | ... | @@ -1899,7 +1936,7 @@ const aarch64 = struct { |
| 1899 | out: *std.ArrayListUnmanaged(Relocation), | 1936 | out: *std.ArrayListUnmanaged(Relocation), |
| 1900 | macho_file: *MachO, | 1937 | macho_file: *MachO, |
| 1901 | ) !void { | 1938 | ) !void { |
| 1902 | const gpa = macho_file.base.allocator; | 1939 | const gpa = macho_file.base.comp.gpa; |
| 1903 | 1940 | ||
| 1904 | const relocs = @as( | 1941 | const relocs = @as( |
| 1905 | [*]align(1) const macho.relocation_info, | 1942 | [*]align(1) const macho.relocation_info, |
| ... | @@ -1921,20 +1958,21 @@ const aarch64 = struct { | ... | @@ -1921,20 +1958,21 @@ const aarch64 = struct { |
| 1921 | addend = rel.r_symbolnum; | 1958 | addend = rel.r_symbolnum; |
| 1922 | i += 1; | 1959 | i += 1; |
| 1923 | if (i >= relocs.len) { | 1960 | if (i >= relocs.len) { |
| 1924 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: unterminated ARM64_RELOC_ADDEND", .{ | 1961 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: unterminated ARM64_RELOC_ADDEND", .{ |
| 1925 | self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, | 1962 | sect.segName(), sect.sectName(), rel_offset, |
| 1926 | }); | 1963 | }); |
| 1927 | return error.ParseFailed; | 1964 | return error.MalformedObject; |
| 1928 | } | 1965 | } |
| 1929 | rel = relocs[i]; | 1966 | rel = relocs[i]; |
| 1930 | switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { | 1967 | switch (@as(macho.reloc_type_arm64, @enumFromInt(rel.r_type))) { |
| 1931 | .ARM64_RELOC_PAGE21, .ARM64_RELOC_PAGEOFF12 => {}, | 1968 | .ARM64_RELOC_PAGE21, .ARM64_RELOC_PAGEOFF12 => {}, |
| 1932 | else => |x| { | 1969 | else => |x| { |
| 1933 | macho_file.base.fatal( | 1970 | try macho_file.reportParseError2( |
| 1934 | "{}: {s},{s}: 0x{x}: ARM64_RELOC_ADDEND followed by {s}", | 1971 | self.index, |
| 1935 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(x) }, | 1972 | "{s},{s}: 0x{x}: ARM64_RELOC_ADDEND followed by {s}", |
| 1973 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(x) }, | ||
| 1936 | ); | 1974 | ); |
| 1937 | return error.ParseFailed; | 1975 | return error.MalformedObject; |
| 1938 | }, | 1976 | }, |
| 1939 | } | 1977 | } |
| 1940 | }, | 1978 | }, |
| ... | @@ -1958,10 +1996,10 @@ const aarch64 = struct { | ... | @@ -1958,10 +1996,10 @@ const aarch64 = struct { |
| 1958 | else | 1996 | else |
| 1959 | addend; | 1997 | addend; |
| 1960 | const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse { | 1998 | const target = self.findAtomInSection(@intCast(taddr), @intCast(nsect)) orelse { |
| 1961 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: bad relocation", .{ | 1999 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: bad relocation", .{ |
| 1962 | self.fmtPath(), sect.segName(), sect.sectName(), rel.r_address, | 2000 | sect.segName(), sect.sectName(), rel.r_address, |
| 1963 | }); | 2001 | }); |
| 1964 | return error.ParseFailed; | 2002 | return error.MalformedObject; |
| 1965 | }; | 2003 | }; |
| 1966 | addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); | 2004 | addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); |
| 1967 | break :blk target; | 2005 | break :blk target; |
| ... | @@ -1971,34 +2009,38 @@ const aarch64 = struct { | ... | @@ -1971,34 +2009,38 @@ const aarch64 = struct { |
| 1971 | @as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR) | 2009 | @as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR) |
| 1972 | blk: { | 2010 | blk: { |
| 1973 | if (rel_type != .ARM64_RELOC_UNSIGNED) { | 2011 | if (rel_type != .ARM64_RELOC_UNSIGNED) { |
| 1974 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: ARM64_RELOC_SUBTRACTOR followed by {s}", .{ | 2012 | try macho_file.reportParseError2(self.index, "{s},{s}: 0x{x}: ARM64_RELOC_SUBTRACTOR followed by {s}", .{ |
| 1975 | self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type), | 2013 | sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type), |
| 1976 | }); | 2014 | }); |
| 1977 | return error.ParseFailed; | 2015 | return error.MalformedObject; |
| 1978 | } | 2016 | } |
| 1979 | break :blk true; | 2017 | break :blk true; |
| 1980 | } else false; | 2018 | } else false; |
| 1981 | 2019 | ||
| 1982 | const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { | 2020 | const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { |
| 1983 | switch (err) { | 2021 | switch (err) { |
| 1984 | error.Pcrel => macho_file.base.fatal( | 2022 | error.Pcrel => try macho_file.reportParseError2( |
| 1985 | "{}: {s},{s}: 0x{x}: PC-relative {s} relocation", | 2023 | self.index, |
| 1986 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 2024 | "{s},{s}: 0x{x}: PC-relative {s} relocation", |
| 2025 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1987 | ), | 2026 | ), |
| 1988 | error.NonPcrel => macho_file.base.fatal( | 2027 | error.NonPcrel => try macho_file.reportParseError2( |
| 1989 | "{}: {s},{s}: 0x{x}: non-PC-relative {s} relocation", | 2028 | self.index, |
| 1990 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 2029 | "{s},{s}: 0x{x}: non-PC-relative {s} relocation", |
| 2030 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1991 | ), | 2031 | ), |
| 1992 | error.InvalidLength => macho_file.base.fatal( | 2032 | error.InvalidLength => try macho_file.reportParseError2( |
| 1993 | "{}: {s},{s}: 0x{x}: invalid length of {d} in {s} relocation", | 2033 | self.index, |
| 1994 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) }, | 2034 | "{s},{s}: 0x{x}: invalid length of {d} in {s} relocation", |
| 2035 | .{ sect.segName(), sect.sectName(), rel_offset, @as(u8, 1) << rel.r_length, @tagName(rel_type) }, | ||
| 1995 | ), | 2036 | ), |
| 1996 | error.NonExtern => macho_file.base.fatal( | 2037 | error.NonExtern => try macho_file.reportParseError2( |
| 1997 | "{}: {s},{s}: 0x{x}: non-extern target in {s} relocation", | 2038 | self.index, |
| 1998 | .{ self.fmtPath(), sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | 2039 | "{s},{s}: 0x{x}: non-extern target in {s} relocation", |
| 2040 | .{ sect.segName(), sect.sectName(), rel_offset, @tagName(rel_type) }, | ||
| 1999 | ), | 2041 | ), |
| 2000 | } | 2042 | } |
| 2001 | return error.ParseFailed; | 2043 | return error.MalformedObject; |
| 2002 | }; | 2044 | }; |
| 2003 | 2045 | ||
| 2004 | out.appendAssumeCapacity(.{ | 2046 | out.appendAssumeCapacity(.{ |
src/link/MachO/Symbol.zig+1-1| ... | @@ -55,7 +55,7 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool { | ... | @@ -55,7 +55,7 @@ pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool { |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 { | 57 | pub fn getName(symbol: Symbol, macho_file: *MachO) [:0]const u8 { |
| 58 | return macho_file.string_intern.getAssumeExists(symbol.name); | 58 | return macho_file.strings.getAssumeExists(symbol.name); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom { | 61 | pub fn getAtom(symbol: Symbol, macho_file: *MachO) ?*Atom { |
src/link/MachO/UnwindInfo.zig+1-1| ... | @@ -372,7 +372,7 @@ pub const Encoding = extern struct { | ... | @@ -372,7 +372,7 @@ pub const Encoding = extern struct { |
| 372 | 372 | ||
| 373 | pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool { | 373 | pub fn isDwarf(enc: Encoding, macho_file: *MachO) bool { |
| 374 | const mode = enc.getMode(); | 374 | const mode = enc.getMode(); |
| 375 | return switch (macho_file.options.cpu_arch.?) { | 375 | return switch (macho_file.getTarget().cpu.arch) { |
| 376 | .aarch64 => @as(macho.UNWIND_ARM64_MODE, @enumFromInt(mode)) == .DWARF, | 376 | .aarch64 => @as(macho.UNWIND_ARM64_MODE, @enumFromInt(mode)) == .DWARF, |
| 377 | .x86_64 => @as(macho.UNWIND_X86_64_MODE, @enumFromInt(mode)) == .DWARF, | 377 | .x86_64 => @as(macho.UNWIND_X86_64_MODE, @enumFromInt(mode)) == .DWARF, |
| 378 | else => unreachable, | 378 | else => unreachable, |
src/link/MachO/eh_frame.zig+8-9| ... | @@ -155,10 +155,10 @@ pub const Fde = struct { | ... | @@ -155,10 +155,10 @@ pub const Fde = struct { |
| 155 | const pc_begin = std.mem.readInt(i64, data[8..][0..8], .little); | 155 | const pc_begin = std.mem.readInt(i64, data[8..][0..8], .little); |
| 156 | const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin); | 156 | const taddr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + 8)) + pc_begin); |
| 157 | fde.atom = object.findAtom(taddr) orelse { | 157 | fde.atom = object.findAtom(taddr) orelse { |
| 158 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: invalid function reference in FDE", .{ | 158 | try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid function reference in FDE", .{ |
| 159 | object.fmtPath(), sect.segName(), sect.sectName(), fde.offset + 8, | 159 | sect.segName(), sect.sectName(), fde.offset + 8, |
| 160 | }); | 160 | }); |
| 161 | return error.ParseFailed; | 161 | return error.MalformedObject; |
| 162 | }; | 162 | }; |
| 163 | const atom = fde.getAtom(macho_file); | 163 | const atom = fde.getAtom(macho_file); |
| 164 | fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file)); | 164 | fde.atom_offset = @intCast(taddr - atom.getInputAddress(macho_file)); |
| ... | @@ -172,11 +172,10 @@ pub const Fde = struct { | ... | @@ -172,11 +172,10 @@ pub const Fde = struct { |
| 172 | if (cie_index) |cie| { | 172 | if (cie_index) |cie| { |
| 173 | fde.cie = cie; | 173 | fde.cie = cie; |
| 174 | } else { | 174 | } else { |
| 175 | macho_file.base.fatal("{}: no matching CIE found for FDE at offset {x}", .{ | 175 | try macho_file.reportParseError2(object.index, "no matching CIE found for FDE at offset {x}", .{ |
| 176 | object.fmtPath(), | ||
| 177 | fde.offset, | 176 | fde.offset, |
| 178 | }); | 177 | }); |
| 179 | return error.ParseFailed; | 178 | return error.MalformedObject; |
| 180 | } | 179 | } |
| 181 | 180 | ||
| 182 | const cie = fde.getCie(macho_file); | 181 | const cie = fde.getCie(macho_file); |
| ... | @@ -194,10 +193,10 @@ pub const Fde = struct { | ... | @@ -194,10 +193,10 @@ pub const Fde = struct { |
| 194 | }; | 193 | }; |
| 195 | const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr); | 194 | const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr); |
| 196 | fde.lsda = object.findAtom(lsda_addr) orelse { | 195 | fde.lsda = object.findAtom(lsda_addr) orelse { |
| 197 | macho_file.base.fatal("{}: {s},{s}: 0x{x}: invalid LSDA reference in FDE", .{ | 196 | try macho_file.reportParseError2(object.index, "{s},{s}: 0x{x}: invalid LSDA reference in FDE", .{ |
| 198 | object.fmtPath(), sect.segName(), sect.sectName(), fde.offset + fde.lsda_ptr_offset, | 197 | sect.segName(), sect.sectName(), fde.offset + fde.lsda_ptr_offset, |
| 199 | }); | 198 | }); |
| 200 | return error.ParseFailed; | 199 | return error.MalformedObject; |
| 201 | }; | 200 | }; |
| 202 | const lsda_atom = fde.getLsdaAtom(macho_file).?; | 201 | const lsda_atom = fde.getLsdaAtom(macho_file).?; |
| 203 | fde.lsda_offset = @intCast(lsda_addr - lsda_atom.getInputAddress(macho_file)); | 202 | fde.lsda_offset = @intCast(lsda_addr - lsda_atom.getInputAddress(macho_file)); |
src/link/MachO/synthetic.zig+17-17| ... | @@ -8,7 +8,7 @@ pub const GotSection = struct { | ... | @@ -8,7 +8,7 @@ pub const GotSection = struct { |
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void { | 10 | pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void { |
| 11 | const gpa = macho_file.base.allocator; | 11 | const gpa = macho_file.base.comp.gpa; |
| 12 | const index = @as(Index, @intCast(got.symbols.items.len)); | 12 | const index = @as(Index, @intCast(got.symbols.items.len)); |
| 13 | const entry = try got.symbols.addOne(gpa); | 13 | const entry = try got.symbols.addOne(gpa); |
| 14 | entry.* = sym_index; | 14 | entry.* = sym_index; |
| ... | @@ -29,7 +29,7 @@ pub const GotSection = struct { | ... | @@ -29,7 +29,7 @@ pub const GotSection = struct { |
| 29 | pub fn addDyldRelocs(got: GotSection, macho_file: *MachO) !void { | 29 | pub fn addDyldRelocs(got: GotSection, macho_file: *MachO) !void { |
| 30 | const tracy = trace(@src()); | 30 | const tracy = trace(@src()); |
| 31 | defer tracy.end(); | 31 | defer tracy.end(); |
| 32 | const gpa = macho_file.base.allocator; | 32 | const gpa = macho_file.base.comp.gpa; |
| 33 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.got_sect_index.?]; | 33 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.got_sect_index.?]; |
| 34 | const seg = macho_file.segments.items[seg_id]; | 34 | const seg = macho_file.segments.items[seg_id]; |
| 35 | 35 | ||
| ... | @@ -111,7 +111,7 @@ pub const StubsSection = struct { | ... | @@ -111,7 +111,7 @@ pub const StubsSection = struct { |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void { | 113 | pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void { |
| 114 | const gpa = macho_file.base.allocator; | 114 | const gpa = macho_file.base.comp.gpa; |
| 115 | const index = @as(Index, @intCast(stubs.symbols.items.len)); | 115 | const index = @as(Index, @intCast(stubs.symbols.items.len)); |
| 116 | const entry = try stubs.symbols.addOne(gpa); | 116 | const entry = try stubs.symbols.addOne(gpa); |
| 117 | entry.* = sym_index; | 117 | entry.* = sym_index; |
| ... | @@ -133,7 +133,7 @@ pub const StubsSection = struct { | ... | @@ -133,7 +133,7 @@ pub const StubsSection = struct { |
| 133 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void { | 133 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void { |
| 134 | const tracy = trace(@src()); | 134 | const tracy = trace(@src()); |
| 135 | defer tracy.end(); | 135 | defer tracy.end(); |
| 136 | const cpu_arch = macho_file.options.cpu_arch.?; | 136 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 137 | const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?]; | 137 | const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?]; |
| 138 | 138 | ||
| 139 | for (stubs.symbols.items, 0..) |sym_index, idx| { | 139 | for (stubs.symbols.items, 0..) |sym_index, idx| { |
| ... | @@ -213,7 +213,7 @@ pub const StubsHelperSection = struct { | ... | @@ -213,7 +213,7 @@ pub const StubsHelperSection = struct { |
| 213 | const tracy = trace(@src()); | 213 | const tracy = trace(@src()); |
| 214 | defer tracy.end(); | 214 | defer tracy.end(); |
| 215 | _ = stubs_helper; | 215 | _ = stubs_helper; |
| 216 | const cpu_arch = macho_file.options.cpu_arch.?; | 216 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 217 | var s: usize = preambleSize(cpu_arch); | 217 | var s: usize = preambleSize(cpu_arch); |
| 218 | for (macho_file.stubs.symbols.items) |sym_index| { | 218 | for (macho_file.stubs.symbols.items) |sym_index| { |
| 219 | const sym = macho_file.getSymbol(sym_index); | 219 | const sym = macho_file.getSymbol(sym_index); |
| ... | @@ -230,7 +230,7 @@ pub const StubsHelperSection = struct { | ... | @@ -230,7 +230,7 @@ pub const StubsHelperSection = struct { |
| 230 | 230 | ||
| 231 | try stubs_helper.writePreamble(macho_file, writer); | 231 | try stubs_helper.writePreamble(macho_file, writer); |
| 232 | 232 | ||
| 233 | const cpu_arch = macho_file.options.cpu_arch.?; | 233 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 234 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; | 234 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; |
| 235 | const preamble_size = preambleSize(cpu_arch); | 235 | const preamble_size = preambleSize(cpu_arch); |
| 236 | const entry_size = entrySize(cpu_arch); | 236 | const entry_size = entrySize(cpu_arch); |
| ... | @@ -272,7 +272,7 @@ pub const StubsHelperSection = struct { | ... | @@ -272,7 +272,7 @@ pub const StubsHelperSection = struct { |
| 272 | 272 | ||
| 273 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { | 273 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { |
| 274 | _ = stubs_helper; | 274 | _ = stubs_helper; |
| 275 | const cpu_arch = macho_file.options.cpu_arch.?; | 275 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 276 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; | 276 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; |
| 277 | const dyld_private_addr = target: { | 277 | const dyld_private_addr = target: { |
| 278 | const sym = macho_file.getSymbol(macho_file.dyld_private_index.?); | 278 | const sym = macho_file.getSymbol(macho_file.dyld_private_index.?); |
| ... | @@ -331,7 +331,7 @@ pub const LaSymbolPtrSection = struct { | ... | @@ -331,7 +331,7 @@ pub const LaSymbolPtrSection = struct { |
| 331 | const tracy = trace(@src()); | 331 | const tracy = trace(@src()); |
| 332 | defer tracy.end(); | 332 | defer tracy.end(); |
| 333 | _ = laptr; | 333 | _ = laptr; |
| 334 | const gpa = macho_file.base.allocator; | 334 | const gpa = macho_file.base.comp.gpa; |
| 335 | 335 | ||
| 336 | const sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?]; | 336 | const sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?]; |
| 337 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.la_symbol_ptr_sect_index.?]; | 337 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.la_symbol_ptr_sect_index.?]; |
| ... | @@ -371,7 +371,7 @@ pub const LaSymbolPtrSection = struct { | ... | @@ -371,7 +371,7 @@ pub const LaSymbolPtrSection = struct { |
| 371 | const tracy = trace(@src()); | 371 | const tracy = trace(@src()); |
| 372 | defer tracy.end(); | 372 | defer tracy.end(); |
| 373 | _ = laptr; | 373 | _ = laptr; |
| 374 | const cpu_arch = macho_file.options.cpu_arch.?; | 374 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| 375 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; | 375 | const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?]; |
| 376 | for (macho_file.stubs.symbols.items, 0..) |sym_index, idx| { | 376 | for (macho_file.stubs.symbols.items, 0..) |sym_index, idx| { |
| 377 | const sym = macho_file.getSymbol(sym_index); | 377 | const sym = macho_file.getSymbol(sym_index); |
| ... | @@ -397,7 +397,7 @@ pub const TlvPtrSection = struct { | ... | @@ -397,7 +397,7 @@ pub const TlvPtrSection = struct { |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void { | 399 | pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void { |
| 400 | const gpa = macho_file.base.allocator; | 400 | const gpa = macho_file.base.comp.gpa; |
| 401 | const index = @as(Index, @intCast(tlv.symbols.items.len)); | 401 | const index = @as(Index, @intCast(tlv.symbols.items.len)); |
| 402 | const entry = try tlv.symbols.addOne(gpa); | 402 | const entry = try tlv.symbols.addOne(gpa); |
| 403 | entry.* = sym_index; | 403 | entry.* = sym_index; |
| ... | @@ -418,7 +418,7 @@ pub const TlvPtrSection = struct { | ... | @@ -418,7 +418,7 @@ pub const TlvPtrSection = struct { |
| 418 | pub fn addDyldRelocs(tlv: TlvPtrSection, macho_file: *MachO) !void { | 418 | pub fn addDyldRelocs(tlv: TlvPtrSection, macho_file: *MachO) !void { |
| 419 | const tracy = trace(@src()); | 419 | const tracy = trace(@src()); |
| 420 | defer tracy.end(); | 420 | defer tracy.end(); |
| 421 | const gpa = macho_file.base.allocator; | 421 | const gpa = macho_file.base.comp.gpa; |
| 422 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.tlv_ptr_sect_index.?]; | 422 | const seg_id = macho_file.sections.items(.segment_id)[macho_file.tlv_ptr_sect_index.?]; |
| 423 | const seg = macho_file.segments.items[seg_id]; | 423 | const seg = macho_file.segments.items[seg_id]; |
| 424 | 424 | ||
| ... | @@ -510,7 +510,7 @@ pub const ObjcStubsSection = struct { | ... | @@ -510,7 +510,7 @@ pub const ObjcStubsSection = struct { |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void { | 512 | pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void { |
| 513 | const gpa = macho_file.base.allocator; | 513 | const gpa = macho_file.base.comp.gpa; |
| 514 | const index = @as(Index, @intCast(objc.symbols.items.len)); | 514 | const index = @as(Index, @intCast(objc.symbols.items.len)); |
| 515 | const entry = try objc.symbols.addOne(gpa); | 515 | const entry = try objc.symbols.addOne(gpa); |
| 516 | entry.* = sym_index; | 516 | entry.* = sym_index; |
| ... | @@ -521,11 +521,11 @@ pub const ObjcStubsSection = struct { | ... | @@ -521,11 +521,11 @@ pub const ObjcStubsSection = struct { |
| 521 | pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 { | 521 | pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 { |
| 522 | assert(index < objc.symbols.items.len); | 522 | assert(index < objc.symbols.items.len); |
| 523 | const header = macho_file.sections.items(.header)[macho_file.objc_stubs_sect_index.?]; | 523 | const header = macho_file.sections.items(.header)[macho_file.objc_stubs_sect_index.?]; |
| 524 | return header.addr + index * entrySize(macho_file.options.cpu_arch.?); | 524 | return header.addr + index * entrySize(macho_file.getTarget().cpu.arch); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | pub fn size(objc: ObjcStubsSection, macho_file: *MachO) usize { | 527 | pub fn size(objc: ObjcStubsSection, macho_file: *MachO) usize { |
| 528 | return objc.symbols.items.len * entrySize(macho_file.options.cpu_arch.?); | 528 | return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch); |
| 529 | } | 529 | } |
| 530 | 530 | ||
| 531 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void { | 531 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void { |
| ... | @@ -535,7 +535,7 @@ pub const ObjcStubsSection = struct { | ... | @@ -535,7 +535,7 @@ pub const ObjcStubsSection = struct { |
| 535 | for (objc.symbols.items, 0..) |sym_index, idx| { | 535 | for (objc.symbols.items, 0..) |sym_index, idx| { |
| 536 | const sym = macho_file.getSymbol(sym_index); | 536 | const sym = macho_file.getSymbol(sym_index); |
| 537 | const addr = objc.getAddress(@intCast(idx), macho_file); | 537 | const addr = objc.getAddress(@intCast(idx), macho_file); |
| 538 | switch (macho_file.options.cpu_arch.?) { | 538 | switch (macho_file.getTarget().cpu.arch) { |
| 539 | .x86_64 => { | 539 | .x86_64 => { |
| 540 | try writer.writeAll(&.{ 0x48, 0x8b, 0x35 }); | 540 | try writer.writeAll(&.{ 0x48, 0x8b, 0x35 }); |
| 541 | { | 541 | { |
| ... | @@ -654,12 +654,12 @@ pub const WeakBindSection = bind.WeakBind; | ... | @@ -654,12 +654,12 @@ pub const WeakBindSection = bind.WeakBind; |
| 654 | pub const LazyBindSection = bind.LazyBind; | 654 | pub const LazyBindSection = bind.LazyBind; |
| 655 | pub const ExportTrieSection = Trie; | 655 | pub const ExportTrieSection = Trie; |
| 656 | 656 | ||
| 657 | const aarch64 = @import("../aarch64.zig"); | 657 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 658 | const assert = std.debug.assert; | 658 | const assert = std.debug.assert; |
| 659 | const bind = @import("dyld_info/bind.zig"); | 659 | const bind = @import("dyld_info/bind.zig"); |
| 660 | const math = std.math; | 660 | const math = std.math; |
| 661 | const std = @import("std"); | 661 | const std = @import("std"); |
| 662 | const trace = @import("../tracy.zig").trace; | 662 | const trace = @import("../../tracy.zig").trace; |
| 663 | 663 | ||
| 664 | const Allocator = std.mem.Allocator; | 664 | const Allocator = std.mem.Allocator; |
| 665 | const MachO = @import("../MachO.zig"); | 665 | const MachO = @import("../MachO.zig"); |