aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 6db725ddec..673e5e9545 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -811,6 +811,20 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
try self.parseSymbolTable();
try self.parseStringTable();
+ std.debug.print("Undef symbols\n", .{});
+ for (self.undef_symbols.items) |sym| {
+ const name = self.string_table.items[sym.n_strx..];
+ const len = blk: {
+ var end: usize = 0;
+ while (true) {
+ if (name[end] == @as(u8, 0)) break;
+ end += 1;
+ }
+ break :blk end;
+ };
+ std.debug.print("name={},sym={}\n", .{ name[0..len], sym });
+ }
+
// Parse dyld info
try self.parseBindingInfo();
try self.parseLazyBindingInfo();
@@ -2090,6 +2104,9 @@ fn parseBindingInfo(self: *MachO) !void {
defer self.base.allocator.free(buffer);
const nread = try self.base.file.?.preadAll(buffer, dyld_info.bind_off);
assert(nread == buffer.len);
+
+ try parseBindingInfos(self, buffer);
+
if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) {
try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
}
@@ -2101,6 +2118,9 @@ fn parseLazyBindingInfo(self: *MachO) !void {
defer self.base.allocator.free(buffer);
const nread = try self.base.file.?.preadAll(buffer, dyld_info.lazy_bind_off);
assert(nread == buffer.len);
+
+ try parseBindingInfos(self, buffer);
+
if (try parseAndFixupBindingInfoBuffer(self.base.allocator, buffer)) {
try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
}
@@ -2155,3 +2175,105 @@ fn parseAndFixupBindingInfoBuffer(allocator: *Allocator, buffer: []u8) !bool {
return buffer_dirty;
}
+
+const BindingEntry = struct {
+ symbol: ?u16 = null,
+ offset: i64,
+ dylib_ordinal: ?i64 = null,
+ segment: u8,
+ bind_type: u8,
+};
+
+fn parseBindingInfos(self: *MachO, buffer: []u8) !void {
+ var symbolsByName = std.StringHashMap(u16).init(self.base.allocator);
+ defer symbolsByName.deinit();
+ try symbolsByName.ensureCapacity(@intCast(u32, self.undef_symbols.items.len));
+
+ for (self.undef_symbols.items) |sym, i| {
+ const name = self.string_table.items[sym.n_strx..];
+ const len = blk: {
+ var end: usize = 0;
+ while (true) {
+ if (name[end] == @as(u8, 0)) break;
+ end += 1;
+ }
+ break :blk end;
+ };
+ symbolsByName.putAssumeCapacityNoClobber(name[0..len], @intCast(u16, i));
+ }
+
+ var stream = std.io.fixedBufferStream(buffer);
+ var reader = stream.reader();
+ var done = false;
+
+ var name = std.ArrayList(u8).init(self.base.allocator);
+ defer name.deinit();
+
+ var entries = std.ArrayList(BindingEntry).init(self.base.allocator);
+ defer entries.deinit();
+ var dylib_ordinal: i64 = 0;
+
+ var entry: BindingEntry = .{
+ .offset = 0,
+ .segment = 0,
+ .bind_type = 0,
+ };
+
+ while (true) {
+ const inst = reader.readByte() catch |err| switch (err) {
+ error.EndOfStream => break,
+ else => return err,
+ };
+ const imm: u8 = inst & macho.BIND_IMMEDIATE_MASK;
+ const opcode: u8 = inst & macho.BIND_OPCODE_MASK;
+
+ switch (opcode) {
+ macho.BIND_OPCODE_DO_BIND => {
+ if (entry.dylib_ordinal == null) {
+ entry.dylib_ordinal = dylib_ordinal;
+ }
+ try entries.append(entry);
+ entry = .{
+ .offset = 0,
+ .segment = 0,
+ .bind_type = 0,
+ };
+ },
+ macho.BIND_OPCODE_DONE => {
+ done = true;
+ },
+ macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
+ name.shrinkRetainingCapacity(0);
+ var next = try reader.readByte();
+ while (next != @as(u8, 0)) {
+ try name.append(next);
+ next = try reader.readByte();
+ }
+ std.debug.print("name={}\n", .{name.items});
+ entry.symbol = symbolsByName.get(name.items[0..]);
+ },
+ macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
+ entry.segment = imm;
+ entry.offset = try std.leb.readILEB128(i64, reader);
+ },
+ macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {
+ entry.dylib_ordinal = imm;
+ },
+ macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => {
+ dylib_ordinal = try std.leb.readILEB128(i64, reader);
+ entry.dylib_ordinal = dylib_ordinal;
+ },
+ macho.BIND_OPCODE_SET_TYPE_IMM => {
+ entry.bind_type = imm;
+ },
+ else => {
+ std.log.warn("unhandled BIND_OPCODE_: 0x{x}", .{opcode});
+ },
+ }
+ }
+ assert(done);
+
+ for (entries.items) |e| {
+ std.debug.print("entry={}\n", .{e});
+ }
+}