| ... | @@ -34,7 +34,6 @@ const Object = @import("Object.zig"); | ... | @@ -34,7 +34,6 @@ const Object = @import("Object.zig"); |
| 34 | const Section = MachO.Section; | 34 | const Section = MachO.Section; |
| 35 | const StringTable = @import("../strtab.zig").StringTable; | 35 | const StringTable = @import("../strtab.zig").StringTable; |
| 36 | const SymbolWithLoc = MachO.SymbolWithLoc; | 36 | const SymbolWithLoc = MachO.SymbolWithLoc; |
| 37 | const SymbolResolver = MachO.SymbolResolver; | | |
| 38 | const TableSection = @import("../table_section.zig").TableSection; | 37 | const TableSection = @import("../table_section.zig").TableSection; |
| 39 | const Trie = @import("Trie.zig"); | 38 | const Trie = @import("Trie.zig"); |
| 40 | const UnwindInfo = @import("UnwindInfo.zig"); | 39 | const UnwindInfo = @import("UnwindInfo.zig"); |
| ... | @@ -76,6 +75,8 @@ pub const Zld = struct { | ... | @@ -76,6 +75,8 @@ pub const Zld = struct { |
| 76 | | 75 | |
| 77 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 76 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 78 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, | 77 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, |
| | 78 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| | 79 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 79 | | 80 | |
| 80 | entry_index: ?u32 = null, | 81 | entry_index: ?u32 = null, |
| 81 | mh_execute_header_index: ?u32 = null, | 82 | mh_execute_header_index: ?u32 = null, |
| ... | @@ -327,53 +328,53 @@ pub const Zld = struct { | ... | @@ -327,53 +328,53 @@ pub const Zld = struct { |
| 327 | } | 328 | } |
| 328 | } | 329 | } |
| 329 | | 330 | |
| 330 | fn addUndefined(self: *Zld, name: []const u8, resolver: *SymbolResolver) !void { | 331 | fn addUndefined(self: *Zld, name: []const u8) !void { |
| 331 | const sym_index = try self.allocateSymbol(); | 332 | const sym_index = try self.allocateSymbol(); |
| 332 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; | 333 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; |
| 333 | const sym = self.getSymbolPtr(sym_loc); | 334 | const sym = self.getSymbolPtr(sym_loc); |
| 334 | sym.n_strx = try self.strtab.insert(self.gpa, name); | 335 | sym.n_strx = try self.strtab.insert(self.gpa, name); |
| 335 | sym.n_type = macho.N_UNDF; | 336 | sym.n_type = macho.N_UNDF; |
| 336 | const global_index = try self.addGlobal(sym_loc); | 337 | const global_index = try self.addGlobal(sym_loc); |
| 337 | try resolver.table.putNoClobber(name, global_index); | 338 | try self.resolver.putNoClobber(self.gpa, name, global_index); |
| 338 | try resolver.unresolved.putNoClobber(global_index, {}); | 339 | try self.unresolved.putNoClobber(self.gpa, global_index, {}); |
| 339 | } | 340 | } |
| 340 | | 341 | |
| 341 | fn resolveSymbols(self: *Zld, resolver: *SymbolResolver) !void { | 342 | fn resolveSymbols(self: *Zld) !void { |
| 342 | // We add the specified entrypoint as the first unresolved symbols so that | 343 | // We add the specified entrypoint as the first unresolved symbols so that |
| 343 | // we search for it in libraries should there be no object files specified | 344 | // we search for it in libraries should there be no object files specified |
| 344 | // on the linker line. | 345 | // on the linker line. |
| 345 | if (self.options.output_mode == .Exe) { | 346 | if (self.options.output_mode == .Exe) { |
| 346 | const entry_name = self.options.entry orelse load_commands.default_entry_point; | 347 | const entry_name = self.options.entry orelse load_commands.default_entry_point; |
| 347 | try self.addUndefined(entry_name, resolver); | 348 | try self.addUndefined(entry_name); |
| 348 | } | 349 | } |
| 349 | | 350 | |
| 350 | // Force resolution of any symbols requested by the user. | 351 | // Force resolution of any symbols requested by the user. |
| 351 | for (self.options.force_undefined_symbols.keys()) |sym_name| { | 352 | for (self.options.force_undefined_symbols.keys()) |sym_name| { |
| 352 | try self.addUndefined(sym_name, resolver); | 353 | try self.addUndefined(sym_name); |
| 353 | } | 354 | } |
| 354 | | 355 | |
| 355 | for (self.objects.items, 0..) |_, object_id| { | 356 | for (self.objects.items, 0..) |_, object_id| { |
| 356 | try self.resolveSymbolsInObject(@as(u32, @intCast(object_id)), resolver); | 357 | try self.resolveSymbolsInObject(@as(u32, @intCast(object_id))); |
| 357 | } | 358 | } |
| 358 | | 359 | |
| 359 | try self.resolveSymbolsInArchives(resolver); | 360 | try self.resolveSymbolsInArchives(); |
| 360 | | 361 | |
| 361 | // Finally, force resolution of dyld_stub_binder if there are imports | 362 | // Finally, force resolution of dyld_stub_binder if there are imports |
| 362 | // requested. | 363 | // requested. |
| 363 | if (resolver.unresolved.count() > 0) { | 364 | if (self.unresolved.count() > 0) { |
| 364 | try self.addUndefined("dyld_stub_binder", resolver); | 365 | try self.addUndefined("dyld_stub_binder"); |
| 365 | } | 366 | } |
| 366 | | 367 | |
| 367 | try self.resolveSymbolsInDylibs(resolver); | 368 | try self.resolveSymbolsInDylibs(); |
| 368 | | 369 | |
| 369 | self.dyld_stub_binder_index = resolver.table.get("dyld_stub_binder"); | 370 | self.dyld_stub_binder_index = self.resolver.get("dyld_stub_binder"); |
| 370 | | 371 | |
| 371 | try self.createMhExecuteHeaderSymbol(resolver); | 372 | try self.createMhExecuteHeaderSymbol(); |
| 372 | try self.createDsoHandleSymbol(resolver); | 373 | try self.createDsoHandleSymbol(); |
| 373 | try self.resolveSymbolsAtLoading(resolver); | 374 | try self.resolveSymbolsAtLoading(); |
| 374 | } | 375 | } |
| 375 | | 376 | |
| 376 | fn resolveSymbolsInObject(self: *Zld, object_id: u32, resolver: *SymbolResolver) !void { | 377 | fn resolveSymbolsInObject(self: *Zld, object_id: u32) !void { |
| 377 | const object = &self.objects.items[object_id]; | 378 | const object = &self.objects.items[object_id]; |
| 378 | const in_symtab = object.in_symtab orelse return; | 379 | const in_symtab = object.in_symtab orelse return; |
| 379 | | 380 | |
| ... | @@ -415,11 +416,11 @@ pub const Zld = struct { | ... | @@ -415,11 +416,11 @@ pub const Zld = struct { |
| 415 | | 416 | |
| 416 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 }; | 417 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 }; |
| 417 | | 418 | |
| 418 | const global_index = resolver.table.get(sym_name) orelse { | 419 | const global_index = self.resolver.get(sym_name) orelse { |
| 419 | const global_index = try self.addGlobal(sym_loc); | 420 | const global_index = try self.addGlobal(sym_loc); |
| 420 | try resolver.table.putNoClobber(sym_name, global_index); | 421 | try self.resolver.putNoClobber(self.gpa, sym_name, global_index); |
| 421 | if (sym.undf() and !sym.tentative()) { | 422 | if (sym.undf() and !sym.tentative()) { |
| 422 | try resolver.unresolved.putNoClobber(global_index, {}); | 423 | try self.unresolved.putNoClobber(self.gpa, global_index, {}); |
| 423 | } | 424 | } |
| 424 | continue; | 425 | continue; |
| 425 | }; | 426 | }; |
| ... | @@ -477,7 +478,7 @@ pub const Zld = struct { | ... | @@ -477,7 +478,7 @@ pub const Zld = struct { |
| 477 | const global_object = &self.objects.items[file]; | 478 | const global_object = &self.objects.items[file]; |
| 478 | global_object.globals_lookup[global.sym_index] = global_index; | 479 | global_object.globals_lookup[global.sym_index] = global_index; |
| 479 | } | 480 | } |
| 480 | _ = resolver.unresolved.swapRemove(resolver.table.get(sym_name).?); | 481 | _ = self.unresolved.swapRemove(self.resolver.get(sym_name).?); |
| 481 | global.* = sym_loc; | 482 | global.* = sym_loc; |
| 482 | } else { | 483 | } else { |
| 483 | object.globals_lookup[sym_index] = global_index; | 484 | object.globals_lookup[sym_index] = global_index; |
| ... | @@ -485,14 +486,14 @@ pub const Zld = struct { | ... | @@ -485,14 +486,14 @@ pub const Zld = struct { |
| 485 | } | 486 | } |
| 486 | } | 487 | } |
| 487 | | 488 | |
| 488 | fn resolveSymbolsInArchives(self: *Zld, resolver: *SymbolResolver) !void { | 489 | fn resolveSymbolsInArchives(self: *Zld) !void { |
| 489 | if (self.archives.items.len == 0) return; | 490 | if (self.archives.items.len == 0) return; |
| 490 | | 491 | |
| 491 | const gpa = self.gpa; | 492 | const gpa = self.gpa; |
| 492 | | 493 | |
| 493 | var next_sym: usize = 0; | 494 | var next_sym: usize = 0; |
| 494 | loop: while (next_sym < resolver.unresolved.count()) { | 495 | loop: while (next_sym < self.unresolved.count()) { |
| 495 | const global = self.globals.items[resolver.unresolved.keys()[next_sym]]; | 496 | const global = self.globals.items[self.unresolved.keys()[next_sym]]; |
| 496 | const sym_name = self.getSymbolName(global); | 497 | const sym_name = self.getSymbolName(global); |
| 497 | | 498 | |
| 498 | for (self.archives.items) |archive| { | 499 | for (self.archives.items) |archive| { |
| ... | @@ -506,7 +507,7 @@ pub const Zld = struct { | ... | @@ -506,7 +507,7 @@ pub const Zld = struct { |
| 506 | const object_id = @as(u16, @intCast(self.objects.items.len)); | 507 | const object_id = @as(u16, @intCast(self.objects.items.len)); |
| 507 | const object = try archive.parseObject(gpa, offsets.items[0]); | 508 | const object = try archive.parseObject(gpa, offsets.items[0]); |
| 508 | try self.objects.append(gpa, object); | 509 | try self.objects.append(gpa, object); |
| 509 | try self.resolveSymbolsInObject(object_id, resolver); | 510 | try self.resolveSymbolsInObject(object_id); |
| 510 | | 511 | |
| 511 | continue :loop; | 512 | continue :loop; |
| 512 | } | 513 | } |
| ... | @@ -515,12 +516,12 @@ pub const Zld = struct { | ... | @@ -515,12 +516,12 @@ pub const Zld = struct { |
| 515 | } | 516 | } |
| 516 | } | 517 | } |
| 517 | | 518 | |
| 518 | fn resolveSymbolsInDylibs(self: *Zld, resolver: *SymbolResolver) !void { | 519 | fn resolveSymbolsInDylibs(self: *Zld) !void { |
| 519 | if (self.dylibs.items.len == 0) return; | 520 | if (self.dylibs.items.len == 0) return; |
| 520 | | 521 | |
| 521 | var next_sym: usize = 0; | 522 | var next_sym: usize = 0; |
| 522 | loop: while (next_sym < resolver.unresolved.count()) { | 523 | loop: while (next_sym < self.unresolved.count()) { |
| 523 | const global_index = resolver.unresolved.keys()[next_sym]; | 524 | const global_index = self.unresolved.keys()[next_sym]; |
| 524 | const global = self.globals.items[global_index]; | 525 | const global = self.globals.items[global_index]; |
| 525 | const sym = self.getSymbolPtr(global); | 526 | const sym = self.getSymbolPtr(global); |
| 526 | const sym_name = self.getSymbolName(global); | 527 | const sym_name = self.getSymbolName(global); |
| ... | @@ -541,7 +542,7 @@ pub const Zld = struct { | ... | @@ -541,7 +542,7 @@ pub const Zld = struct { |
| 541 | sym.n_desc |= macho.N_WEAK_REF; | 542 | sym.n_desc |= macho.N_WEAK_REF; |
| 542 | } | 543 | } |
| 543 | | 544 | |
| 544 | assert(resolver.unresolved.swapRemove(global_index)); | 545 | assert(self.unresolved.swapRemove(global_index)); |
| 545 | continue :loop; | 546 | continue :loop; |
| 546 | } | 547 | } |
| 547 | | 548 | |
| ... | @@ -549,14 +550,14 @@ pub const Zld = struct { | ... | @@ -549,14 +550,14 @@ pub const Zld = struct { |
| 549 | } | 550 | } |
| 550 | } | 551 | } |
| 551 | | 552 | |
| 552 | fn resolveSymbolsAtLoading(self: *Zld, resolver: *SymbolResolver) !void { | 553 | fn resolveSymbolsAtLoading(self: *Zld) !void { |
| 553 | const is_lib = self.options.output_mode == .Lib; | 554 | const is_lib = self.options.output_mode == .Lib; |
| 554 | const is_dyn_lib = self.options.link_mode == .Dynamic and is_lib; | 555 | const is_dyn_lib = self.options.link_mode == .Dynamic and is_lib; |
| 555 | const allow_undef = is_dyn_lib and (self.options.allow_shlib_undefined orelse false); | 556 | const allow_undef = is_dyn_lib and (self.options.allow_shlib_undefined orelse false); |
| 556 | | 557 | |
| 557 | var next_sym: usize = 0; | 558 | var next_sym: usize = 0; |
| 558 | while (next_sym < resolver.unresolved.count()) { | 559 | while (next_sym < self.unresolved.count()) { |
| 559 | const global_index = resolver.unresolved.keys()[next_sym]; | 560 | const global_index = self.unresolved.keys()[next_sym]; |
| 560 | const global = self.globals.items[global_index]; | 561 | const global = self.globals.items[global_index]; |
| 561 | const sym = self.getSymbolPtr(global); | 562 | const sym = self.getSymbolPtr(global); |
| 562 | | 563 | |
| ... | @@ -568,7 +569,7 @@ pub const Zld = struct { | ... | @@ -568,7 +569,7 @@ pub const Zld = struct { |
| 568 | .n_desc = 0, | 569 | .n_desc = 0, |
| 569 | .n_value = 0, | 570 | .n_value = 0, |
| 570 | }; | 571 | }; |
| 571 | _ = resolver.unresolved.swapRemove(global_index); | 572 | _ = self.unresolved.swapRemove(global_index); |
| 572 | continue; | 573 | continue; |
| 573 | } else if (allow_undef) { | 574 | } else if (allow_undef) { |
| 574 | const n_desc = @as( | 575 | const n_desc = @as( |
| ... | @@ -577,7 +578,7 @@ pub const Zld = struct { | ... | @@ -577,7 +578,7 @@ pub const Zld = struct { |
| 577 | ); | 578 | ); |
| 578 | sym.n_type = macho.N_EXT; | 579 | sym.n_type = macho.N_EXT; |
| 579 | sym.n_desc = n_desc; | 580 | sym.n_desc = n_desc; |
| 580 | _ = resolver.unresolved.swapRemove(global_index); | 581 | _ = self.unresolved.swapRemove(global_index); |
| 581 | continue; | 582 | continue; |
| 582 | } | 583 | } |
| 583 | | 584 | |
| ... | @@ -585,9 +586,9 @@ pub const Zld = struct { | ... | @@ -585,9 +586,9 @@ pub const Zld = struct { |
| 585 | } | 586 | } |
| 586 | } | 587 | } |
| 587 | | 588 | |
| 588 | fn createMhExecuteHeaderSymbol(self: *Zld, resolver: *SymbolResolver) !void { | 589 | fn createMhExecuteHeaderSymbol(self: *Zld) !void { |
| 589 | if (self.options.output_mode != .Exe) return; | 590 | if (self.options.output_mode != .Exe) return; |
| 590 | if (resolver.table.get("__mh_execute_header")) |global_index| { | 591 | if (self.resolver.get("__mh_execute_header")) |global_index| { |
| 591 | const global = self.globals.items[global_index]; | 592 | const global = self.globals.items[global_index]; |
| 592 | const sym = self.getSymbol(global); | 593 | const sym = self.getSymbol(global); |
| 593 | self.mh_execute_header_index = global_index; | 594 | self.mh_execute_header_index = global_index; |
| ... | @@ -602,7 +603,7 @@ pub const Zld = struct { | ... | @@ -602,7 +603,7 @@ pub const Zld = struct { |
| 602 | sym.n_type = macho.N_SECT | macho.N_EXT; | 603 | sym.n_type = macho.N_SECT | macho.N_EXT; |
| 603 | sym.n_desc = macho.REFERENCED_DYNAMICALLY; | 604 | sym.n_desc = macho.REFERENCED_DYNAMICALLY; |
| 604 | | 605 | |
| 605 | if (resolver.table.get("__mh_execute_header")) |global_index| { | 606 | if (self.resolver.get("__mh_execute_header")) |global_index| { |
| 606 | const global = &self.globals.items[global_index]; | 607 | const global = &self.globals.items[global_index]; |
| 607 | const global_object = &self.objects.items[global.getFile().?]; | 608 | const global_object = &self.objects.items[global.getFile().?]; |
| 608 | global_object.globals_lookup[global.sym_index] = global_index; | 609 | global_object.globals_lookup[global.sym_index] = global_index; |
| ... | @@ -613,8 +614,8 @@ pub const Zld = struct { | ... | @@ -613,8 +614,8 @@ pub const Zld = struct { |
| 613 | } | 614 | } |
| 614 | } | 615 | } |
| 615 | | 616 | |
| 616 | fn createDsoHandleSymbol(self: *Zld, resolver: *SymbolResolver) !void { | 617 | fn createDsoHandleSymbol(self: *Zld) !void { |
| 617 | const global_index = resolver.table.get("___dso_handle") orelse return; | 618 | const global_index = self.resolver.get("___dso_handle") orelse return; |
| 618 | const global = &self.globals.items[global_index]; | 619 | const global = &self.globals.items[global_index]; |
| 619 | self.dso_handle_index = global_index; | 620 | self.dso_handle_index = global_index; |
| 620 | if (!self.getSymbol(global.*).undf()) return; | 621 | if (!self.getSymbol(global.*).undf()) return; |
| ... | @@ -629,7 +630,7 @@ pub const Zld = struct { | ... | @@ -629,7 +630,7 @@ pub const Zld = struct { |
| 629 | | 630 | |
| 630 | const global_object = &self.objects.items[global.getFile().?]; | 631 | const global_object = &self.objects.items[global.getFile().?]; |
| 631 | global_object.globals_lookup[global.sym_index] = global_index; | 632 | global_object.globals_lookup[global.sym_index] = global_index; |
| 632 | _ = resolver.unresolved.swapRemove(resolver.table.get("___dso_handle").?); | 633 | _ = self.unresolved.swapRemove(self.resolver.get("___dso_handle").?); |
| 633 | global.* = sym_loc; | 634 | global.* = sym_loc; |
| 634 | } | 635 | } |
| 635 | | 636 | |
| ... | @@ -649,6 +650,8 @@ pub const Zld = struct { | ... | @@ -649,6 +650,8 @@ pub const Zld = struct { |
| 649 | self.strtab.deinit(gpa); | 650 | self.strtab.deinit(gpa); |
| 650 | self.locals.deinit(gpa); | 651 | self.locals.deinit(gpa); |
| 651 | self.globals.deinit(gpa); | 652 | self.globals.deinit(gpa); |
| | 653 | self.resolver.deinit(gpa); |
| | 654 | self.unresolved.deinit(gpa); |
| 652 | | 655 | |
| 653 | for (self.objects.items) |*object| { | 656 | for (self.objects.items) |*object| { |
| 654 | object.deinit(gpa); | 657 | object.deinit(gpa); |
| ... | @@ -3066,17 +3069,12 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr | ... | @@ -3066,17 +3069,12 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 3066 | log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)}); | 3069 | log.err("parsing dependent libraries failed with err {s}", .{@errorName(err)}); |
| 3067 | }; | 3070 | }; |
| 3068 | | 3071 | |
| 3069 | var resolver = SymbolResolver{ | 3072 | try zld.resolveSymbols(); |
| 3070 | .arena = arena, | 3073 | try macho_file.reportUndefined(&zld); |
| 3071 | .table = std.StringHashMap(u32).init(arena), | | |
| 3072 | .unresolved = std.AutoArrayHashMap(u32, void).init(arena), | | |
| 3073 | }; | | |
| 3074 | try zld.resolveSymbols(&resolver); | | |
| 3075 | try macho_file.reportUndefined(&zld, &resolver); | | |
| 3076 | | 3074 | |
| 3077 | if (options.output_mode == .Exe) { | 3075 | if (options.output_mode == .Exe) { |
| 3078 | const entry_name = options.entry orelse load_commands.default_entry_point; | 3076 | const entry_name = options.entry orelse load_commands.default_entry_point; |
| 3079 | const global_index = resolver.table.get(entry_name).?; // Error was flagged earlier | 3077 | const global_index = zld.resolver.get(entry_name).?; // Error was flagged earlier |
| 3080 | zld.entry_index = global_index; | 3078 | zld.entry_index = global_index; |
| 3081 | } | 3079 | } |
| 3082 | | 3080 | |
| ... | @@ -3085,7 +3083,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr | ... | @@ -3085,7 +3083,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 3085 | } | 3083 | } |
| 3086 | | 3084 | |
| 3087 | if (gc_sections) { | 3085 | if (gc_sections) { |
| 3088 | try dead_strip.gcAtoms(&zld, &resolver); | 3086 | try dead_strip.gcAtoms(&zld); |
| 3089 | } | 3087 | } |
| 3090 | | 3088 | |
| 3091 | try zld.createDyldPrivateAtom(); | 3089 | try zld.createDyldPrivateAtom(); |