| ... | ... | @@ -131,17 +131,12 @@ la_symbol_ptr_section_index: ?u8 = null, |
| 131 | 131 | data_section_index: ?u8 = null, |
| 132 | 132 | |
| 133 | 133 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 134 | | globals: std.StringArrayHashMapUnmanaged(SymbolWithLoc) = .{}, |
| 135 | | // FIXME Jakub |
| 136 | | // TODO storing index into globals might be dangerous if we delete a global |
| 137 | | // while not having everything resolved. Actually, perhaps `unresolved` |
| 138 | | // should not be stored at the global scope? Is this possible? |
| 139 | | // Otherwise, audit if this can be a problem. |
| 140 | | // An alternative, which I still need to investigate for perf reasons is to |
| 141 | | // store all global names in an adapted with context strtab. |
| 134 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, |
| 135 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| 142 | 136 | unresolved: std.AutoArrayHashMapUnmanaged(u32, bool) = .{}, |
| 143 | 137 | |
| 144 | 138 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 139 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 145 | 140 | |
| 146 | 141 | dyld_stub_binder_index: ?u32 = null, |
| 147 | 142 | dyld_private_atom: ?*Atom = null, |
| ... | ... | @@ -1917,7 +1912,7 @@ fn allocateSpecialSymbols(self: *MachO) !void { |
| 1917 | 1912 | "___dso_handle", |
| 1918 | 1913 | "__mh_execute_header", |
| 1919 | 1914 | }) |name| { |
| 1920 | | const global = self.globals.get(name) orelse continue; |
| 1915 | const global = self.getGlobal(name) orelse continue; |
| 1921 | 1916 | if (global.file != null) continue; |
| 1922 | 1917 | const sym = self.getSymbolPtr(global); |
| 1923 | 1918 | const seg = self.segments.items[self.text_segment_cmd_index.?]; |
| ... | ... | @@ -2074,7 +2069,7 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2074 | 2069 | |
| 2075 | 2070 | const target_sym = self.getSymbol(target); |
| 2076 | 2071 | if (target_sym.undf()) { |
| 2077 | | const global = self.globals.get(self.getSymbolName(target)).?; |
| 2072 | const global = self.getGlobal(self.getSymbolName(target)).?; |
| 2078 | 2073 | try atom.bindings.append(gpa, .{ |
| 2079 | 2074 | .target = global, |
| 2080 | 2075 | .offset = 0, |
| ... | ... | @@ -2106,7 +2101,7 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 2106 | 2101 | const target_sym = self.getSymbol(target); |
| 2107 | 2102 | assert(target_sym.undf()); |
| 2108 | 2103 | |
| 2109 | | const global = self.globals.get(self.getSymbolName(target)).?; |
| 2104 | const global = self.getGlobal(self.getSymbolName(target)).?; |
| 2110 | 2105 | try atom.bindings.append(gpa, .{ |
| 2111 | 2106 | .target = global, |
| 2112 | 2107 | .offset = 0, |
| ... | ... | @@ -2376,7 +2371,7 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi |
| 2376 | 2371 | }); |
| 2377 | 2372 | try atom.rebases.append(gpa, 0); |
| 2378 | 2373 | |
| 2379 | | const global = self.globals.get(self.getSymbolName(target)).?; |
| 2374 | const global = self.getGlobal(self.getSymbolName(target)).?; |
| 2380 | 2375 | try atom.lazy_bindings.append(gpa, .{ |
| 2381 | 2376 | .target = global, |
| 2382 | 2377 | .offset = 0, |
| ... | ... | @@ -2472,7 +2467,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 2472 | 2467 | fn createTentativeDefAtoms(self: *MachO) !void { |
| 2473 | 2468 | const gpa = self.base.allocator; |
| 2474 | 2469 | |
| 2475 | | for (self.globals.values()) |global| { |
| 2470 | for (self.globals.items) |global| { |
| 2476 | 2471 | const sym = self.getSymbolPtr(global); |
| 2477 | 2472 | if (!sym.tentative()) continue; |
| 2478 | 2473 | |
| ... | ... | @@ -2516,25 +2511,22 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2516 | 2511 | |
| 2517 | 2512 | fn createMhExecuteHeaderSymbol(self: *MachO) !void { |
| 2518 | 2513 | if (self.base.options.output_mode != .Exe) return; |
| 2519 | | if (self.globals.get("__mh_execute_header")) |global| { |
| 2514 | if (self.getGlobal("__mh_execute_header")) |global| { |
| 2520 | 2515 | const sym = self.getSymbol(global); |
| 2521 | 2516 | if (!sym.undf() and !(sym.pext() or sym.weakDef())) return; |
| 2522 | 2517 | } |
| 2523 | 2518 | |
| 2524 | 2519 | const gpa = self.base.allocator; |
| 2525 | | const n_strx = try self.strtab.insert(gpa, "__mh_execute_header"); |
| 2526 | | const sym_index = @intCast(u32, self.locals.items.len); |
| 2527 | | try self.locals.append(gpa, .{ |
| 2528 | | .n_strx = n_strx, |
| 2520 | const sym_index = try self.allocateSymbol(); |
| 2521 | self.locals.items[sym_index] = .{ |
| 2522 | .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"), |
| 2529 | 2523 | .n_type = macho.N_SECT | macho.N_EXT, |
| 2530 | 2524 | .n_sect = 0, |
| 2531 | 2525 | .n_desc = macho.REFERENCED_DYNAMICALLY, |
| 2532 | 2526 | .n_value = 0, |
| 2533 | | }); |
| 2527 | }; |
| 2534 | 2528 | |
| 2535 | | const name = try gpa.dupe(u8, "__mh_execute_header"); |
| 2536 | | const gop = try self.globals.getOrPut(gpa, name); |
| 2537 | | defer if (gop.found_existing) gpa.free(name); |
| 2529 | const gop = try self.getOrPutGlobalPtr("__mh_execute_header"); |
| 2538 | 2530 | gop.value_ptr.* = .{ |
| 2539 | 2531 | .sym_index = sym_index, |
| 2540 | 2532 | .file = null, |
| ... | ... | @@ -2542,25 +2534,24 @@ fn createMhExecuteHeaderSymbol(self: *MachO) !void { |
| 2542 | 2534 | } |
| 2543 | 2535 | |
| 2544 | 2536 | fn createDsoHandleSymbol(self: *MachO) !void { |
| 2545 | | const global = self.globals.getPtr("___dso_handle") orelse return; |
| 2537 | const global = self.getGlobalPtr("___dso_handle") orelse return; |
| 2546 | 2538 | const sym = self.getSymbolPtr(global.*); |
| 2547 | 2539 | if (!sym.undf()) return; |
| 2548 | 2540 | |
| 2549 | 2541 | const gpa = self.base.allocator; |
| 2550 | | const n_strx = try self.strtab.insert(gpa, "___dso_handle"); |
| 2551 | | const sym_index = @intCast(u32, self.locals.items.len); |
| 2552 | | try self.locals.append(gpa, .{ |
| 2553 | | .n_strx = n_strx, |
| 2542 | const sym_index = try self.allocateSymbol(); |
| 2543 | self.locals.items[sym_index] = .{ |
| 2544 | .n_strx = try self.strtab.insert(gpa, "___dso_handle"), |
| 2554 | 2545 | .n_type = macho.N_SECT | macho.N_EXT, |
| 2555 | 2546 | .n_sect = 0, |
| 2556 | 2547 | .n_desc = macho.N_WEAK_DEF, |
| 2557 | 2548 | .n_value = 0, |
| 2558 | | }); |
| 2549 | }; |
| 2559 | 2550 | global.* = .{ |
| 2560 | 2551 | .sym_index = sym_index, |
| 2561 | 2552 | .file = null, |
| 2562 | 2553 | }; |
| 2563 | | _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex("___dso_handle").?)); |
| 2554 | _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?); |
| 2564 | 2555 | } |
| 2565 | 2556 | |
| 2566 | 2557 | fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| ... | ... | @@ -2568,19 +2559,14 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 2568 | 2559 | const sym = self.getSymbol(current); |
| 2569 | 2560 | const sym_name = self.getSymbolName(current); |
| 2570 | 2561 | |
| 2571 | | const name = try gpa.dupe(u8, sym_name); |
| 2572 | | const global_index = @intCast(u32, self.globals.values().len); |
| 2573 | | const gop = try self.globals.getOrPut(gpa, name); |
| 2574 | | defer if (gop.found_existing) gpa.free(name); |
| 2575 | | |
| 2562 | const gop = try self.getOrPutGlobalPtr(sym_name); |
| 2576 | 2563 | if (!gop.found_existing) { |
| 2577 | 2564 | gop.value_ptr.* = current; |
| 2578 | 2565 | if (sym.undf() and !sym.tentative()) { |
| 2579 | | try self.unresolved.putNoClobber(gpa, global_index, false); |
| 2566 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, false); |
| 2580 | 2567 | } |
| 2581 | 2568 | return; |
| 2582 | 2569 | } |
| 2583 | | |
| 2584 | 2570 | const global = gop.value_ptr.*; |
| 2585 | 2571 | const global_sym = self.getSymbol(global); |
| 2586 | 2572 | |
| ... | ... | @@ -2619,7 +2605,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 2619 | 2605 | } |
| 2620 | 2606 | if (sym.undf() and !sym.tentative()) return; |
| 2621 | 2607 | |
| 2622 | | _ = self.unresolved.swapRemove(@intCast(u32, self.globals.getIndex(name).?)); |
| 2608 | _ = self.unresolved.swapRemove(self.getGlobalIndex(sym_name).?); |
| 2623 | 2609 | |
| 2624 | 2610 | gop.value_ptr.* = current; |
| 2625 | 2611 | } |
| ... | ... | @@ -2664,7 +2650,7 @@ fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| 2664 | 2650 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id }; |
| 2665 | 2651 | self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) { |
| 2666 | 2652 | error.MultipleSymbolDefinitions => { |
| 2667 | | const global = self.globals.get(sym_name).?; |
| 2653 | const global = self.getGlobal(sym_name).?; |
| 2668 | 2654 | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 2669 | 2655 | if (global.file) |file| { |
| 2670 | 2656 | log.err(" first definition in '{s}'", .{self.objects.items[file].name}); |
| ... | ... | @@ -2684,7 +2670,8 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 2684 | 2670 | const cpu_arch = self.base.options.target.cpu.arch; |
| 2685 | 2671 | var next_sym: usize = 0; |
| 2686 | 2672 | loop: while (next_sym < self.unresolved.count()) { |
| 2687 | | const global = self.globals.values()[self.unresolved.keys()[next_sym]]; |
| 2673 | const global_index = self.unresolved.keys()[next_sym]; |
| 2674 | const global = self.globals.items[global_index]; |
| 2688 | 2675 | const sym_name = self.getSymbolName(global); |
| 2689 | 2676 | |
| 2690 | 2677 | for (self.archives.items) |archive| { |
| ... | ... | @@ -2710,10 +2697,11 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 2710 | 2697 | fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2711 | 2698 | if (self.dylibs.items.len == 0) return; |
| 2712 | 2699 | |
| 2700 | const gpa = self.base.allocator; |
| 2713 | 2701 | var next_sym: usize = 0; |
| 2714 | 2702 | loop: while (next_sym < self.unresolved.count()) { |
| 2715 | 2703 | const global_index = self.unresolved.keys()[next_sym]; |
| 2716 | | const global = self.globals.values()[global_index]; |
| 2704 | const global = self.globals.items[global_index]; |
| 2717 | 2705 | const sym = self.getSymbolPtr(global); |
| 2718 | 2706 | const sym_name = self.getSymbolName(global); |
| 2719 | 2707 | |
| ... | ... | @@ -2722,7 +2710,7 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 2722 | 2710 | |
| 2723 | 2711 | const dylib_id = @intCast(u16, id); |
| 2724 | 2712 | if (!self.referenced_dylibs.contains(dylib_id)) { |
| 2725 | | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); |
| 2713 | try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {}); |
| 2726 | 2714 | } |
| 2727 | 2715 | |
| 2728 | 2716 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| ... | ... | @@ -2760,7 +2748,7 @@ fn resolveSymbolsAtLoading(self: *MachO) !void { |
| 2760 | 2748 | var next_sym: usize = 0; |
| 2761 | 2749 | while (next_sym < self.unresolved.count()) { |
| 2762 | 2750 | const global_index = self.unresolved.keys()[next_sym]; |
| 2763 | | const global = self.globals.values()[global_index]; |
| 2751 | const global = self.globals.items[global_index]; |
| 2764 | 2752 | const sym = self.getSymbolPtr(global); |
| 2765 | 2753 | const sym_name = self.getSymbolName(global); |
| 2766 | 2754 | |
| ... | ... | @@ -2800,26 +2788,29 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 2800 | 2788 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports |
| 2801 | 2789 | |
| 2802 | 2790 | const gpa = self.base.allocator; |
| 2803 | | const n_strx = try self.strtab.insert(gpa, "dyld_stub_binder"); |
| 2804 | | const sym_index = @intCast(u32, self.locals.items.len); |
| 2805 | | try self.locals.append(gpa, .{ |
| 2806 | | .n_strx = n_strx, |
| 2791 | const sym_index = try self.allocateSymbol(); |
| 2792 | const sym = &self.locals.items[sym_index]; |
| 2793 | const sym_name = "dyld_stub_binder"; |
| 2794 | sym.* = .{ |
| 2795 | .n_strx = try self.strtab.insert(gpa, sym_name), |
| 2807 | 2796 | .n_type = macho.N_UNDF, |
| 2808 | 2797 | .n_sect = 0, |
| 2809 | 2798 | .n_desc = 0, |
| 2810 | 2799 | .n_value = 0, |
| 2811 | | }); |
| 2812 | | const sym_name = try gpa.dupe(u8, "dyld_stub_binder"); |
| 2813 | | const global = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 2814 | | try self.globals.putNoClobber(gpa, sym_name, global); |
| 2815 | | const sym = &self.locals.items[sym_index]; |
| 2800 | }; |
| 2801 | const gop = try self.getOrPutGlobalPtr(sym_name); |
| 2802 | gop.value_ptr.* = .{ |
| 2803 | .sym_index = sym_index, |
| 2804 | .file = null, |
| 2805 | }; |
| 2806 | const global = gop.value_ptr.*; |
| 2816 | 2807 | |
| 2817 | 2808 | for (self.dylibs.items) |dylib, id| { |
| 2818 | 2809 | if (!dylib.symbols.contains(sym_name)) continue; |
| 2819 | 2810 | |
| 2820 | 2811 | const dylib_id = @intCast(u16, id); |
| 2821 | 2812 | if (!self.referenced_dylibs.contains(dylib_id)) { |
| 2822 | | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); |
| 2813 | try self.referenced_dylibs.putNoClobber(gpa, dylib_id, {}); |
| 2823 | 2814 | } |
| 2824 | 2815 | |
| 2825 | 2816 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| ... | ... | @@ -3050,14 +3041,20 @@ pub fn deinit(self: *MachO) void { |
| 3050 | 3041 | self.stubs_free_list.deinit(gpa); |
| 3051 | 3042 | self.stubs_table.deinit(gpa); |
| 3052 | 3043 | self.strtab.deinit(gpa); |
| 3044 | |
| 3053 | 3045 | self.locals.deinit(gpa); |
| 3046 | self.globals.deinit(gpa); |
| 3054 | 3047 | self.locals_free_list.deinit(gpa); |
| 3048 | self.globals_free_list.deinit(gpa); |
| 3055 | 3049 | self.unresolved.deinit(gpa); |
| 3056 | 3050 | |
| 3057 | | for (self.globals.keys()) |key| { |
| 3058 | | gpa.free(key); |
| 3051 | { |
| 3052 | var it = self.resolver.keyIterator(); |
| 3053 | while (it.next()) |key_ptr| { |
| 3054 | gpa.free(key_ptr.*); |
| 3055 | } |
| 3056 | self.resolver.deinit(gpa); |
| 3059 | 3057 | } |
| 3060 | | self.globals.deinit(gpa); |
| 3061 | 3058 | |
| 3062 | 3059 | for (self.objects.items) |*object| { |
| 3063 | 3060 | object.deinit(gpa); |
| ... | ... | @@ -3211,6 +3208,29 @@ fn allocateSymbol(self: *MachO) !u32 { |
| 3211 | 3208 | return index; |
| 3212 | 3209 | } |
| 3213 | 3210 | |
| 3211 | fn allocateGlobal(self: *MachO) !u32 { |
| 3212 | try self.globals.ensureUnusedCapacity(self.base.allocator, 1); |
| 3213 | |
| 3214 | const index = blk: { |
| 3215 | if (self.globals_free_list.popOrNull()) |index| { |
| 3216 | log.debug(" (reusing global index {d})", .{index}); |
| 3217 | break :blk index; |
| 3218 | } else { |
| 3219 | log.debug(" (allocating symbol index {d})", .{self.globals.items.len}); |
| 3220 | const index = @intCast(u32, self.globals.items.len); |
| 3221 | _ = self.globals.addOneAssumeCapacity(); |
| 3222 | break :blk index; |
| 3223 | } |
| 3224 | }; |
| 3225 | |
| 3226 | self.globals.items[index] = .{ |
| 3227 | .sym_index = 0, |
| 3228 | .file = null, |
| 3229 | }; |
| 3230 | |
| 3231 | return index; |
| 3232 | } |
| 3233 | |
| 3214 | 3234 | pub fn allocateGotEntry(self: *MachO, target: SymbolWithLoc) !u32 { |
| 3215 | 3235 | const gpa = self.base.allocator; |
| 3216 | 3236 | try self.got_entries.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -3832,7 +3852,7 @@ pub fn updateDeclExports( |
| 3832 | 3852 | |
| 3833 | 3853 | self.resolveGlobalSymbol(sym_loc) catch |err| switch (err) { |
| 3834 | 3854 | error.MultipleSymbolDefinitions => { |
| 3835 | | const global = self.globals.get(exp_name).?; |
| 3855 | const global = self.getGlobal(exp_name).?; |
| 3836 | 3856 | if (sym_loc.sym_index != global.sym_index and global.file != null) { |
| 3837 | 3857 | _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create( |
| 3838 | 3858 | gpa, |
| ... | ... | @@ -3869,11 +3889,13 @@ pub fn deleteExport(self: *MachO, exp: Export) void { |
| 3869 | 3889 | }; |
| 3870 | 3890 | self.locals_free_list.append(gpa, sym_index) catch {}; |
| 3871 | 3891 | |
| 3872 | | if (self.globals.get(sym_name)) |global| blk: { |
| 3873 | | if (global.sym_index != sym_index) break :blk; |
| 3874 | | if (global.file != null) break :blk; |
| 3875 | | const kv = self.globals.fetchSwapRemove(sym_name); |
| 3876 | | gpa.free(kv.?.key); |
| 3892 | if (self.resolver.fetchRemove(sym_name)) |entry| { |
| 3893 | defer gpa.free(entry.key); |
| 3894 | self.globals_free_list.append(gpa, entry.value) catch {}; |
| 3895 | self.globals.items[entry.value] = .{ |
| 3896 | .sym_index = 0, |
| 3897 | .file = null, |
| 3898 | }; |
| 3877 | 3899 | } |
| 3878 | 3900 | } |
| 3879 | 3901 | |
| ... | ... | @@ -4864,30 +4886,23 @@ pub fn addAtomToSection(self: *MachO, atom: *Atom, sect_id: u8) !void { |
| 4864 | 4886 | |
| 4865 | 4887 | pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { |
| 4866 | 4888 | const gpa = self.base.allocator; |
| 4889 | |
| 4867 | 4890 | const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); |
| 4868 | | const global_index = @intCast(u32, self.globals.values().len); |
| 4869 | | const gop = try self.globals.getOrPut(gpa, sym_name); |
| 4870 | | defer if (gop.found_existing) gpa.free(sym_name); |
| 4891 | defer gpa.free(sym_name); |
| 4892 | const gop = try self.getOrPutGlobalPtr(sym_name); |
| 4871 | 4893 | |
| 4872 | 4894 | if (gop.found_existing) { |
| 4873 | | // TODO audit this: can we ever reference anything from outside the Zig module? |
| 4874 | | assert(gop.value_ptr.file == null); |
| 4875 | 4895 | return gop.value_ptr.sym_index; |
| 4876 | 4896 | } |
| 4877 | 4897 | |
| 4878 | | const sym_index = @intCast(u32, self.locals.items.len); |
| 4879 | | try self.locals.append(gpa, .{ |
| 4880 | | .n_strx = try self.strtab.insert(gpa, sym_name), |
| 4881 | | .n_type = macho.N_UNDF, |
| 4882 | | .n_sect = 0, |
| 4883 | | .n_desc = 0, |
| 4884 | | .n_value = 0, |
| 4885 | | }); |
| 4886 | | gop.value_ptr.* = .{ |
| 4887 | | .sym_index = sym_index, |
| 4888 | | .file = null, |
| 4889 | | }; |
| 4890 | | try self.unresolved.putNoClobber(gpa, global_index, true); |
| 4898 | const sym_index = try self.allocateSymbol(); |
| 4899 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| 4900 | gop.value_ptr.* = sym_loc; |
| 4901 | |
| 4902 | const sym = self.getSymbolPtr(sym_loc); |
| 4903 | sym.n_strx = try self.strtab.insert(gpa, sym_name); |
| 4904 | |
| 4905 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, true); |
| 4891 | 4906 | |
| 4892 | 4907 | return sym_index; |
| 4893 | 4908 | } |
| ... | ... | @@ -5055,7 +5070,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5055 | 5070 | if (self.base.options.output_mode == .Exe) { |
| 5056 | 5071 | for (&[_]SymbolWithLoc{ |
| 5057 | 5072 | try self.getEntryPoint(), |
| 5058 | | self.globals.get("__mh_execute_header").?, |
| 5073 | self.getGlobal("__mh_execute_header").?, |
| 5059 | 5074 | }) |global| { |
| 5060 | 5075 | const sym = self.getSymbol(global); |
| 5061 | 5076 | const sym_name = self.getSymbolName(global); |
| ... | ... | @@ -5068,7 +5083,7 @@ fn writeDyldInfoData(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5068 | 5083 | } |
| 5069 | 5084 | } else { |
| 5070 | 5085 | assert(self.base.options.output_mode == .Lib); |
| 5071 | | for (self.globals.values()) |global| { |
| 5086 | for (self.globals.items) |global| { |
| 5072 | 5087 | const sym = self.getSymbol(global); |
| 5073 | 5088 | |
| 5074 | 5089 | if (sym.undf()) continue; |
| ... | ... | @@ -5271,9 +5286,9 @@ fn writeFunctionStarts(self: *MachO, ncmds: *u32, lc_writer: anytype) !void { |
| 5271 | 5286 | // We need to sort by address first |
| 5272 | 5287 | var addresses = std.ArrayList(u64).init(gpa); |
| 5273 | 5288 | defer addresses.deinit(); |
| 5274 | | try addresses.ensureTotalCapacityPrecise(self.globals.count()); |
| 5289 | try addresses.ensureTotalCapacityPrecise(self.globals.items.len); |
| 5275 | 5290 | |
| 5276 | | for (self.globals.values()) |global| { |
| 5291 | for (self.globals.items) |global| { |
| 5277 | 5292 | const sym = self.getSymbol(global); |
| 5278 | 5293 | if (sym.undf()) continue; |
| 5279 | 5294 | if (sym.n_desc == N_DESC_GCED) continue; |
| ... | ... | @@ -5453,7 +5468,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5453 | 5468 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| 5454 | 5469 | const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = null }; |
| 5455 | 5470 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5456 | | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip |
| 5471 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 5457 | 5472 | try locals.append(sym); |
| 5458 | 5473 | } |
| 5459 | 5474 | |
| ... | ... | @@ -5463,7 +5478,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5463 | 5478 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| 5464 | 5479 | const sym_loc = SymbolWithLoc{ .sym_index = @intCast(u32, sym_id), .file = @intCast(u32, object_id) }; |
| 5465 | 5480 | if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip |
| 5466 | | if (self.globals.contains(self.getSymbolName(sym_loc))) continue; // global symbol is either an export or import, skip |
| 5481 | if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip |
| 5467 | 5482 | var out_sym = sym; |
| 5468 | 5483 | out_sym.n_strx = try self.strtab.insert(gpa, self.getSymbolName(sym_loc)); |
| 5469 | 5484 | try locals.append(out_sym); |
| ... | ... | @@ -5477,7 +5492,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5477 | 5492 | var exports = std.ArrayList(macho.nlist_64).init(gpa); |
| 5478 | 5493 | defer exports.deinit(); |
| 5479 | 5494 | |
| 5480 | | for (self.globals.values()) |global| { |
| 5495 | for (self.globals.items) |global| { |
| 5481 | 5496 | const sym = self.getSymbol(global); |
| 5482 | 5497 | if (sym.undf()) continue; // import, skip |
| 5483 | 5498 | if (sym.n_desc == N_DESC_GCED) continue; // GCed, skip |
| ... | ... | @@ -5491,7 +5506,7 @@ fn writeSymtab(self: *MachO, lc: *macho.symtab_command) !SymtabCtx { |
| 5491 | 5506 | |
| 5492 | 5507 | var imports_table = std.AutoHashMap(SymbolWithLoc, u32).init(gpa); |
| 5493 | 5508 | |
| 5494 | | for (self.globals.values()) |global| { |
| 5509 | for (self.globals.items) |global| { |
| 5495 | 5510 | const sym = self.getSymbol(global); |
| 5496 | 5511 | if (sym.n_strx == 0) continue; // no name, skip |
| 5497 | 5512 | if (!sym.undf()) continue; // not an import, skip |
| ... | ... | @@ -5798,6 +5813,43 @@ pub fn getSymbolName(self: *MachO, sym_with_loc: SymbolWithLoc) []const u8 { |
| 5798 | 5813 | } |
| 5799 | 5814 | } |
| 5800 | 5815 | |
| 5816 | /// Returns pointer to the global entry for `name` if one exists. |
| 5817 | pub fn getGlobalPtr(self: *MachO, name: []const u8) ?*SymbolWithLoc { |
| 5818 | const global_index = self.resolver.get(name) orelse return null; |
| 5819 | return &self.globals.items[global_index]; |
| 5820 | } |
| 5821 | |
| 5822 | /// Returns the global entry for `name` if one exists. |
| 5823 | pub fn getGlobal(self: *const MachO, name: []const u8) ?SymbolWithLoc { |
| 5824 | const global_index = self.resolver.get(name) orelse return null; |
| 5825 | return self.globals.items[global_index]; |
| 5826 | } |
| 5827 | |
| 5828 | /// Returns the index of the global entry for `name` if one exists. |
| 5829 | pub fn getGlobalIndex(self: *const MachO, name: []const u8) ?u32 { |
| 5830 | return self.resolver.get(name); |
| 5831 | } |
| 5832 | |
| 5833 | const GetOrPutGlobalPtrResult = struct { |
| 5834 | found_existing: bool, |
| 5835 | value_ptr: *SymbolWithLoc, |
| 5836 | }; |
| 5837 | |
| 5838 | /// Return pointer to the global entry for `name` if one exists. |
| 5839 | /// Puts a new global entry for `name` if one doesn't exist, and |
| 5840 | /// returns a pointer to it. |
| 5841 | pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResult { |
| 5842 | if (self.getGlobalPtr(name)) |ptr| { |
| 5843 | return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr }; |
| 5844 | } |
| 5845 | const gpa = self.base.allocator; |
| 5846 | const global_index = try self.allocateGlobal(); |
| 5847 | const global_name = try gpa.dupe(u8, name); |
| 5848 | _ = try self.resolver.put(gpa, global_name, global_index); |
| 5849 | const ptr = &self.globals.items[global_index]; |
| 5850 | return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr }; |
| 5851 | } |
| 5852 | |
| 5801 | 5853 | /// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor. |
| 5802 | 5854 | /// Returns null on failure. |
| 5803 | 5855 | pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom { |
| ... | ... | @@ -5834,7 +5886,7 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom |
| 5834 | 5886 | /// Asserts output mode is executable. |
| 5835 | 5887 | pub fn getEntryPoint(self: MachO) error{MissingMainEntrypoint}!SymbolWithLoc { |
| 5836 | 5888 | const entry_name = self.base.options.entry orelse "_main"; |
| 5837 | | const global = self.globals.get(entry_name) orelse { |
| 5889 | const global = self.getGlobal(entry_name) orelse { |
| 5838 | 5890 | log.err("entrypoint '{s}' not found", .{entry_name}); |
| 5839 | 5891 | return error.MissingMainEntrypoint; |
| 5840 | 5892 | }; |
| ... | ... | @@ -6342,9 +6394,9 @@ fn logSymtab(self: *MachO) void { |
| 6342 | 6394 | } |
| 6343 | 6395 | |
| 6344 | 6396 | log.debug("globals table:", .{}); |
| 6345 | | for (self.globals.keys()) |name, id| { |
| 6346 | | const value = self.globals.values()[id]; |
| 6347 | | log.debug(" {s} => %{d} in object({?d})", .{ name, value.sym_index, value.file }); |
| 6397 | for (self.globals.items) |global| { |
| 6398 | const name = self.getSymbolName(global); |
| 6399 | log.debug(" {s} => %{d} in object({?d})", .{ name, global.sym_index, global.file }); |
| 6348 | 6400 | } |
| 6349 | 6401 | |
| 6350 | 6402 | log.debug("GOT entries:", .{}); |