aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/dyld_info/bind.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-07-01 18:14:45 -0700
committerAndrew Kelley <andrew@ziglang.org>2025-07-07 22:43:52 -0700
commitc8fcd2ff2c032b2de8cc1a57e075552d1cab35df (patch)
tree7155f58049ecd0e948533f6b64cba1553dd33ae2 /src/link/MachO/dyld_info/bind.zig
parentf71d97e4cbb0e56213cb76657ad6c9edf6134868 (diff)
downloadzig-c8fcd2ff2c032b2de8cc1a57e075552d1cab35df.tar.gz
zig-c8fcd2ff2c032b2de8cc1a57e075552d1cab35df.zip
MachO: update to new std.io APIs
Diffstat (limited to 'src/link/MachO/dyld_info/bind.zig')
-rw-r--r--src/link/MachO/dyld_info/bind.zig342
1 files changed, 155 insertions, 187 deletions
diff --git a/src/link/MachO/dyld_info/bind.zig b/src/link/MachO/dyld_info/bind.zig
index 328d6a402c..f6697b6275 100644
--- a/src/link/MachO/dyld_info/bind.zig
+++ b/src/link/MachO/dyld_info/bind.zig
@@ -1,7 +1,7 @@
pub const Entry = struct {
target: MachO.Ref,
offset: u64,
- segment_id: u8,
+ segment_id: u4,
addend: i64,
pub fn lessThan(ctx: *MachO, entry: Entry, other: Entry) bool {
@@ -20,14 +20,12 @@ pub const Bind = struct {
entries: std.ArrayListUnmanaged(Entry) = .empty,
buffer: std.ArrayListUnmanaged(u8) = .empty,
- const Self = @This();
-
- pub fn deinit(self: *Self, gpa: Allocator) void {
- self.entries.deinit(gpa);
- self.buffer.deinit(gpa);
+ pub fn deinit(bind: *Bind, gpa: Allocator) void {
+ bind.entries.deinit(gpa);
+ bind.buffer.deinit(gpa);
}
- pub fn updateSize(self: *Self, macho_file: *MachO) !void {
+ pub fn updateSize(bind: *Bind, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -56,15 +54,12 @@ pub const Bind = struct {
const addend = rel.addend + rel.getRelocAddend(cpu_arch);
const sym = rel.getTargetSymbol(atom.*, macho_file);
if (sym.isTlvInit(macho_file)) continue;
- const entry = Entry{
+ if (sym.flags.import or (!(sym.flags.@"export" and sym.flags.weak) and sym.flags.interposable)) (try bind.entries.addOne(gpa)).* = .{
.target = rel.getTargetSymbolRef(atom.*, macho_file),
.offset = atom_addr + rel_offset - seg.vmaddr,
.segment_id = seg_id,
.addend = addend,
};
- if (sym.flags.import or (!(sym.flags.@"export" and sym.flags.weak) and sym.flags.interposable)) {
- try self.entries.append(gpa, entry);
- }
}
}
}
@@ -75,15 +70,12 @@ pub const Bind = struct {
for (macho_file.got.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
- const entry = Entry{
+ if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) {
- try self.entries.append(gpa, entry);
- }
}
}
@@ -94,15 +86,12 @@ pub const Bind = struct {
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
- const bind_entry = Entry{
+ if (sym.flags.import and sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.import and sym.flags.weak) {
- try self.entries.append(gpa, bind_entry);
- }
}
}
@@ -113,49 +102,48 @@ pub const Bind = struct {
for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
- const entry = Entry{
+ if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.import or (sym.flags.@"export" and sym.flags.interposable and !sym.flags.weak)) {
- try self.entries.append(gpa, entry);
- }
}
}
- try self.finalize(gpa, macho_file);
- macho_file.dyld_info_cmd.bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));
+ try bind.finalize(gpa, macho_file);
+ macho_file.dyld_info_cmd.bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
}
- fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
- if (self.entries.items.len == 0) return;
+ fn finalize(bind: *Bind, gpa: Allocator, ctx: *MachO) !void {
+ if (bind.entries.items.len == 0) return;
- const writer = self.buffer.writer(gpa);
+ var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &bind.buffer);
+ const bw = &aw.writer;
+ defer bind.buffer = aw.toArrayList();
log.debug("bind opcodes", .{});
- std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);
+ std.mem.sort(Entry, bind.entries.items, ctx, Entry.lessThan);
var start: usize = 0;
var seg_id: ?u8 = null;
- for (self.entries.items, 0..) |entry, i| {
+ for (bind.entries.items, 0..) |entry, i| {
if (seg_id != null and seg_id.? == entry.segment_id) continue;
- try finalizeSegment(self.entries.items[start..i], ctx, writer);
+ try finalizeSegment(bind.entries.items[start..i], ctx, bw);
seg_id = entry.segment_id;
start = i;
}
- try finalizeSegment(self.entries.items[start..], ctx, writer);
- try done(writer);
+ try finalizeSegment(bind.entries.items[start..], ctx, bw);
+ try done(bw);
}
- fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {
+ fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *Writer) Writer.Error!void {
if (entries.len == 0) return;
const seg_id = entries[0].segment_id;
- try setSegmentOffset(seg_id, 0, writer);
+ try setSegmentOffset(seg_id, 0, bw);
var offset: u64 = 0;
var addend: i64 = 0;
@@ -175,15 +163,15 @@ pub const Bind = struct {
if (target == null or !target.?.eql(current.target)) {
switch (state) {
.start => {},
- .bind_single => try doBind(writer),
- .bind_times_skip => try doBindTimesSkip(count, skip, writer),
+ .bind_single => try doBind(bw),
+ .bind_times_skip => try doBindTimesSkip(count, skip, bw),
}
state = .start;
target = current.target;
const sym = current.target.getSymbol(ctx).?;
const name = sym.getName(ctx);
- const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
+ const flags: u4 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
const ordinal: i16 = ord: {
if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
if (sym.flags.import) {
@@ -195,13 +183,13 @@ pub const Bind = struct {
break :ord macho.BIND_SPECIAL_DYLIB_SELF;
};
- try setSymbol(name, flags, writer);
- try setTypePointer(writer);
- try setDylibOrdinal(ordinal, writer);
+ try setSymbol(name, flags, bw);
+ try setTypePointer(bw);
+ try setDylibOrdinal(ordinal, bw);
if (current.addend != addend) {
addend = current.addend;
- try setAddend(addend, writer);
+ try setAddend(addend, bw);
}
}
@@ -210,11 +198,11 @@ pub const Bind = struct {
switch (state) {
.start => {
if (current.offset < offset) {
- try addAddr(@bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset))), writer);
+ try addAddr(@bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset))), bw);
offset = offset - (offset - current.offset);
} else if (current.offset > offset) {
const delta = current.offset - offset;
- try addAddr(delta, writer);
+ try addAddr(delta, bw);
offset += delta;
}
state = .bind_single;
@@ -223,7 +211,7 @@ pub const Bind = struct {
},
.bind_single => {
if (current.offset == offset) {
- try doBind(writer);
+ try doBind(bw);
state = .start;
} else if (current.offset > offset) {
const delta = current.offset - offset;
@@ -237,9 +225,9 @@ pub const Bind = struct {
if (current.offset < offset) {
count -= 1;
if (count == 1) {
- try doBindAddAddr(skip, writer);
+ try doBindAddAddr(skip, bw);
} else {
- try doBindTimesSkip(count, skip, writer);
+ try doBindTimesSkip(count, skip, bw);
}
state = .start;
offset = offset - (@sizeOf(u64) + skip);
@@ -248,7 +236,7 @@ pub const Bind = struct {
count += 1;
offset += @sizeOf(u64) + skip;
} else {
- try doBindTimesSkip(count, skip, writer);
+ try doBindTimesSkip(count, skip, bw);
state = .start;
i -= 1;
}
@@ -258,13 +246,13 @@ pub const Bind = struct {
switch (state) {
.start => unreachable,
- .bind_single => try doBind(writer),
- .bind_times_skip => try doBindTimesSkip(count, skip, writer),
+ .bind_single => try doBind(bw),
+ .bind_times_skip => try doBindTimesSkip(count, skip, bw),
}
}
- pub fn write(self: Self, writer: anytype) !void {
- try writer.writeAll(self.buffer.items);
+ pub fn write(bind: Bind, bw: *Writer) Writer.Error!void {
+ try bw.writeAll(bind.buffer.items);
}
};
@@ -272,14 +260,12 @@ pub const WeakBind = struct {
entries: std.ArrayListUnmanaged(Entry) = .empty,
buffer: std.ArrayListUnmanaged(u8) = .empty,
- const Self = @This();
-
- pub fn deinit(self: *Self, gpa: Allocator) void {
- self.entries.deinit(gpa);
- self.buffer.deinit(gpa);
+ pub fn deinit(bind: *WeakBind, gpa: Allocator) void {
+ bind.entries.deinit(gpa);
+ bind.buffer.deinit(gpa);
}
- pub fn updateSize(self: *Self, macho_file: *MachO) !void {
+ pub fn updateSize(bind: *WeakBind, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -308,15 +294,12 @@ pub const WeakBind = struct {
const addend = rel.addend + rel.getRelocAddend(cpu_arch);
const sym = rel.getTargetSymbol(atom.*, macho_file);
if (sym.isTlvInit(macho_file)) continue;
- const entry = Entry{
+ if (!sym.isLocal() and sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
.target = rel.getTargetSymbolRef(atom.*, macho_file),
.offset = atom_addr + rel_offset - seg.vmaddr,
.segment_id = seg_id,
.addend = addend,
};
- if (!sym.isLocal() and sym.flags.weak) {
- try self.entries.append(gpa, entry);
- }
}
}
}
@@ -327,15 +310,12 @@ pub const WeakBind = struct {
for (macho_file.got.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.got.getAddress(@intCast(idx), macho_file);
- const entry = Entry{
+ if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.weak) {
- try self.entries.append(gpa, entry);
- }
}
}
@@ -347,15 +327,12 @@ pub const WeakBind = struct {
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
- const bind_entry = Entry{
+ if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.weak) {
- try self.entries.append(gpa, bind_entry);
- }
}
}
@@ -366,49 +343,48 @@ pub const WeakBind = struct {
for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file);
- const entry = Entry{
+ if (sym.flags.weak) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if (sym.flags.weak) {
- try self.entries.append(gpa, entry);
- }
}
}
- try self.finalize(gpa, macho_file);
- macho_file.dyld_info_cmd.weak_bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));
+ try bind.finalize(gpa, macho_file);
+ macho_file.dyld_info_cmd.weak_bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
}
- fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
- if (self.entries.items.len == 0) return;
+ fn finalize(bind: *WeakBind, gpa: Allocator, ctx: *MachO) !void {
+ if (bind.entries.items.len == 0) return;
- const writer = self.buffer.writer(gpa);
+ var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &bind.buffer);
+ const bw = &aw.writer;
+ defer bind.buffer = aw.toArrayList();
log.debug("weak bind opcodes", .{});
- std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);
+ std.mem.sort(Entry, bind.entries.items, ctx, Entry.lessThan);
var start: usize = 0;
var seg_id: ?u8 = null;
- for (self.entries.items, 0..) |entry, i| {
+ for (bind.entries.items, 0..) |entry, i| {
if (seg_id != null and seg_id.? == entry.segment_id) continue;
- try finalizeSegment(self.entries.items[start..i], ctx, writer);
+ try finalizeSegment(bind.entries.items[start..i], ctx, bw);
seg_id = entry.segment_id;
start = i;
}
- try finalizeSegment(self.entries.items[start..], ctx, writer);
- try done(writer);
+ try finalizeSegment(bind.entries.items[start..], ctx, bw);
+ try done(bw);
}
- fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {
+ fn finalizeSegment(entries: []const Entry, ctx: *MachO, bw: *Writer) Writer.Error!void {
if (entries.len == 0) return;
const seg_id = entries[0].segment_id;
- try setSegmentOffset(seg_id, 0, writer);
+ try setSegmentOffset(seg_id, 0, bw);
var offset: u64 = 0;
var addend: i64 = 0;
@@ -428,8 +404,8 @@ pub const WeakBind = struct {
if (target == null or !target.?.eql(current.target)) {
switch (state) {
.start => {},
- .bind_single => try doBind(writer),
- .bind_times_skip => try doBindTimesSkip(count, skip, writer),
+ .bind_single => try doBind(bw),
+ .bind_times_skip => try doBindTimesSkip(count, skip, bw),
}
state = .start;
target = current.target;
@@ -438,12 +414,12 @@ pub const WeakBind = struct {
const name = sym.getName(ctx);
const flags: u8 = 0; // TODO NON_WEAK_DEFINITION
- try setSymbol(name, flags, writer);
- try setTypePointer(writer);
+ try setSymbol(name, flags, bw);
+ try setTypePointer(bw);
if (current.addend != addend) {
addend = current.addend;
- try setAddend(addend, writer);
+ try setAddend(addend, bw);
}
}
@@ -452,11 +428,11 @@ pub const WeakBind = struct {
switch (state) {
.start => {
if (current.offset < offset) {
- try addAddr(@as(u64, @bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset)))), writer);
+ try addAddr(@as(u64, @bitCast(@as(i64, @intCast(current.offset)) - @as(i64, @intCast(offset)))), bw);
offset = offset - (offset - current.offset);
} else if (current.offset > offset) {
const delta = current.offset - offset;
- try addAddr(delta, writer);
+ try addAddr(delta, bw);
offset += delta;
}
state = .bind_single;
@@ -465,7 +441,7 @@ pub const WeakBind = struct {
},
.bind_single => {
if (current.offset == offset) {
- try doBind(writer);
+ try doBind(bw);
state = .start;
} else if (current.offset > offset) {
const delta = current.offset - offset;
@@ -479,9 +455,9 @@ pub const WeakBind = struct {
if (current.offset < offset) {
count -= 1;
if (count == 1) {
- try doBindAddAddr(skip, writer);
+ try doBindAddAddr(skip, bw);
} else {
- try doBindTimesSkip(count, skip, writer);
+ try doBindTimesSkip(count, skip, bw);
}
state = .start;
offset = offset - (@sizeOf(u64) + skip);
@@ -490,7 +466,7 @@ pub const WeakBind = struct {
count += 1;
offset += @sizeOf(u64) + skip;
} else {
- try doBindTimesSkip(count, skip, writer);
+ try doBindTimesSkip(count, skip, bw);
state = .start;
i -= 1;
}
@@ -500,13 +476,13 @@ pub const WeakBind = struct {
switch (state) {
.start => unreachable,
- .bind_single => try doBind(writer),
- .bind_times_skip => try doBindTimesSkip(count, skip, writer),
+ .bind_single => try doBind(bw),
+ .bind_times_skip => try doBindTimesSkip(count, skip, bw),
}
}
- pub fn write(self: Self, writer: anytype) !void {
- try writer.writeAll(self.buffer.items);
+ pub fn write(bind: WeakBind, bw: *Writer) Writer.Error!void {
+ try bw.writeAll(bind.buffer.items);
}
};
@@ -515,15 +491,13 @@ pub const LazyBind = struct {
buffer: std.ArrayListUnmanaged(u8) = .empty,
offsets: std.ArrayListUnmanaged(u32) = .empty,
- const Self = @This();
-
- pub fn deinit(self: *Self, gpa: Allocator) void {
- self.entries.deinit(gpa);
- self.buffer.deinit(gpa);
- self.offsets.deinit(gpa);
+ pub fn deinit(bind: *LazyBind, gpa: Allocator) void {
+ bind.entries.deinit(gpa);
+ bind.buffer.deinit(gpa);
+ bind.offsets.deinit(gpa);
}
- pub fn updateSize(self: *Self, macho_file: *MachO) !void {
+ pub fn updateSize(bind: *LazyBind, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -537,36 +511,35 @@ pub const LazyBind = struct {
for (macho_file.stubs.symbols.items, 0..) |ref, idx| {
const sym = ref.getSymbol(macho_file).?;
const addr = sect.addr + idx * @sizeOf(u64);
- const bind_entry = Entry{
+ if ((sym.flags.import and !sym.flags.weak) or (sym.flags.interposable and !sym.flags.weak)) (try bind.entries.addOne(gpa)).* = .{
.target = ref,
.offset = addr - seg.vmaddr,
.segment_id = seg_id,
.addend = 0,
};
- if ((sym.flags.import and !sym.flags.weak) or (sym.flags.interposable and !sym.flags.weak)) {
- try self.entries.append(gpa, bind_entry);
- }
}
- try self.finalize(gpa, macho_file);
- macho_file.dyld_info_cmd.lazy_bind_size = mem.alignForward(u32, @intCast(self.buffer.items.len), @alignOf(u64));
+ try bind.finalize(gpa, macho_file);
+ macho_file.dyld_info_cmd.lazy_bind_size = mem.alignForward(u32, @intCast(bind.buffer.items.len), @alignOf(u64));
}
- fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
- try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len);
+ fn finalize(bind: *LazyBind, gpa: Allocator, ctx: *MachO) !void {
+ try bind.offsets.ensureTotalCapacityPrecise(gpa, bind.entries.items.len);
- const writer = self.buffer.writer(gpa);
+ var aw: std.io.Writer.Allocating = .fromArrayList(gpa, &bind.buffer);
+ const bw = &aw.writer;
+ defer bind.buffer = aw.toArrayList();
log.debug("lazy bind opcodes", .{});
var addend: i64 = 0;
- for (self.entries.items) |entry| {
- self.offsets.appendAssumeCapacity(@intCast(self.buffer.items.len));
+ for (bind.entries.items) |entry| {
+ bind.offsets.appendAssumeCapacity(@intCast(bind.buffer.items.len));
const sym = entry.target.getSymbol(ctx).?;
const name = sym.getName(ctx);
- const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
+ const flags: u4 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0;
const ordinal: i16 = ord: {
if (sym.flags.interposable) break :ord macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
if (sym.flags.import) {
@@ -578,121 +551,116 @@ pub const LazyBind = struct {
break :ord macho.BIND_SPECIAL_DYLIB_SELF;
};
- try setSegmentOffset(entry.segment_id, entry.offset, writer);
- try setSymbol(name, flags, writer);
- try setDylibOrdinal(ordinal, writer);
+ try setSegmentOffset(entry.segment_id, entry.offset, bw);
+ try setSymbol(name, flags, bw);
+ try setDylibOrdinal(ordinal, bw);
if (entry.addend != addend) {
- try setAddend(entry.addend, writer);
+ try setAddend(entry.addend, bw);
addend = entry.addend;
}
- try doBind(writer);
- try done(writer);
+ try doBind(bw);
+ try done(bw);
}
}
- pub fn write(self: Self, writer: anytype) !void {
- try writer.writeAll(self.buffer.items);
+ pub fn write(bind: LazyBind, bw: *Writer) Writer.Error!void {
+ try bw.writeAll(bind.buffer.items);
}
};
-fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void {
+fn setSegmentOffset(segment_id: u4, offset: u64, bw: *Writer) Writer.Error!void {
log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
- try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));
- try std.leb.writeUleb128(writer, offset);
+ try bw.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segment_id);
+ try bw.writeLeb128(offset);
}
-fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void {
+fn setSymbol(name: []const u8, flags: u4, bw: *Writer) Writer.Error!void {
log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });
- try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags)));
- try writer.writeAll(name);
- try writer.writeByte(0);
+ try bw.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
+ try bw.writeAll(name);
+ try bw.writeByte(0);
}
-fn setTypePointer(writer: anytype) !void {
+fn setTypePointer(bw: *Writer) Writer.Error!void {
log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});
- try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER)));
+ try bw.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @intCast(macho.BIND_TYPE_POINTER)));
}
-fn setDylibOrdinal(ordinal: i16, writer: anytype) !void {
- if (ordinal <= 0) {
- switch (ordinal) {
- macho.BIND_SPECIAL_DYLIB_SELF,
- macho.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE,
- macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP,
- => {},
- else => unreachable, // Invalid dylib special binding
- }
- log.debug(">>> set dylib special: {d}", .{ordinal});
- const cast = @as(u16, @bitCast(ordinal));
- try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @as(u4, @truncate(cast)));
- } else {
- const cast = @as(u16, @bitCast(ordinal));
- log.debug(">>> set dylib ordinal: {d}", .{ordinal});
- if (cast <= 0xf) {
- try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @as(u4, @truncate(cast)));
- } else {
- try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
- try std.leb.writeUleb128(writer, cast);
- }
+fn setDylibOrdinal(ordinal: i16, bw: *Writer) Writer.Error!void {
+ switch (ordinal) {
+ else => unreachable, // Invalid dylib special binding
+ macho.BIND_SPECIAL_DYLIB_SELF,
+ macho.BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE,
+ macho.BIND_SPECIAL_DYLIB_FLAT_LOOKUP,
+ => {
+ log.debug(">>> set dylib special: {d}", .{ordinal});
+ try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @as(u4, @bitCast(@as(i4, @intCast(ordinal)))));
+ },
+ 1...std.math.maxInt(i16) => {
+ log.debug(">>> set dylib ordinal: {d}", .{ordinal});
+ if (std.math.cast(u4, ordinal)) |imm| {
+ try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | imm);
+ } else {
+ try bw.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
+ try bw.writeUleb128(ordinal);
+ }
+ },
}
}
-fn setAddend(addend: i64, writer: anytype) !void {
+fn setAddend(addend: i64, bw: *Writer) Writer.Error!void {
log.debug(">>> set addend: {x}", .{addend});
- try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);
- try std.leb.writeIleb128(writer, addend);
+ try bw.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);
+ try bw.writeLeb128(addend);
}
-fn doBind(writer: anytype) !void {
+fn doBind(bw: *Writer) Writer.Error!void {
log.debug(">>> bind", .{});
- try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
+ try bw.writeByte(macho.BIND_OPCODE_DO_BIND);
}
-fn doBindAddAddr(addr: u64, writer: anytype) !void {
+fn doBindAddAddr(addr: u64, bw: *Writer) Writer.Error!void {
log.debug(">>> bind with add: {x}", .{addr});
- if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) {
- const imm = @divExact(addr, @sizeOf(u64));
- if (imm <= 0xf) {
- try writer.writeByte(
- macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | @as(u4, @truncate(imm)),
- );
- return;
- }
- }
- try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
- try std.leb.writeUleb128(writer, addr);
+ if (std.math.divExact(u64, addr, @sizeOf(u64))) |scaled| {
+ if (std.math.cast(u4, scaled)) |imm_scaled| return bw.writeByte(
+ macho.BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | imm_scaled,
+ );
+ } else |_| {}
+ try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
+ try bw.writeLeb128(addr);
}
-fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void {
+fn doBindTimesSkip(count: usize, skip: u64, bw: *Writer) Writer.Error!void {
log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });
- try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
- try std.leb.writeUleb128(writer, count);
- try std.leb.writeUleb128(writer, skip);
+ try bw.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
+ try bw.writeLeb128(count);
+ try bw.writeLeb128(skip);
}
-fn addAddr(addr: u64, writer: anytype) !void {
+fn addAddr(addr: u64, bw: *Writer) Writer.Error!void {
log.debug(">>> add: {x}", .{addr});
- try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);
- try std.leb.writeUleb128(writer, addr);
+ try bw.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);
+ try bw.writeLeb128(addr);
}
-fn done(writer: anytype) !void {
+fn done(bw: *Writer) Writer.Error!void {
log.debug(">>> done", .{});
- try writer.writeByte(macho.BIND_OPCODE_DONE);
+ try bw.writeByte(macho.BIND_OPCODE_DONE);
}
+const std = @import("std");
const assert = std.debug.assert;
const leb = std.leb;
const log = std.log.scoped(.link_dyld_info);
const macho = std.macho;
const mem = std.mem;
const testing = std.testing;
-const trace = @import("../../../tracy.zig").trace;
-const std = @import("std");
+const Allocator = std.mem.Allocator;
+const Writer = std.io.Writer;
-const Allocator = mem.Allocator;
+const trace = @import("../../../tracy.zig").trace;
const File = @import("../file.zig").File;
const MachO = @import("../../MachO.zig");
const Symbol = @import("../Symbol.zig");