mirror of
https://github.com/ziglang/zig.git
synced 2026-02-07 15:07:12 +00:00
139 lines
4.6 KiB
Zig
139 lines
4.6 KiB
Zig
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,
|
|
bind_flags: u4 = 0,
|
|
};
|
|
|
|
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 | pointer.bind_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 | pointer.bind_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);
|
|
}
|
|
}
|