| ... | ... | @@ -811,6 +811,20 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void { |
| 811 | 811 | try self.parseSymbolTable(); |
| 812 | 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 | 828 | // Parse dyld info |
| 815 | 829 | try self.parseBindingInfo(); |
| 816 | 830 | try self.parseLazyBindingInfo(); |
| ... | ... | @@ -2090,6 +2104,9 @@ fn parseBindingInfo(self: *MachO) !void { |
| 2090 | 2104 | defer self.base.allocator.free(buffer); |
| 2091 | 2105 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.bind_off); |
| 2092 | 2106 | assert(nread == buffer.len); |
| 2107 | |
| 2108 | try parseBindingInfos(self, buffer); |
| 2109 | |
| 2093 | 2110 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { |
| 2094 | 2111 | try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off); |
| 2095 | 2112 | } |
| ... | ... | @@ -2101,6 +2118,9 @@ fn parseLazyBindingInfo(self: *MachO) !void { |
| 2101 | 2118 | defer self.base.allocator.free(buffer); |
| 2102 | 2119 | const nread = try self.base.file.?.preadAll(buffer, dyld_info.lazy_bind_off); |
| 2103 | 2120 | assert(nread == buffer.len); |
| 2121 | |
| 2122 | try parseBindingInfos(self, buffer); |
| 2123 | |
| 2104 | 2124 | if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) { |
| 2105 | 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 | 2175 | |
| 2156 | 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 | } |