| ... | @@ -811,6 +811,20 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { | ... | @@ -811,6 +811,20 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 811 | try self.parseSymbolTable(); | 811 | try self.parseSymbolTable(); |
| 812 | try self.parseStringTable(); | 812 | try self.parseStringTable(); |
| 813 | | 813 | |
| | 814 | std.debug.print("Undef symbols\n", .{}); |
| | 815 | for (self.undef_symbols.items) |sym| { |
| | 816 | const name = self.string_table.items[sym.n_strx..]; |
| | 817 | const len = blk: { |
| | 818 | var end: usize = 0; |
| | 819 | while (true) { |
| | 820 | if (name[end] == @as(u8, 0)) break; |
| | 821 | end += 1; |
| | 822 | } |
| | 823 | break :blk end; |
| | 824 | }; |
| | 825 | std.debug.print("name={},sym={}\n", .{ name[0..len], sym }); |
| | 826 | } |
| | 827 | |
| 814 | // Parse dyld info | 828 | // Parse dyld info |
| 815 | try self.parseBindingInfo(); | 829 | try self.parseBindingInfo(); |
| 816 | try self.parseLazyBindingInfo(); | 830 | try self.parseLazyBindingInfo(); |
| ... | @@ -2090,6 +2104,9 @@ fn parseBindingInfo(self: *MachO) !void { | ... | @@ -2090,6 +2104,9 @@ fn parseBindingInfo(self: *MachO) !void { |
| 2090 | defer self.base.allocator.free(buffer); | 2104 | defer self.base.allocator.free(buffer); |
| 2091 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.bind_off); | 2105 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.bind_off); |
| 2092 | assert(nread == buffer.len); | 2106 | assert(nread == buffer.len); |
| | 2107 | |
| | 2108 | try parseBindingInfos(self, buffer); |
| | 2109 | |
| 2093 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { | 2110 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { |
| 2094 | try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off); | 2111 | try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off); |
| 2095 | } | 2112 | } |
| ... | @@ -2101,6 +2118,9 @@ fn parseLazyBindingInfo(self: *MachO) !void { | ... | @@ -2101,6 +2118,9 @@ fn parseLazyBindingInfo(self: *MachO) !void { |
| 2101 | defer self.base.allocator.free(buffer); | 2118 | defer self.base.allocator.free(buffer); |
| 2102 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.lazy_bind_off); | 2119 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.lazy_bind_off); |
| 2103 | assert(nread == buffer.len); | 2120 | assert(nread == buffer.len); |
| | 2121 | |
| | 2122 | try parseBindingInfos(self, buffer); |
| | 2123 | |
| 2104 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { | 2124 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { |
| 2105 | try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); | 2125 | try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off); |
| 2106 | } | 2126 | } |
| ... | @@ -2155,3 +2175,105 @@ fn parseAndFixupBindingInfoBuffer(allocator: *Allocator, buffer: []u8) !bool { | ... | @@ -2155,3 +2175,105 @@ fn parseAndFixupBindingInfoBuffer(allocator: *Allocator, buffer: []u8) !bool { |
| 2155 | | 2175 | |
| 2156 | return buffer_dirty; | 2176 | return buffer_dirty; |
| 2157 | } | 2177 | } |
| | 2178 | |
| | 2179 | const BindingEntry = struct { |
| | 2180 | symbol: ?u16 = null, |
| | 2181 | offset: i64, |
| | 2182 | dylib_ordinal: ?i64 = null, |
| | 2183 | segment: u8, |
| | 2184 | bind_type: u8, |
| | 2185 | }; |
| | 2186 | |
| | 2187 | fn parseBindingInfos(self: *MachO, buffer: []u8) !void { |
| | 2188 | var symbolsByName = std.StringHashMap(u16).init(self.base.allocator); |
| | 2189 | defer symbolsByName.deinit(); |
| | 2190 | try symbolsByName.ensureCapacity(@intCast(u32, self.undef_symbols.items.len)); |
| | 2191 | |
| | 2192 | for (self.undef_symbols.items) |sym, i| { |
| | 2193 | const name = self.string_table.items[sym.n_strx..]; |
| | 2194 | const len = blk: { |
| | 2195 | var end: usize = 0; |
| | 2196 | while (true) { |
| | 2197 | if (name[end] == @as(u8, 0)) break; |
| | 2198 | end += 1; |
| | 2199 | } |
| | 2200 | break :blk end; |
| | 2201 | }; |
| | 2202 | symbolsByName.putAssumeCapacityNoClobber(name[0..len], @intCast(u16, i)); |
| | 2203 | } |
| | 2204 | |
| | 2205 | var stream = std.io.fixedBufferStream(buffer); |
| | 2206 | var reader = stream.reader(); |
| | 2207 | var done = false; |
| | 2208 | |
| | 2209 | var name = std.ArrayList(u8).init(self.base.allocator); |
| | 2210 | defer name.deinit(); |
| | 2211 | |
| | 2212 | var entries = std.ArrayList(BindingEntry).init(self.base.allocator); |
| | 2213 | defer entries.deinit(); |
| | 2214 | var dylib_ordinal: i64 = 0; |
| | 2215 | |
| | 2216 | var entry: BindingEntry = .{ |
| | 2217 | .offset = 0, |
| | 2218 | .segment = 0, |
| | 2219 | .bind_type = 0, |
| | 2220 | }; |
| | 2221 | |
| | 2222 | while (true) { |
| | 2223 | const inst = reader.readByte() catch |err| switch (err) { |
| | 2224 | error.EndOfStream => break, |
| | 2225 | else => return err, |
| | 2226 | }; |
| | 2227 | const imm: u8 = inst & macho.BIND_IMMEDIATE_MASK; |
| | 2228 | const opcode: u8 = inst & macho.BIND_OPCODE_MASK; |
| | 2229 | |
| | 2230 | switch (opcode) { |
| | 2231 | macho.BIND_OPCODE_DO_BIND => { |
| | 2232 | if (entry.dylib_ordinal == null) { |
| | 2233 | entry.dylib_ordinal = dylib_ordinal; |
| | 2234 | } |
| | 2235 | try entries.append(entry); |
| | 2236 | entry = .{ |
| | 2237 | .offset = 0, |
| | 2238 | .segment = 0, |
| | 2239 | .bind_type = 0, |
| | 2240 | }; |
| | 2241 | }, |
| | 2242 | macho.BIND_OPCODE_DONE => { |
| | 2243 | done = true; |
| | 2244 | }, |
| | 2245 | macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => { |
| | 2246 | name.shrinkRetainingCapacity(0); |
| | 2247 | var next = try reader.readByte(); |
| | 2248 | while (next != @as(u8, 0)) { |
| | 2249 | try name.append(next); |
| | 2250 | next = try reader.readByte(); |
| | 2251 | } |
| | 2252 | std.debug.print("name={}\n", .{name.items}); |
| | 2253 | entry.symbol = symbolsByName.get(name.items[0..]); |
| | 2254 | }, |
| | 2255 | macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => { |
| | 2256 | entry.segment = imm; |
| | 2257 | entry.offset = try std.leb.readILEB128(i64, reader); |
| | 2258 | }, |
| | 2259 | macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => { |
| | 2260 | entry.dylib_ordinal = imm; |
| | 2261 | }, |
| | 2262 | macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => { |
| | 2263 | dylib_ordinal = try std.leb.readILEB128(i64, reader); |
| | 2264 | entry.dylib_ordinal = dylib_ordinal; |
| | 2265 | }, |
| | 2266 | macho.BIND_OPCODE_SET_TYPE_IMM => { |
| | 2267 | entry.bind_type = imm; |
| | 2268 | }, |
| | 2269 | else => { |
| | 2270 | std.log.warn("unhandled BIND_OPCODE_: 0x{x}", .{opcode}); |
| | 2271 | }, |
| | 2272 | } |
| | 2273 | } |
| | 2274 | assert(done); |
| | 2275 | |
| | 2276 | for (entries.items) |e| { |
| | 2277 | std.debug.print("entry={}\n", .{e}); |
| | 2278 | } |
| | 2279 | } |