authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-08 19:22:46+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log0cc4938419c52681d7f7d5a48054e3f8aa827840
tree1e4ad2106aa974b73f1097d0d2bc29431ae50435
parent12187586d15b6eae0330a652a6b1532d2b457991

zld: re-enable all of linker after complete rewrite


2 files changed, 144 insertions(+), 125 deletions(-)

src/link/MachO/Symbol.zig+2-2
...@@ -225,7 +225,7 @@ pub fn needsTlvOffset(self: Symbol, zld: *Zld) bool {...@@ -225,7 +225,7 @@ pub fn needsTlvOffset(self: Symbol, zld: *Zld) bool {
225 return sect_type == macho.S_THREAD_LOCAL_VARIABLES;225 return sect_type == macho.S_THREAD_LOCAL_VARIABLES;
226}226}
227227
228pub fn asNlist(symbol: *Symbol, strtab: *StringTable) !macho.nlist_64 {228pub fn asNlist(symbol: *Symbol, zld: *Zld, strtab: *StringTable) !macho.nlist_64 {
229 const n_strx = try strtab.getOrPut(symbol.name);229 const n_strx = try strtab.getOrPut(symbol.name);
230 const nlist = nlist: {230 const nlist = nlist: {
231 switch (symbol.payload) {231 switch (symbol.payload) {
...@@ -233,7 +233,7 @@ pub fn asNlist(symbol: *Symbol, strtab: *StringTable) !macho.nlist_64 {...@@ -233,7 +233,7 @@ pub fn asNlist(symbol: *Symbol, strtab: *StringTable) !macho.nlist_64 {
233 var nlist = macho.nlist_64{233 var nlist = macho.nlist_64{
234 .n_strx = n_strx,234 .n_strx = n_strx,
235 .n_type = macho.N_SECT,235 .n_type = macho.N_SECT,
236 .n_sect = regular.section,236 .n_sect = regular.sectionId(zld),
237 .n_desc = 0,237 .n_desc = 0,
238 .n_value = regular.address,238 .n_value = regular.address,
239 };239 };
src/link/MachO/Zld.zig+142-123
...@@ -337,6 +337,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -337,6 +337,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
337 log.warn(" {}", .{sect});337 log.warn(" {}", .{sect});
338 entry.value_ptr.*.print(self);338 entry.value_ptr.*.print(self);
339 }339 }
340
340 try self.flush();341 try self.flush();
341}342}
342343
...@@ -1109,23 +1110,31 @@ fn writeTextBlocks(self: *Zld) !void {...@@ -1109,23 +1110,31 @@ fn writeTextBlocks(self: *Zld) !void {
11091110
1110 const seg = self.load_commands.items[match.seg].Segment;1111 const seg = self.load_commands.items[match.seg].Segment;
1111 const sect = seg.sections.items[match.sect];1112 const sect = seg.sections.items[match.sect];
1113 const sect_type = sectionType(sect);
11121114
1113 log.warn("writing text blocks for section {s},{s}", .{ segmentName(sect), sectionName(sect) });1115 log.warn("writing text blocks for section {s},{s}", .{ segmentName(sect), sectionName(sect) });
11141116
1115 var code = try self.allocator.alloc(u8, sect.size);1117 var code = try self.allocator.alloc(u8, sect.size);
1116 defer self.allocator.free(code);1118 defer self.allocator.free(code);
11171119
1118 var base_off: u64 = sect.size;1120 if (sect_type == macho.S_ZEROFILL or
1121 sect_type == macho.S_THREAD_LOCAL_ZEROFILL or
1122 sect_type == macho.S_THREAD_LOCAL_VARIABLES)
1123 {
1124 mem.set(u8, code, 0);
1125 } else {
1126 var base_off: u64 = sect.size;
11191127
1120 while (true) {1128 while (true) {
1121 base_off -= block.size;1129 base_off -= block.size;
11221130
1123 try block.resolveRelocs(self);1131 try block.resolveRelocs(self);
1124 mem.copy(u8, code[base_off..][0..block.size], block.code);1132 mem.copy(u8, code[base_off..][0..block.size], block.code);
11251133
1126 if (block.prev) |prev| {1134 if (block.prev) |prev| {
1127 block = prev;1135 block = prev;
1128 } else break;1136 } else break;
1137 }
1129 }1138 }
11301139
1131 try self.file.?.pwriteAll(code, sect.offset);1140 try self.file.?.pwriteAll(code, sect.offset);
...@@ -2001,104 +2010,100 @@ fn addRpaths(self: *Zld, rpaths: []const []const u8) !void {...@@ -2001,104 +2010,100 @@ fn addRpaths(self: *Zld, rpaths: []const []const u8) !void {
20012010
2002fn flush(self: *Zld) !void {2011fn flush(self: *Zld) !void {
2003 try self.writeTextBlocks();2012 try self.writeTextBlocks();
2004 // try self.writeStubHelperCommon();2013 try self.writeStubHelperCommon();
20052014
2006 // if (self.common_section_index) |index| {2015 if (self.common_section_index) |index| {
2007 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2016 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2008 // const sect = &seg.sections.items[index];2017 const sect = &seg.sections.items[index];
2009 // sect.offset = 0;2018 sect.offset = 0;
2010 // }2019 }
20112020
2012 // if (self.bss_section_index) |index| {2021 if (self.bss_section_index) |index| {
2013 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2022 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2014 // const sect = &seg.sections.items[index];2023 const sect = &seg.sections.items[index];
2015 // sect.offset = 0;2024 sect.offset = 0;
2016 // }2025 }
20172026
2018 // if (self.tlv_bss_section_index) |index| {2027 if (self.tlv_bss_section_index) |index| {
2019 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2028 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2020 // const sect = &seg.sections.items[index];2029 const sect = &seg.sections.items[index];
2021 // sect.offset = 0;2030 sect.offset = 0;
2022 // }2031 }
20232032
2024 // if (self.tlv_section_index) |index| {2033 if (self.tlv_section_index) |index| {
2025 // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;2034 // TODO this should be part of relocation resolution routine.
2026 // const sect = &seg.sections.items[index];2035 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
20272036 const sect = &seg.sections.items[index];
2028 // var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));2037
2029 // defer self.allocator.free(buffer);2038 const base_addr = if (self.tlv_data_section_index) |i|
2030 // _ = try self.file.?.preadAll(buffer, sect.offset);2039 seg.sections.items[i].addr
20312040 else
2032 // var stream = std.io.fixedBufferStream(buffer);2041 seg.sections.items[self.tlv_bss_section_index.?].addr;
2033 // var writer = stream.writer();2042
20342043 var block: *TextBlock = self.blocks.get(.{
2035 // std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp);2044 .seg = self.data_segment_cmd_index.?,
20362045 .sect = index,
2037 // const seek_amt = 2 * @sizeOf(u64);2046 }) orelse unreachable;
2038 // for (self.threadlocal_offsets.items) |tlv| {2047
2039 // try writer.context.seekBy(seek_amt);2048 var buffer = try self.allocator.alloc(u8, @intCast(usize, sect.size));
2040 // try writer.writeIntLittle(u64, tlv.offset);2049 defer self.allocator.free(buffer);
2041 // }2050 _ = try self.file.?.preadAll(buffer, sect.offset);
20422051
2043 // try self.file.?.pwriteAll(buffer, sect.offset);2052 while (true) {
2044 // }2053 for (block.tlv_offsets.items) |tlv_offset| {
20452054 const sym = self.locals.items[tlv_offset.local_sym_index];
2046 // if (self.mod_init_func_section_index) |index| {2055 assert(sym.payload == .regular);
2047 // const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2056 const offset = sym.payload.regular.address - base_addr;
2048 // const sect = &seg.sections.items[index];2057 mem.writeIntLittle(u64, buffer[tlv_offset.offset..][0..@sizeOf(u64)], offset);
20492058 }
2050 // var initializers = std.ArrayList(u64).init(self.allocator);2059
2051 // defer initializers.deinit();2060 if (block.prev) |prev| {
20522061 block = prev;
2053 // for (self.objects.items) |object| {2062 } else break;
2054 // for (object.initializers.items) |sym_id| {2063 }
2055 // const address = object.symbols.items[sym_id].payload.regular.address;2064
2056 // try initializers.append(address);2065 try self.file.?.pwriteAll(buffer, sect.offset);
2057 // }2066 }
2058 // }2067
20592068 try self.writeGotEntries();
2060 // _ = try self.file.?.pwriteAll(mem.sliceAsBytes(initializers.items), sect.offset);2069 try self.setEntryPoint();
2061 // sect.size = @intCast(u32, initializers.items.len * @sizeOf(u64));2070 try self.writeRebaseInfoTable();
2062 // }2071 try self.writeBindInfoTable();
20632072 try self.writeLazyBindInfoTable();
2064 // try self.writeGotEntries();2073 try self.writeExportInfo();
2065 // try self.setEntryPoint();2074 // TODO DICE for x86_64
2066 // try self.writeRebaseInfoTable();
2067 // try self.writeBindInfoTable();
2068 // try self.writeLazyBindInfoTable();
2069 // try self.writeExportInfo();
2070 // try self.writeDataInCode();2075 // try self.writeDataInCode();
20712076
2072 // {2077 {
2073 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2078 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2074 // const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;2079 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
2075 // symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);2080 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
2076 // }2081 }
20772082
2078 // try self.writeSymbolTable();2083 try self.writeSymbolTable();
2079 // try self.writeStringTable();2084 try self.writeStringTable();
20802085
2081 // {2086 {
2082 // // Seal __LINKEDIT size2087 // Seal __LINKEDIT size
2083 // const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2088 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2084 // seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2089 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
2085 // }2090 }
20862091
2087 // if (self.target.?.cpu.arch == .aarch64) {2092 if (self.target.?.cpu.arch == .aarch64) {
2088 // try self.writeCodeSignaturePadding();2093 try self.writeCodeSignaturePadding();
2089 // }2094 }
20902095
2091 // try self.writeLoadCommands();2096 try self.writeLoadCommands();
2092 // try self.writeHeader();2097 try self.writeHeader();
20932098
2094 // if (self.target.?.cpu.arch == .aarch64) {2099 if (self.target.?.cpu.arch == .aarch64) {
2095 // try self.writeCodeSignature();2100 try self.writeCodeSignature();
2096 // }2101 }
20972102
2098 // if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {2103 if (comptime std.Target.current.isDarwin() and std.Target.current.cpu.arch == .aarch64) {
2099 // const out_path = self.output.?.path;2104 const out_path = self.output.?.path;
2100 // try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});2105 try fs.cwd().copyFile(out_path, fs.cwd(), out_path, .{});
2101 // }2106 }
2102}2107}
21032108
2104fn writeGotEntries(self: *Zld) !void {2109fn writeGotEntries(self: *Zld) !void {
...@@ -2140,8 +2145,35 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2140,8 +2145,35 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2140 var pointers = std.ArrayList(Pointer).init(self.allocator);2145 var pointers = std.ArrayList(Pointer).init(self.allocator);
2141 defer pointers.deinit();2146 defer pointers.deinit();
21422147
2143 try pointers.ensureCapacity(self.local_rebases.items.len);2148 {
2144 pointers.appendSliceAssumeCapacity(self.local_rebases.items);2149 var it = self.blocks.iterator();
2150 while (it.next()) |entry| {
2151 const match = entry.key_ptr.*;
2152 var block: *TextBlock = entry.value_ptr.*;
2153
2154 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
2155
2156 const seg = self.load_commands.items[match.seg].Segment;
2157 const sect = seg.sections.items[match.sect];
2158
2159 while (true) {
2160 const sym = self.locals.items[block.local_sym_index];
2161 assert(sym.payload == .regular);
2162 const base_offset = sym.payload.regular.address - seg.inner.vmaddr;
2163
2164 for (block.rebases.items) |offset| {
2165 try pointers.append(.{
2166 .offset = base_offset + offset,
2167 .segment_id = match.seg,
2168 });
2169 }
2170
2171 if (block.prev) |prev| {
2172 block = prev;
2173 } else break;
2174 }
2175 }
2176 }
21452177
2146 if (self.got_section_index) |idx| {2178 if (self.got_section_index) |idx| {
2147 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2179 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
...@@ -2159,24 +2191,6 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2159,24 +2191,6 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2159 }2191 }
2160 }2192 }
21612193
2162 if (self.mod_init_func_section_index) |idx| {
2163 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2164 const sect = seg.sections.items[idx];
2165 const base_offset = sect.addr - seg.inner.vmaddr;
2166 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
2167
2168 var index: u64 = 0;
2169 for (self.objects.items) |object| {
2170 for (object.initializers.items) |_| {
2171 try pointers.append(.{
2172 .offset = base_offset + index * @sizeOf(u64),
2173 .segment_id = segment_id,
2174 });
2175 index += 1;
2176 }
2177 }
2178 }
2179
2180 if (self.la_symbol_ptr_section_index) |idx| {2194 if (self.la_symbol_ptr_section_index) |idx| {
2181 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;2195 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2182 const sect = seg.sections.items[idx];2196 const sect = seg.sections.items[idx];
...@@ -2240,10 +2254,15 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2240,10 +2254,15 @@ fn writeBindInfoTable(self: *Zld) !void {
22402254
2241 const proxy = sym.payload.proxy;2255 const proxy = sym.payload.proxy;
2242 for (proxy.bind_info.items) |info| {2256 for (proxy.bind_info.items) |info| {
2243 const seg = self.load_commands.items[info.segment_id].Segment;2257 const bind_sym = self.locals.items[info.local_sym_index];
2258 assert(bind_sym.payload == .regular);
2259 const reg = bind_sym.payload.regular;
2260 const base_address = self.load_commands.items[reg.segment_id].Segment.inner.vmaddr;
2261 const offset = reg.address + info.offset - base_address;
2262
2244 try pointers.append(.{2263 try pointers.append(.{
2245 .offset = info.address - seg.inner.vmaddr,2264 .offset = offset,
2246 .segment_id = info.segment_id,2265 .segment_id = reg.segment_id,
2247 .dylib_ordinal = proxy.dylibOrdinal(),2266 .dylib_ordinal = proxy.dylibOrdinal(),
2248 .name = sym.name,2267 .name = sym.name,
2249 });2268 });
...@@ -2462,7 +2481,7 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2462,7 +2481,7 @@ fn writeSymbolTable(self: *Zld) !void {
24622481
2463 for (self.locals.items) |symbol| {2482 for (self.locals.items) |symbol| {
2464 if (symbol.isTemp()) continue; // TODO when merging codepaths, this should go into freelist2483 if (symbol.isTemp()) continue; // TODO when merging codepaths, this should go into freelist
2465 const nlist = try symbol.asNlist(&self.strtab);2484 const nlist = try symbol.asNlist(self, &self.strtab);
2466 locals.appendAssumeCapacity(nlist);2485 locals.appendAssumeCapacity(nlist);
2467 }2486 }
24682487
...@@ -2475,7 +2494,7 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2475,7 +2494,7 @@ fn writeSymbolTable(self: *Zld) !void {
2475 defer undef_dir.deinit();2494 defer undef_dir.deinit();
24762495
2477 for (self.globals.values()) |sym| {2496 for (self.globals.values()) |sym| {
2478 const nlist = try sym.asNlist(&self.strtab);2497 const nlist = try sym.asNlist(self, &self.strtab);
2479 switch (sym.payload) {2498 switch (sym.payload) {
2480 .regular => try exports.append(nlist),2499 .regular => try exports.append(nlist),
2481 .proxy => {2500 .proxy => {