mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
lib/std/Build/CheckObject: dump Mach-O dyld_info_only rebase data
This commit is contained in:
parent
40952b4cdb
commit
5bda88f9a3
1 changed files with 95 additions and 3 deletions
|
|
@ -577,9 +577,10 @@ const MachODumper = struct {
|
|||
const writer = output.writer();
|
||||
|
||||
var symtab: ?Symtab = null;
|
||||
var segments = std.ArrayList(macho.segment_command_u64);
|
||||
var sections = std.ArrayList(macho.section_64).init(gpa);
|
||||
var imports = std.ArrayList([]const u8).init(gpa);
|
||||
var text_seg: ?macho.segment_command_64 = null;
|
||||
var text_seg: ?u8 = null;
|
||||
var dyld_info_lc: ?macho.dyld_info_command = null;
|
||||
|
||||
try dumpHeader(hdr, writer);
|
||||
|
|
@ -597,8 +598,10 @@ const MachODumper = struct {
|
|||
for (cmd.getSections()) |sect| {
|
||||
sections.appendAssumeCapacity(sect);
|
||||
}
|
||||
const seg_id: u8 = @intCast(segments.items.len);
|
||||
try segments.append(seg);
|
||||
if (mem.eql(u8, seg.segName(), "__TEXT")) {
|
||||
text_seg = seg;
|
||||
text_seg = seg_id;
|
||||
}
|
||||
},
|
||||
.SYMTAB => {
|
||||
|
|
@ -631,9 +634,13 @@ const MachODumper = struct {
|
|||
|
||||
if (dyld_info_lc) |lc| {
|
||||
try writer.writeAll(dyld_info_label ++ "\n");
|
||||
if (lc.rebase_size > 0) {
|
||||
const data = bytes[lc.rebase_off..][0..lc.rebase_size];
|
||||
try dumpRebaseInfo(gpa, data, segments.items, writer);
|
||||
}
|
||||
if (lc.export_size > 0) {
|
||||
const data = bytes[lc.export_off..][0..lc.export_size];
|
||||
try dumpExportsTrie(gpa, data, text_seg.?, writer);
|
||||
try dumpExportsTrie(gpa, data, segments.items[text_seg.?], writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -994,6 +1001,91 @@ const MachODumper = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn dumpRebaseInfo(
|
||||
gpa: Allocator,
|
||||
data: []const u8,
|
||||
segments: []const macho.segment_command_64,
|
||||
writer: anytype,
|
||||
) !void {
|
||||
var rebases = std.ArrayList(u64).init(gpa);
|
||||
defer rebases.deinit();
|
||||
try parseRebaseInfo(data, segments, &rebases);
|
||||
mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
|
||||
try writer.writeAll("rebase info\n");
|
||||
for (rebases.items) |addr| {
|
||||
try writer.print("0x{x}\n", .{addr});
|
||||
}
|
||||
}
|
||||
|
||||
fn parseRebaseInfo(
|
||||
data: []const u8,
|
||||
segments: []const macho.segment_command_64,
|
||||
rebases: *std.ArrayList(u64),
|
||||
) !void {
|
||||
var stream = std.io.fixedBufferStream(data);
|
||||
var creader = std.io.countingReader(stream.reader());
|
||||
const reader = creader.reader();
|
||||
|
||||
var seg_id: ?u8 = null;
|
||||
var offset: u64 = 0;
|
||||
while (true) {
|
||||
const byte = reader.readByte() catch break;
|
||||
const opc = byte & macho.REBASE_OPCODE_MASK;
|
||||
const imm = byte & macho.REBASE_IMMEDIATE_MASK;
|
||||
switch (opc) {
|
||||
macho.REBASE_OPCODE_DONE => break,
|
||||
macho.REBASE_OPCODE_SET_TYPE_IMM => {},
|
||||
macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
|
||||
seg_id = imm;
|
||||
offset = try std.leb.readULEB128(u64, reader);
|
||||
},
|
||||
macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
|
||||
offset += imm * @sizeOf(u64);
|
||||
},
|
||||
macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
|
||||
const addend = try std.leb.readULEB128(u64, reader);
|
||||
offset += addend;
|
||||
},
|
||||
macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
|
||||
const addend = try std.leb.readULEB128(u64, reader);
|
||||
const seg = segments.items[seg_id.?];
|
||||
const addr = seg.vmaddr + offset;
|
||||
try rebases.append(addr);
|
||||
offset += addend + @sizeOf(u64);
|
||||
},
|
||||
macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES,
|
||||
macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES,
|
||||
macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB,
|
||||
=> {
|
||||
var ntimes: u64 = 1;
|
||||
var skip: u64 = 0;
|
||||
switch (opc) {
|
||||
macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES => {
|
||||
ntimes = imm;
|
||||
},
|
||||
macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
|
||||
ntimes = try std.leb.readULEB128(u64, reader);
|
||||
},
|
||||
macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
|
||||
ntimes = try std.leb.readULEB128(u64, reader);
|
||||
skip = try std.leb.readULEB128(u64, reader);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
const seg = segments.items[seg_id.?];
|
||||
const base_addr = seg.vmaddr;
|
||||
var count: usize = 0;
|
||||
while (count < ntimes) : (count += 1) {
|
||||
const addr = base_addr + offset;
|
||||
try rebases.append(addr);
|
||||
offset += skip + @sizeOf(u64);
|
||||
}
|
||||
},
|
||||
else => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dumpExportsTrie(
|
||||
gpa: Allocator,
|
||||
data: []const u8,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue