| ... | ... | @@ -187,7 +187,6 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 187 | 187 | |
| 188 | 188 | load_commands_dirty: bool = false, |
| 189 | 189 | sections_order_dirty: bool = false, |
| 190 | | has_dices: bool = false, |
| 191 | 190 | |
| 192 | 191 | /// A helper var to indicate if we are at the start of the incremental updates, or |
| 193 | 192 | /// already somewhere further along the update-and-run chain. |
| ... | ... | @@ -6139,55 +6138,74 @@ fn writeFunctionStarts(self: *MachO) !void { |
| 6139 | 6138 | self.load_commands_dirty = true; |
| 6140 | 6139 | } |
| 6141 | 6140 | |
| 6142 | | fn writeDices(self: *MachO) !void { |
| 6143 | | if (!self.has_dices) return; |
| 6141 | fn filterDataInCode( |
| 6142 | dices: []const macho.data_in_code_entry, |
| 6143 | start_addr: u64, |
| 6144 | end_addr: u64, |
| 6145 | ) []const macho.data_in_code_entry { |
| 6146 | const Predicate = struct { |
| 6147 | addr: u64, |
| 6144 | 6148 | |
| 6149 | pub fn predicate(self: @This(), dice: macho.data_in_code_entry) bool { |
| 6150 | return dice.offset >= self.addr; |
| 6151 | } |
| 6152 | }; |
| 6153 | |
| 6154 | const start = MachO.findFirst(macho.data_in_code_entry, dices, 0, Predicate{ .addr = start_addr }); |
| 6155 | const end = MachO.findFirst(macho.data_in_code_entry, dices, start, Predicate{ .addr = end_addr }); |
| 6156 | |
| 6157 | return dices[start..end]; |
| 6158 | } |
| 6159 | |
| 6160 | fn writeDataInCode(self: *MachO) !void { |
| 6145 | 6161 | const tracy = trace(@src()); |
| 6146 | 6162 | defer tracy.end(); |
| 6147 | 6163 | |
| 6148 | | var buf = std.ArrayList(u8).init(self.base.allocator); |
| 6149 | | defer buf.deinit(); |
| 6164 | var out_dice = std.ArrayList(macho.data_in_code_entry).init(self.base.allocator); |
| 6165 | defer out_dice.deinit(); |
| 6150 | 6166 | |
| 6151 | | var atom: *Atom = self.atoms.get(.{ |
| 6167 | const text_sect = self.getSection(.{ |
| 6152 | 6168 | .seg = self.text_segment_cmd_index orelse return, |
| 6153 | 6169 | .sect = self.text_section_index orelse return, |
| 6154 | | }) orelse return; |
| 6155 | | |
| 6156 | | while (atom.prev) |prev| { |
| 6157 | | atom = prev; |
| 6158 | | } |
| 6159 | | |
| 6160 | | const text_sect = self.getSection(.{ |
| 6161 | | .seg = self.text_segment_cmd_index.?, |
| 6162 | | .sect = self.text_section_index.?, |
| 6163 | 6170 | }); |
| 6164 | 6171 | |
| 6165 | | while (true) { |
| 6166 | | if (atom.dices.items.len > 0) { |
| 6172 | for (self.objects.items) |object| { |
| 6173 | const dice = object.parseDataInCode() orelse continue; |
| 6174 | const source_symtab = object.getSourceSymtab(); |
| 6175 | try out_dice.ensureUnusedCapacity(dice.len); |
| 6176 | |
| 6177 | for (object.managed_atoms.items) |atom| { |
| 6167 | 6178 | const sym = atom.getSymbol(self); |
| 6168 | | const base_off = math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset) orelse return error.Overflow; |
| 6169 | | |
| 6170 | | try buf.ensureUnusedCapacity(atom.dices.items.len * @sizeOf(macho.data_in_code_entry)); |
| 6171 | | for (atom.dices.items) |dice| { |
| 6172 | | const rebased_dice = macho.data_in_code_entry{ |
| 6173 | | .offset = base_off + dice.offset, |
| 6174 | | .length = dice.length, |
| 6175 | | .kind = dice.kind, |
| 6176 | | }; |
| 6177 | | buf.appendSliceAssumeCapacity(mem.asBytes(&rebased_dice)); |
| 6179 | if (sym.n_desc == N_DESC_GCED) continue; |
| 6180 | if (atom.sym_index >= source_symtab.len) continue; // synthetic, linker generated |
| 6181 | |
| 6182 | const match = self.getMatchingSectionFromOrdinal(sym.n_sect); |
| 6183 | if (match.seg != self.text_segment_cmd_index.? and match.sect != self.text_section_index.?) { |
| 6184 | continue; |
| 6178 | 6185 | } |
| 6179 | | } |
| 6180 | 6186 | |
| 6181 | | if (atom.next) |next| { |
| 6182 | | atom = next; |
| 6183 | | } else break; |
| 6187 | const source_sym = source_symtab[atom.sym_index]; |
| 6188 | const source_addr = math.cast(u32, source_sym.n_value) orelse return error.Overflow; |
| 6189 | const filtered_dice = filterDataInCode(dice, source_addr, source_addr + atom.size); |
| 6190 | const base = math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset) orelse |
| 6191 | return error.Overflow; |
| 6192 | |
| 6193 | for (filtered_dice) |single| { |
| 6194 | const offset = single.offset - source_addr + base; |
| 6195 | out_dice.appendAssumeCapacity(.{ |
| 6196 | .offset = offset, |
| 6197 | .length = single.length, |
| 6198 | .kind = single.kind, |
| 6199 | }); |
| 6200 | } |
| 6201 | } |
| 6184 | 6202 | } |
| 6185 | 6203 | |
| 6186 | 6204 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6187 | 6205 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].linkedit_data; |
| 6188 | 6206 | |
| 6189 | 6207 | const dataoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 6190 | | const datasize = buf.items.len; |
| 6208 | const datasize = out_dice.items.len * @sizeOf(macho.data_in_code_entry); |
| 6191 | 6209 | dice_cmd.dataoff = @intCast(u32, dataoff); |
| 6192 | 6210 | dice_cmd.datasize = @intCast(u32, datasize); |
| 6193 | 6211 | seg.inner.filesize = dice_cmd.dataoff + dice_cmd.datasize - seg.inner.fileoff; |
| ... | ... | @@ -6197,7 +6215,7 @@ fn writeDices(self: *MachO) !void { |
| 6197 | 6215 | dice_cmd.dataoff + dice_cmd.datasize, |
| 6198 | 6216 | }); |
| 6199 | 6217 | |
| 6200 | | try self.base.file.?.pwriteAll(buf.items, dice_cmd.dataoff); |
| 6218 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(out_dice.items), dice_cmd.dataoff); |
| 6201 | 6219 | self.load_commands_dirty = true; |
| 6202 | 6220 | } |
| 6203 | 6221 | |
| ... | ... | @@ -6392,7 +6410,7 @@ fn writeLinkeditSegment(self: *MachO) !void { |
| 6392 | 6410 | |
| 6393 | 6411 | try self.writeDyldInfoData(); |
| 6394 | 6412 | try self.writeFunctionStarts(); |
| 6395 | | try self.writeDices(); |
| 6413 | try self.writeDataInCode(); |
| 6396 | 6414 | try self.writeSymtab(); |
| 6397 | 6415 | try self.writeStrtab(); |
| 6398 | 6416 | |