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