| ... | @@ -3289,9 +3289,9 @@ fn setEntryPoint(self: *MachO) !void { | ... | @@ -3289,9 +3289,9 @@ fn setEntryPoint(self: *MachO) !void { |
| 3289 | if (self.base.options.output_mode != .Exe) return; | 3289 | if (self.base.options.output_mode != .Exe) return; |
| 3290 | | 3290 | |
| 3291 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 3291 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 3292 | const entry_name = self.base.options.entry orelse "_main"; | 3292 | const global = self.getEntryPoint() orelse { |
| 3293 | const global = self.globals.get(entry_name) orelse { | 3293 | const name = self.base.options.entry orelse "_main"; |
| 3294 | log.err("entrypoint '{s}' not found", .{entry_name}); | 3294 | log.err("entrypoint '{s}' not found", .{name}); |
| 3295 | return error.MissingMainEntrypoint; | 3295 | return error.MissingMainEntrypoint; |
| 3296 | }; | 3296 | }; |
| 3297 | const sym = self.getSymbol(global); | 3297 | const sym = self.getSymbol(global); |
| ... | @@ -5492,15 +5492,27 @@ fn gcAtoms(self: *MachO, gc_roots: *std.AutoHashMap(*Atom, void)) !void { | ... | @@ -5492,15 +5492,27 @@ fn gcAtoms(self: *MachO, gc_roots: *std.AutoHashMap(*Atom, void)) !void { |
| 5492 | | 5492 | |
| 5493 | const gpa = self.base.allocator; | 5493 | const gpa = self.base.allocator; |
| 5494 | | 5494 | |
| 5495 | // Add all exports as GC roots | 5495 | if (self.base.options.output_mode == .Exe) { |
| 5496 | for (self.globals.values()) |global| { | 5496 | // Add entrypoint as GC root |
| 5497 | const sym = self.getSymbol(global); | 5497 | if (self.getEntryPoint()) |global| { |
| 5498 | if (!sym.sect()) continue; | 5498 | if (self.getAtomForSymbol(global)) |gc_root| { |
| 5499 | const gc_root = self.getAtomForSymbol(global) orelse { | 5499 | _ = try gc_roots.getOrPut(gc_root); |
| 5500 | log.debug("skipping {s}", .{self.getSymbolName(global)}); | 5500 | } else { |
| 5501 | continue; | 5501 | log.debug("skipping {s}", .{self.getSymbolName(global)}); |
| 5502 | }; | 5502 | } |
| 5503 | _ = try gc_roots.getOrPut(gc_root); | 5503 | } |
| | 5504 | } else { |
| | 5505 | assert(self.base.options.output_mode == .Lib); |
| | 5506 | // Add exports as GC roots |
| | 5507 | for (self.globals.values()) |global| { |
| | 5508 | const sym = self.getSymbol(global); |
| | 5509 | if (!sym.sect()) continue; |
| | 5510 | const gc_root = self.getAtomForSymbol(global) orelse { |
| | 5511 | log.debug("skipping {s}", .{self.getSymbolName(global)}); |
| | 5512 | continue; |
| | 5513 | }; |
| | 5514 | _ = try gc_roots.getOrPut(gc_root); |
| | 5515 | } |
| 5504 | } | 5516 | } |
| 5505 | | 5517 | |
| 5506 | // Add any atom targeting an import as GC root | 5518 | // Add any atom targeting an import as GC root |
| ... | @@ -5836,19 +5848,37 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5836,19 +5848,37 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5836 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 5848 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 5837 | const base_address = text_segment.inner.vmaddr; | 5849 | const base_address = text_segment.inner.vmaddr; |
| 5838 | | 5850 | |
| 5839 | for (self.globals.values()) |global| { | 5851 | if (self.base.options.output_mode == .Exe) { |
| 5840 | const sym = self.getSymbol(global); | 5852 | for (&[_]SymbolWithLoc{ |
| 5841 | if (sym.undf()) continue; | 5853 | self.getEntryPoint().?, // We would already errored out if no entrypoint was found. |
| 5842 | if (!sym.ext()) continue; | 5854 | self.globals.get("__mh_execute_header").?, |
| 5843 | if (sym.n_desc == N_DESC_GCED) continue; | 5855 | }) |global| { |
| 5844 | const sym_name = self.getSymbolName(global); | 5856 | const sym = self.getSymbol(global); |
| 5845 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); | 5857 | const sym_name = self.getSymbolName(global); |
| 5846 | | 5858 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 5847 | try trie.put(gpa, .{ | 5859 | try trie.put(gpa, .{ |
| 5848 | .name = sym_name, | 5860 | .name = sym_name, |
| 5849 | .vmaddr_offset = sym.n_value - base_address, | 5861 | .vmaddr_offset = sym.n_value - base_address, |
| 5850 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | 5862 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 5851 | }); | 5863 | }); |
| | 5864 | } |
| | 5865 | } else { |
| | 5866 | assert(self.base.options.output_mode == .Lib); |
| | 5867 | for (self.globals.values()) |global| { |
| | 5868 | const sym = self.getSymbol(global); |
| | 5869 | |
| | 5870 | if (sym.undf()) continue; |
| | 5871 | if (!sym.ext()) continue; |
| | 5872 | if (sym.n_desc == N_DESC_GCED) continue; |
| | 5873 | |
| | 5874 | const sym_name = self.getSymbolName(global); |
| | 5875 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| | 5876 | try trie.put(gpa, .{ |
| | 5877 | .name = sym_name, |
| | 5878 | .vmaddr_offset = sym.n_value - base_address, |
| | 5879 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| | 5880 | }); |
| | 5881 | } |
| 5852 | } | 5882 | } |
| 5853 | | 5883 | |
| 5854 | try trie.finalize(gpa); | 5884 | try trie.finalize(gpa); |
| ... | @@ -6602,6 +6632,13 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom | ... | @@ -6602,6 +6632,13 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom |
| 6602 | return self.tlv_ptr_entries.items[tlv_ptr_index].atom; | 6632 | return self.tlv_ptr_entries.items[tlv_ptr_index].atom; |
| 6603 | } | 6633 | } |
| 6604 | | 6634 | |
| | 6635 | /// Returns symbol location corresponding to the set entrypoint. |
| | 6636 | /// Asserts output mode is executable. |
| | 6637 | pub fn getEntryPoint(self: MachO) ?SymbolWithLoc { |
| | 6638 | const entry_name = self.base.options.entry orelse "_main"; |
| | 6639 | return self.globals.get(entry_name); |
| | 6640 | } |
| | 6641 | |
| 6605 | pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate: anytype) usize { | 6642 | pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate: anytype) usize { |
| 6606 | if (!@hasDecl(@TypeOf(predicate), "predicate")) | 6643 | if (!@hasDecl(@TypeOf(predicate), "predicate")) |
| 6607 | @compileError("Predicate is required to define fn predicate(@This(), T) bool"); | 6644 | @compileError("Predicate is required to define fn predicate(@This(), T) bool"); |