mirror of
https://github.com/ziglang/zig.git
synced 2026-01-01 19:13:16 +00:00
macho: use latest bind functionality
This commit is contained in:
parent
1181543dad
commit
b9fa80e588
@ -12,6 +12,7 @@ const aarch64 = @import("../codegen/aarch64.zig");
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
|
||||
const bind = @import("MachO/bind.zig");
|
||||
const trace = @import("../tracy.zig").trace;
|
||||
const build_options = @import("build_options");
|
||||
const Module = @import("../Module.zig");
|
||||
@ -26,7 +27,6 @@ const Trie = @import("MachO/Trie.zig");
|
||||
const CodeSignature = @import("MachO/CodeSignature.zig");
|
||||
|
||||
usingnamespace @import("MachO/commands.zig");
|
||||
usingnamespace @import("MachO/imports.zig");
|
||||
|
||||
pub const base_tag: File.Tag = File.Tag.macho;
|
||||
|
||||
@ -108,9 +108,9 @@ locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
/// Table of all global symbols
|
||||
globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
|
||||
/// Table of all extern nonlazy symbols, indexed by name.
|
||||
nonlazy_imports: std.StringArrayHashMapUnmanaged(ExternSymbol) = .{},
|
||||
nonlazy_imports: std.StringArrayHashMapUnmanaged(Import) = .{},
|
||||
/// Table of all extern lazy symbols, indexed by name.
|
||||
lazy_imports: std.StringArrayHashMapUnmanaged(ExternSymbol) = .{},
|
||||
lazy_imports: std.StringArrayHashMapUnmanaged(Import) = .{},
|
||||
|
||||
locals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
globals_free_list: std.ArrayListUnmanaged(u32) = .{},
|
||||
@ -169,6 +169,17 @@ pie_fixups: std.ArrayListUnmanaged(PieFixup) = .{},
|
||||
/// rather than sitting in the global scope.
|
||||
stub_fixups: std.ArrayListUnmanaged(StubFixup) = .{},
|
||||
|
||||
pub const Import = struct {
|
||||
/// MachO symbol table entry.
|
||||
symbol: macho.nlist_64,
|
||||
|
||||
/// Id of the dynamic library where the specified entries can be found.
|
||||
dylib_ordinal: i64,
|
||||
|
||||
/// Index of this import within the import list.
|
||||
index: u32,
|
||||
};
|
||||
|
||||
pub const PieFixup = struct {
|
||||
/// Target address we wanted to address in absolute terms.
|
||||
address: u64,
|
||||
@ -1285,9 +1296,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
|
||||
try self.writeStubInStubHelper(fixup.symbol);
|
||||
try self.writeLazySymbolPointer(fixup.symbol);
|
||||
|
||||
const extern_sym = &self.lazy_imports.items()[fixup.symbol].value;
|
||||
extern_sym.segment = self.data_segment_cmd_index.?;
|
||||
extern_sym.offset = fixup.symbol * @sizeOf(u64);
|
||||
self.rebase_info_dirty = true;
|
||||
self.lazy_binding_info_dirty = true;
|
||||
}
|
||||
@ -2065,7 +2073,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
const name = try self.base.allocator.dupe(u8, "dyld_stub_binder");
|
||||
const offset = try self.makeString("dyld_stub_binder");
|
||||
try self.nonlazy_imports.putNoClobber(self.base.allocator, name, .{
|
||||
.inner = .{
|
||||
.symbol = .{
|
||||
.n_strx = offset,
|
||||
.n_type = std.macho.N_UNDF | std.macho.N_EXT,
|
||||
.n_sect = 0,
|
||||
@ -2073,8 +2081,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
|
||||
.n_value = 0,
|
||||
},
|
||||
.dylib_ordinal = 1, // TODO this is currently hardcoded.
|
||||
.segment = self.data_const_segment_cmd_index.?,
|
||||
.offset = index * @sizeOf(u64),
|
||||
.index = index,
|
||||
});
|
||||
self.binding_info_dirty = true;
|
||||
}
|
||||
@ -2238,7 +2245,7 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {
|
||||
const sym_name = try self.base.allocator.dupe(u8, name);
|
||||
const dylib_ordinal = 1; // TODO this is now hardcoded, since we only support libSystem.
|
||||
try self.lazy_imports.putNoClobber(self.base.allocator, sym_name, .{
|
||||
.inner = .{
|
||||
.symbol = .{
|
||||
.n_strx = offset,
|
||||
.n_type = macho.N_UNDF | macho.N_EXT,
|
||||
.n_sect = 0,
|
||||
@ -2246,6 +2253,7 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {
|
||||
.n_value = 0,
|
||||
},
|
||||
.dylib_ordinal = dylib_ordinal,
|
||||
.index = index,
|
||||
});
|
||||
log.debug("adding new extern symbol '{s}' with dylib ordinal '{}'", .{ name, dylib_ordinal });
|
||||
return index;
|
||||
@ -2767,10 +2775,10 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
|
||||
defer undefs.deinit();
|
||||
try undefs.ensureCapacity(nundefs);
|
||||
for (self.lazy_imports.items()) |entry| {
|
||||
undefs.appendAssumeCapacity(entry.value.inner);
|
||||
undefs.appendAssumeCapacity(entry.value.symbol);
|
||||
}
|
||||
for (self.nonlazy_imports.items()) |entry| {
|
||||
undefs.appendAssumeCapacity(entry.value.inner);
|
||||
undefs.appendAssumeCapacity(entry.value.symbol);
|
||||
}
|
||||
|
||||
const locals_off = symtab.symoff;
|
||||
@ -2832,20 +2840,20 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
|
||||
var writer = stream.writer();
|
||||
|
||||
stubs.reserved1 = 0;
|
||||
for (self.lazy_imports.items()) |_, i| {
|
||||
for (lazy) |_, i| {
|
||||
const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
|
||||
try writer.writeIntLittle(u32, symtab_idx);
|
||||
}
|
||||
|
||||
const base_id = @intCast(u32, lazy.len);
|
||||
got.reserved1 = base_id;
|
||||
for (self.nonlazy_imports.items()) |_, i| {
|
||||
for (nonlazy) |_, i| {
|
||||
const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id);
|
||||
try writer.writeIntLittle(u32, symtab_idx);
|
||||
}
|
||||
|
||||
la_symbol_ptr.reserved1 = got.reserved1 + @intCast(u32, nonlazy.len);
|
||||
for (self.lazy_imports.items()) |_, i| {
|
||||
for (lazy) |_, i| {
|
||||
const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
|
||||
try writer.writeIntLittle(u32, symtab_idx);
|
||||
}
|
||||
@ -2962,14 +2970,33 @@ fn writeRebaseInfoTable(self: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const size = try rebaseInfoSize(self.lazy_imports.items());
|
||||
var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
|
||||
defer pointers.deinit();
|
||||
|
||||
if (self.la_symbol_ptr_section_index) |idx| {
|
||||
try pointers.ensureCapacity(pointers.items.len + self.lazy_imports.items().len);
|
||||
const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
|
||||
const sect = seg.sections.items[idx];
|
||||
const base_offset = sect.addr - seg.inner.vmaddr;
|
||||
const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
|
||||
|
||||
for (self.lazy_imports.items()) |entry| {
|
||||
pointers.appendAssumeCapacity(.{
|
||||
.offset = base_offset + entry.value.index * @sizeOf(u64),
|
||||
.segment_id = segment_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std.sort.sort(bind.Pointer, pointers.items, {}, bind.pointerCmp);
|
||||
|
||||
const size = try bind.rebaseInfoSize(pointers.items);
|
||||
var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
|
||||
defer self.base.allocator.free(buffer);
|
||||
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
try writeRebaseInfo(self.lazy_imports.items(), stream.writer());
|
||||
try bind.writeRebaseInfo(pointers.items, stream.writer());
|
||||
|
||||
const linkedit_segment = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
|
||||
const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
|
||||
const allocated_size = self.allocatedSizeLinkedit(dyld_info.rebase_off);
|
||||
const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
|
||||
@ -2994,14 +3021,33 @@ fn writeBindingInfoTable(self: *MachO) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const size = try bindInfoSize(self.nonlazy_imports.items());
|
||||
var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
|
||||
defer pointers.deinit();
|
||||
|
||||
if (self.data_got_section_index) |idx| {
|
||||
try pointers.ensureCapacity(pointers.items.len + self.nonlazy_imports.items().len);
|
||||
const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
|
||||
const sect = seg.sections.items[idx];
|
||||
const base_offset = sect.addr - seg.inner.vmaddr;
|
||||
const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
|
||||
|
||||
for (self.nonlazy_imports.items()) |entry| {
|
||||
pointers.appendAssumeCapacity(.{
|
||||
.offset = base_offset + entry.value.index * @sizeOf(u64),
|
||||
.segment_id = segment_id,
|
||||
.dylib_ordinal = entry.value.dylib_ordinal,
|
||||
.name = entry.key,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const size = try bind.bindInfoSize(pointers.items);
|
||||
var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
|
||||
defer self.base.allocator.free(buffer);
|
||||
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
try writeBindInfo(self.nonlazy_imports.items(), stream.writer());
|
||||
try bind.writeBindInfo(pointers.items, stream.writer());
|
||||
|
||||
const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
|
||||
const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
|
||||
const allocated_size = self.allocatedSizeLinkedit(dyld_info.bind_off);
|
||||
const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
|
||||
@ -3023,14 +3069,36 @@ fn writeBindingInfoTable(self: *MachO) !void {
|
||||
fn writeLazyBindingInfoTable(self: *MachO) !void {
|
||||
if (!self.lazy_binding_info_dirty) return;
|
||||
|
||||
const size = try lazyBindInfoSize(self.lazy_imports.items());
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
var pointers = std.ArrayList(bind.Pointer).init(self.base.allocator);
|
||||
defer pointers.deinit();
|
||||
|
||||
if (self.la_symbol_ptr_section_index) |idx| {
|
||||
try pointers.ensureCapacity(self.lazy_imports.items().len);
|
||||
const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
|
||||
const sect = seg.sections.items[idx];
|
||||
const base_offset = sect.addr - seg.inner.vmaddr;
|
||||
const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
|
||||
|
||||
for (self.lazy_imports.items()) |entry| {
|
||||
pointers.appendAssumeCapacity(.{
|
||||
.offset = base_offset + entry.value.index * @sizeOf(u64),
|
||||
.segment_id = segment_id,
|
||||
.dylib_ordinal = entry.value.dylib_ordinal,
|
||||
.name = entry.key,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const size = try bind.lazyBindInfoSize(pointers.items);
|
||||
var buffer = try self.base.allocator.alloc(u8, @intCast(usize, size));
|
||||
defer self.base.allocator.free(buffer);
|
||||
|
||||
var stream = std.io.fixedBufferStream(buffer);
|
||||
try writeLazyBindInfo(self.lazy_imports.items(), stream.writer());
|
||||
try bind.writeLazyBindInfo(pointers.items, stream.writer());
|
||||
|
||||
const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
|
||||
const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
|
||||
const allocated_size = self.allocatedSizeLinkedit(dyld_info.lazy_bind_off);
|
||||
const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
|
||||
|
||||
145
src/link/MachO/bind.zig
Normal file
145
src/link/MachO/bind.zig
Normal file
@ -0,0 +1,145 @@
|
||||
const std = @import("std");
|
||||
const leb = std.leb;
|
||||
const macho = std.macho;
|
||||
|
||||
pub const Pointer = struct {
|
||||
offset: u64,
|
||||
segment_id: u16,
|
||||
dylib_ordinal: ?i64 = null,
|
||||
name: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn pointerCmp(context: void, a: Pointer, b: Pointer) bool {
|
||||
if (a.segment_id < b.segment_id) return true;
|
||||
if (a.segment_id == b.segment_id) {
|
||||
return a.offset < b.offset;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn rebaseInfoSize(pointers: []const Pointer) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (pointers) |pointer| {
|
||||
size += 2;
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
size += 1;
|
||||
}
|
||||
|
||||
size += 1 + stream.bytes_written;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeRebaseInfo(pointers: []const Pointer, writer: anytype) !void {
|
||||
for (pointers) |pointer| {
|
||||
try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.REBASE_TYPE_POINTER));
|
||||
try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, pointer.segment_id));
|
||||
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @truncate(u4, 1));
|
||||
}
|
||||
try writer.writeByte(macho.REBASE_OPCODE_DONE);
|
||||
}
|
||||
|
||||
pub fn bindInfoSize(pointers: []const Pointer) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (pointers) |pointer| {
|
||||
size += 1;
|
||||
if (pointer.dylib_ordinal.? > 15) {
|
||||
try leb.writeULEB128(writer, @bitCast(u64, pointer.dylib_ordinal.?));
|
||||
}
|
||||
size += 1;
|
||||
|
||||
size += 1;
|
||||
size += pointer.name.?.len;
|
||||
size += 1;
|
||||
|
||||
size += 1;
|
||||
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
size += 1;
|
||||
}
|
||||
|
||||
size += stream.bytes_written + 1;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeBindInfo(pointers: []const Pointer, writer: anytype) !void {
|
||||
for (pointers) |pointer| {
|
||||
if (pointer.dylib_ordinal.? > 15) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
|
||||
try leb.writeULEB128(writer, @bitCast(u64, pointer.dylib_ordinal.?));
|
||||
} else if (pointer.dylib_ordinal.? > 0) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @truncate(u4, @bitCast(u64, pointer.dylib_ordinal.?)));
|
||||
} else {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, pointer.dylib_ordinal.?)));
|
||||
}
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.BIND_TYPE_POINTER));
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags.
|
||||
try writer.writeAll(pointer.name.?);
|
||||
try writer.writeByte(0);
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, pointer.segment_id));
|
||||
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
|
||||
}
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_DONE);
|
||||
}
|
||||
|
||||
pub fn lazyBindInfoSize(pointers: []const Pointer) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (pointers) |pointer| {
|
||||
size += 1;
|
||||
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
|
||||
size += 1;
|
||||
if (pointer.dylib_ordinal.? > 15) {
|
||||
try leb.writeULEB128(writer, @bitCast(u64, pointer.dylib_ordinal.?));
|
||||
}
|
||||
|
||||
size += 1;
|
||||
size += pointer.name.?.len;
|
||||
size += 1;
|
||||
|
||||
size += 2;
|
||||
}
|
||||
|
||||
size += stream.bytes_written;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeLazyBindInfo(pointers: []const Pointer, writer: anytype) !void {
|
||||
for (pointers) |pointer| {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, pointer.segment_id));
|
||||
|
||||
try leb.writeILEB128(writer, pointer.offset);
|
||||
|
||||
if (pointer.dylib_ordinal.? > 15) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
|
||||
try leb.writeULEB128(writer, @bitCast(u64, pointer.dylib_ordinal.?));
|
||||
} else if (pointer.dylib_ordinal.? > 0) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @truncate(u4, @bitCast(u64, pointer.dylib_ordinal.?)));
|
||||
} else {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, pointer.dylib_ordinal.?)));
|
||||
}
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags.
|
||||
try writer.writeAll(pointer.name.?);
|
||||
try writer.writeByte(0);
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
|
||||
try writer.writeByte(macho.BIND_OPCODE_DONE);
|
||||
}
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
const std = @import("std");
|
||||
const leb = std.leb;
|
||||
const macho = std.macho;
|
||||
const mem = std.mem;
|
||||
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = mem.Allocator;
|
||||
|
||||
pub const ExternSymbol = struct {
|
||||
/// MachO symbol table entry.
|
||||
inner: macho.nlist_64,
|
||||
|
||||
/// Id of the dynamic library where the specified entries can be found.
|
||||
/// Id of 0 means self.
|
||||
/// TODO this should really be an id into the table of all defined
|
||||
/// dylibs.
|
||||
dylib_ordinal: i64 = 0,
|
||||
|
||||
/// Id of the segment where this symbol is defined (will have its address
|
||||
/// resolved).
|
||||
segment: u16 = 0,
|
||||
|
||||
/// Offset relative to the start address of the `segment`.
|
||||
offset: u32 = 0,
|
||||
};
|
||||
|
||||
pub fn rebaseInfoSize(symbols: anytype) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (symbols) |entry| {
|
||||
size += 2;
|
||||
try leb.writeILEB128(writer, entry.value.offset);
|
||||
size += 1;
|
||||
}
|
||||
|
||||
size += 1 + stream.bytes_written;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeRebaseInfo(symbols: anytype, writer: anytype) !void {
|
||||
for (symbols) |entry| {
|
||||
const symbol = entry.value;
|
||||
try writer.writeByte(macho.REBASE_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.REBASE_TYPE_POINTER));
|
||||
try writer.writeByte(macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment));
|
||||
try leb.writeILEB128(writer, symbol.offset);
|
||||
try writer.writeByte(macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES | @truncate(u4, 1));
|
||||
}
|
||||
try writer.writeByte(macho.REBASE_OPCODE_DONE);
|
||||
}
|
||||
|
||||
pub fn bindInfoSize(symbols: anytype) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (symbols) |entry| {
|
||||
const symbol = entry.value;
|
||||
|
||||
size += 1;
|
||||
if (symbol.dylib_ordinal > 15) {
|
||||
try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal));
|
||||
}
|
||||
size += 1;
|
||||
|
||||
size += 1;
|
||||
size += entry.key.len;
|
||||
size += 1;
|
||||
|
||||
size += 1;
|
||||
try leb.writeILEB128(writer, symbol.offset);
|
||||
size += 2;
|
||||
}
|
||||
|
||||
size += stream.bytes_written;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeBindInfo(symbols: anytype, writer: anytype) !void {
|
||||
for (symbols) |entry| {
|
||||
const symbol = entry.value;
|
||||
|
||||
if (symbol.dylib_ordinal > 15) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
|
||||
try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal));
|
||||
} else if (symbol.dylib_ordinal > 0) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal)));
|
||||
} else {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal)));
|
||||
}
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @truncate(u4, macho.BIND_TYPE_POINTER));
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags.
|
||||
try writer.writeAll(entry.key);
|
||||
try writer.writeByte(0);
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment));
|
||||
try leb.writeILEB128(writer, symbol.offset);
|
||||
try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
|
||||
try writer.writeByte(macho.BIND_OPCODE_DONE);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lazyBindInfoSize(symbols: anytype) !u64 {
|
||||
var stream = std.io.countingWriter(std.io.null_writer);
|
||||
var writer = stream.writer();
|
||||
var size: u64 = 0;
|
||||
|
||||
for (symbols) |entry| {
|
||||
const symbol = entry.value;
|
||||
size += 1;
|
||||
try leb.writeILEB128(writer, symbol.offset);
|
||||
size += 1;
|
||||
if (symbol.dylib_ordinal > 15) {
|
||||
try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal));
|
||||
}
|
||||
|
||||
size += 1;
|
||||
size += entry.key.len;
|
||||
size += 1;
|
||||
|
||||
size += 2;
|
||||
}
|
||||
|
||||
size += stream.bytes_written;
|
||||
return size;
|
||||
}
|
||||
|
||||
pub fn writeLazyBindInfo(symbols: anytype, writer: anytype) !void {
|
||||
for (symbols) |entry| {
|
||||
const symbol = entry.value;
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @truncate(u4, symbol.segment));
|
||||
try leb.writeILEB128(writer, symbol.offset);
|
||||
|
||||
if (symbol.dylib_ordinal > 15) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
|
||||
try leb.writeULEB128(writer, @bitCast(u64, symbol.dylib_ordinal));
|
||||
} else if (symbol.dylib_ordinal > 0) {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal)));
|
||||
} else {
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | @truncate(u4, @bitCast(u64, symbol.dylib_ordinal)));
|
||||
}
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM); // TODO Sometimes we might want to add flags.
|
||||
try writer.writeAll(entry.key);
|
||||
try writer.writeByte(0);
|
||||
|
||||
try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
|
||||
try writer.writeByte(macho.BIND_OPCODE_DONE);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user