| ... | ... | @@ -78,9 +78,10 @@ pub const Zld = struct { |
| 78 | 78 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| 79 | 79 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 80 | 80 | |
| 81 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 82 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 83 | |
| 81 | 84 | entry_index: ?u32 = null, |
| 82 | | mh_execute_header_index: ?u32 = null, |
| 83 | | dso_handle_index: ?u32 = null, |
| 84 | 85 | dyld_stub_binder_index: ?u32 = null, |
| 85 | 86 | dyld_private_atom_index: ?Atom.Index = null, |
| 86 | 87 | |
| ... | ... | @@ -188,15 +189,23 @@ pub const Zld = struct { |
| 188 | 189 | } |
| 189 | 190 | } |
| 190 | 191 | |
| 191 | | fn addUndefined(self: *Zld, name: []const u8) !void { |
| 192 | fn addUndefined(self: *Zld, name: []const u8) !u32 { |
| 193 | const gop = try self.getOrPutGlobalPtr(name); |
| 194 | const global_index = self.getGlobalIndex(name).?; |
| 195 | |
| 196 | if (gop.found_existing) return global_index; |
| 197 | |
| 192 | 198 | const sym_index = try self.allocateSymbol(); |
| 193 | 199 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; |
| 200 | gop.value_ptr.* = sym_loc; |
| 201 | |
| 194 | 202 | const sym = self.getSymbolPtr(sym_loc); |
| 195 | 203 | sym.n_strx = try self.strtab.insert(self.gpa, name); |
| 196 | 204 | sym.n_type = macho.N_UNDF; |
| 197 | | const global_index = try self.addGlobal(sym_loc); |
| 198 | | try self.resolver.putNoClobber(self.gpa, name, global_index); |
| 205 | |
| 199 | 206 | try self.unresolved.putNoClobber(self.gpa, global_index, {}); |
| 207 | |
| 208 | return global_index; |
| 200 | 209 | } |
| 201 | 210 | |
| 202 | 211 | fn resolveSymbols(self: *Zld) !void { |
| ... | ... | @@ -205,12 +214,12 @@ pub const Zld = struct { |
| 205 | 214 | // on the linker line. |
| 206 | 215 | if (self.options.output_mode == .Exe) { |
| 207 | 216 | const entry_name = self.options.entry orelse load_commands.default_entry_point; |
| 208 | | try self.addUndefined(entry_name); |
| 217 | _ = try self.addUndefined(entry_name); |
| 209 | 218 | } |
| 210 | 219 | |
| 211 | 220 | // Force resolution of any symbols requested by the user. |
| 212 | 221 | for (self.options.force_undefined_symbols.keys()) |sym_name| { |
| 213 | | try self.addUndefined(sym_name); |
| 222 | _ = try self.addUndefined(sym_name); |
| 214 | 223 | } |
| 215 | 224 | |
| 216 | 225 | for (self.objects.items, 0..) |_, object_id| { |
| ... | ... | @@ -222,13 +231,11 @@ pub const Zld = struct { |
| 222 | 231 | // Finally, force resolution of dyld_stub_binder if there are imports |
| 223 | 232 | // requested. |
| 224 | 233 | if (self.unresolved.count() > 0) { |
| 225 | | try self.addUndefined("dyld_stub_binder"); |
| 234 | self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder"); |
| 226 | 235 | } |
| 227 | 236 | |
| 228 | 237 | try self.resolveSymbolsInDylibs(); |
| 229 | 238 | |
| 230 | | self.dyld_stub_binder_index = self.resolver.get("dyld_stub_binder"); |
| 231 | | |
| 232 | 239 | try self.createMhExecuteHeaderSymbol(); |
| 233 | 240 | try self.createDsoHandleSymbol(); |
| 234 | 241 | try self.resolveSymbolsAtLoading(); |
| ... | ... | @@ -276,15 +283,16 @@ pub const Zld = struct { |
| 276 | 283 | |
| 277 | 284 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 }; |
| 278 | 285 | |
| 279 | | const global_index = self.resolver.get(sym_name) orelse { |
| 280 | | const global_index = try self.addGlobal(sym_loc); |
| 281 | | try self.resolver.putNoClobber(self.gpa, sym_name, global_index); |
| 286 | const gop = try self.getOrPutGlobalPtr(sym_name); |
| 287 | if (!gop.found_existing) { |
| 288 | gop.value_ptr.* = sym_loc; |
| 282 | 289 | if (sym.undf() and !sym.tentative()) { |
| 283 | | try self.unresolved.putNoClobber(self.gpa, global_index, {}); |
| 290 | try self.unresolved.putNoClobber(self.gpa, self.getGlobalIndex(sym_name).?, {}); |
| 284 | 291 | } |
| 285 | 292 | continue; |
| 286 | | }; |
| 287 | | const global = &self.globals.items[global_index]; |
| 293 | } |
| 294 | const global_index = self.getGlobalIndex(sym_name).?; |
| 295 | const global = gop.value_ptr; |
| 288 | 296 | const global_sym = self.getSymbol(global.*); |
| 289 | 297 | |
| 290 | 298 | // Cases to consider: sym vs global_sym |
| ... | ... | @@ -338,7 +346,7 @@ pub const Zld = struct { |
| 338 | 346 | const global_object = &self.objects.items[file]; |
| 339 | 347 | global_object.globals_lookup[global.sym_index] = global_index; |
| 340 | 348 | } |
| 341 | | _ = self.unresolved.swapRemove(self.resolver.get(sym_name).?); |
| 349 | _ = self.unresolved.swapRemove(global_index); |
| 342 | 350 | global.* = sym_loc; |
| 343 | 351 | } else { |
| 344 | 352 | object.globals_lookup[sym_index] = global_index; |
| ... | ... | @@ -448,50 +456,51 @@ pub const Zld = struct { |
| 448 | 456 | |
| 449 | 457 | fn createMhExecuteHeaderSymbol(self: *Zld) !void { |
| 450 | 458 | if (self.options.output_mode != .Exe) return; |
| 451 | | if (self.resolver.get("__mh_execute_header")) |global_index| { |
| 452 | | const global = self.globals.items[global_index]; |
| 453 | | const sym = self.getSymbol(global); |
| 454 | | self.mh_execute_header_index = global_index; |
| 455 | | if (!sym.undf() and !(sym.pext() or sym.weakDef())) return; |
| 456 | | } |
| 457 | 459 | |
| 458 | 460 | const gpa = self.gpa; |
| 459 | 461 | const sym_index = try self.allocateSymbol(); |
| 460 | 462 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; |
| 461 | 463 | const sym = self.getSymbolPtr(sym_loc); |
| 462 | | sym.n_strx = try self.strtab.insert(gpa, "__mh_execute_header"); |
| 463 | | sym.n_type = macho.N_SECT | macho.N_EXT; |
| 464 | | sym.n_desc = macho.REFERENCED_DYNAMICALLY; |
| 464 | sym.* = .{ |
| 465 | .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"), |
| 466 | .n_type = macho.N_SECT | macho.N_EXT, |
| 467 | .n_sect = 0, |
| 468 | .n_desc = macho.REFERENCED_DYNAMICALLY, |
| 469 | .n_value = 0, |
| 470 | }; |
| 465 | 471 | |
| 466 | | if (self.resolver.get("__mh_execute_header")) |global_index| { |
| 467 | | const global = &self.globals.items[global_index]; |
| 468 | | const global_object = &self.objects.items[global.getFile().?]; |
| 469 | | global_object.globals_lookup[global.sym_index] = global_index; |
| 470 | | global.* = sym_loc; |
| 471 | | self.mh_execute_header_index = global_index; |
| 472 | | } else { |
| 473 | | self.mh_execute_header_index = try self.addGlobal(sym_loc); |
| 472 | const gop = try self.getOrPutGlobalPtr("__mh_execute_header"); |
| 473 | if (gop.found_existing) { |
| 474 | const global = gop.value_ptr.*; |
| 475 | if (global.getFile()) |file| { |
| 476 | const global_object = &self.objects.items[file]; |
| 477 | global_object.globals_lookup[global.sym_index] = self.getGlobalIndex("__mh_execute_header").?; |
| 478 | } |
| 474 | 479 | } |
| 480 | gop.value_ptr.* = sym_loc; |
| 475 | 481 | } |
| 476 | 482 | |
| 477 | 483 | fn createDsoHandleSymbol(self: *Zld) !void { |
| 478 | | const global_index = self.resolver.get("___dso_handle") orelse return; |
| 479 | | const global = &self.globals.items[global_index]; |
| 480 | | self.dso_handle_index = global_index; |
| 484 | const global = self.getGlobalPtr("___dso_handle") orelse return; |
| 481 | 485 | if (!self.getSymbol(global.*).undf()) return; |
| 482 | 486 | |
| 483 | | const gpa = self.gpa; |
| 484 | 487 | const sym_index = try self.allocateSymbol(); |
| 485 | 488 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; |
| 486 | 489 | const sym = self.getSymbolPtr(sym_loc); |
| 487 | | sym.n_strx = try self.strtab.insert(gpa, "___dso_handle"); |
| 488 | | sym.n_type = macho.N_SECT | macho.N_EXT; |
| 489 | | sym.n_desc = macho.N_WEAK_DEF; |
| 490 | | |
| 491 | | const global_object = &self.objects.items[global.getFile().?]; |
| 492 | | global_object.globals_lookup[global.sym_index] = global_index; |
| 493 | | _ = self.unresolved.swapRemove(self.resolver.get("___dso_handle").?); |
| 490 | sym.* = .{ |
| 491 | .n_strx = try self.strtab.insert(self.gpa, "___dso_handle"), |
| 492 | .n_type = macho.N_SECT | macho.N_EXT, |
| 493 | .n_sect = 0, |
| 494 | .n_desc = macho.N_WEAK_DEF, |
| 495 | .n_value = 0, |
| 496 | }; |
| 497 | const global_index = self.getGlobalIndex("___dso_handle").?; |
| 498 | if (global.getFile()) |file| { |
| 499 | const global_object = &self.objects.items[file]; |
| 500 | global_object.globals_lookup[global.sym_index] = global_index; |
| 501 | } |
| 494 | 502 | global.* = sym_loc; |
| 503 | _ = self.unresolved.swapRemove(global_index); |
| 495 | 504 | } |
| 496 | 505 | |
| 497 | 506 | pub fn deinit(self: *Zld) void { |
| ... | ... | @@ -512,6 +521,8 @@ pub const Zld = struct { |
| 512 | 521 | self.globals.deinit(gpa); |
| 513 | 522 | self.resolver.deinit(gpa); |
| 514 | 523 | self.unresolved.deinit(gpa); |
| 524 | self.locals_free_list.deinit(gpa); |
| 525 | self.globals_free_list.deinit(gpa); |
| 515 | 526 | |
| 516 | 527 | for (self.objects.items) |*object| { |
| 517 | 528 | object.deinit(gpa); |
| ... | ... | @@ -609,10 +620,24 @@ pub const Zld = struct { |
| 609 | 620 | return index; |
| 610 | 621 | } |
| 611 | 622 | |
| 612 | | fn addGlobal(self: *Zld, sym_loc: SymbolWithLoc) !u32 { |
| 613 | | const global_index = @as(u32, @intCast(self.globals.items.len)); |
| 614 | | try self.globals.append(self.gpa, sym_loc); |
| 615 | | return global_index; |
| 623 | fn allocateGlobal(self: *Zld) !u32 { |
| 624 | try self.globals.ensureUnusedCapacity(self.gpa, 1); |
| 625 | |
| 626 | const index = blk: { |
| 627 | if (self.globals_free_list.popOrNull()) |index| { |
| 628 | log.debug(" (reusing global index {d})", .{index}); |
| 629 | break :blk index; |
| 630 | } else { |
| 631 | log.debug(" (allocating symbol index {d})", .{self.globals.items.len}); |
| 632 | const index = @as(u32, @intCast(self.globals.items.len)); |
| 633 | _ = self.globals.addOneAssumeCapacity(); |
| 634 | break :blk index; |
| 635 | } |
| 636 | }; |
| 637 | |
| 638 | self.globals.items[index] = .{ .sym_index = 0 }; |
| 639 | |
| 640 | return index; |
| 616 | 641 | } |
| 617 | 642 | |
| 618 | 643 | pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void { |
| ... | ... | @@ -656,27 +681,6 @@ pub const Zld = struct { |
| 656 | 681 | } |
| 657 | 682 | } |
| 658 | 683 | |
| 659 | | fn allocateSpecialSymbols(self: *Zld) !void { |
| 660 | | for (&[_]?u32{ |
| 661 | | self.dso_handle_index, |
| 662 | | self.mh_execute_header_index, |
| 663 | | }) |maybe_index| { |
| 664 | | const global_index = maybe_index orelse continue; |
| 665 | | const global = self.globals.items[global_index]; |
| 666 | | if (global.getFile() != null) continue; |
| 667 | | const name = self.getSymbolName(global); |
| 668 | | const sym = self.getSymbolPtr(global); |
| 669 | | const segment_index = self.getSegmentByName("__TEXT").?; |
| 670 | | const seg = self.segments.items[segment_index]; |
| 671 | | sym.n_sect = 1; |
| 672 | | sym.n_value = seg.vmaddr; |
| 673 | | log.debug("allocating {s} at the start of {s}", .{ |
| 674 | | name, |
| 675 | | seg.segName(), |
| 676 | | }); |
| 677 | | } |
| 678 | | } |
| 679 | | |
| 680 | 684 | fn writeAtoms(self: *Zld) !void { |
| 681 | 685 | const gpa = self.gpa; |
| 682 | 686 | const slice = self.sections.slice(); |
| ... | ... | @@ -2037,6 +2041,36 @@ pub const Zld = struct { |
| 2037 | 2041 | } |
| 2038 | 2042 | } |
| 2039 | 2043 | |
| 2044 | pub fn getGlobalIndex(self: *const Zld, name: []const u8) ?u32 { |
| 2045 | return self.resolver.get(name); |
| 2046 | } |
| 2047 | |
| 2048 | pub fn getGlobalPtr(self: *Zld, name: []const u8) ?*SymbolWithLoc { |
| 2049 | const global_index = self.resolver.get(name) orelse return null; |
| 2050 | return &self.globals.items[global_index]; |
| 2051 | } |
| 2052 | |
| 2053 | pub fn getGlobal(self: *const Zld, name: []const u8) ?SymbolWithLoc { |
| 2054 | const global_index = self.resolver.get(name) orelse return null; |
| 2055 | return self.globals.items[global_index]; |
| 2056 | } |
| 2057 | |
| 2058 | const GetOrPutGlobalPtrResult = struct { |
| 2059 | found_existing: bool, |
| 2060 | value_ptr: *SymbolWithLoc, |
| 2061 | }; |
| 2062 | |
| 2063 | pub fn getOrPutGlobalPtr(self: *Zld, name: []const u8) !GetOrPutGlobalPtrResult { |
| 2064 | if (self.getGlobalPtr(name)) |ptr| { |
| 2065 | return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; |
| 2066 | } |
| 2067 | const global_index = try self.allocateGlobal(); |
| 2068 | const global_name = try self.gpa.dupe(u8, name); |
| 2069 | _ = try self.resolver.put(self.gpa, global_name, global_index); |
| 2070 | const ptr = &self.globals.items[global_index]; |
| 2071 | return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr }; |
| 2072 | } |
| 2073 | |
| 2040 | 2074 | pub fn getGotEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 { |
| 2041 | 2075 | const index = self.got_table.lookup.get(sym_with_loc) orelse return null; |
| 2042 | 2076 | const header = self.sections.items(.header)[self.got_section_index.?]; |
| ... | ... | @@ -2934,7 +2968,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr |
| 2934 | 2968 | try zld.createSegments(); |
| 2935 | 2969 | try zld.allocateSegments(); |
| 2936 | 2970 | |
| 2937 | | try zld.allocateSpecialSymbols(); |
| 2971 | try MachO.allocateSpecialSymbols(&zld); |
| 2938 | 2972 | |
| 2939 | 2973 | if (build_options.enable_logging) { |
| 2940 | 2974 | zld.logSymtab(); |