authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-04-07 22:27:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-04-13 10:56:03+02:00
logdb44a7803fac38096526e9b8baba60d966d77ab6
tree5bb8d077642a1d871f9e08503265d896f56b9a66
parentb667fe2c62044ec56e05edd74f8ab3f080f813b1

zld: resolve target addresses for relocs


3 files changed, 209 insertions(+), 215 deletions(-)

src/link/MachO/Object.zig+3-1
...@@ -191,11 +191,13 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -191,11 +191,13 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
191}191}
192192
193pub fn parseSections(self: *Object) !void {193pub fn parseSections(self: *Object) !void {
194 log.warn("parsing sections in {s}", .{self.name.?});
194 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;195 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
195196
196 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);197 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
197198
198 for (seg.sections.items) |sect| {199 for (seg.sections.items) |sect| {
200 log.warn("parsing section '{s},{s}'", .{ parseName(&sect.segname), parseName(&sect.sectname) });
199 // Read sections' code201 // Read sections' code
200 var code = try self.allocator.alloc(u8, sect.size);202 var code = try self.allocator.alloc(u8, sect.size);
201 _ = try self.file.?.preadAll(code, sect.offset);203 _ = try self.file.?.preadAll(code, sect.offset);
...@@ -215,7 +217,7 @@ pub fn parseSections(self: *Object) !void {...@@ -215,7 +217,7 @@ pub fn parseSections(self: *Object) !void {
215217
216 break :relocs try reloc.parse(218 break :relocs try reloc.parse(
217 self.allocator,219 self.allocator,
218 &section.code,220 section.code,
219 mem.bytesAsSlice(macho.relocation_info, raw_relocs),221 mem.bytesAsSlice(macho.relocation_info, raw_relocs),
220 );222 );
221 } else null;223 } else null;
src/link/MachO/Zld.zig+125-146
...@@ -16,6 +16,7 @@ const Allocator = mem.Allocator;...@@ -16,6 +16,7 @@ const Allocator = mem.Allocator;
16const Archive = @import("Archive.zig");16const Archive = @import("Archive.zig");
17const CodeSignature = @import("CodeSignature.zig");17const CodeSignature = @import("CodeSignature.zig");
18const Object = @import("Object.zig");18const Object = @import("Object.zig");
19const Relocation = @import("reloc.zig").Relocation;
19const Symbol = @import("Symbol.zig");20const Symbol = @import("Symbol.zig");
20const Trie = @import("Trie.zig");21const Trie = @import("Trie.zig");
2122
...@@ -77,7 +78,7 @@ symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},...@@ -77,7 +78,7 @@ symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},
77strtab: std.ArrayListUnmanaged(u8) = .{},78strtab: std.ArrayListUnmanaged(u8) = .{},
7879
79threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},80threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
80rebases: std.ArrayListUnmanaged(Pointer) = .{},81local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
81stubs: std.StringArrayHashMapUnmanaged(u32) = .{},82stubs: std.StringArrayHashMapUnmanaged(u32) = .{},
82got_entries: std.StringArrayHashMapUnmanaged(GotEntry) = .{},83got_entries: std.StringArrayHashMapUnmanaged(GotEntry) = .{},
8384
...@@ -186,7 +187,7 @@ pub fn init(allocator: *Allocator) Zld {...@@ -186,7 +187,7 @@ pub fn init(allocator: *Allocator) Zld {
186187
187pub fn deinit(self: *Zld) void {188pub fn deinit(self: *Zld) void {
188 self.threadlocal_offsets.deinit(self.allocator);189 self.threadlocal_offsets.deinit(self.allocator);
189 self.rebases.deinit(self.allocator);190 self.local_rebases.deinit(self.allocator);
190191
191 for (self.stubs.items()) |entry| {192 for (self.stubs.items()) |entry| {
192 self.allocator.free(entry.key);193 self.allocator.free(entry.key);
...@@ -280,9 +281,8 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {...@@ -280,9 +281,8 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
280 self.allocateLinkeditSegment();281 self.allocateLinkeditSegment();
281 try self.allocateSymbols();282 try self.allocateSymbols();
282 try self.allocateStubsAndGotEntries();283 try self.allocateStubsAndGotEntries();
283 self.printDebug();284 try self.writeStubHelperCommon();
284 // try self.writeStubHelperCommon();285 try self.resolveRelocsAndWriteSections();
285 // try self.resolveRelocsAndWriteSections();
286 // try self.flush();286 // try self.flush();
287}287}
288288
...@@ -1051,7 +1051,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1051,7 +1051,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1051 code[9] = 0xff;1051 code[9] = 0xff;
1052 code[10] = 0x25;1052 code[10] = 0x25;
1053 {1053 {
1054 const dyld_stub_binder = self.nonlazy_imports.get("dyld_stub_binder").?;1054 const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?;
1055 const addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));1055 const addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));
1056 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);1056 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
1057 mem.writeIntLittle(u32, code[11..], displacement);1057 mem.writeIntLittle(u32, code[11..], displacement);
...@@ -1095,7 +1095,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1095,7 +1095,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1095 code[10] = 0xbf;1095 code[10] = 0xbf;
1096 code[11] = 0xa9;1096 code[11] = 0xa9;
1097 binder_blk_outer: {1097 binder_blk_outer: {
1098 const dyld_stub_binder = self.nonlazy_imports.get("dyld_stub_binder").?;1098 const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?;
1099 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);1099 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
1100 const target_addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));1100 const target_addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));
1101 binder_blk: {1101 binder_blk: {
...@@ -1113,7 +1113,6 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1113,7 +1113,6 @@ fn writeStubHelperCommon(self: *Zld) !void {
1113 const new_this_addr = this_addr + @sizeOf(u32);1113 const new_this_addr = this_addr + @sizeOf(u32);
1114 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk;1114 const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :binder_blk;
1115 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;1115 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;
1116 log.debug("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal });
1117 // Pad with nop to please division.1116 // Pad with nop to please division.
1118 // nop1117 // nop
1119 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32());1118 mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32());
...@@ -1149,8 +1148,8 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1149,8 +1148,8 @@ fn writeStubHelperCommon(self: *Zld) !void {
1149 }1148 }
1150 };1149 };
11511150
1152 for (self.lazy_imports.items()) |_, i| {1151 for (self.stubs.items()) |entry| {
1153 const index = @intCast(u32, i);1152 const index = entry.value;
1154 try self.writeLazySymbolPointer(index);1153 try self.writeLazySymbolPointer(index);
1155 try self.writeStub(index);1154 try self.writeStub(index);
1156 try self.writeStubInStubHelper(index);1155 try self.writeStubInStubHelper(index);
...@@ -1458,6 +1457,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1458,6 +1457,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14581457
1459 if (self.got_entries.contains(sym_name)) continue;1458 if (self.got_entries.contains(sym_name)) continue;
14601459
1460 // TODO clean this up
1461 const is_import = self.symtab.get(sym_name).?.tag == .Import;1461 const is_import = self.symtab.get(sym_name).?.tag == .Import;
1462 var name = try self.allocator.dupe(u8, sym_name);1462 var name = try self.allocator.dupe(u8, sym_name);
1463 const index = @intCast(u32, self.got_entries.items().len);1463 const index = @intCast(u32, self.got_entries.items().len);
...@@ -1509,8 +1509,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1509,8 +1509,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
15091509
1510fn resolveRelocsAndWriteSections(self: *Zld) !void {1510fn resolveRelocsAndWriteSections(self: *Zld) !void {
1511 for (self.objects.items) |object, object_id| {1511 for (self.objects.items) |object, object_id| {
1512 log.debug("\n\n", .{});1512 log.warn("relocating object {s}", .{object.name});
1513 log.debug("relocating object {s}", .{object.name});
15141513
1515 for (object.sections.items) |sect, source_sect_id| {1514 for (object.sections.items) |sect, source_sect_id| {
1516 const segname = parseName(&sect.inner.segname);1515 const segname = parseName(&sect.inner.segname);
...@@ -1529,78 +1528,86 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1529,78 +1528,86 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1529 const target_sect_addr = target_sect.addr + target_mapping.offset;1528 const target_sect_addr = target_sect.addr + target_mapping.offset;
1530 const target_sect_off = target_sect.offset + target_mapping.offset;1529 const target_sect_off = target_sect.offset + target_mapping.offset;
15311530
1532 for (sect.relocs) |reloc| {1531 if (sect.relocs) |relocs| {
1533 const source_addr = target_sect_addr + reloc.offset;1532 for (relocs) |rel| {
1533 const source_addr = target_sect_addr + rel.offset;
15341534
1535 var args: Relocation.ResolveArgs = .{1535 var args: Relocation.ResolveArgs = .{
1536 .source_addr = source_addr,1536 .source_addr = source_addr,
1537 .target_addr = undefined,1537 .target_addr = undefined,
1538 };1538 .subtractor = null,
1539 };
15391540
1540 if (reloc.cast(Relocation.Unsigned)) |unsigned| {1541 switch (rel.@"type") {
1541 // TODO resolve target addr1542 .unsigned => {
1543 args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target);
15421544
1543 if (unsigned.subtractor) |subtractor| {1545 const unsigned = rel.cast(Relocation.Unsigned) orelse unreachable;
1544 args.subtractor = undefined; // TODO resolve1546 if (unsigned.subtractor) |subtractor| {
1545 }1547 args.subtractor = try self.relocTargetAddr(@intCast(u16, object_id), subtractor);
1548 }
15461549
1547 rebases: {1550 rebases: {
1548 var hit: bool = false;1551 var hit: bool = false;
1549 if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) {1552 if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) {
1550 if (self.data_section_index) |index| {1553 if (self.data_section_index) |index| {
1551 if (index == target_mapping.target_sect_id) hit = true;1554 if (index == target_mapping.target_sect_id) hit = true;
1555 }
1556 }
1557 if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) {
1558 if (self.data_const_section_index) |index| {
1559 if (index == target_mapping.target_sect_id) hit = true;
1560 }
1561 }
1562
1563 if (!hit) break :rebases;
1564
1565 try self.local_rebases.append(self.allocator, .{
1566 .offset = source_addr - target_seg.inner.vmaddr,
1567 .segment_id = target_mapping.target_seg_id,
1568 });
1552 }1569 }
1553 }1570 // TLV is handled via a separate offset mechanism.
1554 if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) {1571 // Calculate the offset to the initializer.
1555 if (self.data_const_section_index) |index| {1572 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1556 if (index == target_mapping.target_sect_id) hit = true;1573 const sym = object.symtab.items[rel.target.symbol];
1574 const sym_name = object.getString(sym.inner.n_strx);
1575
1576 // TODO we don't want to save offset to tlv_bootstrap
1577 if (mem.eql(u8, sym_name, "__tlv_boostrap")) break :tlv;
1578
1579 const base_addr = blk: {
1580 if (self.tlv_data_section_index) |index| {
1581 const tlv_data = target_seg.sections.items[index];
1582 break :blk tlv_data.addr;
1583 } else {
1584 const tlv_bss = target_seg.sections.items[self.tlv_bss_section_index.?];
1585 break :blk tlv_bss.addr;
1586 }
1587 };
1588 // Since we require TLV data to always preceed TLV bss section, we calculate
1589 // offsets wrt to the former if it is defined; otherwise, wrt to the latter.
1590 try self.threadlocal_offsets.append(self.allocator, args.target_addr - base_addr);
1557 }1591 }
1558 }1592 },
15591593 .got_page, .got_page_off => {
1560 if (!hit) break :rebases;1594 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
15611595 const got = dc_seg.sections.items[self.got_section_index.?];
1562 try self.local_rebases.append(self.allocator, .{1596 const sym = object.symtab.items[rel.target.symbol];
1563 .offset = source_addr - target_seg.inner.vmaddr,1597 const sym_name = object.getString(sym.inner.n_strx);
1564 .segment_id = target_mapping.target_seg_id,1598 const entry = self.got_entries.get(sym_name) orelse unreachable;
1565 });1599 args.target_addr = got.addr + entry.index * @sizeOf(u64);
1600 },
1601 else => {
1602 args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target);
1603 },
1566 }1604 }
1567 // TLV is handled via a separate offset mechanism.
1568 // Calculate the offset to the initializer.
1569 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1570 const sym = object.symtab.items[reloc.target.symbol];
1571 const sym_name = object.getString(sym.inner.n_strx);
1572
1573 // TODO we don't want to save offset to tlv_bootstrap
1574 if (mem.eql(u8, sym_name, "__tlv_boostrap")) break :tlv;
15751605
1576 const base_addr = blk: {1606 try rel.resolve(args);
1577 if (self.tlv_data_section_index) |index| {
1578 const tlv_data = target_seg.sections.items[index];
1579 break :blk tlv_data.addr;
1580 } else {
1581 const tlv_bss = target_seg.sections.items[self.tlv_bss_section_index.?];
1582 break :blk tlv_bss.addr;
1583 }
1584 };
1585 // Since we require TLV data to always preceed TLV bss section, we calculate
1586 // offsets wrt to the former if it is defined; otherwise, wrt to the latter.
1587 try self.threadlocal_offsets.append(self.allocator, target_addr - base_addr);
1588 }
1589 } else if (reloc.cast(Relocation.GotPageOff)) |page_off| {
1590 // TODO here we need to work out the indirection to GOT.
1591 } else {
1592 // TODO resolve target addr.
1593 }1607 }
1594
1595 log.debug("{s}", .{reloc.@"type"});
1596 log.debug(" | offset 0x{x}", .{reloc.offset});
1597 log.debug(" | source address 0x{x}", .{args.source_addr});
1598 log.debug(" | target address 0x{x}", .{args.target_addr});
1599
1600 try reloc.resolve(args);
1601 }1608 }
16021609
1603 log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{1610 log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
1604 segname,1611 segname,
1605 sectname,1612 sectname,
1606 object.name,1613 object.name,
...@@ -1612,7 +1619,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1612,7 +1619,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1612 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or1619 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
1613 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)1620 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
1614 {1621 {
1615 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{1622 log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1616 parseName(&target_sect.segname),1623 parseName(&target_sect.segname),
1617 parseName(&target_sect.sectname),1624 parseName(&target_sect.sectname),
1618 target_sect_off,1625 target_sect_off,
...@@ -1630,88 +1637,60 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1630,88 +1637,60 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1630 }1637 }
1631}1638}
16321639
1633fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64 {1640fn relocTargetAddr(self: *Zld, object_id: u16, target: Relocation.Target) !u64 {
1634 const object = self.objects.items[object_id];1641 const object = self.objects.items[object_id];
1635 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;1642 const target_addr = blk: {
1643 switch (target) {
1644 .symbol => |sym_id| {
1645 const sym = object.symtab.items[sym_id];
1646 const sym_name = object.getString(sym.inner.n_strx);
16361647
1637 const is_got: bool = is_got: {1648 switch (sym.tag) {
1638 switch (self.arch.?) {1649 .Stab => unreachable, // TODO is this even allowed to happen?
1639 .x86_64 => {1650 .Local, .Weak, .Strong => {
1640 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);1651 // Relocate using section offsets only.
1641 break :is_got = switch (rel_type) {1652 const target_mapping = self.mappings.get(.{
1642 .X86_64_RELOC_GOT, .X86_64_RELOC_GOT_LOAD => true,1653 .object_id = object_id,
1643 else => false,1654 .source_sect_id = sym.inner.n_sect - 1,
1644 };1655 }) orelse unreachable;
1645 },1656 const source_sect = object.sections.items[target_mapping.source_sect_id];
1646 .aarch64 => {1657 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1647 const rel_type = @intToEnum(macho.reloc_type_aarch64, rel.r_type);1658 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1648 break :is_got = switch (rel_type) {1659 const target_sect_addr = target_sect.addr + target_mapping.offset;
1649 .ARM64_RELOC_GOT_LOAD_PAGE21,1660 log.warn(" | symbol local to object", .{});
1650 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,1661 break :blk target_sect_addr + sym.inner.n_value - source_sect.inner.addr;
1651 .ARM64_RELOC_POINTER_TO_GOT,1662 },
1652 => true,1663 else => {
1653 else => false,1664 if (self.stubs.get(sym_name)) |index| {
1654 };1665 log.warn(" | symbol stub {s}", .{sym_name});
1666 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1667 const stubs = segment.sections.items[self.stubs_section_index.?];
1668 break :blk stubs.addr + index * stubs.reserved2;
1669 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1670 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1671 const tlv = segment.sections.items[self.tlv_section_index.?];
1672 break :blk tlv.addr;
1673 } else {
1674 const global = self.symtab.get(sym_name) orelse {
1675 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1676 return error.FailedToResolveRelocationTarget;
1677 };
1678 break :blk global.inner.n_value;
1679 }
1680 },
1681 }
1655 },1682 },
1656 }1683 .section => |sect_id| {
1657 };
1658
1659 const target_addr = blk: {
1660 if (rel.r_extern == 1) {
1661 const sym = object.symtab.items[rel.r_symbolnum];
1662 if (sym.isSect()) {
1663 // Relocate using section offsets only.
1664 const target_mapping = self.mappings.get(.{1684 const target_mapping = self.mappings.get(.{
1665 .object_id = object_id,1685 .object_id = object_id,
1666 .source_sect_id = sym.n_sect - 1,1686 .source_sect_id = sect_id,
1667 }) orelse unreachable;1687 }) orelse unreachable;
1668 const source_sect = seg.sections.items[target_mapping.source_sect_id];
1669 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1688 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1670 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];1689 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1671 const target_sect_addr = target_sect.addr + target_mapping.offset;1690 break :blk target_sect.addr + target_mapping.offset;
1672 log.debug(" | symbol local to object", .{});1691 },
1673 break :blk target_sect_addr + sym.n_value - source_sect.addr;
1674 } else if (sym.isUndf()) {
1675 // Relocate to either the global symbol, or an import from
1676 // shared library.
1677 const sym_name = object.getString(sym.n_strx);
1678 if (self.globals.get(sym_name)) |glob| {
1679 break :blk glob.inner.n_value;
1680 } else if (self.externs.getEntry(sym_name)) |ext| {
1681 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1682 const stubs = segment.sections.items[self.stubs_section_index.?];
1683 break :blk stubs.addr + ext.index * stubs.reserved2;
1684 } else if (self.nonlazy_imports.get(sym_name)) |ext| {
1685 const segment = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1686 const got = segment.sections.items[self.got_section_index.?];
1687 break :blk got.addr + ext.index * @sizeOf(u64);
1688 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1689 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1690 const tlv = segment.sections.items[self.tlv_section_index.?];
1691 break :blk tlv.addr;
1692 } else {
1693 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1694 return error.FailedToResolveRelocationTarget;
1695 }
1696 } else {
1697 log.err("unexpected symbol {}, {s}", .{ sym, object.getString(sym.n_strx) });
1698 return error.UnexpectedSymbolWhenRelocating;
1699 }
1700 } else {
1701 // TODO I think we need to reparse the relocation_info as scattered_relocation_info
1702 // here to get the actual section plus offset into that section of the relocated
1703 // symbol. Unless the fine-grained location is encoded within the cell in the code
1704 // buffer?
1705 const target_mapping = self.mappings.get(.{
1706 .object_id = object_id,
1707 .source_sect_id = @intCast(u16, rel.r_symbolnum - 1),
1708 }) orelse unreachable;
1709 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1710 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1711 break :blk target_sect.addr + target_mapping.offset;
1712 }1692 }
1713 };1693 };
1714
1715 return target_addr;1694 return target_addr;
1716}1695}
17171696
src/link/MachO/reloc.zig+81-68
...@@ -3,6 +3,7 @@ const aarch64 = @import("../../codegen/aarch64.zig");...@@ -3,6 +3,7 @@ const aarch64 = @import("../../codegen/aarch64.zig");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const log = std.log.scoped(.reloc);4const log = std.log.scoped(.reloc);
5const macho = std.macho;5const macho = std.macho;
6const math = std.math;
6const mem = std.mem;7const mem = std.mem;
7const meta = std.meta;8const meta = std.meta;
89
...@@ -10,7 +11,7 @@ const Allocator = mem.Allocator;...@@ -10,7 +11,7 @@ const Allocator = mem.Allocator;
1011
11pub const Relocation = struct {12pub const Relocation = struct {
12 @"type": Type,13 @"type": Type,
13 code: *[]u8,14 code: []u8,
14 offset: u32,15 offset: u32,
15 target: Target,16 target: Target,
1617
...@@ -24,20 +25,26 @@ pub const Relocation = struct {...@@ -24,20 +25,26 @@ pub const Relocation = struct {
24 pub const ResolveArgs = struct {25 pub const ResolveArgs = struct {
25 source_addr: u64,26 source_addr: u64,
26 target_addr: u64,27 target_addr: u64,
27 subtractor: i64 = undefined,28 subtractor: ?u64,
28 };29 };
2930
30 pub fn resolve(base: *Relocation, args: ResolveArgs) !void {31 pub fn resolve(base: *Relocation, args: ResolveArgs) !void {
31 switch (base.@"type") {32 log.warn("{s}", .{base.@"type"});
32 .branch => try base.cast(Branch).?.resolve(args.source_addr, args.target_addr),33 log.warn(" | offset 0x{x}", .{base.offset});
33 .unsigned => try base.cast(Unsigned).?.resolve(args.target_addr, args.subtractor),34 log.warn(" | source address 0x{x}", .{args.source_addr});
34 .page => try base.cast(Page).?.resolve(args.source_addr, args.target_addr),35 log.warn(" | target address 0x{x}", .{args.target_addr});
35 .page_off => try base.cast(PageOff).?.resolve(args.target_addr),36 log.warn(" | subtractor address 0x{x}", .{args.subtractor});
36 .got_page => try base.cast(GotPage).?.resolve(args.source_addr, args.target_addr),37
37 .got_page_off => try base.cast(GotPageOff).?.resolve(args.target_addr),38 return switch (base.@"type") {
38 .tlvp_page => try base.cast(TlvpPage).?.resolve(args.source_addr, args.target_addr),39 .branch => @fieldParentPtr(Branch, "base", base).resolve(args.source_addr, args.target_addr),
39 .tlvp_page_off => try base.cast(TlvpPageOff).?.resolve(args.target_addr),40 .unsigned => @fieldParentPtr(Unsigned, "base", base).resolve(args.target_addr, args.subtractor),
40 }41 .page => @fieldParentPtr(Page, "base", base).resolve(args.source_addr, args.target_addr),
42 .page_off => @fieldParentPtr(PageOff, "base", base).resolve(args.target_addr),
43 .got_page => @fieldParentPtr(GotPage, "base", base).resolve(args.source_addr, args.target_addr),
44 .got_page_off => @fieldParentPtr(GotPageOff, "base", base).resolve(args.target_addr),
45 .tlvp_page => @fieldParentPtr(TlvpPage, "base", base).resolve(args.source_addr, args.target_addr),
46 .tlvp_page_off => @fieldParentPtr(TlvpPageOff, "base", base).resolve(args.target_addr),
47 };
41 }48 }
4249
43 pub const Type = enum {50 pub const Type = enum {
...@@ -73,9 +80,12 @@ pub const Relocation = struct {...@@ -73,9 +80,12 @@ pub const Relocation = struct {
7380
74 pub fn resolve(branch: Branch, source_addr: u64, target_addr: u64) !void {81 pub fn resolve(branch: Branch, source_addr: u64, target_addr: u64) !void {
75 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));82 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));
83
84 log.warn(" | displacement 0x{x}", .{displacement});
85
76 var inst = branch.inst;86 var inst = branch.inst;
77 inst.AddSubtractImmediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);87 inst.UnconditionalBranchImmediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
78 mem.writeIntLittle(u32, branch.base.code.*[branch.base.offset..], inst.toU32());88 mem.writeIntLittle(u32, branch.base.code[0..4], inst.toU32());
79 }89 }
80 };90 };
8191
...@@ -92,22 +102,25 @@ pub const Relocation = struct {...@@ -92,22 +102,25 @@ pub const Relocation = struct {
92102
93 pub const base_type: Relocation.Type = .unsigned;103 pub const base_type: Relocation.Type = .unsigned;
94104
95 pub fn resolve(unsigned: Unsigned, target_addr: u64, subtractor: i64) !void {105 pub fn resolve(unsigned: Unsigned, target_addr: u64, subtractor: ?u64) !void {
96 const result = @intCast(i64, target_addr) - subtractor + unsigned.addend;106 const result = if (subtractor) |sub|
107 @intCast(i64, target_addr) - @intCast(i64, sub) + unsigned.addend
108 else
109 @intCast(i64, target_addr) + unsigned.addend;
97110
98 log.debug(" | calculated addend 0x{x}", .{unsigned.addend});111 log.warn(" | calculated addend 0x{x}", .{unsigned.addend});
99 log.debug(" | calculated unsigned value 0x{x}", .{result});112 log.warn(" | calculated unsigned value 0x{x}", .{result});
100113
101 if (unsigned.is_64bit) {114 if (unsigned.is_64bit) {
102 mem.writeIntLittle(115 mem.writeIntLittle(
103 u64,116 u64,
104 unsigned.base.code.*[unsigned.base.offset..],117 unsigned.base.code[0..8],
105 @bitCast(u64, result),118 @bitCast(u64, result),
106 );119 );
107 } else {120 } else {
108 mem.writeIntLittle(121 mem.writeIntLittle(
109 u32,122 u32,
110 unsigned.base.code.*[unsigned.base.offset..],123 unsigned.base.code[0..4],
111 @truncate(u32, @bitCast(u64, result)),124 @truncate(u32, @bitCast(u64, result)),
112 );125 );
113 }126 }
...@@ -128,13 +141,14 @@ pub const Relocation = struct {...@@ -128,13 +141,14 @@ pub const Relocation = struct {
128 const target_page = @intCast(i32, ta >> 12);141 const target_page = @intCast(i32, ta >> 12);
129 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));142 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
130143
131 log.debug(" | moving by {} pages", .{pages});144 log.warn(" | calculated addend 0x{x}", .{page.addend});
145 log.warn(" | moving by {} pages", .{pages});
132146
133 var inst = page.inst;147 var inst = page.inst;
134 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);148 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
135 inst.PCRelativeAddress.immlo = @truncate(u2, pages);149 inst.PCRelativeAddress.immlo = @truncate(u2, pages);
136150
137 mem.writeIntLittle(u32, page.base.code.*[page.base.offset..], inst.toU32());151 mem.writeIntLittle(u32, page.base.code[0..4], inst.toU32());
138 }152 }
139 };153 };
140154
...@@ -155,8 +169,8 @@ pub const Relocation = struct {...@@ -155,8 +169,8 @@ pub const Relocation = struct {
155 const ta = if (page_off.addend) |a| target_addr + a else target_addr;169 const ta = if (page_off.addend) |a| target_addr + a else target_addr;
156 const narrowed = @truncate(u12, ta);170 const narrowed = @truncate(u12, ta);
157171
158 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});172 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});
159 log.debug(" | {s} opcode", .{page_off.op_kind});173 log.warn(" | {s} opcode", .{page_off.op_kind});
160174
161 var inst = page_off.inst;175 var inst = page_off.inst;
162 if (page_off.op_kind == .arithmetic) {176 if (page_off.op_kind == .arithmetic) {
...@@ -178,7 +192,7 @@ pub const Relocation = struct {...@@ -178,7 +192,7 @@ pub const Relocation = struct {
178 inst.LoadStoreRegister.offset = offset;192 inst.LoadStoreRegister.offset = offset;
179 }193 }
180194
181 mem.writeIntLittle(u32, page_off.base.code.*[page_off.base.offset..], inst.toU32());195 mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
182 }196 }
183 };197 };
184198
...@@ -194,13 +208,13 @@ pub const Relocation = struct {...@@ -194,13 +208,13 @@ pub const Relocation = struct {
194 const target_page = @intCast(i32, target_addr >> 12);208 const target_page = @intCast(i32, target_addr >> 12);
195 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));209 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
196210
197 log.debug(" | moving by {} pages", .{pages});211 log.warn(" | moving by {} pages", .{pages});
198212
199 var inst = page.inst;213 var inst = page.inst;
200 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);214 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
201 inst.PCRelativeAddress.immlo = @truncate(u2, pages);215 inst.PCRelativeAddress.immlo = @truncate(u2, pages);
202216
203 mem.writeIntLittle(u32, page.base.code.*[page.base.offset..], inst.toU32());217 mem.writeIntLittle(u32, page.base.code[0..4], inst.toU32());
204 }218 }
205 };219 };
206220
...@@ -214,13 +228,13 @@ pub const Relocation = struct {...@@ -214,13 +228,13 @@ pub const Relocation = struct {
214 pub fn resolve(page_off: GotPageOff, target_addr: u64) !void {228 pub fn resolve(page_off: GotPageOff, target_addr: u64) !void {
215 const narrowed = @truncate(u12, target_addr);229 const narrowed = @truncate(u12, target_addr);
216230
217 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});231 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});
218232
219 var inst = page_off.inst;233 var inst = page_off.inst;
220 const offset = try math.divExact(u12, narrowed, 8);234 const offset = try math.divExact(u12, narrowed, 8);
221 inst.LoadStoreRegister.offset = offset;235 inst.LoadStoreRegister.offset = offset;
222236
223 mem.writeIntLittle(u32, page_off.base.code.*[page_off.base.offset..], inst.toU32());237 mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
224 }238 }
225 };239 };
226240
...@@ -236,13 +250,13 @@ pub const Relocation = struct {...@@ -236,13 +250,13 @@ pub const Relocation = struct {
236 const target_page = @intCast(i32, target_addr >> 12);250 const target_page = @intCast(i32, target_addr >> 12);
237 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));251 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
238252
239 log.debug(" | moving by {} pages", .{pages});253 log.warn(" | moving by {} pages", .{pages});
240254
241 var inst = page.inst;255 var inst = page.inst;
242 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);256 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
243 inst.PCRelativeAddress.immlo = @truncate(u2, pages);257 inst.PCRelativeAddress.immlo = @truncate(u2, pages);
244258
245 mem.writeIntLittle(u32, page.base.code.*[page.base.offset..], inst.toU32());259 mem.writeIntLittle(u32, page.base.code[0..4], inst.toU32());
246 }260 }
247 };261 };
248262
...@@ -258,17 +272,17 @@ pub const Relocation = struct {...@@ -258,17 +272,17 @@ pub const Relocation = struct {
258 pub fn resolve(page_off: TlvpPageOff, target_addr: u64) !void {272 pub fn resolve(page_off: TlvpPageOff, target_addr: u64) !void {
259 const narrowed = @truncate(u12, target_addr);273 const narrowed = @truncate(u12, target_addr);
260274
261 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});275 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});
262276
263 var inst = page_off.inst;277 var inst = page_off.inst;
264 inst.AddSubtractImmediate.imm12 = narrowed;278 inst.AddSubtractImmediate.imm12 = narrowed;
265279
266 mem.writeIntLittle(u32, page_off.base.code.*[page_off.base.offset..], inst.toU32());280 mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32());
267 }281 }
268 };282 };
269};283};
270284
271pub fn parse(allocator: *Allocator, code: *[]u8, relocs: []const macho.relocation_info) ![]*Relocation {285pub fn parse(allocator: *Allocator, code: []u8, relocs: []const macho.relocation_info) ![]*Relocation {
272 var it = RelocIterator{286 var it = RelocIterator{
273 .buffer = relocs,287 .buffer = relocs,
274 };288 };
...@@ -280,8 +294,9 @@ pub fn parse(allocator: *Allocator, code: *[]u8, relocs: []const macho.relocatio...@@ -280,8 +294,9 @@ pub fn parse(allocator: *Allocator, code: *[]u8, relocs: []const macho.relocatio
280 .parsed = std.ArrayList(*Relocation).init(allocator),294 .parsed = std.ArrayList(*Relocation).init(allocator),
281 };295 };
282 defer parser.deinit();296 defer parser.deinit();
297 try parser.parse();
283298
284 return parser.parse();299 return parser.parsed.toOwnedSlice();
285}300}
286301
287const RelocIterator = struct {302const RelocIterator = struct {
...@@ -292,12 +307,12 @@ const RelocIterator = struct {...@@ -292,12 +307,12 @@ const RelocIterator = struct {
292 self.index += 1;307 self.index += 1;
293 if (self.index < self.buffer.len) {308 if (self.index < self.buffer.len) {
294 const reloc = self.buffer[@intCast(u64, self.index)];309 const reloc = self.buffer[@intCast(u64, self.index)];
295 log.debug("{s}", .{@intToEnum(macho.reloc_type_arm64, reloc.r_type)});310 log.warn("{s}", .{@intToEnum(macho.reloc_type_arm64, reloc.r_type)});
296 log.debug(" | offset = {}", .{reloc.r_address});311 log.warn(" | offset = {}", .{reloc.r_address});
297 log.debug(" | PC = {}", .{reloc.r_pcrel == 1});312 log.warn(" | PC = {}", .{reloc.r_pcrel == 1});
298 log.debug(" | length = {}", .{reloc.r_length});313 log.warn(" | length = {}", .{reloc.r_length});
299 log.debug(" | symbolnum = {}", .{reloc.r_symbolnum});314 log.warn(" | symbolnum = {}", .{reloc.r_symbolnum});
300 log.debug(" | extern = {}", .{reloc.r_extern == 1});315 log.warn(" | extern = {}", .{reloc.r_extern == 1});
301 return reloc;316 return reloc;
302 }317 }
303 return null;318 return null;
...@@ -316,7 +331,7 @@ const RelocIterator = struct {...@@ -316,7 +331,7 @@ const RelocIterator = struct {
316const Parser = struct {331const Parser = struct {
317 allocator: *Allocator,332 allocator: *Allocator,
318 it: *RelocIterator,333 it: *RelocIterator,
319 code: *[]u8,334 code: []u8,
320 parsed: std.ArrayList(*Relocation),335 parsed: std.ArrayList(*Relocation),
321 addend: ?u32 = null,336 addend: ?u32 = null,
322 subtractor: ?Relocation.Target = null,337 subtractor: ?Relocation.Target = null,
...@@ -325,7 +340,7 @@ const Parser = struct {...@@ -325,7 +340,7 @@ const Parser = struct {
325 parser.parsed.deinit();340 parser.parsed.deinit();
326 }341 }
327342
328 fn parse(parser: *Parser) ![]*Relocation {343 fn parse(parser: *Parser) !void {
329 while (parser.it.next()) |reloc| {344 while (parser.it.next()) |reloc| {
330 switch (@intToEnum(macho.reloc_type_arm64, reloc.r_type)) {345 switch (@intToEnum(macho.reloc_type_arm64, reloc.r_type)) {
331 .ARM64_RELOC_BRANCH26 => {346 .ARM64_RELOC_BRANCH26 => {
...@@ -360,8 +375,6 @@ const Parser = struct {...@@ -360,8 +375,6 @@ const Parser = struct {
360 },375 },
361 }376 }
362 }377 }
363
364 return parser.parsed.toOwnedSlice();
365 }378 }
366379
367 fn parseAddend(parser: *Parser, reloc: macho.relocation_info) !void {380 fn parseAddend(parser: *Parser, reloc: macho.relocation_info) !void {
...@@ -395,7 +408,7 @@ const Parser = struct {...@@ -395,7 +408,7 @@ const Parser = struct {
395 assert(reloc.r_length == 2);408 assert(reloc.r_length == 2);
396409
397 const offset = @intCast(u32, reloc.r_address);410 const offset = @intCast(u32, reloc.r_address);
398 const inst = parser.code.*[offset..][0..4];411 const inst = parser.code[offset..][0..4];
399 const parsed_inst = aarch64.Instruction{ .UnconditionalBranchImmediate = mem.bytesToValue(412 const parsed_inst = aarch64.Instruction{ .UnconditionalBranchImmediate = mem.bytesToValue(
400 meta.TagPayload(413 meta.TagPayload(
401 aarch64.Instruction,414 aarch64.Instruction,
...@@ -412,14 +425,14 @@ const Parser = struct {...@@ -412,14 +425,14 @@ const Parser = struct {
412 branch.* = .{425 branch.* = .{
413 .base = .{426 .base = .{
414 .@"type" = .branch,427 .@"type" = .branch,
415 .code = parser.code,428 .code = inst,
416 .offset = @intCast(u32, reloc.r_address),429 .offset = @intCast(u32, reloc.r_address),
417 .target = target,430 .target = target,
418 },431 },
419 .inst = parsed_inst,432 .inst = parsed_inst,
420 };433 };
421434
422 log.debug(" | emitting {}", .{branch});435 log.warn(" | emitting {}", .{branch});
423 try parser.parsed.append(&branch.base);436 try parser.parsed.append(&branch.base);
424 }437 }
425438
...@@ -431,7 +444,7 @@ const Parser = struct {...@@ -431,7 +444,7 @@ const Parser = struct {
431 const target = Relocation.Target.from_reloc(reloc);444 const target = Relocation.Target.from_reloc(reloc);
432445
433 const offset = @intCast(u32, reloc.r_address);446 const offset = @intCast(u32, reloc.r_address);
434 const inst = parser.code.*[offset..][0..4];447 const inst = parser.code[offset..][0..4];
435 const parsed_inst = aarch64.Instruction{ .PCRelativeAddress = mem.bytesToValue(meta.TagPayload(448 const parsed_inst = aarch64.Instruction{ .PCRelativeAddress = mem.bytesToValue(meta.TagPayload(
436 aarch64.Instruction,449 aarch64.Instruction,
437 aarch64.Instruction.PCRelativeAddress,450 aarch64.Instruction.PCRelativeAddress,
...@@ -450,7 +463,7 @@ const Parser = struct {...@@ -450,7 +463,7 @@ const Parser = struct {
450 page.* = .{463 page.* = .{
451 .base = .{464 .base = .{
452 .@"type" = .page,465 .@"type" = .page,
453 .code = parser.code,466 .code = inst,
454 .offset = offset,467 .offset = offset,
455 .target = target,468 .target = target,
456 },469 },
...@@ -458,7 +471,7 @@ const Parser = struct {...@@ -458,7 +471,7 @@ const Parser = struct {
458 .inst = parsed_inst,471 .inst = parsed_inst,
459 };472 };
460473
461 log.debug(" | emitting {}", .{page});474 log.warn(" | emitting {}", .{page});
462475
463 break :ptr &page.base;476 break :ptr &page.base;
464 },477 },
...@@ -469,14 +482,14 @@ const Parser = struct {...@@ -469,14 +482,14 @@ const Parser = struct {
469 page.* = .{482 page.* = .{
470 .base = .{483 .base = .{
471 .@"type" = .got_page,484 .@"type" = .got_page,
472 .code = parser.code,485 .code = inst,
473 .offset = offset,486 .offset = offset,
474 .target = target,487 .target = target,
475 },488 },
476 .inst = parsed_inst,489 .inst = parsed_inst,
477 };490 };
478491
479 log.debug(" | emitting {}", .{page});492 log.warn(" | emitting {}", .{page});
480493
481 break :ptr &page.base;494 break :ptr &page.base;
482 },495 },
...@@ -487,14 +500,14 @@ const Parser = struct {...@@ -487,14 +500,14 @@ const Parser = struct {
487 page.* = .{500 page.* = .{
488 .base = .{501 .base = .{
489 .@"type" = .tlvp_page,502 .@"type" = .tlvp_page,
490 .code = parser.code,503 .code = inst,
491 .offset = offset,504 .offset = offset,
492 .target = target,505 .target = target,
493 },506 },
494 .inst = parsed_inst,507 .inst = parsed_inst,
495 };508 };
496509
497 log.debug(" | emitting {}", .{page});510 log.warn(" | emitting {}", .{page});
498511
499 break :ptr &page.base;512 break :ptr &page.base;
500 },513 },
...@@ -517,7 +530,7 @@ const Parser = struct {...@@ -517,7 +530,7 @@ const Parser = struct {
517 assert(reloc.r_length == 2);530 assert(reloc.r_length == 2);
518531
519 const offset = @intCast(u32, reloc.r_address);532 const offset = @intCast(u32, reloc.r_address);
520 const inst = parser.code.*[offset..][0..4];533 const inst = parser.code[offset..][0..4];
521534
522 var op_kind: Relocation.PageOff.OpKind = undefined;535 var op_kind: Relocation.PageOff.OpKind = undefined;
523 var parsed_inst: aarch64.Instruction = undefined;536 var parsed_inst: aarch64.Instruction = undefined;
...@@ -542,7 +555,7 @@ const Parser = struct {...@@ -542,7 +555,7 @@ const Parser = struct {
542 page_off.* = .{555 page_off.* = .{
543 .base = .{556 .base = .{
544 .@"type" = .page_off,557 .@"type" = .page_off,
545 .code = parser.code,558 .code = inst,
546 .offset = offset,559 .offset = offset,
547 .target = target,560 .target = target,
548 },561 },
...@@ -551,7 +564,7 @@ const Parser = struct {...@@ -551,7 +564,7 @@ const Parser = struct {
551 .addend = parser.addend,564 .addend = parser.addend,
552 };565 };
553566
554 log.debug(" | emitting {}", .{page_off});567 log.warn(" | emitting {}", .{page_off});
555 try parser.parsed.append(&page_off.base);568 try parser.parsed.append(&page_off.base);
556 }569 }
557570
...@@ -562,7 +575,7 @@ const Parser = struct {...@@ -562,7 +575,7 @@ const Parser = struct {
562 assert(reloc.r_length == 2);575 assert(reloc.r_length == 2);
563576
564 const offset = @intCast(u32, reloc.r_address);577 const offset = @intCast(u32, reloc.r_address);
565 const inst = parser.code.*[offset..][0..4];578 const inst = parser.code[offset..][0..4];
566 assert(!isArithmeticOp(inst));579 assert(!isArithmeticOp(inst));
567580
568 const parsed_inst = mem.bytesToValue(meta.TagPayload(581 const parsed_inst = mem.bytesToValue(meta.TagPayload(
...@@ -579,7 +592,7 @@ const Parser = struct {...@@ -579,7 +592,7 @@ const Parser = struct {
579 page_off.* = .{592 page_off.* = .{
580 .base = .{593 .base = .{
581 .@"type" = .got_page_off,594 .@"type" = .got_page_off,
582 .code = parser.code,595 .code = inst,
583 .offset = offset,596 .offset = offset,
584 .target = target,597 .target = target,
585 },598 },
...@@ -588,7 +601,7 @@ const Parser = struct {...@@ -588,7 +601,7 @@ const Parser = struct {
588 },601 },
589 };602 };
590603
591 log.debug(" | emitting {}", .{page_off});604 log.warn(" | emitting {}", .{page_off});
592 try parser.parsed.append(&page_off.base);605 try parser.parsed.append(&page_off.base);
593 }606 }
594607
...@@ -605,7 +618,7 @@ const Parser = struct {...@@ -605,7 +618,7 @@ const Parser = struct {
605 };618 };
606619
607 const offset = @intCast(u32, reloc.r_address);620 const offset = @intCast(u32, reloc.r_address);
608 const inst = parser.code.*[offset..][0..4];621 const inst = parser.code[offset..][0..4];
609 const parsed: RegInfo = parsed: {622 const parsed: RegInfo = parsed: {
610 if (isArithmeticOp(inst)) {623 if (isArithmeticOp(inst)) {
611 const parsed_inst = mem.bytesAsValue(meta.TagPayload(624 const parsed_inst = mem.bytesAsValue(meta.TagPayload(
...@@ -638,7 +651,7 @@ const Parser = struct {...@@ -638,7 +651,7 @@ const Parser = struct {
638 page_off.* = .{651 page_off.* = .{
639 .base = .{652 .base = .{
640 .@"type" = .tlvp_page_off,653 .@"type" = .tlvp_page_off,
641 .code = parser.code,654 .code = inst,
642 .offset = @intCast(u32, reloc.r_address),655 .offset = @intCast(u32, reloc.r_address),
643 .target = target,656 .target = target,
644 },657 },
...@@ -655,7 +668,7 @@ const Parser = struct {...@@ -655,7 +668,7 @@ const Parser = struct {
655 },668 },
656 };669 };
657670
658 log.debug(" | emitting {}", .{page_off});671 log.warn(" | emitting {}", .{page_off});
659 try parser.parsed.append(&page_off.base);672 try parser.parsed.append(&page_off.base);
660 }673 }
661674
...@@ -700,14 +713,14 @@ const Parser = struct {...@@ -700,14 +713,14 @@ const Parser = struct {
700 };713 };
701 const offset = @intCast(u32, reloc.r_address);714 const offset = @intCast(u32, reloc.r_address);
702 const addend: i64 = if (is_64bit)715 const addend: i64 = if (is_64bit)
703 mem.readIntLittle(i64, parser.code.*[offset..][0..8])716 mem.readIntLittle(i64, parser.code[offset..][0..8])
704 else717 else
705 mem.readIntLittle(i32, parser.code.*[offset..][0..4]);718 mem.readIntLittle(i32, parser.code[offset..][0..4]);
706719
707 unsigned.* = .{720 unsigned.* = .{
708 .base = .{721 .base = .{
709 .@"type" = .unsigned,722 .@"type" = .unsigned,
710 .code = parser.code,723 .code = if (is_64bit) parser.code[offset..][0..8] else parser.code[offset..][0..4],
711 .offset = offset,724 .offset = offset,
712 .target = target,725 .target = target,
713 },726 },
...@@ -716,7 +729,7 @@ const Parser = struct {...@@ -716,7 +729,7 @@ const Parser = struct {
716 .addend = addend,729 .addend = addend,
717 };730 };
718731
719 log.debug(" | emitting {}", .{unsigned});732 log.warn(" | emitting {}", .{unsigned});
720 try parser.parsed.append(&unsigned.base);733 try parser.parsed.append(&unsigned.base);
721 }734 }
722};735};