| ... | @@ -114,6 +114,8 @@ stub_helper_stubs_start_off: ?u64 = null, | ... | @@ -114,6 +114,8 @@ stub_helper_stubs_start_off: ?u64 = null, |
| 114 | | 114 | |
| 115 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, | 115 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 116 | | 116 | |
| | 117 | has_dices: bool = false, |
| | 118 | |
| 117 | pub const Output = struct { | 119 | pub const Output = struct { |
| 118 | tag: enum { exe, dylib }, | 120 | tag: enum { exe, dylib }, |
| 119 | path: []const u8, | 121 | path: []const u8, |
| ... | @@ -131,6 +133,7 @@ pub const TextBlock = struct { | ... | @@ -131,6 +133,7 @@ pub const TextBlock = struct { |
| 131 | size: u64, | 133 | size: u64, |
| 132 | alignment: u32, | 134 | alignment: u32, |
| 133 | rebases: std.ArrayList(u64), | 135 | rebases: std.ArrayList(u64), |
| | 136 | dices: std.ArrayList(macho.data_in_code_entry), |
| 134 | next: ?*TextBlock = null, | 137 | next: ?*TextBlock = null, |
| 135 | prev: ?*TextBlock = null, | 138 | prev: ?*TextBlock = null, |
| 136 | | 139 | |
| ... | @@ -149,6 +152,7 @@ pub const TextBlock = struct { | ... | @@ -149,6 +152,7 @@ pub const TextBlock = struct { |
| 149 | .size = undefined, | 152 | .size = undefined, |
| 150 | .alignment = undefined, | 153 | .alignment = undefined, |
| 151 | .rebases = std.ArrayList(u64).init(allocator), | 154 | .rebases = std.ArrayList(u64).init(allocator), |
| | 155 | .dices = std.ArrayList(macho.data_in_code_entry).init(allocator), |
| 152 | }; | 156 | }; |
| 153 | } | 157 | } |
| 154 | | 158 | |
| ... | @@ -163,6 +167,7 @@ pub const TextBlock = struct { | ... | @@ -163,6 +167,7 @@ pub const TextBlock = struct { |
| 163 | self.allocator.free(self.code); | 167 | self.allocator.free(self.code); |
| 164 | self.relocs.deinit(); | 168 | self.relocs.deinit(); |
| 165 | self.rebases.deinit(); | 169 | self.rebases.deinit(); |
| | 170 | self.dices.deinit(); |
| 166 | } | 171 | } |
| 167 | | 172 | |
| 168 | pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void { | 173 | pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void { |
| ... | @@ -205,6 +210,9 @@ pub const TextBlock = struct { | ... | @@ -205,6 +210,9 @@ pub const TextBlock = struct { |
| 205 | if (self.rebases.items.len > 0) { | 210 | if (self.rebases.items.len > 0) { |
| 206 | log.warn(" rebases: {any}", .{self.rebases.items}); | 211 | log.warn(" rebases: {any}", .{self.rebases.items}); |
| 207 | } | 212 | } |
| | 213 | if (self.dices.items.len > 0) { |
| | 214 | log.warn(" dices: {any}", .{self.dices.items}); |
| | 215 | } |
| 208 | log.warn(" size = {}", .{self.size}); | 216 | log.warn(" size = {}", .{self.size}); |
| 209 | log.warn(" align = {}", .{self.alignment}); | 217 | log.warn(" align = {}", .{self.alignment}); |
| 210 | } | 218 | } |
| ... | @@ -2071,8 +2079,7 @@ fn flush(self: *Zld) !void { | ... | @@ -2071,8 +2079,7 @@ fn flush(self: *Zld) !void { |
| 2071 | try self.writeBindInfoTable(); | 2079 | try self.writeBindInfoTable(); |
| 2072 | try self.writeLazyBindInfoTable(); | 2080 | try self.writeLazyBindInfoTable(); |
| 2073 | try self.writeExportInfo(); | 2081 | try self.writeExportInfo(); |
| 2074 | // TODO DICE for x86_64 | 2082 | try self.writeDices(); |
| 2075 | // try self.writeDataInCode(); | | |
| 2076 | | 2083 | |
| 2077 | { | 2084 | { |
| 2078 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2085 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| ... | @@ -2606,7 +2613,9 @@ fn writeStringTable(self: *Zld) !void { | ... | @@ -2606,7 +2613,9 @@ fn writeStringTable(self: *Zld) !void { |
| 2606 | } | 2613 | } |
| 2607 | } | 2614 | } |
| 2608 | | 2615 | |
| 2609 | fn writeDataInCode(self: *Zld) !void { | 2616 | fn writeDices(self: *Zld) !void { |
| | 2617 | if (!self.has_dices) return; |
| | 2618 | |
| 2610 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2619 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2611 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; | 2620 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; |
| 2612 | const fileoff = seg.inner.fileoff + seg.inner.filesize; | 2621 | const fileoff = seg.inner.fileoff + seg.inner.filesize; |
| ... | @@ -2614,24 +2623,40 @@ fn writeDataInCode(self: *Zld) !void { | ... | @@ -2614,24 +2623,40 @@ fn writeDataInCode(self: *Zld) !void { |
| 2614 | var buf = std.ArrayList(u8).init(self.allocator); | 2623 | var buf = std.ArrayList(u8).init(self.allocator); |
| 2615 | defer buf.deinit(); | 2624 | defer buf.deinit(); |
| 2616 | | 2625 | |
| | 2626 | var block: *TextBlock = self.blocks.get(.{ |
| | 2627 | .seg = self.text_segment_cmd_index orelse return, |
| | 2628 | .sect = self.text_section_index orelse return, |
| | 2629 | }) orelse return; |
| | 2630 | |
| | 2631 | while (block.prev) |prev| { |
| | 2632 | block = prev; |
| | 2633 | } |
| | 2634 | |
| 2617 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2635 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2618 | const text_sect = text_seg.sections.items[self.text_section_index.?]; | 2636 | const text_sect = text_seg.sections.items[self.text_section_index.?]; |
| 2619 | for (self.objects.items) |object| { | | |
| 2620 | const source_sect = object.sections.items[object.text_section_index.?]; | | |
| 2621 | const target_map = source_sect.target_map orelse continue; | | |
| 2622 | | 2637 | |
| 2623 | try buf.ensureCapacity( | 2638 | while (true) { |
| 2624 | buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), | 2639 | if (block.dices.items.len > 0) { |
| 2625 | ); | 2640 | const sym = self.locals.items[block.local_sym_index]; |
| 2626 | for (object.data_in_code_entries.items) |dice| { | 2641 | const reg = sym.payload.regular; |
| 2627 | const new_dice: macho.data_in_code_entry = .{ | 2642 | const base_off = try math.cast(u32, reg.address - text_sect.addr + text_sect.offset); |
| 2628 | .offset = text_sect.offset + target_map.offset + dice.offset, | 2643 | |
| 2629 | .length = dice.length, | 2644 | try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry)); |
| 2630 | .kind = dice.kind, | 2645 | for (block.dices.items) |dice| { |
| 2631 | }; | 2646 | const rebased_dice = macho.data_in_code_entry{ |
| 2632 | buf.appendSliceAssumeCapacity(mem.asBytes(&new_dice)); | 2647 | .offset = base_off + dice.offset, |
| | 2648 | .length = dice.length, |
| | 2649 | .kind = dice.kind, |
| | 2650 | }; |
| | 2651 | buf.appendSliceAssumeCapacity(mem.asBytes(&rebased_dice)); |
| | 2652 | } |
| 2633 | } | 2653 | } |
| | 2654 | |
| | 2655 | if (block.next) |next| { |
| | 2656 | block = next; |
| | 2657 | } else break; |
| 2634 | } | 2658 | } |
| | 2659 | |
| 2635 | const datasize = @intCast(u32, buf.items.len); | 2660 | const datasize = @intCast(u32, buf.items.len); |
| 2636 | | 2661 | |
| 2637 | dice_cmd.dataoff = @intCast(u32, fileoff); | 2662 | dice_cmd.dataoff = @intCast(u32, fileoff); |