| ... | ... | @@ -3289,9 +3289,9 @@ fn setEntryPoint(self: *MachO) !void { |
| 3289 | 3289 | if (self.base.options.output_mode != .Exe) return; |
| 3290 | 3290 | |
| 3291 | 3291 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 3292 | | const entry_name = self.base.options.entry orelse "_main"; |
| 3293 | | const global = self.globals.get(entry_name) orelse { |
| 3294 | | log.err("entrypoint '{s}' not found", .{entry_name}); |
| 3292 | const global = self.getEntryPoint() orelse { |
| 3293 | const name = self.base.options.entry orelse "_main"; |
| 3294 | log.err("entrypoint '{s}' not found", .{name}); |
| 3295 | 3295 | return error.MissingMainEntrypoint; |
| 3296 | 3296 | }; |
| 3297 | 3297 | const sym = self.getSymbol(global); |
| ... | ... | @@ -5492,15 +5492,27 @@ fn gcAtoms(self: *MachO, gc_roots: *std.AutoHashMap(*Atom, void)) !void { |
| 5492 | 5492 | |
| 5493 | 5493 | const gpa = self.base.allocator; |
| 5494 | 5494 | |
| 5495 | | // Add all exports as GC roots |
| 5496 | | for (self.globals.values()) |global| { |
| 5497 | | const sym = self.getSymbol(global); |
| 5498 | | if (!sym.sect()) continue; |
| 5499 | | const gc_root = self.getAtomForSymbol(global) orelse { |
| 5500 | | log.debug("skipping {s}", .{self.getSymbolName(global)}); |
| 5501 | | continue; |
| 5502 | | }; |
| 5503 | | _ = try gc_roots.getOrPut(gc_root); |
| 5495 | if (self.base.options.output_mode == .Exe) { |
| 5496 | // Add entrypoint as GC root |
| 5497 | if (self.getEntryPoint()) |global| { |
| 5498 | if (self.getAtomForSymbol(global)) |gc_root| { |
| 5499 | _ = try gc_roots.getOrPut(gc_root); |
| 5500 | } else { |
| 5501 | log.debug("skipping {s}", .{self.getSymbolName(global)}); |
| 5502 | } |
| 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 | 5518 | // Add any atom targeting an import as GC root |
| ... | ... | @@ -5836,19 +5848,37 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5836 | 5848 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 5837 | 5849 | const base_address = text_segment.inner.vmaddr; |
| 5838 | 5850 | |
| 5839 | | for (self.globals.values()) |global| { |
| 5840 | | const sym = self.getSymbol(global); |
| 5841 | | if (sym.undf()) continue; |
| 5842 | | if (!sym.ext()) continue; |
| 5843 | | if (sym.n_desc == N_DESC_GCED) continue; |
| 5844 | | const sym_name = self.getSymbolName(global); |
| 5845 | | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 5846 | | |
| 5847 | | try trie.put(gpa, .{ |
| 5848 | | .name = sym_name, |
| 5849 | | .vmaddr_offset = sym.n_value - base_address, |
| 5850 | | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 5851 | | }); |
| 5851 | if (self.base.options.output_mode == .Exe) { |
| 5852 | for (&[_]SymbolWithLoc{ |
| 5853 | self.getEntryPoint().?, // We would already errored out if no entrypoint was found. |
| 5854 | self.globals.get("__mh_execute_header").?, |
| 5855 | }) |global| { |
| 5856 | const sym = self.getSymbol(global); |
| 5857 | const sym_name = self.getSymbolName(global); |
| 5858 | log.debug(" (putting '{s}' defined at 0x{x})", .{ sym_name, sym.n_value }); |
| 5859 | try trie.put(gpa, .{ |
| 5860 | .name = sym_name, |
| 5861 | .vmaddr_offset = sym.n_value - base_address, |
| 5862 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 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 | 5884 | try trie.finalize(gpa); |
| ... | ... | @@ -6602,6 +6632,13 @@ pub fn getTlvPtrAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom |
| 6602 | 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 | 6642 | pub fn findFirst(comptime T: type, haystack: []const T, start: usize, predicate: anytype) usize { |
| 6606 | 6643 | if (!@hasDecl(@TypeOf(predicate), "predicate")) |
| 6607 | 6644 | @compileError("Predicate is required to define fn predicate(@This(), T) bool"); |