| ... | @@ -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 | } |
| 342 | | 343 | |
| ... | @@ -1109,23 +1110,31 @@ fn writeTextBlocks(self: *Zld) !void { | ... | @@ -1109,23 +1110,31 @@ fn writeTextBlocks(self: *Zld) !void { |
| 1109 | | 1110 | |
| 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); |
| 1112 | | 1114 | |
| 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) }); |
| 1114 | | 1116 | |
| 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); |
| 1117 | | 1119 | |
| 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; |
| 1119 | | 1127 | |
| 1120 | while (true) { | 1128 | while (true) { |
| 1121 | base_off -= block.size; | 1129 | base_off -= block.size; |
| 1122 | | 1130 | |
| 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); |
| 1125 | | 1133 | |
| 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 | } |
| 1130 | | 1139 | |
| 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 { |
| 2001 | | 2010 | |
| 2002 | fn flush(self: *Zld) !void { | 2011 | fn flush(self: *Zld) !void { |
| 2003 | try self.writeTextBlocks(); | 2012 | try self.writeTextBlocks(); |
| 2004 | // try self.writeStubHelperCommon(); | 2013 | try self.writeStubHelperCommon(); |
| 2005 | | 2014 | |
| 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 | } |
| 2011 | | 2020 | |
| 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 | } |
| 2017 | | 2026 | |
| 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 | } |
| 2023 | | 2032 | |
| 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; |
| 2027 | | 2036 | 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 |
| 2031 | | 2040 | else |
| 2032 | // var stream = std.io.fixedBufferStream(buffer); | 2041 | seg.sections.items[self.tlv_bss_section_index.?].addr; |
| 2033 | // var writer = stream.writer(); | 2042 | |
| 2034 | | 2043 | var block: *TextBlock = self.blocks.get(.{ |
| 2035 | // std.sort.sort(TlvOffset, self.threadlocal_offsets.items, {}, TlvOffset.cmp); | 2044 | .seg = self.data_segment_cmd_index.?, |
| 2036 | | 2045 | .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); |
| 2042 | | 2051 | |
| 2043 | // try self.file.?.pwriteAll(buffer, sect.offset); | 2052 | while (true) { |
| 2044 | // } | 2053 | for (block.tlv_offsets.items) |tlv_offset| { |
| 2045 | | 2054 | 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); |
| 2049 | | 2058 | } |
| 2050 | // var initializers = std.ArrayList(u64).init(self.allocator); | 2059 | |
| 2051 | // defer initializers.deinit(); | 2060 | if (block.prev) |prev| { |
| 2052 | | 2061 | 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 | |
| 2059 | | 2068 | 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(); |
| 2063 | | 2072 | 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(); |
| 2071 | | 2076 | |
| 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 | } |
| 2077 | | 2082 | |
| 2078 | // try self.writeSymbolTable(); | 2083 | try self.writeSymbolTable(); |
| 2079 | // try self.writeStringTable(); | 2084 | try self.writeStringTable(); |
| 2080 | | 2085 | |
| 2081 | // { | 2086 | { |
| 2082 | // // Seal __LINKEDIT size | 2087 | // 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 | } |
| 2086 | | 2091 | |
| 2087 | // if (self.target.?.cpu.arch == .aarch64) { | 2092 | if (self.target.?.cpu.arch == .aarch64) { |
| 2088 | // try self.writeCodeSignaturePadding(); | 2093 | try self.writeCodeSignaturePadding(); |
| 2089 | // } | 2094 | } |
| 2090 | | 2095 | |
| 2091 | // try self.writeLoadCommands(); | 2096 | try self.writeLoadCommands(); |
| 2092 | // try self.writeHeader(); | 2097 | try self.writeHeader(); |
| 2093 | | 2098 | |
| 2094 | // if (self.target.?.cpu.arch == .aarch64) { | 2099 | if (self.target.?.cpu.arch == .aarch64) { |
| 2095 | // try self.writeCodeSignature(); | 2100 | try self.writeCodeSignature(); |
| 2096 | // } | 2101 | } |
| 2097 | | 2102 | |
| 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 | } |
| 2103 | | 2108 | |
| 2104 | fn writeGotEntries(self: *Zld) !void { | 2109 | fn 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(); |
| 2142 | | 2147 | |
| 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 | } |
| 2145 | | 2177 | |
| 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 | } |
| 2161 | | 2193 | |
| 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 { |
| 2240 | | 2254 | |
| 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 { |
| 2462 | | 2481 | |
| 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 freelist | 2483 | 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 | } |
| 2468 | | 2487 | |
| ... | @@ -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(); |
| 2476 | | 2495 | |
| 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 => { |