authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-17 17:30:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-17 17:30:16+02:00
log97914d93a9733307309d5660ee5ce044f56a98cc
tree99799b029f0ad3959832609d62d7c59bb4465094
parentd81783375c2555b2e2cb6a028ea648179031bc93

zld: fixup flush function


2 files changed, 134 insertions(+), 157 deletions(-)

src/link/MachO/TextBlock.zig+26-17
...@@ -1,11 +1,14 @@...@@ -1,11 +1,14 @@
1const TextBlock = @This();1const TextBlock = @This();
22
3const std = @import("std");3const std = @import("std");
4const aarch64 = @import("../../codegen/aarch64.zig");
4const assert = std.debug.assert;5const assert = std.debug.assert;
5const commands = @import("commands.zig");6const commands = @import("commands.zig");
6const log = std.log.scoped(.text_block);7const log = std.log.scoped(.text_block);
7const macho = std.macho;8const macho = std.macho;
9const math = std.math;
8const mem = std.mem;10const mem = std.mem;
11const meta = std.meta;
912
10const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
11const Arch = std.Target.Cpu.Arch;14const Arch = std.Target.Cpu.Arch;
...@@ -44,25 +47,22 @@ pub const Stab = union(enum) {...@@ -44,25 +47,22 @@ pub const Stab = union(enum) {
44 defer nlists.deinit();47 defer nlists.deinit();
4548
46 const sym = zld.locals.items[local_sym_index];49 const sym = zld.locals.items[local_sym_index];
47 const reg = sym.payload.regular;
48
49 switch (stab) {50 switch (stab) {
50 .function => |size| {51 .function => |size| {
51 try nlists.ensureUnusedCapacity(4);52 try nlists.ensureUnusedCapacity(4);
52 const section_id = reg.sectionId(zld);
53 nlists.appendAssumeCapacity(.{53 nlists.appendAssumeCapacity(.{
54 .n_strx = 0,54 .n_strx = 0,
55 .n_type = macho.N_BNSYM,55 .n_type = macho.N_BNSYM,
56 .n_sect = section_id,56 .n_sect = sym.n_sect,
57 .n_desc = 0,57 .n_desc = 0,
58 .n_value = reg.address,58 .n_value = sym.n_value,
59 });59 });
60 nlists.appendAssumeCapacity(.{60 nlists.appendAssumeCapacity(.{
61 .n_strx = sym.strx,61 .n_strx = sym.n_strx,
62 .n_type = macho.N_FUN,62 .n_type = macho.N_FUN,
63 .n_sect = section_id,63 .n_sect = sym.n_sect,
64 .n_desc = 0,64 .n_desc = 0,
65 .n_value = reg.address,65 .n_value = sym.n_value,
66 });66 });
67 nlists.appendAssumeCapacity(.{67 nlists.appendAssumeCapacity(.{
68 .n_strx = 0,68 .n_strx = 0,
...@@ -74,14 +74,14 @@ pub const Stab = union(enum) {...@@ -74,14 +74,14 @@ pub const Stab = union(enum) {
74 nlists.appendAssumeCapacity(.{74 nlists.appendAssumeCapacity(.{
75 .n_strx = 0,75 .n_strx = 0,
76 .n_type = macho.N_ENSYM,76 .n_type = macho.N_ENSYM,
77 .n_sect = section_id,77 .n_sect = sym.n_sect,
78 .n_desc = 0,78 .n_desc = 0,
79 .n_value = size,79 .n_value = size,
80 });80 });
81 },81 },
82 .global => {82 .global => {
83 try nlists.append(.{83 try nlists.append(.{
84 .n_strx = sym.strx,84 .n_strx = sym.n_strx,
85 .n_type = macho.N_GSYM,85 .n_type = macho.N_GSYM,
86 .n_sect = 0,86 .n_sect = 0,
87 .n_desc = 0,87 .n_desc = 0,
...@@ -90,11 +90,11 @@ pub const Stab = union(enum) {...@@ -90,11 +90,11 @@ pub const Stab = union(enum) {
90 },90 },
91 .static => {91 .static => {
92 try nlists.append(.{92 try nlists.append(.{
93 .n_strx = sym.strx,93 .n_strx = sym.n_strx,
94 .n_type = macho.N_STSYM,94 .n_type = macho.N_STSYM,
95 .n_sect = reg.sectionId(zld),95 .n_sect = sym.n_sect,
96 .n_desc = 0,96 .n_desc = 0,
97 .n_value = reg.address,97 .n_value = sym.n_value,
98 });98 });
99 },99 },
100 }100 }
...@@ -1006,7 +1006,10 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {...@@ -1006,7 +1006,10 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
1006 const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment;1006 const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment;
1007 const got = dc_seg.sections.items[zld.got_section_index.?];1007 const got = dc_seg.sections.items[zld.got_section_index.?];
1008 const got_index = zld.got_entries.getIndex(.{1008 const got_index = zld.got_entries.getIndex(.{
1009 .where = rel.where,1009 .where = switch (rel.where) {
1010 .local => .local,
1011 .import => .import,
1012 },
1010 .where_index = rel.where_index,1013 .where_index = rel.where_index,
1011 }) orelse {1014 }) orelse {
1012 const sym = switch (rel.where) {1015 const sym = switch (rel.where) {
...@@ -1024,8 +1027,8 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {...@@ -1024,8 +1027,8 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
1024 .local => {1027 .local => {
1025 const sym = zld.locals.items[rel.where_index];1028 const sym = zld.locals.items[rel.where_index];
1026 const is_tlv = is_tlv: {1029 const is_tlv = is_tlv: {
1027 const sym = zld.locals.items[self.local_sym_index];1030 const source_sym = zld.locals.items[self.local_sym_index];
1028 const match = zld.unpackSectionId(sym.n_sect);1031 const match = zld.unpackSectionId(source_sym.n_sect);
1029 const seg = zld.load_commands.items[match.seg].Segment;1032 const seg = zld.load_commands.items[match.seg].Segment;
1030 const sect = seg.sections.items[match.sect];1033 const sect = seg.sections.items[match.sect];
1031 break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES;1034 break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES;
...@@ -1073,7 +1076,13 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {...@@ -1073,7 +1076,13 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
1073 log.warn(" | source_addr = 0x{x}", .{source_addr});1076 log.warn(" | source_addr = 0x{x}", .{source_addr});
1074 log.warn(" | target_addr = 0x{x}", .{target_addr});1077 log.warn(" | target_addr = 0x{x}", .{target_addr});
10751078
1076 try rel.resolve(self, source_addr, target_addr);1079 try rel.resolve(.{
1080 .block = self,
1081 .offset = rel.offset,
1082 .source_addr = source_addr,
1083 .target_addr = target_addr,
1084 .zld = zld,
1085 });
1077 }1086 }
1078}1087}
10791088
src/link/MachO/Zld.zig+108-140
...@@ -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 }
298308
299 return error.TODO;309 try self.flush();
300
301 // try self.flush();
302}310}
303311
304fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {312fn 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 {
10971105
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 };
12531269
1254 for (self.stubs.items) |sym| {1270 for (self.stubs.keys()) |key| {
1255 // TODO weak bound pointers1271 // 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}
12621277
...@@ -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.?];
22202235
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);
22232238
2224 var stream = std.io.fixedBufferStream(buffer);2239 var stream = std.io.fixedBufferStream(buffer);
2225 var writer = stream.writer();2240 var writer = stream.writer();
22262241
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 custom2258 // 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}
22512271
...@@ -2265,8 +2285,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2265,8 +2285,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22652285
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;
22702289
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.?);
22902309
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;
22932312
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.?);
23062325
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.?);
23452364
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;
23482367
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 {
23682387
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;
23732391
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 }
23852401
...@@ -2390,21 +2406,21 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2390,21 +2406,21 @@ fn writeBindInfoTable(self: *Zld) !void {
2390 }2406 }
2391 }2407 }
23922408
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.?);
23982414
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 // }
24082424
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.?);
24362452
2437 try pointers.ensureCapacity(self.stubs.items.len);2453 try pointers.ensureCapacity(self.stubs.count());
24382454
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);
25142530
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", .{});
25432558
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 });
25672562
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 {
25982593
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();
26012596 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 }
26182597
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 }
26732652
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;
26892656
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);
26992666
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);
27042671
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.?];
27222689
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());
27252692
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();
27422709
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 }
27492714
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 }
27632726
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 }
27702731
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);
28182778
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}
30543014
3015fn packDylibOrdinal(ordinal: u16) u16 {
3016 return ordinal * macho.N_SYMBOL_RESOLVER;
3017}
3018
3019fn unpackDylibOrdinal(pack: u16) u16 {
3020 return @divExact(pack, macho.N_SYMBOL_RESOLVER);
3021}
3022
3055pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anytype) usize {3023pub 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");