| ... | @@ -283,7 +283,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { | ... | @@ -283,7 +283,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { |
| 283 | try self.allocateStubsAndGotEntries(); | 283 | try self.allocateStubsAndGotEntries(); |
| 284 | try self.writeStubHelperCommon(); | 284 | try self.writeStubHelperCommon(); |
| 285 | try self.resolveRelocsAndWriteSections(); | 285 | try self.resolveRelocsAndWriteSections(); |
| 286 | // try self.flush(); | 286 | try self.flush(); |
| 287 | } | 287 | } |
| 288 | | 288 | |
| 289 | fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | 289 | fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| ... | @@ -386,7 +386,7 @@ fn mapAndUpdateSections( | ... | @@ -386,7 +386,7 @@ fn mapAndUpdateSections( |
| 386 | .target_sect_id = target_sect_id, | 386 | .target_sect_id = target_sect_id, |
| 387 | .offset = @intCast(u32, offset), | 387 | .offset = @intCast(u32, offset), |
| 388 | }); | 388 | }); |
| 389 | log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ | 389 | log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ |
| 390 | object.name, | 390 | object.name, |
| 391 | parseName(&source_sect.segname), | 391 | parseName(&source_sect.segname), |
| 392 | parseName(&source_sect.sectname), | 392 | parseName(&source_sect.sectname), |
| ... | @@ -596,7 +596,7 @@ fn updateMetadata(self: *Zld) !void { | ... | @@ -596,7 +596,7 @@ fn updateMetadata(self: *Zld) !void { |
| 596 | }); | 596 | }); |
| 597 | }, | 597 | }, |
| 598 | else => { | 598 | else => { |
| 599 | log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); | 599 | log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname }); |
| 600 | }, | 600 | }, |
| 601 | } | 601 | } |
| 602 | } | 602 | } |
| ... | @@ -620,7 +620,7 @@ fn updateMetadata(self: *Zld) !void { | ... | @@ -620,7 +620,7 @@ fn updateMetadata(self: *Zld) !void { |
| 620 | | 620 | |
| 621 | const segname = parseName(&source_sect.segname); | 621 | const segname = parseName(&source_sect.segname); |
| 622 | const sectname = parseName(&source_sect.sectname); | 622 | const sectname = parseName(&source_sect.sectname); |
| 623 | log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); | 623 | log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname }); |
| 624 | try self.unhandled_sections.putNoClobber(self.allocator, .{ | 624 | try self.unhandled_sections.putNoClobber(self.allocator, .{ |
| 625 | .object_id = object_id, | 625 | .object_id = object_id, |
| 626 | .source_sect_id = source_sect_id, | 626 | .source_sect_id = source_sect_id, |
| ... | @@ -964,7 +964,7 @@ fn allocateSymbols(self: *Zld) !void { | ... | @@ -964,7 +964,7 @@ fn allocateSymbols(self: *Zld) !void { |
| 964 | const target_addr = target_sect.addr + target_mapping.offset; | 964 | const target_addr = target_sect.addr + target_mapping.offset; |
| 965 | const n_value = source_sym.inner.n_value - source_sect.addr + target_addr; | 965 | const n_value = source_sym.inner.n_value - source_sect.addr + target_addr; |
| 966 | | 966 | |
| 967 | log.debug("resolving '{s}' symbol at 0x{x}", .{ entry.key, n_value }); | 967 | log.warn("resolving '{s}' symbol at 0x{x}", .{ entry.key, n_value }); |
| 968 | | 968 | |
| 969 | // TODO there might be a more generic way of doing this. | 969 | // TODO there might be a more generic way of doing this. |
| 970 | var n_sect: u8 = 0; | 970 | var n_sect: u8 = 0; |
| ... | @@ -1172,7 +1172,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void { | ... | @@ -1172,7 +1172,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void { |
| 1172 | var buf: [@sizeOf(u64)]u8 = undefined; | 1172 | var buf: [@sizeOf(u64)]u8 = undefined; |
| 1173 | mem.writeIntLittle(u64, &buf, end); | 1173 | mem.writeIntLittle(u64, &buf, end); |
| 1174 | const off = la_symbol_ptr.offset + index * @sizeOf(u64); | 1174 | const off = la_symbol_ptr.offset + index * @sizeOf(u64); |
| 1175 | log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off }); | 1175 | log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off }); |
| 1176 | try self.file.?.pwriteAll(&buf, off); | 1176 | try self.file.?.pwriteAll(&buf, off); |
| 1177 | } | 1177 | } |
| 1178 | | 1178 | |
| ... | @@ -1185,7 +1185,7 @@ fn writeStub(self: *Zld, index: u32) !void { | ... | @@ -1185,7 +1185,7 @@ fn writeStub(self: *Zld, index: u32) !void { |
| 1185 | const stub_off = stubs.offset + index * stubs.reserved2; | 1185 | const stub_off = stubs.offset + index * stubs.reserved2; |
| 1186 | const stub_addr = stubs.addr + index * stubs.reserved2; | 1186 | const stub_addr = stubs.addr + index * stubs.reserved2; |
| 1187 | const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64); | 1187 | const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64); |
| 1188 | log.debug("writing stub at 0x{x}", .{stub_off}); | 1188 | log.warn("writing stub at 0x{x}", .{stub_off}); |
| 1189 | var code = try self.allocator.alloc(u8, stubs.reserved2); | 1189 | var code = try self.allocator.alloc(u8, stubs.reserved2); |
| 1190 | defer self.allocator.free(code); | 1190 | defer self.allocator.free(code); |
| 1191 | switch (self.arch.?) { | 1191 | switch (self.arch.?) { |
| ... | @@ -1444,7 +1444,7 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1444,7 +1444,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1444 | | 1444 | |
| 1445 | fn resolveStubsAndGotEntries(self: *Zld) !void { | 1445 | fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1446 | for (self.objects.items) |object, object_id| { | 1446 | for (self.objects.items) |object, object_id| { |
| 1447 | log.debug("\nresolving stubs and got entries from {s}", .{object.name}); | 1447 | log.warn("\nresolving stubs and got entries from {s}", .{object.name}); |
| 1448 | | 1448 | |
| 1449 | for (object.sections.items) |sect| { | 1449 | for (object.sections.items) |sect| { |
| 1450 | const relocs = sect.relocs orelse continue; | 1450 | const relocs = sect.relocs orelse continue; |
| ... | @@ -1469,7 +1469,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1469,7 +1469,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1469 | .local_index = if (is_import) 0 else reloc.target.symbol, | 1469 | .local_index = if (is_import) 0 else reloc.target.symbol, |
| 1470 | }); | 1470 | }); |
| 1471 | | 1471 | |
| 1472 | log.debug(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) }); | 1472 | log.warn(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) }); |
| 1473 | }, | 1473 | }, |
| 1474 | else => { | 1474 | else => { |
| 1475 | const sym = object.symtab.items[reloc.target.symbol]; | 1475 | const sym = object.symtab.items[reloc.target.symbol]; |
| ... | @@ -1486,7 +1486,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1486,7 +1486,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1486 | const index = @intCast(u32, self.stubs.items().len); | 1486 | const index = @intCast(u32, self.stubs.items().len); |
| 1487 | try self.stubs.putNoClobber(self.allocator, name, index); | 1487 | try self.stubs.putNoClobber(self.allocator, name, index); |
| 1488 | | 1488 | |
| 1489 | log.debug(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) }); | 1489 | log.warn(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) }); |
| 1490 | }, | 1490 | }, |
| 1491 | } | 1491 | } |
| 1492 | } | 1492 | } |
| ... | @@ -1504,7 +1504,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1504,7 +1504,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1504 | .local_index = 0, | 1504 | .local_index = 0, |
| 1505 | }); | 1505 | }); |
| 1506 | | 1506 | |
| 1507 | log.debug(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")}); | 1507 | log.warn(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")}); |
| 1508 | } | 1508 | } |
| 1509 | | 1509 | |
| 1510 | fn resolveRelocsAndWriteSections(self: *Zld) !void { | 1510 | fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| ... | @@ -1520,7 +1520,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { | ... | @@ -1520,7 +1520,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1520 | .object_id = @intCast(u16, object_id), | 1520 | .object_id = @intCast(u16, object_id), |
| 1521 | .source_sect_id = @intCast(u16, source_sect_id), | 1521 | .source_sect_id = @intCast(u16, source_sect_id), |
| 1522 | }) orelse { | 1522 | }) orelse { |
| 1523 | log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname }); | 1523 | log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname }); |
| 1524 | continue; | 1524 | continue; |
| 1525 | }; | 1525 | }; |
| 1526 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; | 1526 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| ... | @@ -2128,6 +2128,7 @@ fn flush(self: *Zld) !void { | ... | @@ -2128,6 +2128,7 @@ fn flush(self: *Zld) !void { |
| 2128 | try self.file.?.pwriteAll(buffer, sect.offset); | 2128 | try self.file.?.pwriteAll(buffer, sect.offset); |
| 2129 | } | 2129 | } |
| 2130 | | 2130 | |
| | 2131 | try self.writeGotEntries(); |
| 2131 | try self.setEntryPoint(); | 2132 | try self.setEntryPoint(); |
| 2132 | try self.writeRebaseInfoTable(); | 2133 | try self.writeRebaseInfoTable(); |
| 2133 | try self.writeBindInfoTable(); | 2134 | try self.writeBindInfoTable(); |
| ... | @@ -2143,7 +2144,8 @@ fn flush(self: *Zld) !void { | ... | @@ -2143,7 +2144,8 @@ fn flush(self: *Zld) !void { |
| 2143 | symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | 2144 | symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 2144 | } | 2145 | } |
| 2145 | | 2146 | |
| 2146 | try self.writeDebugInfo(); | 2147 | // try self.writeDebugInfo(); |
| | 2148 | try self.populateStringTable(); |
| 2147 | try self.writeSymbolTable(); | 2149 | try self.writeSymbolTable(); |
| 2148 | try self.writeDynamicSymbolTable(); | 2150 | try self.writeDynamicSymbolTable(); |
| 2149 | try self.writeStringTable(); | 2151 | try self.writeStringTable(); |
| ... | @@ -2170,60 +2172,52 @@ fn flush(self: *Zld) !void { | ... | @@ -2170,60 +2172,52 @@ fn flush(self: *Zld) !void { |
| 2170 | } | 2172 | } |
| 2171 | } | 2173 | } |
| 2172 | | 2174 | |
| | 2175 | fn writeGotEntries(self: *Zld) !void { |
| | 2176 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 2177 | const sect = seg.sections.items[self.got_section_index.?]; |
| | 2178 | |
| | 2179 | var buffer = try self.allocator.alloc(u8, self.got_entries.items().len * @sizeOf(u64)); |
| | 2180 | defer self.allocator.free(buffer); |
| | 2181 | |
| | 2182 | var stream = std.io.fixedBufferStream(buffer); |
| | 2183 | var writer = stream.writer(); |
| | 2184 | |
| | 2185 | for (self.got_entries.items()) |entry| { |
| | 2186 | try writer.writeIntLittle(u64, entry.value.target_addr); |
| | 2187 | } |
| | 2188 | |
| | 2189 | log.warn("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len }); |
| | 2190 | |
| | 2191 | try self.file.?.pwriteAll(buffer, sect.offset); |
| | 2192 | } |
| | 2193 | |
| 2173 | fn setEntryPoint(self: *Zld) !void { | 2194 | fn setEntryPoint(self: *Zld) !void { |
| 2174 | // TODO we should respect the -entry flag passed in by the user to set a custom | 2195 | // TODO we should respect the -entry flag passed in by the user to set a custom |
| 2175 | // entrypoint. For now, assume default of `_main`. | 2196 | // entrypoint. For now, assume default of `_main`. |
| 2176 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2197 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2177 | const text = seg.sections.items[self.text_section_index.?]; | 2198 | const text = seg.sections.items[self.text_section_index.?]; |
| 2178 | const entry_syms = self.locals.get("_main") orelse return error.MissingMainEntrypoint; | 2199 | const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint; |
| 2179 | | | |
| 2180 | var entry_sym: ?macho.nlist_64 = null; | | |
| 2181 | for (entry_syms.items) |es| { | | |
| 2182 | switch (es.tt) { | | |
| 2183 | .Global => { | | |
| 2184 | entry_sym = es.inner; | | |
| 2185 | break; | | |
| 2186 | }, | | |
| 2187 | .WeakGlobal => { | | |
| 2188 | entry_sym = es.inner; | | |
| 2189 | }, | | |
| 2190 | .Local => {}, | | |
| 2191 | } | | |
| 2192 | } | | |
| 2193 | if (entry_sym == null) { | | |
| 2194 | log.err("no (weak) global definition of _main found", .{}); | | |
| 2195 | return error.MissingMainEntrypoint; | | |
| 2196 | } | | |
| 2197 | | | |
| 2198 | const name = try self.allocator.dupe(u8, "_main"); | | |
| 2199 | try self.exports.putNoClobber(self.allocator, name, .{ | | |
| 2200 | .n_strx = entry_sym.?.n_strx, | | |
| 2201 | .n_value = entry_sym.?.n_value, | | |
| 2202 | .n_type = macho.N_SECT | macho.N_EXT, | | |
| 2203 | .n_desc = entry_sym.?.n_desc, | | |
| 2204 | .n_sect = entry_sym.?.n_sect, | | |
| 2205 | }); | | |
| 2206 | | | |
| 2207 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; | 2200 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; |
| 2208 | ec.entryoff = @intCast(u32, entry_sym.?.n_value - seg.inner.vmaddr); | 2201 | ec.entryoff = @intCast(u32, entry_sym.inner.n_value - seg.inner.vmaddr); |
| 2209 | } | 2202 | } |
| 2210 | | 2203 | |
| 2211 | fn writeRebaseInfoTable(self: *Zld) !void { | 2204 | fn writeRebaseInfoTable(self: *Zld) !void { |
| 2212 | var pointers = std.ArrayList(Pointer).init(self.allocator); | 2205 | var pointers = std.ArrayList(Pointer).init(self.allocator); |
| 2213 | defer pointers.deinit(); | 2206 | defer pointers.deinit(); |
| 2214 | | 2207 | |
| 2215 | try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len); | 2208 | try pointers.ensureCapacity(self.local_rebases.items.len); |
| 2216 | pointers.appendSliceAssumeCapacity(self.local_rebases.items); | 2209 | pointers.appendSliceAssumeCapacity(self.local_rebases.items); |
| 2217 | | 2210 | |
| 2218 | if (self.got_section_index) |idx| { | 2211 | if (self.got_section_index) |idx| { |
| 2219 | // TODO this should be cleaned up! | 2212 | // TODO this should be cleaned up! |
| 2220 | try pointers.ensureCapacity(pointers.items.len + self.nonlazy_pointers.items().len); | | |
| 2221 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 2213 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2222 | const sect = seg.sections.items[idx]; | 2214 | const sect = seg.sections.items[idx]; |
| 2223 | const base_offset = sect.addr - seg.inner.vmaddr; | 2215 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2224 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | 2216 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2225 | const index_offset = @intCast(u32, self.nonlazy_imports.items().len); | 2217 | const index_offset = @intCast(u32, self.got_entries.items().len); |
| 2226 | for (self.nonlazy_pointers.items()) |entry| { | 2218 | |
| | 2219 | try pointers.ensureCapacity(pointers.items.len + self.got_entries.items().len); |
| | 2220 | for (self.got_entries.items()) |entry| { |
| 2227 | const index = index_offset + entry.value.index; | 2221 | const index = index_offset + entry.value.index; |
| 2228 | pointers.appendAssumeCapacity(.{ | 2222 | pointers.appendAssumeCapacity(.{ |
| 2229 | .offset = base_offset + index * @sizeOf(u64), | 2223 | .offset = base_offset + index * @sizeOf(u64), |
| ... | @@ -2269,14 +2263,15 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2269,14 +2263,15 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2269 | } | 2263 | } |
| 2270 | | 2264 | |
| 2271 | if (self.la_symbol_ptr_section_index) |idx| { | 2265 | if (self.la_symbol_ptr_section_index) |idx| { |
| 2272 | try pointers.ensureCapacity(pointers.items.len + self.lazy_imports.items().len); | | |
| 2273 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2266 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2274 | const sect = seg.sections.items[idx]; | 2267 | const sect = seg.sections.items[idx]; |
| 2275 | const base_offset = sect.addr - seg.inner.vmaddr; | 2268 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2276 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2269 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2277 | for (self.lazy_imports.items()) |entry| { | 2270 | |
| | 2271 | try pointers.ensureCapacity(pointers.items.len + self.stubs.items().len); |
| | 2272 | for (self.stubs.items()) |entry| { |
| 2278 | pointers.appendAssumeCapacity(.{ | 2273 | pointers.appendAssumeCapacity(.{ |
| 2279 | .offset = base_offset + entry.value.index * @sizeOf(u64), | 2274 | .offset = base_offset + entry.value * @sizeOf(u64), |
| 2280 | .segment_id = segment_id, | 2275 | .segment_id = segment_id, |
| 2281 | }); | 2276 | }); |
| 2282 | } | 2277 | } |
| ... | @@ -2297,7 +2292,7 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2297,7 +2292,7 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2297 | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64))); | 2292 | dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64))); |
| 2298 | seg.inner.filesize += dyld_info.rebase_size; | 2293 | seg.inner.filesize += dyld_info.rebase_size; |
| 2299 | | 2294 | |
| 2300 | log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size }); | 2295 | log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size }); |
| 2301 | | 2296 | |
| 2302 | try self.file.?.pwriteAll(buffer, dyld_info.rebase_off); | 2297 | try self.file.?.pwriteAll(buffer, dyld_info.rebase_off); |
| 2303 | } | 2298 | } |
| ... | @@ -2307,16 +2302,23 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2307,16 +2302,23 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2307 | defer pointers.deinit(); | 2302 | defer pointers.deinit(); |
| 2308 | | 2303 | |
| 2309 | if (self.got_section_index) |idx| { | 2304 | if (self.got_section_index) |idx| { |
| 2310 | try pointers.ensureCapacity(pointers.items.len + self.nonlazy_imports.items().len); | | |
| 2311 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 2305 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2312 | const sect = seg.sections.items[idx]; | 2306 | const sect = seg.sections.items[idx]; |
| 2313 | const base_offset = sect.addr - seg.inner.vmaddr; | 2307 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2314 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | 2308 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2315 | for (self.nonlazy_imports.items()) |entry| { | 2309 | |
| | 2310 | try pointers.ensureCapacity(pointers.items.len + self.got_entries.items().len); |
| | 2311 | for (self.got_entries.items()) |entry| { |
| | 2312 | const dylib_ordinal = dylib_ordinal: { |
| | 2313 | const sym = self.symtab.get(entry.key) orelse continue; // local indirection |
| | 2314 | if (sym.tag != .Import) continue; // local indirection |
| | 2315 | break :dylib_ordinal sym.file.? + 1; |
| | 2316 | }; |
| | 2317 | |
| 2316 | pointers.appendAssumeCapacity(.{ | 2318 | pointers.appendAssumeCapacity(.{ |
| 2317 | .offset = base_offset + entry.value.index * @sizeOf(u64), | 2319 | .offset = base_offset + entry.value.index * @sizeOf(u64), |
| 2318 | .segment_id = segment_id, | 2320 | .segment_id = segment_id, |
| 2319 | .dylib_ordinal = entry.value.dylib_ordinal, | 2321 | .dylib_ordinal = dylib_ordinal, |
| 2320 | .name = entry.key, | 2322 | .name = entry.key, |
| 2321 | }); | 2323 | }); |
| 2322 | } | 2324 | } |
| ... | @@ -2327,10 +2329,14 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2327,10 +2329,14 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2327 | const sect = seg.sections.items[idx]; | 2329 | const sect = seg.sections.items[idx]; |
| 2328 | const base_offset = sect.addr - seg.inner.vmaddr; | 2330 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2329 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2331 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| | 2332 | |
| | 2333 | const sym = self.symtab.get("__tlv_bootstrap") orelse unreachable; |
| | 2334 | const dylib_ordinal = sym.file.? + 1; |
| | 2335 | |
| 2330 | try pointers.append(.{ | 2336 | try pointers.append(.{ |
| 2331 | .offset = base_offset + self.tlv_bootstrap.?.index * @sizeOf(u64), | 2337 | .offset = base_offset, |
| 2332 | .segment_id = segment_id, | 2338 | .segment_id = segment_id, |
| 2333 | .dylib_ordinal = self.tlv_bootstrap.?.dylib_ordinal, | 2339 | .dylib_ordinal = dylib_ordinal, |
| 2334 | .name = "__tlv_bootstrap", | 2340 | .name = "__tlv_bootstrap", |
| 2335 | }); | 2341 | }); |
| 2336 | } | 2342 | } |
| ... | @@ -2348,7 +2354,7 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2348,7 +2354,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2348 | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2354 | dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2349 | seg.inner.filesize += dyld_info.bind_size; | 2355 | seg.inner.filesize += dyld_info.bind_size; |
| 2350 | | 2356 | |
| 2351 | log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size }); | 2357 | log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size }); |
| 2352 | | 2358 | |
| 2353 | try self.file.?.pwriteAll(buffer, dyld_info.bind_off); | 2359 | try self.file.?.pwriteAll(buffer, dyld_info.bind_off); |
| 2354 | } | 2360 | } |
| ... | @@ -2356,18 +2362,26 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2356,18 +2362,26 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2356 | fn writeLazyBindInfoTable(self: *Zld) !void { | 2362 | fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2357 | var pointers = std.ArrayList(Pointer).init(self.allocator); | 2363 | var pointers = std.ArrayList(Pointer).init(self.allocator); |
| 2358 | defer pointers.deinit(); | 2364 | defer pointers.deinit(); |
| 2359 | try pointers.ensureCapacity(self.lazy_imports.items().len); | | |
| 2360 | | 2365 | |
| 2361 | if (self.la_symbol_ptr_section_index) |idx| { | 2366 | if (self.la_symbol_ptr_section_index) |idx| { |
| 2362 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2367 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2363 | const sect = seg.sections.items[idx]; | 2368 | const sect = seg.sections.items[idx]; |
| 2364 | const base_offset = sect.addr - seg.inner.vmaddr; | 2369 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2365 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2370 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2366 | for (self.lazy_imports.items()) |entry| { | 2371 | |
| | 2372 | try pointers.ensureCapacity(self.stubs.items().len); |
| | 2373 | |
| | 2374 | for (self.stubs.items()) |entry| { |
| | 2375 | const dylib_ordinal = dylib_ordinal: { |
| | 2376 | const sym = self.symtab.get(entry.key) orelse unreachable; |
| | 2377 | assert(sym.tag == .Import); |
| | 2378 | break :dylib_ordinal sym.file.? + 1; |
| | 2379 | }; |
| | 2380 | |
| 2367 | pointers.appendAssumeCapacity(.{ | 2381 | pointers.appendAssumeCapacity(.{ |
| 2368 | .offset = base_offset + entry.value.index * @sizeOf(u64), | 2382 | .offset = base_offset + entry.value * @sizeOf(u64), |
| 2369 | .segment_id = segment_id, | 2383 | .segment_id = segment_id, |
| 2370 | .dylib_ordinal = entry.value.dylib_ordinal, | 2384 | .dylib_ordinal = dylib_ordinal, |
| 2371 | .name = entry.key, | 2385 | .name = entry.key, |
| 2372 | }); | 2386 | }); |
| 2373 | } | 2387 | } |
| ... | @@ -2386,7 +2400,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { | ... | @@ -2386,7 +2400,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2386 | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2400 | dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2387 | seg.inner.filesize += dyld_info.lazy_bind_size; | 2401 | seg.inner.filesize += dyld_info.lazy_bind_size; |
| 2388 | | 2402 | |
| 2389 | log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size }); | 2403 | log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size }); |
| 2390 | | 2404 | |
| 2391 | try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); | 2405 | try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); |
| 2392 | try self.populateLazyBindOffsetsInStubHelper(buffer); | 2406 | try self.populateLazyBindOffsetsInStubHelper(buffer); |
| ... | @@ -2437,7 +2451,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { | ... | @@ -2437,7 +2451,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2437 | else => {}, | 2451 | else => {}, |
| 2438 | } | 2452 | } |
| 2439 | } | 2453 | } |
| 2440 | assert(self.lazy_imports.items().len <= offsets.items.len); | 2454 | assert(self.stubs.items().len <= offsets.items.len); |
| 2441 | | 2455 | |
| 2442 | const stub_size: u4 = switch (self.arch.?) { | 2456 | const stub_size: u4 = switch (self.arch.?) { |
| 2443 | .x86_64 => 10, | 2457 | .x86_64 => 10, |
| ... | @@ -2450,10 +2464,9 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { | ... | @@ -2450,10 +2464,9 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2450 | else => unreachable, | 2464 | else => unreachable, |
| 2451 | }; | 2465 | }; |
| 2452 | var buf: [@sizeOf(u32)]u8 = undefined; | 2466 | var buf: [@sizeOf(u32)]u8 = undefined; |
| 2453 | for (self.lazy_imports.items()) |entry| { | 2467 | for (self.stubs.items()) |entry| { |
| 2454 | const symbol = entry.value; | 2468 | const placeholder_off = self.stub_helper_stubs_start_off.? + entry.value * stub_size + off; |
| 2455 | const placeholder_off = self.stub_helper_stubs_start_off.? + symbol.index * stub_size + off; | 2469 | mem.writeIntLittle(u32, &buf, offsets.items[entry.value]); |
| 2456 | mem.writeIntLittle(u32, &buf, offsets.items[symbol.index]); | | |
| 2457 | try self.file.?.pwriteAll(&buf, placeholder_off); | 2470 | try self.file.?.pwriteAll(&buf, placeholder_off); |
| 2458 | } | 2471 | } |
| 2459 | } | 2472 | } |
| ... | @@ -2463,11 +2476,16 @@ fn writeExportInfo(self: *Zld) !void { | ... | @@ -2463,11 +2476,16 @@ fn writeExportInfo(self: *Zld) !void { |
| 2463 | defer trie.deinit(); | 2476 | defer trie.deinit(); |
| 2464 | | 2477 | |
| 2465 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2478 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2466 | for (self.exports.items()) |entry| { | 2479 | for (self.symtab.items()) |entry| { |
| | 2480 | switch (entry.value.tag) { |
| | 2481 | .Weak, .Strong => {}, |
| | 2482 | else => continue, |
| | 2483 | } |
| 2467 | const name = entry.key; | 2484 | const name = entry.key; |
| 2468 | const symbol = entry.value; | 2485 | const symbol = entry.value.inner; |
| 2469 | // TODO figure out if we should put all exports into the export trie | 2486 | |
| 2470 | assert(symbol.n_value >= text_segment.inner.vmaddr); | 2487 | assert(symbol.n_value >= text_segment.inner.vmaddr); |
| | 2488 | |
| 2471 | try trie.put(.{ | 2489 | try trie.put(.{ |
| 2472 | .name = name, | 2490 | .name = name, |
| 2473 | .vmaddr_offset = symbol.n_value - text_segment.inner.vmaddr, | 2491 | .vmaddr_offset = symbol.n_value - text_segment.inner.vmaddr, |
| ... | @@ -2488,7 +2506,7 @@ fn writeExportInfo(self: *Zld) !void { | ... | @@ -2488,7 +2506,7 @@ fn writeExportInfo(self: *Zld) !void { |
| 2488 | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); | 2506 | dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64))); |
| 2489 | seg.inner.filesize += dyld_info.export_size; | 2507 | seg.inner.filesize += dyld_info.export_size; |
| 2490 | | 2508 | |
| 2491 | log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size }); | 2509 | log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size }); |
| 2492 | | 2510 | |
| 2493 | try self.file.?.pwriteAll(buffer, dyld_info.export_off); | 2511 | try self.file.?.pwriteAll(buffer, dyld_info.export_off); |
| 2494 | } | 2512 | } |
| ... | @@ -2508,7 +2526,7 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2508,7 +2526,7 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2508 | const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) { | 2526 | const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) { |
| 2509 | error.MissingDebugInfo => { | 2527 | error.MissingDebugInfo => { |
| 2510 | // TODO audit cases with missing debug info and audit our dwarf.zig module. | 2528 | // TODO audit cases with missing debug info and audit our dwarf.zig module. |
| 2511 | log.debug("invalid or missing debug info in {s}; skipping", .{object.name}); | 2529 | log.warn("invalid or missing debug info in {s}; skipping", .{object.name}); |
| 2512 | continue; | 2530 | continue; |
| 2513 | }, | 2531 | }, |
| 2514 | else => |e| return e, | 2532 | else => |e| return e, |
| ... | @@ -2558,7 +2576,7 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2558,7 +2576,7 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2558 | .n_value = mtime, | 2576 | .n_value = mtime, |
| 2559 | }); | 2577 | }); |
| 2560 | } | 2578 | } |
| 2561 | log.debug("analyzing debug info in '{s}'", .{object.name}); | 2579 | log.warn("analyzing debug info in '{s}'", .{object.name}); |
| 2562 | | 2580 | |
| 2563 | for (object.symtab.items) |source_sym| { | 2581 | for (object.symtab.items) |source_sym| { |
| 2564 | const symname = object.getString(source_sym.n_strx); | 2582 | const symname = object.getString(source_sym.n_strx); |
| ... | @@ -2639,7 +2657,7 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2639,7 +2657,7 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2639 | | 2657 | |
| 2640 | const stabs_off = symtab.symoff; | 2658 | const stabs_off = symtab.symoff; |
| 2641 | const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64); | 2659 | const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64); |
| 2642 | log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off }); | 2660 | log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off }); |
| 2643 | try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off); | 2661 | try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off); |
| 2644 | | 2662 | |
| 2645 | linkedit.inner.filesize += stabs_size; | 2663 | linkedit.inner.filesize += stabs_size; |
| ... | @@ -2649,66 +2667,56 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2649,66 +2667,56 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2649 | dysymtab.nlocalsym = symtab.nsyms; | 2667 | dysymtab.nlocalsym = symtab.nsyms; |
| 2650 | } | 2668 | } |
| 2651 | | 2669 | |
| | 2670 | fn populateStringTable(self: *Zld) !void { |
| | 2671 | for (self.symtab.items()) |*entry| { |
| | 2672 | const n_strx = try self.makeString(entry.key); |
| | 2673 | entry.value.inner.n_strx = n_strx; |
| | 2674 | } |
| | 2675 | } |
| | 2676 | |
| 2652 | fn writeSymbolTable(self: *Zld) !void { | 2677 | fn writeSymbolTable(self: *Zld) !void { |
| 2653 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2678 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2654 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 2679 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| 2655 | | 2680 | |
| | 2681 | // TODO figure out how to add locals |
| 2656 | var locals = std.ArrayList(macho.nlist_64).init(self.allocator); | 2682 | var locals = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2657 | defer locals.deinit(); | 2683 | defer locals.deinit(); |
| 2658 | | 2684 | |
| 2659 | for (self.locals.items()) |entries| { | | |
| 2660 | log.debug("'{s}': {} entries", .{ entries.key, entries.value.items.len }); | | |
| 2661 | // var symbol: ?macho.nlist_64 = null; | | |
| 2662 | for (entries.value.items) |entry| { | | |
| 2663 | log.debug(" | {}", .{entry.inner}); | | |
| 2664 | log.debug(" | {}", .{entry.tt}); | | |
| 2665 | log.debug(" | {s}", .{self.objects.items[entry.object_id].name}); | | |
| 2666 | try locals.append(entry.inner); | | |
| 2667 | } | | |
| 2668 | } | | |
| 2669 | const nlocals = locals.items.len; | | |
| 2670 | | | |
| 2671 | const nexports = self.exports.items().len; | | |
| 2672 | var exports = std.ArrayList(macho.nlist_64).init(self.allocator); | 2685 | var exports = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2673 | defer exports.deinit(); | 2686 | defer exports.deinit(); |
| 2674 | | 2687 | |
| 2675 | try exports.ensureCapacity(nexports); | | |
| 2676 | for (self.exports.items()) |entry| { | | |
| 2677 | exports.appendAssumeCapacity(entry.value); | | |
| 2678 | } | | |
| 2679 | | | |
| 2680 | const has_tlv: bool = self.tlv_bootstrap != null; | | |
| 2681 | | | |
| 2682 | var nundefs = self.lazy_imports.items().len + self.nonlazy_imports.items().len; | | |
| 2683 | if (has_tlv) nundefs += 1; | | |
| 2684 | | | |
| 2685 | var undefs = std.ArrayList(macho.nlist_64).init(self.allocator); | 2688 | var undefs = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2686 | defer undefs.deinit(); | 2689 | defer undefs.deinit(); |
| 2687 | | 2690 | |
| 2688 | try undefs.ensureCapacity(nundefs); | 2691 | for (self.symtab.items()) |entry| { |
| 2689 | for (self.lazy_imports.items()) |entry| { | 2692 | switch (entry.value.tag) { |
| 2690 | undefs.appendAssumeCapacity(entry.value.symbol); | 2693 | .Weak, .Strong => { |
| 2691 | } | 2694 | try exports.append(entry.value.inner); |
| 2692 | for (self.nonlazy_imports.items()) |entry| { | 2695 | }, |
| 2693 | undefs.appendAssumeCapacity(entry.value.symbol); | 2696 | .Import => { |
| 2694 | } | 2697 | try undefs.append(entry.value.inner); |
| 2695 | if (has_tlv) { | 2698 | }, |
| 2696 | undefs.appendAssumeCapacity(self.tlv_bootstrap.?.symbol); | 2699 | else => unreachable, |
| | 2700 | } |
| 2697 | } | 2701 | } |
| 2698 | | 2702 | |
| | 2703 | const nlocals = locals.items.len; |
| | 2704 | const nexports = exports.items.len; |
| | 2705 | const nundefs = undefs.items.len; |
| | 2706 | |
| 2699 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); | 2707 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); |
| 2700 | const locals_size = nlocals * @sizeOf(macho.nlist_64); | 2708 | const locals_size = nlocals * @sizeOf(macho.nlist_64); |
| 2701 | log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); | 2709 | log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off }); |
| 2702 | try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); | 2710 | try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off); |
| 2703 | | 2711 | |
| 2704 | const exports_off = locals_off + locals_size; | 2712 | const exports_off = locals_off + locals_size; |
| 2705 | const exports_size = nexports * @sizeOf(macho.nlist_64); | 2713 | const exports_size = nexports * @sizeOf(macho.nlist_64); |
| 2706 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); | 2714 | log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); |
| 2707 | try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); | 2715 | try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); |
| 2708 | | 2716 | |
| 2709 | const undefs_off = exports_off + exports_size; | 2717 | const undefs_off = exports_off + exports_size; |
| 2710 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); | 2718 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); |
| 2711 | log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); | 2719 | log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); |
| 2712 | try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); | 2720 | try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); |
| 2713 | | 2721 | |
| 2714 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); | 2722 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); |
| ... | @@ -2733,44 +2741,45 @@ fn writeDynamicSymbolTable(self: *Zld) !void { | ... | @@ -2733,44 +2741,45 @@ fn writeDynamicSymbolTable(self: *Zld) !void { |
| 2733 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; | 2741 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 2734 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; | 2742 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| 2735 | | 2743 | |
| 2736 | const lazy = self.lazy_imports.items(); | 2744 | const nstubs = @intCast(u32, self.stubs.items().len); |
| 2737 | const nonlazy = self.nonlazy_imports.items(); | 2745 | const ngot_entries = @intCast(u32, self.got_entries.items().len); |
| 2738 | const got_locals = self.nonlazy_pointers.items(); | 2746 | |
| 2739 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | 2747 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 2740 | dysymtab.nindirectsyms = @intCast(u32, lazy.len * 2 + nonlazy.len + got_locals.len); | 2748 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; |
| | 2749 | |
| 2741 | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); | 2750 | const needed_size = dysymtab.nindirectsyms * @sizeOf(u32); |
| 2742 | seg.inner.filesize += needed_size; | 2751 | seg.inner.filesize += needed_size; |
| 2743 | | 2752 | |
| 2744 | log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{ | 2753 | log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{ |
| 2745 | dysymtab.indirectsymoff, | 2754 | dysymtab.indirectsymoff, |
| 2746 | dysymtab.indirectsymoff + needed_size, | 2755 | dysymtab.indirectsymoff + needed_size, |
| 2747 | }); | 2756 | }); |
| 2748 | | 2757 | |
| 2749 | var buf = try self.allocator.alloc(u8, needed_size); | 2758 | var buf = try self.allocator.alloc(u8, needed_size); |
| 2750 | defer self.allocator.free(buf); | 2759 | defer self.allocator.free(buf); |
| | 2760 | |
| 2751 | var stream = std.io.fixedBufferStream(buf); | 2761 | var stream = std.io.fixedBufferStream(buf); |
| 2752 | var writer = stream.writer(); | 2762 | var writer = stream.writer(); |
| 2753 | | 2763 | |
| 2754 | stubs.reserved1 = 0; | 2764 | stubs.reserved1 = 0; |
| 2755 | for (lazy) |_, i| { | 2765 | for (self.stubs.items()) |entry| { |
| 2756 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); | 2766 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value); |
| 2757 | try writer.writeIntLittle(u32, symtab_idx); | 2767 | try writer.writeIntLittle(u32, symtab_idx); |
| 2758 | } | 2768 | } |
| 2759 | | 2769 | |
| 2760 | const base_id = @intCast(u32, lazy.len); | 2770 | got.reserved1 = nstubs; |
| 2761 | got.reserved1 = base_id; | 2771 | for (self.got_entries.items()) |entry| { |
| 2762 | for (nonlazy) |_, i| { | 2772 | if (entry.value.tag == .import) { |
| 2763 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id); | 2773 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value.index + nstubs); |
| 2764 | try writer.writeIntLittle(u32, symtab_idx); | 2774 | try writer.writeIntLittle(u32, symtab_idx); |
| 2765 | } | 2775 | } else { |
| 2766 | // TODO there should be one common set of GOT entries. | 2776 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); |
| 2767 | for (got_locals) |_| { | 2777 | } |
| 2768 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); | | |
| 2769 | } | 2778 | } |
| 2770 | | 2779 | |
| 2771 | la_symbol_ptr.reserved1 = got.reserved1 + @intCast(u32, nonlazy.len) + @intCast(u32, got_locals.len); | 2780 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; |
| 2772 | for (lazy) |_, i| { | 2781 | for (self.stubs.items()) |entry| { |
| 2773 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); | 2782 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + entry.value); |
| 2774 | try writer.writeIntLittle(u32, symtab_idx); | 2783 | try writer.writeIntLittle(u32, symtab_idx); |
| 2775 | } | 2784 | } |
| 2776 | | 2785 | |
| ... | @@ -2784,7 +2793,7 @@ fn writeStringTable(self: *Zld) !void { | ... | @@ -2784,7 +2793,7 @@ fn writeStringTable(self: *Zld) !void { |
| 2784 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); | 2793 | symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64))); |
| 2785 | seg.inner.filesize += symtab.strsize; | 2794 | seg.inner.filesize += symtab.strsize; |
| 2786 | | 2795 | |
| 2787 | log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); | 2796 | log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize }); |
| 2788 | | 2797 | |
| 2789 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); | 2798 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); |
| 2790 | | 2799 | |
| ... | @@ -2830,7 +2839,7 @@ fn writeDataInCode(self: *Zld) !void { | ... | @@ -2830,7 +2839,7 @@ fn writeDataInCode(self: *Zld) !void { |
| 2830 | dice_cmd.datasize = datasize; | 2839 | dice_cmd.datasize = datasize; |
| 2831 | seg.inner.filesize += datasize; | 2840 | seg.inner.filesize += datasize; |
| 2832 | | 2841 | |
| 2833 | log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize }); | 2842 | log.warn("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize }); |
| 2834 | | 2843 | |
| 2835 | try self.file.?.pwriteAll(buf.items, fileoff); | 2844 | try self.file.?.pwriteAll(buf.items, fileoff); |
| 2836 | } | 2845 | } |
| ... | @@ -2851,7 +2860,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void { | ... | @@ -2851,7 +2860,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void { |
| 2851 | seg.inner.filesize += needed_size; | 2860 | seg.inner.filesize += needed_size; |
| 2852 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?); | 2861 | seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?); |
| 2853 | | 2862 | |
| 2854 | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); | 2863 | log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); |
| 2855 | | 2864 | |
| 2856 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file | 2865 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 2857 | // except for code signature data. | 2866 | // except for code signature data. |
| ... | @@ -2877,7 +2886,7 @@ fn writeCodeSignature(self: *Zld) !void { | ... | @@ -2877,7 +2886,7 @@ fn writeCodeSignature(self: *Zld) !void { |
| 2877 | var stream = std.io.fixedBufferStream(buffer); | 2886 | var stream = std.io.fixedBufferStream(buffer); |
| 2878 | try code_sig.write(stream.writer()); | 2887 | try code_sig.write(stream.writer()); |
| 2879 | | 2888 | |
| 2880 | log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len }); | 2889 | log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len }); |
| 2881 | try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff); | 2890 | try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff); |
| 2882 | } | 2891 | } |
| 2883 | | 2892 | |
| ... | @@ -2895,7 +2904,7 @@ fn writeLoadCommands(self: *Zld) !void { | ... | @@ -2895,7 +2904,7 @@ fn writeLoadCommands(self: *Zld) !void { |
| 2895 | } | 2904 | } |
| 2896 | | 2905 | |
| 2897 | const off = @sizeOf(macho.mach_header_64); | 2906 | const off = @sizeOf(macho.mach_header_64); |
| 2898 | log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); | 2907 | log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); |
| 2899 | try self.file.?.pwriteAll(buffer, off); | 2908 | try self.file.?.pwriteAll(buffer, off); |
| 2900 | } | 2909 | } |
| 2901 | | 2910 | |
| ... | @@ -2933,7 +2942,7 @@ fn writeHeader(self: *Zld) !void { | ... | @@ -2933,7 +2942,7 @@ fn writeHeader(self: *Zld) !void { |
| 2933 | for (self.load_commands.items) |cmd| { | 2942 | for (self.load_commands.items) |cmd| { |
| 2934 | header.sizeofcmds += cmd.cmdsize(); | 2943 | header.sizeofcmds += cmd.cmdsize(); |
| 2935 | } | 2944 | } |
| 2936 | log.debug("writing Mach-O header {}", .{header}); | 2945 | log.warn("writing Mach-O header {}", .{header}); |
| 2937 | try self.file.?.pwriteAll(mem.asBytes(&header), 0); | 2946 | try self.file.?.pwriteAll(mem.asBytes(&header), 0); |
| 2938 | } | 2947 | } |
| 2939 | | 2948 | |
| ... | @@ -2947,7 +2956,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 { | ... | @@ -2947,7 +2956,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 2947 | fn makeString(self: *Zld, bytes: []const u8) !u32 { | 2956 | fn makeString(self: *Zld, bytes: []const u8) !u32 { |
| 2948 | try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1); | 2957 | try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1); |
| 2949 | const offset = @intCast(u32, self.strtab.items.len); | 2958 | const offset = @intCast(u32, self.strtab.items.len); |
| 2950 | log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); | 2959 | log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset }); |
| 2951 | self.strtab.appendSliceAssumeCapacity(bytes); | 2960 | self.strtab.appendSliceAssumeCapacity(bytes); |
| 2952 | self.strtab.appendAssumeCapacity(0); | 2961 | self.strtab.appendAssumeCapacity(0); |
| 2953 | return offset; | 2962 | return offset; |
| ... | @@ -2963,11 +2972,6 @@ pub fn parseName(name: *const [16]u8) []const u8 { | ... | @@ -2963,11 +2972,6 @@ pub fn parseName(name: *const [16]u8) []const u8 { |
| 2963 | return name[0..len]; | 2972 | return name[0..len]; |
| 2964 | } | 2973 | } |
| 2965 | | 2974 | |
| 2966 | fn aarch64IsArithmetic(inst: *const [4]u8) callconv(.Inline) bool { | | |
| 2967 | const group_decode = @truncate(u5, inst[3]); | | |
| 2968 | return ((group_decode >> 2) == 4); | | |
| 2969 | } | | |
| 2970 | | | |
| 2971 | fn printDebug(self: Zld) void { | 2975 | fn printDebug(self: Zld) void { |
| 2972 | log.warn("symtab", .{}); | 2976 | log.warn("symtab", .{}); |
| 2973 | for (self.symtab.items()) |entry| { | 2977 | for (self.symtab.items()) |entry| { |