| ... | ... | @@ -233,6 +233,16 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 233 | 233 | try self.parseLibs(args.libs, args.syslibroot); |
| 234 | 234 | try self.resolveSymbols(); |
| 235 | 235 | try self.parseTextBlocks(); |
| 236 | |
| 237 | { |
| 238 | // Add dyld_stub_binder as the final GOT entry. |
| 239 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; |
| 240 | try self.got_entries.putNoClobber(self.allocator, .{ |
| 241 | .where = .import, |
| 242 | .where_index = resolv.where_index, |
| 243 | }, {}); |
| 244 | } |
| 245 | |
| 236 | 246 | try self.sortSections(); |
| 237 | 247 | try self.addRpaths(args.rpaths); |
| 238 | 248 | try self.addDataInCodeLC(); |
| ... | ... | @@ -296,9 +306,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 296 | 306 | entry.value_ptr.*.print(self); |
| 297 | 307 | } |
| 298 | 308 | |
| 299 | | return error.TODO; |
| 300 | | |
| 301 | | // try self.flush(); |
| 309 | try self.flush(); |
| 302 | 310 | } |
| 303 | 311 | |
| 304 | 312 | fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void { |
| ... | ... | @@ -1097,7 +1105,7 @@ fn writeTextBlocks(self: *Zld) !void { |
| 1097 | 1105 | |
| 1098 | 1106 | const sym = self.locals.items[block.local_sym_index]; |
| 1099 | 1107 | log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{ |
| 1100 | | self.getString(sym.strx), |
| 1108 | self.getString(sym.n_strx), |
| 1101 | 1109 | aligned_base_off, |
| 1102 | 1110 | aligned_base_off + block.size, |
| 1103 | 1111 | block.size, |
| ... | ... | @@ -1154,8 +1162,12 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1154 | 1162 | code[9] = 0xff; |
| 1155 | 1163 | code[10] = 0x25; |
| 1156 | 1164 | { |
| 1157 | | const dyld_stub_binder = self.globals.get("dyld_stub_binder").?; |
| 1158 | | const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64)); |
| 1165 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; |
| 1166 | const got_index = self.got_entries.getIndex(.{ |
| 1167 | .where = .import, |
| 1168 | .where_index = resolv.where_index, |
| 1169 | }) orelse unreachable; |
| 1170 | const addr = got.addr + got_index * @sizeOf(u64); |
| 1159 | 1171 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); |
| 1160 | 1172 | mem.writeIntLittle(u32, code[11..], displacement); |
| 1161 | 1173 | } |
| ... | ... | @@ -1198,9 +1210,13 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1198 | 1210 | code[10] = 0xbf; |
| 1199 | 1211 | code[11] = 0xa9; |
| 1200 | 1212 | binder_blk_outer: { |
| 1201 | | const dyld_stub_binder = self.globals.get("dyld_stub_binder").?; |
| 1213 | const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable; |
| 1214 | const got_index = self.got_entries.getIndex(.{ |
| 1215 | .where = .import, |
| 1216 | .where_index = resolv.where_index, |
| 1217 | }) orelse unreachable; |
| 1202 | 1218 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| 1203 | | const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64)); |
| 1219 | const target_addr = got.addr + got_index * @sizeOf(u64); |
| 1204 | 1220 | binder_blk: { |
| 1205 | 1221 | const displacement = math.divExact(u64, target_addr - this_addr, 4) catch break :binder_blk; |
| 1206 | 1222 | const literal = math.cast(u18, displacement) catch break :binder_blk; |
| ... | ... | @@ -1251,12 +1267,11 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1251 | 1267 | } |
| 1252 | 1268 | }; |
| 1253 | 1269 | |
| 1254 | | for (self.stubs.items) |sym| { |
| 1270 | for (self.stubs.keys()) |key| { |
| 1255 | 1271 | // TODO weak bound pointers |
| 1256 | | const index = sym.stubs_index orelse unreachable; |
| 1257 | | try self.writeLazySymbolPointer(index); |
| 1258 | | try self.writeStub(index); |
| 1259 | | try self.writeStubInStubHelper(index); |
| 1272 | try self.writeLazySymbolPointer(key); |
| 1273 | try self.writeStub(key); |
| 1274 | try self.writeStubInStubHelper(key); |
| 1260 | 1275 | } |
| 1261 | 1276 | } |
| 1262 | 1277 | |
| ... | ... | @@ -1764,7 +1779,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1764 | 1779 | .n_strx = undef.n_strx, |
| 1765 | 1780 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 1766 | 1781 | .n_sect = 0, |
| 1767 | | .n_desc = (dylib.ordinal.? * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, |
| 1782 | .n_desc = packDylibOrdinal(dylib.ordinal.?), |
| 1768 | 1783 | .n_value = 0, |
| 1769 | 1784 | }); |
| 1770 | 1785 | resolv.* = .{ |
| ... | ... | @@ -2218,16 +2233,16 @@ fn writeGotEntries(self: *Zld) !void { |
| 2218 | 2233 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2219 | 2234 | const sect = seg.sections.items[self.got_section_index.?]; |
| 2220 | 2235 | |
| 2221 | | var buffer = try self.allocator.alloc(u8, self.got_entries.items.len * @sizeOf(u64)); |
| 2236 | var buffer = try self.allocator.alloc(u8, self.got_entries.count() * @sizeOf(u64)); |
| 2222 | 2237 | defer self.allocator.free(buffer); |
| 2223 | 2238 | |
| 2224 | 2239 | var stream = std.io.fixedBufferStream(buffer); |
| 2225 | 2240 | var writer = stream.writer(); |
| 2226 | 2241 | |
| 2227 | | for (self.got_entries.items) |sym| { |
| 2228 | | const address: u64 = switch (sym.payload) { |
| 2229 | | .regular => |reg| reg.address, |
| 2230 | | else => 0, |
| 2242 | for (self.got_entries.keys()) |key| { |
| 2243 | const address: u64 = switch (key.where) { |
| 2244 | .local => self.locals.items[key.where_index].n_value, |
| 2245 | .import => 0, |
| 2231 | 2246 | }; |
| 2232 | 2247 | try writer.writeIntLittle(u64, address); |
| 2233 | 2248 | } |
| ... | ... | @@ -2243,9 +2258,14 @@ fn setEntryPoint(self: *Zld) !void { |
| 2243 | 2258 | // TODO we should respect the -entry flag passed in by the user to set a custom |
| 2244 | 2259 | // entrypoint. For now, assume default of `_main`. |
| 2245 | 2260 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2246 | | const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint; |
| 2261 | const resolv = self.symbol_resolver.get("_main") orelse { |
| 2262 | log.err("'_main' export not found", .{}); |
| 2263 | return error.MissingMainEntrypoint; |
| 2264 | }; |
| 2265 | assert(resolv.where == .global); |
| 2266 | const sym = self.globals.items[resolv.where_index]; |
| 2247 | 2267 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; |
| 2248 | | ec.entryoff = @intCast(u32, sym.payload.regular.address - seg.inner.vmaddr); |
| 2268 | ec.entryoff = @intCast(u32, sym.n_value - seg.inner.vmaddr); |
| 2249 | 2269 | ec.stacksize = self.stack_size; |
| 2250 | 2270 | } |
| 2251 | 2271 | |
| ... | ... | @@ -2265,8 +2285,7 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2265 | 2285 | |
| 2266 | 2286 | while (true) { |
| 2267 | 2287 | const sym = self.locals.items[block.local_sym_index]; |
| 2268 | | assert(sym.payload == .regular); |
| 2269 | | const base_offset = sym.payload.regular.address - seg.inner.vmaddr; |
| 2288 | const base_offset = sym.n_value - seg.inner.vmaddr; |
| 2270 | 2289 | |
| 2271 | 2290 | for (block.rebases.items) |offset| { |
| 2272 | 2291 | try pointers.append(.{ |
| ... | ... | @@ -2288,11 +2307,11 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2288 | 2307 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2289 | 2308 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2290 | 2309 | |
| 2291 | | for (self.got_entries.items) |sym| { |
| 2292 | | if (sym.payload == .proxy) continue; |
| 2310 | for (self.got_entries.keys()) |key, i| { |
| 2311 | if (key.where == .import) continue; |
| 2293 | 2312 | |
| 2294 | 2313 | try pointers.append(.{ |
| 2295 | | .offset = base_offset + sym.got_index.? * @sizeOf(u64), |
| 2314 | .offset = base_offset + i * @sizeOf(u64), |
| 2296 | 2315 | .segment_id = segment_id, |
| 2297 | 2316 | }); |
| 2298 | 2317 | } |
| ... | ... | @@ -2304,10 +2323,10 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2304 | 2323 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2305 | 2324 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2306 | 2325 | |
| 2307 | | try pointers.ensureCapacity(pointers.items.len + self.stubs.items.len); |
| 2308 | | for (self.stubs.items) |sym| { |
| 2326 | try pointers.ensureCapacity(pointers.items.len + self.stubs.count()); |
| 2327 | for (self.stubs.keys()) |_, i| { |
| 2309 | 2328 | pointers.appendAssumeCapacity(.{ |
| 2310 | | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2329 | .offset = base_offset + i * @sizeOf(u64), |
| 2311 | 2330 | .segment_id = segment_id, |
| 2312 | 2331 | }); |
| 2313 | 2332 | } |
| ... | ... | @@ -2343,15 +2362,15 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2343 | 2362 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2344 | 2363 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2345 | 2364 | |
| 2346 | | for (self.got_entries.items) |sym| { |
| 2347 | | if (sym.payload != .proxy) continue; |
| 2365 | for (self.got_entries.keys()) |key, i| { |
| 2366 | if (key.where == .local) continue; |
| 2348 | 2367 | |
| 2349 | | const proxy = sym.payload.proxy; |
| 2368 | const sym = self.imports.items[key.where_index]; |
| 2350 | 2369 | try pointers.append(.{ |
| 2351 | | .offset = base_offset + sym.got_index.? * @sizeOf(u64), |
| 2370 | .offset = base_offset + i * @sizeOf(u64), |
| 2352 | 2371 | .segment_id = segment_id, |
| 2353 | | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2354 | | .name = self.getString(sym.strx), |
| 2372 | .dylib_ordinal = unpackDylibOrdinal(sym.n_desc), |
| 2373 | .name = self.getString(sym.n_strx), |
| 2355 | 2374 | }); |
| 2356 | 2375 | } |
| 2357 | 2376 | } |
| ... | ... | @@ -2368,18 +2387,15 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2368 | 2387 | |
| 2369 | 2388 | while (true) { |
| 2370 | 2389 | const sym = self.locals.items[block.local_sym_index]; |
| 2371 | | assert(sym.payload == .regular); |
| 2372 | | const base_offset = sym.payload.regular.address - seg.inner.vmaddr; |
| 2390 | const base_offset = sym.n_value - seg.inner.vmaddr; |
| 2373 | 2391 | |
| 2374 | 2392 | for (block.bindings.items) |binding| { |
| 2375 | 2393 | const bind_sym = self.imports.items[binding.local_sym_index]; |
| 2376 | | const proxy = bind_sym.payload.proxy; |
| 2377 | | |
| 2378 | 2394 | try pointers.append(.{ |
| 2379 | 2395 | .offset = binding.offset + base_offset, |
| 2380 | 2396 | .segment_id = match.seg, |
| 2381 | | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2382 | | .name = self.getString(bind_sym.strx), |
| 2397 | .dylib_ordinal = unpackDylibOrdinal(bind_sym.n_desc), |
| 2398 | .name = self.getString(bind_sym.n_strx), |
| 2383 | 2399 | }); |
| 2384 | 2400 | } |
| 2385 | 2401 | |
| ... | ... | @@ -2390,21 +2406,21 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2390 | 2406 | } |
| 2391 | 2407 | } |
| 2392 | 2408 | |
| 2393 | | if (self.tlv_section_index) |idx| { |
| 2394 | | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2395 | | const sect = seg.sections.items[idx]; |
| 2396 | | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2397 | | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2409 | // if (self.tlv_section_index) |idx| { |
| 2410 | // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2411 | // const sect = seg.sections.items[idx]; |
| 2412 | // const base_offset = sect.addr - seg.inner.vmaddr; |
| 2413 | // const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2398 | 2414 | |
| 2399 | | const sym = self.globals.get("__tlv_bootstrap") orelse unreachable; |
| 2400 | | const proxy = sym.payload.proxy; |
| 2401 | | try pointers.append(.{ |
| 2402 | | .offset = base_offset, |
| 2403 | | .segment_id = segment_id, |
| 2404 | | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2405 | | .name = self.getString(sym.strx), |
| 2406 | | }); |
| 2407 | | } |
| 2415 | // const sym = self.globals.get("__tlv_bootstrap") orelse unreachable; |
| 2416 | // const proxy = sym.payload.proxy; |
| 2417 | // try pointers.append(.{ |
| 2418 | // .offset = base_offset, |
| 2419 | // .segment_id = segment_id, |
| 2420 | // .dylib_ordinal = proxy.dylibOrdinal(), |
| 2421 | // .name = self.getString(sym.strx), |
| 2422 | // }); |
| 2423 | // } |
| 2408 | 2424 | |
| 2409 | 2425 | const size = try bindInfoSize(pointers.items); |
| 2410 | 2426 | var buffer = try self.allocator.alloc(u8, @intCast(usize, size)); |
| ... | ... | @@ -2434,15 +2450,15 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2434 | 2450 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2435 | 2451 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2436 | 2452 | |
| 2437 | | try pointers.ensureCapacity(self.stubs.items.len); |
| 2453 | try pointers.ensureCapacity(self.stubs.count()); |
| 2438 | 2454 | |
| 2439 | | for (self.stubs.items) |sym| { |
| 2440 | | const proxy = sym.payload.proxy; |
| 2455 | for (self.stubs.keys()) |key, i| { |
| 2456 | const sym = self.imports.items[key]; |
| 2441 | 2457 | pointers.appendAssumeCapacity(.{ |
| 2442 | | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2458 | .offset = base_offset + i * @sizeOf(u64), |
| 2443 | 2459 | .segment_id = segment_id, |
| 2444 | | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2445 | | .name = self.getString(sym.strx), |
| 2460 | .dylib_ordinal = unpackDylibOrdinal(sym.n_desc), |
| 2461 | .name = self.getString(sym.n_strx), |
| 2446 | 2462 | }); |
| 2447 | 2463 | } |
| 2448 | 2464 | } |
| ... | ... | @@ -2510,7 +2526,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2510 | 2526 | else => {}, |
| 2511 | 2527 | } |
| 2512 | 2528 | } |
| 2513 | | assert(self.stubs.items.len <= offsets.items.len); |
| 2529 | assert(self.stubs.count() <= offsets.items.len); |
| 2514 | 2530 | |
| 2515 | 2531 | const stub_size: u4 = switch (self.target.?.cpu.arch) { |
| 2516 | 2532 | .x86_64 => 10, |
| ... | ... | @@ -2523,8 +2539,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2523 | 2539 | else => unreachable, |
| 2524 | 2540 | }; |
| 2525 | 2541 | var buf: [@sizeOf(u32)]u8 = undefined; |
| 2526 | | for (self.stubs.items) |sym| { |
| 2527 | | const index = sym.stubs_index orelse unreachable; |
| 2542 | for (self.stubs.keys()) |_, index| { |
| 2528 | 2543 | const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off; |
| 2529 | 2544 | mem.writeIntLittle(u32, &buf, offsets.items[index]); |
| 2530 | 2545 | try self.file.?.pwriteAll(&buf, placeholder_off); |
| ... | ... | @@ -2541,33 +2556,13 @@ fn writeExportInfo(self: *Zld) !void { |
| 2541 | 2556 | // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER. |
| 2542 | 2557 | log.debug("writing export trie", .{}); |
| 2543 | 2558 | |
| 2544 | | const Sorter = struct { |
| 2545 | | fn lessThan(_: void, a: []const u8, b: []const u8) bool { |
| 2546 | | return mem.lessThan(u8, a, b); |
| 2547 | | } |
| 2548 | | }; |
| 2549 | | |
| 2550 | | var sorted_globals = std.ArrayList([]const u8).init(self.allocator); |
| 2551 | | defer sorted_globals.deinit(); |
| 2552 | | |
| 2553 | | for (self.globals.values()) |sym| { |
| 2554 | | if (sym.payload != .regular) continue; |
| 2555 | | const reg = sym.payload.regular; |
| 2556 | | if (reg.linkage != .global) continue; |
| 2557 | | try sorted_globals.append(self.getString(sym.strx)); |
| 2558 | | } |
| 2559 | | |
| 2560 | | std.sort.sort([]const u8, sorted_globals.items, {}, Sorter.lessThan); |
| 2561 | | |
| 2562 | | for (sorted_globals.items) |sym_name| { |
| 2563 | | const sym = self.globals.get(sym_name) orelse unreachable; |
| 2564 | | const reg = sym.payload.regular; |
| 2565 | | |
| 2566 | | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, reg.address }); |
| 2559 | for (self.globals.items) |sym| { |
| 2560 | const sym_name = self.getString(sym.n_strx); |
| 2561 | log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value }); |
| 2567 | 2562 | |
| 2568 | 2563 | try trie.put(.{ |
| 2569 | 2564 | .name = sym_name, |
| 2570 | | .vmaddr_offset = reg.address - base_address, |
| 2565 | .vmaddr_offset = sym.n_value - base_address, |
| 2571 | 2566 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 2572 | 2567 | }); |
| 2573 | 2568 | } |
| ... | ... | @@ -2598,23 +2593,7 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2598 | 2593 | |
| 2599 | 2594 | var locals = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2600 | 2595 | defer locals.deinit(); |
| 2601 | | |
| 2602 | | var exports = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2603 | | defer exports.deinit(); |
| 2604 | | |
| 2605 | | for (self.locals.items) |symbol, i| { |
| 2606 | | if (i == 0) continue; // skip null symbol |
| 2607 | | if (symbol.isTemp(self)) continue; // TODO when merging codepaths, this should go into freelist |
| 2608 | | |
| 2609 | | const reg = symbol.payload.regular; |
| 2610 | | const nlist = try symbol.asNlist(self); |
| 2611 | | |
| 2612 | | if (reg.linkage == .translation_unit) { |
| 2613 | | try locals.append(nlist); |
| 2614 | | } else { |
| 2615 | | try exports.append(nlist); |
| 2616 | | } |
| 2617 | | } |
| 2596 | try locals.appendSlice(self.locals.items); |
| 2618 | 2597 | |
| 2619 | 2598 | if (self.has_stabs) { |
| 2620 | 2599 | for (self.objects.items) |object| { |
| ... | ... | @@ -2671,21 +2650,9 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2671 | 2650 | } |
| 2672 | 2651 | } |
| 2673 | 2652 | |
| 2674 | | var undefs = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2675 | | defer undefs.deinit(); |
| 2676 | | var undef_dir = std.StringHashMap(u32).init(self.allocator); |
| 2677 | | defer undef_dir.deinit(); |
| 2678 | | |
| 2679 | | for (self.imports.items) |sym| { |
| 2680 | | const nlist = try sym.asNlist(self); |
| 2681 | | const id = @intCast(u32, undefs.items.len); |
| 2682 | | try undefs.append(nlist); |
| 2683 | | try undef_dir.putNoClobber(self.getString(sym.strx), id); |
| 2684 | | } |
| 2685 | | |
| 2686 | 2653 | const nlocals = locals.items.len; |
| 2687 | | const nexports = exports.items.len; |
| 2688 | | const nundefs = undefs.items.len; |
| 2654 | const nexports = self.globals.items.len; |
| 2655 | const nundefs = self.imports.items.len; |
| 2689 | 2656 | |
| 2690 | 2657 | const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64); |
| 2691 | 2658 | const locals_size = nlocals * @sizeOf(macho.nlist_64); |
| ... | ... | @@ -2695,12 +2662,12 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2695 | 2662 | const exports_off = locals_off + locals_size; |
| 2696 | 2663 | const exports_size = nexports * @sizeOf(macho.nlist_64); |
| 2697 | 2664 | log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off }); |
| 2698 | | try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off); |
| 2665 | try self.file.?.pwriteAll(mem.sliceAsBytes(self.globals.items), exports_off); |
| 2699 | 2666 | |
| 2700 | 2667 | const undefs_off = exports_off + exports_size; |
| 2701 | 2668 | const undefs_size = nundefs * @sizeOf(macho.nlist_64); |
| 2702 | 2669 | log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off }); |
| 2703 | | try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off); |
| 2670 | try self.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off); |
| 2704 | 2671 | |
| 2705 | 2672 | symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs); |
| 2706 | 2673 | seg.inner.filesize += locals_size + exports_size + undefs_size; |
| ... | ... | @@ -2720,8 +2687,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2720 | 2687 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2721 | 2688 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 2722 | 2689 | |
| 2723 | | const nstubs = @intCast(u32, self.stubs.items.len); |
| 2724 | | const ngot_entries = @intCast(u32, self.got_entries.items.len); |
| 2690 | const nstubs = @intCast(u32, self.stubs.count()); |
| 2691 | const ngot_entries = @intCast(u32, self.got_entries.count()); |
| 2725 | 2692 | |
| 2726 | 2693 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 2727 | 2694 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; |
| ... | ... | @@ -2741,31 +2708,25 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2741 | 2708 | var writer = stream.writer(); |
| 2742 | 2709 | |
| 2743 | 2710 | stubs.reserved1 = 0; |
| 2744 | | for (self.stubs.items) |sym| { |
| 2745 | | const sym_name = self.getString(sym.strx); |
| 2746 | | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2747 | | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2711 | for (self.stubs.keys()) |key| { |
| 2712 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key); |
| 2748 | 2713 | } |
| 2749 | 2714 | |
| 2750 | 2715 | got.reserved1 = nstubs; |
| 2751 | | for (self.got_entries.items) |sym| { |
| 2752 | | switch (sym.payload) { |
| 2753 | | .proxy => { |
| 2754 | | const sym_name = self.getString(sym.strx); |
| 2755 | | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2756 | | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2716 | for (self.got_entries.keys()) |key| { |
| 2717 | switch (key.where) { |
| 2718 | .import => { |
| 2719 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key.where_index); |
| 2757 | 2720 | }, |
| 2758 | | else => { |
| 2721 | .local => { |
| 2759 | 2722 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); |
| 2760 | 2723 | }, |
| 2761 | 2724 | } |
| 2762 | 2725 | } |
| 2763 | 2726 | |
| 2764 | 2727 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; |
| 2765 | | for (self.stubs.items) |sym| { |
| 2766 | | const sym_name = self.getString(sym.strx); |
| 2767 | | const id = undef_dir.get(sym_name) orelse unreachable; |
| 2768 | | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); |
| 2728 | for (self.stubs.keys()) |key| { |
| 2729 | try writer.writeIntLittle(u32, dysymtab.iundefsym + key); |
| 2769 | 2730 | } |
| 2770 | 2731 | |
| 2771 | 2732 | try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff); |
| ... | ... | @@ -2813,8 +2774,7 @@ fn writeDices(self: *Zld) !void { |
| 2813 | 2774 | while (true) { |
| 2814 | 2775 | if (block.dices.items.len > 0) { |
| 2815 | 2776 | const sym = self.locals.items[block.local_sym_index]; |
| 2816 | | const reg = sym.payload.regular; |
| 2817 | | const base_off = try math.cast(u32, reg.address - text_sect.addr + text_sect.offset); |
| 2777 | const base_off = try math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset); |
| 2818 | 2778 | |
| 2819 | 2779 | try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry)); |
| 2820 | 2780 | for (block.dices.items) |dice| { |
| ... | ... | @@ -3052,6 +3012,14 @@ pub fn unpackSectionId(self: Zld, section_id: u8) MatchingSection { |
| 3052 | 3012 | return match; |
| 3053 | 3013 | } |
| 3054 | 3014 | |
| 3015 | fn packDylibOrdinal(ordinal: u16) u16 { |
| 3016 | return ordinal * macho.N_SYMBOL_RESOLVER; |
| 3017 | } |
| 3018 | |
| 3019 | fn unpackDylibOrdinal(pack: u16) u16 { |
| 3020 | return @divExact(pack, macho.N_SYMBOL_RESOLVER); |
| 3021 | } |
| 3022 | |
| 3055 | 3023 | pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anytype) usize { |
| 3056 | 3024 | if (!@hasDecl(@TypeOf(predicate), "predicate")) |
| 3057 | 3025 | @compileError("Predicate is required to define fn predicate(@This(), T) bool"); |