authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-10 00:14:53+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-12-10 00:14:53+01:00
log5bda88f9a37604f95e66274362b98514c685c715
tree937a3e294faca1b8a72d859ecd1a5332e99ef247
parent40952b4cdbd81e10236ba4b6c126b46a8b87b60e

lib/std/Build/CheckObject: dump Mach-O dyld_info_only rebase data


1 files changed, 95 insertions(+), 3 deletions(-)

lib/std/Build/Step/CheckObject.zig+95-3
......@@ -577,9 +577,10 @@ const MachODumper = struct {
577577 const writer = output.writer();
578578
579579 var symtab: ?Symtab = null;
580 var segments = std.ArrayList(macho.segment_command_u64);
580581 var sections = std.ArrayList(macho.section_64).init(gpa);
581582 var imports = std.ArrayList([]const u8).init(gpa);
582 var text_seg: ?macho.segment_command_64 = null;
583 var text_seg: ?u8 = null;
583584 var dyld_info_lc: ?macho.dyld_info_command = null;
584585
585586 try dumpHeader(hdr, writer);
......@@ -597,8 +598,10 @@ const MachODumper = struct {
597598 for (cmd.getSections()) |sect| {
598599 sections.appendAssumeCapacity(sect);
599600 }
601 const seg_id: u8 = @intCast(segments.items.len);
602 try segments.append(seg);
600603 if (mem.eql(u8, seg.segName(), "__TEXT")) {
601 text_seg = seg;
604 text_seg = seg_id;
602605 }
603606 },
604607 .SYMTAB => {
......@@ -631,9 +634,13 @@ const MachODumper = struct {
631634
632635 if (dyld_info_lc) |lc| {
633636 try writer.writeAll(dyld_info_label ++ "\n");
637 if (lc.rebase_size > 0) {
638 const data = bytes[lc.rebase_off..][0..lc.rebase_size];
639 try dumpRebaseInfo(gpa, data, segments.items, writer);
640 }
634641 if (lc.export_size > 0) {
635642 const data = bytes[lc.export_off..][0..lc.export_size];
636 try dumpExportsTrie(gpa, data, text_seg.?, writer);
643 try dumpExportsTrie(gpa, data, segments.items[text_seg.?], writer);
637644 }
638645 }
639646
......@@ -994,6 +1001,91 @@ const MachODumper = struct {
9941001 }
9951002 }
9961003
1004 fn dumpRebaseInfo(
1005 gpa: Allocator,
1006 data: []const u8,
1007 segments: []const macho.segment_command_64,
1008 writer: anytype,
1009 ) !void {
1010 var rebases = std.ArrayList(u64).init(gpa);
1011 defer rebases.deinit();
1012 try parseRebaseInfo(data, segments, &rebases);
1013 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
1014 try writer.writeAll("rebase info\n");
1015 for (rebases.items) |addr| {
1016 try writer.print("0x{x}\n", .{addr});
1017 }
1018 }
1019
1020 fn parseRebaseInfo(
1021 data: []const u8,
1022 segments: []const macho.segment_command_64,
1023 rebases: *std.ArrayList(u64),
1024 ) !void {
1025 var stream = std.io.fixedBufferStream(data);
1026 var creader = std.io.countingReader(stream.reader());
1027 const reader = creader.reader();
1028
1029 var seg_id: ?u8 = null;
1030 var offset: u64 = 0;
1031 while (true) {
1032 const byte = reader.readByte() catch break;
1033 const opc = byte & macho.REBASE_OPCODE_MASK;
1034 const imm = byte & macho.REBASE_IMMEDIATE_MASK;
1035 switch (opc) {
1036 macho.REBASE_OPCODE_DONE => break,
1037 macho.REBASE_OPCODE_SET_TYPE_IMM => {},
1038 macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
1039 seg_id = imm;
1040 offset = try std.leb.readULEB128(u64, reader);
1041 },
1042 macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => {
1043 offset += imm * @sizeOf(u64);
1044 },
1045 macho.REBASE_OPCODE_ADD_ADDR_ULEB => {
1046 const addend = try std.leb.readULEB128(u64, reader);
1047 offset += addend;
1048 },
1049 macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => {
1050 const addend = try std.leb.readULEB128(u64, reader);
1051 const seg = segments.items[seg_id.?];
1052 const addr = seg.vmaddr + offset;
1053 try rebases.append(addr);
1054 offset += addend + @sizeOf(u64);
1055 },
1056 macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES,
1057 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES,
1058 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB,
1059 => {
1060 var ntimes: u64 = 1;
1061 var skip: u64 = 0;
1062 switch (opc) {
1063 macho.REBASE_OPCODE_DO_REBASE_IMM_TIMES => {
1064 ntimes = imm;
1065 },
1066 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => {
1067 ntimes = try std.leb.readULEB128(u64, reader);
1068 },
1069 macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => {
1070 ntimes = try std.leb.readULEB128(u64, reader);
1071 skip = try std.leb.readULEB128(u64, reader);
1072 },
1073 else => unreachable,
1074 }
1075 const seg = segments.items[seg_id.?];
1076 const base_addr = seg.vmaddr;
1077 var count: usize = 0;
1078 while (count < ntimes) : (count += 1) {
1079 const addr = base_addr + offset;
1080 try rebases.append(addr);
1081 offset += skip + @sizeOf(u64);
1082 }
1083 },
1084 else => break,
1085 }
1086 }
1087 }
1088
9971089 fn dumpExportsTrie(
9981090 gpa: Allocator,
9991091 data: []const u8,