| ... | @@ -577,9 +577,10 @@ const MachODumper = struct { | ... | @@ -577,9 +577,10 @@ const MachODumper = struct { |
| 577 | const writer = output.writer(); | 577 | const writer = output.writer(); |
| 578 | | 578 | |
| 579 | var symtab: ?Symtab = null; | 579 | var symtab: ?Symtab = null; |
| | 580 | var segments = std.ArrayList(macho.segment_command_u64); |
| 580 | var sections = std.ArrayList(macho.section_64).init(gpa); | 581 | var sections = std.ArrayList(macho.section_64).init(gpa); |
| 581 | var imports = std.ArrayList([]const u8).init(gpa); | 582 | var imports = std.ArrayList([]const u8).init(gpa); |
| 582 | var text_seg: ?macho.segment_command_64 = null; | 583 | var text_seg: ?u8 = null; |
| 583 | var dyld_info_lc: ?macho.dyld_info_command = null; | 584 | var dyld_info_lc: ?macho.dyld_info_command = null; |
| 584 | | 585 | |
| 585 | try dumpHeader(hdr, writer); | 586 | try dumpHeader(hdr, writer); |
| ... | @@ -597,8 +598,10 @@ const MachODumper = struct { | ... | @@ -597,8 +598,10 @@ const MachODumper = struct { |
| 597 | for (cmd.getSections()) |sect| { | 598 | for (cmd.getSections()) |sect| { |
| 598 | sections.appendAssumeCapacity(sect); | 599 | sections.appendAssumeCapacity(sect); |
| 599 | } | 600 | } |
| | 601 | const seg_id: u8 = @intCast(segments.items.len); |
| | 602 | try segments.append(seg); |
| 600 | if (mem.eql(u8, seg.segName(), "__TEXT")) { | 603 | if (mem.eql(u8, seg.segName(), "__TEXT")) { |
| 601 | text_seg = seg; | 604 | text_seg = seg_id; |
| 602 | } | 605 | } |
| 603 | }, | 606 | }, |
| 604 | .SYMTAB => { | 607 | .SYMTAB => { |
| ... | @@ -631,9 +634,13 @@ const MachODumper = struct { | ... | @@ -631,9 +634,13 @@ const MachODumper = struct { |
| 631 | | 634 | |
| 632 | if (dyld_info_lc) |lc| { | 635 | if (dyld_info_lc) |lc| { |
| 633 | try writer.writeAll(dyld_info_label ++ "\n"); | 636 | 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 | } |
| 634 | if (lc.export_size > 0) { | 641 | if (lc.export_size > 0) { |
| 635 | const data = bytes[lc.export_off..][0..lc.export_size]; | 642 | 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); |
| 637 | } | 644 | } |
| 638 | } | 645 | } |
| 639 | | 646 | |
| ... | @@ -994,6 +1001,91 @@ const MachODumper = struct { | ... | @@ -994,6 +1001,91 @@ const MachODumper = struct { |
| 994 | } | 1001 | } |
| 995 | } | 1002 | } |
| 996 | | 1003 | |
| | 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 | |
| 997 | fn dumpExportsTrie( | 1089 | fn dumpExportsTrie( |
| 998 | gpa: Allocator, | 1090 | gpa: Allocator, |
| 999 | data: []const u8, | 1091 | data: []const u8, |