| author | |
| committer | |
| log | a089a6dc4ff04a10360019185ecaacd0564eb84c |
| tree | d4d0bb835024ad110fdbdbff3513f2777906b70d |
| parent | 2c184f9a5fc78be4f38cc74106c203b7bc80deb4 |
3 files changed, 55 insertions(+), 84 deletions(-)
src/link/MachO.zig+52-34| ... | @@ -187,7 +187,6 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, | ... | @@ -187,7 +187,6 @@ error_flags: File.ErrorFlags = File.ErrorFlags{}, |
| 187 | 187 | ||
| 188 | load_commands_dirty: bool = false, | 188 | load_commands_dirty: bool = false, |
| 189 | sections_order_dirty: bool = false, | 189 | sections_order_dirty: bool = false, |
| 190 | has_dices: bool = false, | ||
| 191 | 190 | ||
| 192 | /// A helper var to indicate if we are at the start of the incremental updates, or | 191 | /// A helper var to indicate if we are at the start of the incremental updates, or |
| 193 | /// already somewhere further along the update-and-run chain. | 192 | /// already somewhere further along the update-and-run chain. |
| ... | @@ -6139,55 +6138,74 @@ fn writeFunctionStarts(self: *MachO) !void { | ... | @@ -6139,55 +6138,74 @@ fn writeFunctionStarts(self: *MachO) !void { |
| 6139 | self.load_commands_dirty = true; | 6138 | self.load_commands_dirty = true; |
| 6140 | } | 6139 | } |
| 6141 | 6140 | ||
| 6142 | fn writeDices(self: *MachO) !void { | 6141 | fn filterDataInCode( |
| 6143 | if (!self.has_dices) return; | 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 | const tracy = trace(@src()); | 6161 | const tracy = trace(@src()); |
| 6146 | defer tracy.end(); | 6162 | defer tracy.end(); |
| 6147 | 6163 | ||
| 6148 | var buf = std.ArrayList(u8).init(self.base.allocator); | 6164 | var out_dice = std.ArrayList(macho.data_in_code_entry).init(self.base.allocator); |
| 6149 | defer buf.deinit(); | 6165 | defer out_dice.deinit(); |
| 6150 | 6166 | ||
| 6151 | var atom: *Atom = self.atoms.get(.{ | 6167 | const text_sect = self.getSection(.{ |
| 6152 | .seg = self.text_segment_cmd_index orelse return, | 6168 | .seg = self.text_segment_cmd_index orelse return, |
| 6153 | .sect = self.text_section_index orelse return, | 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) { | 6172 | for (self.objects.items) |object| { |
| 6166 | if (atom.dices.items.len > 0) { | 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 | const sym = atom.getSymbol(self); | 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; | 6179 | if (sym.n_desc == N_DESC_GCED) continue; |
| 6169 | 6180 | if (atom.sym_index >= source_symtab.len) continue; // synthetic, linker generated | |
| 6170 | try buf.ensureUnusedCapacity(atom.dices.items.len * @sizeOf(macho.data_in_code_entry)); | 6181 | |
| 6171 | for (atom.dices.items) |dice| { | 6182 | const match = self.getMatchingSectionFromOrdinal(sym.n_sect); |
| 6172 | const rebased_dice = macho.data_in_code_entry{ | 6183 | if (match.seg != self.text_segment_cmd_index.? and match.sect != self.text_section_index.?) { |
| 6173 | .offset = base_off + dice.offset, | 6184 | continue; |
| 6174 | .length = dice.length, | ||
| 6175 | .kind = dice.kind, | ||
| 6176 | }; | ||
| 6177 | buf.appendSliceAssumeCapacity(mem.asBytes(&rebased_dice)); | ||
| 6178 | } | 6185 | } |
| 6179 | } | ||
| 6180 | 6186 | ||
| 6181 | if (atom.next) |next| { | 6187 | const source_sym = source_symtab[atom.sym_index]; |
| 6182 | atom = next; | 6188 | const source_addr = math.cast(u32, source_sym.n_value) orelse return error.Overflow; |
| 6183 | } else break; | 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 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; | 6204 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; |
| 6187 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].linkedit_data; | 6205 | const dice_cmd = &self.load_commands.items[self.data_in_code_cmd_index.?].linkedit_data; |
| 6188 | 6206 | ||
| 6189 | const dataoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); | 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 | dice_cmd.dataoff = @intCast(u32, dataoff); | 6209 | dice_cmd.dataoff = @intCast(u32, dataoff); |
| 6192 | dice_cmd.datasize = @intCast(u32, datasize); | 6210 | dice_cmd.datasize = @intCast(u32, datasize); |
| 6193 | seg.inner.filesize = dice_cmd.dataoff + dice_cmd.datasize - seg.inner.fileoff; | 6211 | seg.inner.filesize = dice_cmd.dataoff + dice_cmd.datasize - seg.inner.fileoff; |
| ... | @@ -6197,7 +6215,7 @@ fn writeDices(self: *MachO) !void { | ... | @@ -6197,7 +6215,7 @@ fn writeDices(self: *MachO) !void { |
| 6197 | dice_cmd.dataoff + dice_cmd.datasize, | 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 | self.load_commands_dirty = true; | 6219 | self.load_commands_dirty = true; |
| 6202 | } | 6220 | } |
| 6203 | 6221 | ||
| ... | @@ -6392,7 +6410,7 @@ fn writeLinkeditSegment(self: *MachO) !void { | ... | @@ -6392,7 +6410,7 @@ fn writeLinkeditSegment(self: *MachO) !void { |
| 6392 | 6410 | ||
| 6393 | try self.writeDyldInfoData(); | 6411 | try self.writeDyldInfoData(); |
| 6394 | try self.writeFunctionStarts(); | 6412 | try self.writeFunctionStarts(); |
| 6395 | try self.writeDices(); | 6413 | try self.writeDataInCode(); |
| 6396 | try self.writeSymtab(); | 6414 | try self.writeSymtab(); |
| 6397 | try self.writeStrtab(); | 6415 | try self.writeStrtab(); |
| 6398 | 6416 |
src/link/MachO/Atom.zig-5| ... | @@ -59,9 +59,6 @@ bindings: std.ArrayListUnmanaged(Binding) = .{}, | ... | @@ -59,9 +59,6 @@ bindings: std.ArrayListUnmanaged(Binding) = .{}, |
| 59 | /// List of lazy bindings (cf bindings above). | 59 | /// List of lazy bindings (cf bindings above). |
| 60 | lazy_bindings: std.ArrayListUnmanaged(Binding) = .{}, | 60 | lazy_bindings: std.ArrayListUnmanaged(Binding) = .{}, |
| 61 | 61 | ||
| 62 | /// List of data-in-code entries. This is currently specific to x86_64 only. | ||
| 63 | dices: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | ||
| 64 | |||
| 65 | /// Points to the previous and next neighbours | 62 | /// Points to the previous and next neighbours |
| 66 | next: ?*Atom, | 63 | next: ?*Atom, |
| 67 | prev: ?*Atom, | 64 | prev: ?*Atom, |
| ... | @@ -147,7 +144,6 @@ pub const empty = Atom{ | ... | @@ -147,7 +144,6 @@ pub const empty = Atom{ |
| 147 | }; | 144 | }; |
| 148 | 145 | ||
| 149 | pub fn deinit(self: *Atom, allocator: Allocator) void { | 146 | pub fn deinit(self: *Atom, allocator: Allocator) void { |
| 150 | self.dices.deinit(allocator); | ||
| 151 | self.lazy_bindings.deinit(allocator); | 147 | self.lazy_bindings.deinit(allocator); |
| 152 | self.bindings.deinit(allocator); | 148 | self.bindings.deinit(allocator); |
| 153 | self.rebases.deinit(allocator); | 149 | self.rebases.deinit(allocator); |
| ... | @@ -157,7 +153,6 @@ pub fn deinit(self: *Atom, allocator: Allocator) void { | ... | @@ -157,7 +153,6 @@ pub fn deinit(self: *Atom, allocator: Allocator) void { |
| 157 | } | 153 | } |
| 158 | 154 | ||
| 159 | pub fn clearRetainingCapacity(self: *Atom) void { | 155 | pub fn clearRetainingCapacity(self: *Atom) void { |
| 160 | self.dices.clearRetainingCapacity(); | ||
| 161 | self.lazy_bindings.clearRetainingCapacity(); | 156 | self.lazy_bindings.clearRetainingCapacity(); |
| 162 | self.bindings.clearRetainingCapacity(); | 157 | self.bindings.clearRetainingCapacity(); |
| 163 | self.rebases.clearRetainingCapacity(); | 158 | self.rebases.clearRetainingCapacity(); |
src/link/MachO/Object.zig+3-45| ... | @@ -177,7 +177,6 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { | ... | @@ -177,7 +177,6 @@ pub fn parse(self: *Object, allocator: Allocator, target: std.Target) !void { |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | try self.parseSymtab(allocator); | 179 | try self.parseSymtab(allocator); |
| 180 | self.parseDataInCode(); | ||
| 181 | } | 180 | } |
| 182 | 181 | ||
| 183 | const Context = struct { | 182 | const Context = struct { |
| ... | @@ -264,25 +263,6 @@ fn filterRelocs( | ... | @@ -264,25 +263,6 @@ fn filterRelocs( |
| 264 | return relocs[start..end]; | 263 | return relocs[start..end]; |
| 265 | } | 264 | } |
| 266 | 265 | ||
| 267 | fn filterDice( | ||
| 268 | dices: []const macho.data_in_code_entry, | ||
| 269 | start_addr: u64, | ||
| 270 | end_addr: u64, | ||
| 271 | ) []const macho.data_in_code_entry { | ||
| 272 | const Predicate = struct { | ||
| 273 | addr: u64, | ||
| 274 | |||
| 275 | pub fn predicate(self: @This(), dice: macho.data_in_code_entry) bool { | ||
| 276 | return dice.offset >= self.addr; | ||
| 277 | } | ||
| 278 | }; | ||
| 279 | |||
| 280 | const start = MachO.findFirst(macho.data_in_code_entry, dices, 0, Predicate{ .addr = start_addr }); | ||
| 281 | const end = MachO.findFirst(macho.data_in_code_entry, dices, start, Predicate{ .addr = end_addr }); | ||
| 282 | |||
| 283 | return dices[start..end]; | ||
| 284 | } | ||
| 285 | |||
| 286 | /// Splits object into atoms assuming one-shot linking mode. | 266 | /// Splits object into atoms assuming one-shot linking mode. |
| 287 | pub fn splitIntoAtomsOneShot( | 267 | pub fn splitIntoAtomsOneShot( |
| 288 | self: *Object, | 268 | self: *Object, |
| ... | @@ -378,15 +358,6 @@ pub fn splitIntoAtomsOneShot( | ... | @@ -378,15 +358,6 @@ pub fn splitIntoAtomsOneShot( |
| 378 | context, | 358 | context, |
| 379 | ); | 359 | ); |
| 380 | 360 | ||
| 381 | macho_file.has_dices = macho_file.has_dices or blk: { | ||
| 382 | if (self.text_section_index) |index| { | ||
| 383 | if (index != id) break :blk false; | ||
| 384 | if (self.data_in_code_entries.len == 0) break :blk false; | ||
| 385 | break :blk true; | ||
| 386 | } | ||
| 387 | break :blk false; | ||
| 388 | }; | ||
| 389 | |||
| 390 | if (subsections_via_symbols and filtered_syms.len > 0) { | 361 | if (subsections_via_symbols and filtered_syms.len > 0) { |
| 391 | // If the first nlist does not match the start of the section, | 362 | // If the first nlist does not match the start of the section, |
| 392 | // then we need to encapsulate the memory range [section start, first symbol) | 363 | // then we need to encapsulate the memory range [section start, first symbol) |
| ... | @@ -574,19 +545,6 @@ fn createAtomFromSubsection( | ... | @@ -574,19 +545,6 @@ fn createAtomFromSubsection( |
| 574 | .base_offset = @intCast(i32, base_offset), | 545 | .base_offset = @intCast(i32, base_offset), |
| 575 | }); | 546 | }); |
| 576 | 547 | ||
| 577 | if (macho_file.has_dices) { | ||
| 578 | const dices = filterDice(self.data_in_code_entries, sym.n_value, sym.n_value + size); | ||
| 579 | try atom.dices.ensureTotalCapacity(gpa, dices.len); | ||
| 580 | |||
| 581 | for (dices) |dice| { | ||
| 582 | atom.dices.appendAssumeCapacity(.{ | ||
| 583 | .offset = dice.offset - (math.cast(u32, sym.n_value) orelse return error.Overflow), | ||
| 584 | .length = dice.length, | ||
| 585 | .kind = dice.kind, | ||
| 586 | }); | ||
| 587 | } | ||
| 588 | } | ||
| 589 | |||
| 590 | // Since this is atom gets a helper local temporary symbol that didn't exist | 548 | // Since this is atom gets a helper local temporary symbol that didn't exist |
| 591 | // in the object file which encompasses the entire section, we need traverse | 549 | // in the object file which encompasses the entire section, we need traverse |
| 592 | // the filtered symbols and note which symbol is contained within so that | 550 | // the filtered symbols and note which symbol is contained within so that |
| ... | @@ -651,11 +609,11 @@ pub fn getSourceSymtab(self: Object) []const macho.nlist_64 { | ... | @@ -651,11 +609,11 @@ pub fn getSourceSymtab(self: Object) []const macho.nlist_64 { |
| 651 | ); | 609 | ); |
| 652 | } | 610 | } |
| 653 | 611 | ||
| 654 | fn parseDataInCode(self: *Object) void { | 612 | pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry { |
| 655 | const index = self.data_in_code_cmd_index orelse return; | 613 | const index = self.data_in_code_cmd_index orelse return null; |
| 656 | const data_in_code = self.load_commands.items[index].linkedit_data; | 614 | const data_in_code = self.load_commands.items[index].linkedit_data; |
| 657 | const raw_dice = self.contents[data_in_code.dataoff..][0..data_in_code.datasize]; | 615 | const raw_dice = self.contents[data_in_code.dataoff..][0..data_in_code.datasize]; |
| 658 | self.data_in_code_entries = mem.bytesAsSlice( | 616 | return mem.bytesAsSlice( |
| 659 | macho.data_in_code_entry, | 617 | macho.data_in_code_entry, |
| 660 | @alignCast(@alignOf(macho.data_in_code_entry), raw_dice), | 618 | @alignCast(@alignOf(macho.data_in_code_entry), raw_dice), |
| 661 | ); | 619 | ); |