| ... | ... | @@ -114,6 +114,8 @@ stub_helper_stubs_start_off: ?u64 = null, |
| 114 | 114 | |
| 115 | 115 | blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, |
| 116 | 116 | |
| 117 | has_dices: bool = false, |
| 118 | |
| 117 | 119 | pub const Output = struct { |
| 118 | 120 | tag: enum { exe, dylib }, |
| 119 | 121 | path: []const u8, |
| ... | ... | @@ -131,6 +133,7 @@ pub const TextBlock = struct { |
| 131 | 133 | size: u64, |
| 132 | 134 | alignment: u32, |
| 133 | 135 | rebases: std.ArrayList(u64), |
| 136 | dices: std.ArrayList(macho.data_in_code_entry), |
| 134 | 137 | next: ?*TextBlock = null, |
| 135 | 138 | prev: ?*TextBlock = null, |
| 136 | 139 | |
| ... | ... | @@ -149,6 +152,7 @@ pub const TextBlock = struct { |
| 149 | 152 | .size = undefined, |
| 150 | 153 | .alignment = undefined, |
| 151 | 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 | 167 | self.allocator.free(self.code); |
| 164 | 168 | self.relocs.deinit(); |
| 165 | 169 | self.rebases.deinit(); |
| 170 | self.dices.deinit(); |
| 166 | 171 | } |
| 167 | 172 | |
| 168 | 173 | pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void { |
| ... | ... | @@ -205,6 +210,9 @@ pub const TextBlock = struct { |
| 205 | 210 | if (self.rebases.items.len > 0) { |
| 206 | 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 | 216 | log.warn(" size = {}", .{self.size}); |
| 209 | 217 | log.warn(" align = {}", .{self.alignment}); |
| 210 | 218 | } |
| ... | ... | @@ -2071,8 +2079,7 @@ fn flush(self: *Zld) !void { |
| 2071 | 2079 | try self.writeBindInfoTable(); |
| 2072 | 2080 | try self.writeLazyBindInfoTable(); |
| 2073 | 2081 | try self.writeExportInfo(); |
| 2074 | | // TODO DICE for x86_64 |
| 2075 | | // try self.writeDataInCode(); |
| 2082 | try self.writeDices(); |
| 2076 | 2083 | |
| 2077 | 2084 | { |
| 2078 | 2085 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| ... | ... | @@ -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 | 2619 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2611 | 2620 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].LinkeditData; |
| 2612 | 2621 | const fileoff = seg.inner.fileoff + seg.inner.filesize; |
| ... | ... | @@ -2614,24 +2623,40 @@ fn writeDataInCode(self: *Zld) !void { |
| 2614 | 2623 | var buf = std.ArrayList(u8).init(self.allocator); |
| 2615 | 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 | 2635 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2618 | 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( |
| 2624 | | buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), |
| 2625 | | ); |
| 2626 | | for (object.data_in_code_entries.items) |dice| { |
| 2627 | | const new_dice: macho.data_in_code_entry = .{ |
| 2628 | | .offset = text_sect.offset + target_map.offset + dice.offset, |
| 2629 | | .length = dice.length, |
| 2630 | | .kind = dice.kind, |
| 2631 | | }; |
| 2632 | | buf.appendSliceAssumeCapacity(mem.asBytes(&new_dice)); |
| 2638 | while (true) { |
| 2639 | if (block.dices.items.len > 0) { |
| 2640 | const sym = self.locals.items[block.local_sym_index]; |
| 2641 | const reg = sym.payload.regular; |
| 2642 | const base_off = try math.cast(u32, reg.address - text_sect.addr + text_sect.offset); |
| 2643 | |
| 2644 | try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry)); |
| 2645 | for (block.dices.items) |dice| { |
| 2646 | const rebased_dice = macho.data_in_code_entry{ |
| 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 | 2660 | const datasize = @intCast(u32, buf.items.len); |
| 2636 | 2661 | |
| 2637 | 2662 | dice_cmd.dataoff = @intCast(u32, fileoff); |