| author | |
| committer | |
| log | a04bc1ed14319bf22769b01709bb7174388734f0 |
| tree | 1d49c86fc82a250ece34fc0b46244ddcb042ba08 |
| parent | dfa69e3c308fe7a5cb8b78c494312e1d280afa18 |
3 files changed, 144 insertions(+), 309 deletions(-)
src/link/MachO/Object.zig+8-19| ... | ... | @@ -48,8 +48,6 @@ dwarf_debug_ranges_index: ?u16 = null, |
| 48 | 48 | |
| 49 | 49 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 50 | 50 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 51 | ||
| 52 | initializers: std.ArrayListUnmanaged(u32) = .{}, | |
| 53 | 51 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, |
| 54 | 52 | |
| 55 | 53 | symbols: std.ArrayListUnmanaged(*Symbol) = .{}, |
| ... | ... | @@ -157,7 +155,6 @@ pub fn deinit(self: *Object) void { |
| 157 | 155 | } |
| 158 | 156 | self.load_commands.deinit(self.allocator); |
| 159 | 157 | self.data_in_code_entries.deinit(self.allocator); |
| 160 | self.initializers.deinit(self.allocator); | |
| 161 | 158 | self.symtab.deinit(self.allocator); |
| 162 | 159 | self.strtab.deinit(self.allocator); |
| 163 | 160 | self.symbols.deinit(self.allocator); |
| ... | ... | @@ -573,6 +570,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 573 | 570 | symbol.payload = .{ |
| 574 | 571 | .regular = .{ |
| 575 | 572 | .linkage = .translation_unit, |
| 573 | .address = sect.addr, | |
| 576 | 574 | .segment_id = match.seg, |
| 577 | 575 | .section_id = match.sect, |
| 578 | 576 | .file = self, |
| ... | ... | @@ -657,6 +655,13 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { |
| 657 | 655 | }); |
| 658 | 656 | defer self.allocator.free(name); |
| 659 | 657 | const symbol = try Symbol.new(self.allocator, name); |
| 658 | symbol.payload = .{ | |
| 659 | .regular = .{ | |
| 660 | .linkage = .translation_unit, | |
| 661 | .address = sect.addr, | |
| 662 | .file = self, | |
| 663 | }, | |
| 664 | }; | |
| 660 | 665 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); |
| 661 | 666 | break :symbol symbol; |
| 662 | 667 | }; |
| ... | ... | @@ -666,22 +671,6 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { |
| 666 | 671 | return symbol; |
| 667 | 672 | } |
| 668 | 673 | |
| 669 | pub fn parseInitializers(self: *Object) !void { | |
| 670 | const index = self.mod_init_func_section_index orelse return; | |
| 671 | const section = self.sections.items[index]; | |
| 672 | ||
| 673 | log.debug("parsing initializers in {s}", .{self.name.?}); | |
| 674 | ||
| 675 | // Parse C++ initializers | |
| 676 | const relocs = section.relocs orelse unreachable; | |
| 677 | try self.initializers.ensureCapacity(self.allocator, relocs.len); | |
| 678 | for (relocs) |rel| { | |
| 679 | self.initializers.appendAssumeCapacity(rel.target.symbol); | |
| 680 | } | |
| 681 | ||
| 682 | mem.reverse(u32, self.initializers.items); | |
| 683 | } | |
| 684 | ||
| 685 | 674 | fn parseSymtab(self: *Object) !void { |
| 686 | 675 | const index = self.symtab_cmd_index orelse return; |
| 687 | 676 | const symtab_cmd = self.load_commands.items[index].Symtab; |
src/link/MachO/Zld.zig+6-219| ... | ... | @@ -120,16 +120,6 @@ pub const Output = struct { |
| 120 | 120 | install_name: ?[]const u8 = null, |
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | const TlvOffset = struct { | |
| 124 | source_addr: u64, | |
| 125 | offset: u64, | |
| 126 | ||
| 127 | fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool { | |
| 128 | _ = context; | |
| 129 | return a.source_addr < b.source_addr; | |
| 130 | } | |
| 131 | }; | |
| 132 | ||
| 133 | 123 | pub const TextBlock = struct { |
| 134 | 124 | local_sym_index: u32, |
| 135 | 125 | aliases: ?[]u32 = null, |
| ... | ... | @@ -274,12 +264,11 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 274 | 264 | try self.parseLibs(args.libs, args.syslibroot); |
| 275 | 265 | try self.resolveSymbols(); |
| 276 | 266 | try self.parseTextBlocks(); |
| 267 | try self.sortSections(); | |
| 268 | try self.addRpaths(args.rpaths); | |
| 269 | try self.addDataInCodeLC(); | |
| 270 | try self.addCodeSignatureLC(); | |
| 277 | 271 | return error.TODO; |
| 278 | // try self.updateMetadata(); | |
| 279 | // try self.sortSections(); | |
| 280 | // try self.addRpaths(args.rpaths); | |
| 281 | // try self.addDataInCodeLC(); | |
| 282 | // try self.addCodeSignatureLC(); | |
| 283 | 272 | // try self.allocateTextSegment(); |
| 284 | 273 | // try self.allocateDataConstSegment(); |
| 285 | 274 | // try self.allocateDataSegment(); |
| ... | ... | @@ -343,106 +332,6 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi |
| 343 | 332 | } |
| 344 | 333 | } |
| 345 | 334 | |
| 346 | fn mapAndUpdateSections( | |
| 347 | self: *Zld, | |
| 348 | object: *Object, | |
| 349 | source_sect_id: u16, | |
| 350 | target_seg_id: u16, | |
| 351 | target_sect_id: u16, | |
| 352 | ) !void { | |
| 353 | const source_sect = &object.sections.items[source_sect_id]; | |
| 354 | const target_seg = &self.load_commands.items[target_seg_id].Segment; | |
| 355 | const target_sect = &target_seg.sections.items[target_sect_id]; | |
| 356 | ||
| 357 | const alignment = try math.powi(u32, 2, target_sect.@"align"); | |
| 358 | const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment); | |
| 359 | const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment); | |
| 360 | ||
| 361 | log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{ | |
| 362 | object.name.?, | |
| 363 | segmentName(source_sect.inner), | |
| 364 | sectionName(source_sect.inner), | |
| 365 | segmentName(target_sect.*), | |
| 366 | sectionName(target_sect.*), | |
| 367 | offset, | |
| 368 | offset + size, | |
| 369 | }); | |
| 370 | log.debug(" | flags 0x{x}", .{source_sect.inner.flags}); | |
| 371 | ||
| 372 | source_sect.target_map = .{ | |
| 373 | .segment_id = target_seg_id, | |
| 374 | .section_id = target_sect_id, | |
| 375 | .offset = @intCast(u32, offset), | |
| 376 | }; | |
| 377 | target_sect.size = offset + size; | |
| 378 | } | |
| 379 | ||
| 380 | fn updateMetadata(self: *Zld) !void { | |
| 381 | for (self.objects.items) |object| { | |
| 382 | // Find ideal section alignment and update section mappings | |
| 383 | for (object.sections.items) |sect, sect_id| { | |
| 384 | const match = (try self.getMatchingSection(sect.inner)) orelse { | |
| 385 | log.debug("{s}: unhandled section type 0x{x} for '{s},{s}'", .{ | |
| 386 | object.name.?, | |
| 387 | sect.inner.flags, | |
| 388 | segmentName(sect.inner), | |
| 389 | sectionName(sect.inner), | |
| 390 | }); | |
| 391 | continue; | |
| 392 | }; | |
| 393 | const target_seg = &self.load_commands.items[match.seg].Segment; | |
| 394 | const target_sect = &target_seg.sections.items[match.sect]; | |
| 395 | target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align"); | |
| 396 | ||
| 397 | try self.mapAndUpdateSections(object, @intCast(u16, sect_id), match.seg, match.sect); | |
| 398 | } | |
| 399 | } | |
| 400 | ||
| 401 | tlv_align: { | |
| 402 | const has_tlv = | |
| 403 | self.tlv_section_index != null or | |
| 404 | self.tlv_data_section_index != null or | |
| 405 | self.tlv_bss_section_index != null; | |
| 406 | ||
| 407 | if (!has_tlv) break :tlv_align; | |
| 408 | ||
| 409 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | |
| 410 | ||
| 411 | if (self.tlv_section_index) |index| { | |
| 412 | const sect = &seg.sections.items[index]; | |
| 413 | sect.@"align" = 3; // __thread_vars is always 8byte aligned | |
| 414 | } | |
| 415 | ||
| 416 | // Apparently __tlv_data and __tlv_bss need to have matching alignment, so fix it up. | |
| 417 | // <rdar://problem/24221680> All __thread_data and __thread_bss sections must have same alignment | |
| 418 | // https://github.com/apple-opensource/ld64/blob/e28c028b20af187a16a7161d89e91868a450cadc/src/ld/ld.cpp#L1172 | |
| 419 | const data_align: u32 = data: { | |
| 420 | if (self.tlv_data_section_index) |index| { | |
| 421 | const sect = &seg.sections.items[index]; | |
| 422 | break :data sect.@"align"; | |
| 423 | } | |
| 424 | break :tlv_align; | |
| 425 | }; | |
| 426 | const bss_align: u32 = bss: { | |
| 427 | if (self.tlv_bss_section_index) |index| { | |
| 428 | const sect = &seg.sections.items[index]; | |
| 429 | break :bss sect.@"align"; | |
| 430 | } | |
| 431 | break :tlv_align; | |
| 432 | }; | |
| 433 | const max_align = math.max(data_align, bss_align); | |
| 434 | ||
| 435 | if (self.tlv_data_section_index) |index| { | |
| 436 | const sect = &seg.sections.items[index]; | |
| 437 | sect.@"align" = max_align; | |
| 438 | } | |
| 439 | if (self.tlv_bss_section_index) |index| { | |
| 440 | const sect = &seg.sections.items[index]; | |
| 441 | sect.@"align" = max_align; | |
| 442 | } | |
| 443 | } | |
| 444 | } | |
| 445 | ||
| 446 | 335 | pub const MatchingSection = struct { |
| 447 | 336 | seg: u16, |
| 448 | 337 | sect: u16, |
| ... | ... | @@ -946,36 +835,6 @@ fn sortSections(self: *Zld) !void { |
| 946 | 835 | maybe_index.* = new_index; |
| 947 | 836 | } |
| 948 | 837 | } |
| 949 | ||
| 950 | for (self.objects.items) |object| { | |
| 951 | for (object.sections.items) |*sect| { | |
| 952 | const target_map = sect.target_map orelse continue; | |
| 953 | ||
| 954 | const new_index = blk: { | |
| 955 | if (self.text_segment_cmd_index.? == target_map.segment_id) { | |
| 956 | break :blk text_index_mapping.get(target_map.section_id) orelse unreachable; | |
| 957 | } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) { | |
| 958 | break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable; | |
| 959 | } else if (self.data_segment_cmd_index.? == target_map.segment_id) { | |
| 960 | break :blk data_index_mapping.get(target_map.section_id) orelse unreachable; | |
| 961 | } else unreachable; | |
| 962 | }; | |
| 963 | ||
| 964 | log.debug("remapping in {s}: '{s},{s}': {} => {}", .{ | |
| 965 | object.name.?, | |
| 966 | segmentName(sect.inner), | |
| 967 | sectionName(sect.inner), | |
| 968 | target_map.section_id, | |
| 969 | new_index, | |
| 970 | }); | |
| 971 | ||
| 972 | sect.target_map = .{ | |
| 973 | .segment_id = target_map.segment_id, | |
| 974 | .section_id = new_index, | |
| 975 | .offset = target_map.offset, | |
| 976 | }; | |
| 977 | } | |
| 978 | } | |
| 979 | 838 | } |
| 980 | 839 | |
| 981 | 840 | fn allocateTextSegment(self: *Zld) !void { |
| ... | ... | @@ -1431,6 +1290,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1431 | 1290 | symbol.payload = .{ |
| 1432 | 1291 | .regular = .{ |
| 1433 | 1292 | .linkage = .translation_unit, |
| 1293 | .address = sym.n_value, | |
| 1434 | 1294 | .weak_ref = Symbol.isWeakRef(sym), |
| 1435 | 1295 | .file = object, |
| 1436 | 1296 | .local_sym_index = @intCast(u32, self.locals.items.len), |
| ... | ... | @@ -1470,6 +1330,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1470 | 1330 | symbol.payload = .{ |
| 1471 | 1331 | .regular = .{ |
| 1472 | 1332 | .linkage = linkage, |
| 1333 | .address = sym.n_value, | |
| 1473 | 1334 | .weak_ref = Symbol.isWeakRef(sym), |
| 1474 | 1335 | .file = object, |
| 1475 | 1336 | }, |
| ... | ... | @@ -1672,80 +1533,6 @@ fn parseTextBlocks(self: *Zld) !void { |
| 1672 | 1533 | } |
| 1673 | 1534 | } |
| 1674 | 1535 | |
| 1675 | fn resolveRelocsAndWriteSections(self: *Zld) !void { | |
| 1676 | for (self.objects.items) |object| { | |
| 1677 | log.debug("relocating object {s}", .{object.name}); | |
| 1678 | ||
| 1679 | for (object.sections.items) |sect| { | |
| 1680 | if (sectionType(sect.inner) == macho.S_MOD_INIT_FUNC_POINTERS or | |
| 1681 | sectionType(sect.inner) == macho.S_MOD_TERM_FUNC_POINTERS) continue; | |
| 1682 | ||
| 1683 | const segname = segmentName(sect.inner); | |
| 1684 | const sectname = sectionName(sect.inner); | |
| 1685 | ||
| 1686 | log.debug("relocating section '{s},{s}'", .{ segname, sectname }); | |
| 1687 | ||
| 1688 | // Get target mapping | |
| 1689 | const target_map = sect.target_map orelse { | |
| 1690 | log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname }); | |
| 1691 | continue; | |
| 1692 | }; | |
| 1693 | const target_seg = self.load_commands.items[target_map.segment_id].Segment; | |
| 1694 | const target_sect = target_seg.sections.items[target_map.section_id]; | |
| 1695 | const target_sect_addr = target_sect.addr + target_map.offset; | |
| 1696 | const target_sect_off = target_sect.offset + target_map.offset; | |
| 1697 | ||
| 1698 | if (sect.relocs) |relocs| { | |
| 1699 | for (relocs) |rel| { | |
| 1700 | const source_addr = target_sect_addr + rel.offset; | |
| 1701 | ||
| 1702 | var args: reloc.Relocation.ResolveArgs = .{ | |
| 1703 | .source_addr = source_addr, | |
| 1704 | .target_addr = undefined, | |
| 1705 | }; | |
| 1706 | ||
| 1707 | switch (rel.@"type") { | |
| 1708 | .unsigned => { | |
| 1709 | args.target_addr = try self.relocTargetAddr(object, rel.target); | |
| 1710 | ||
| 1711 | const unsigned = rel.cast(reloc.Unsigned) orelse unreachable; | |
| 1712 | if (unsigned.subtractor) |subtractor| { | |
| 1713 | args.subtractor = try self.relocTargetAddr(object, subtractor); | |
| 1714 | } | |
| 1715 | if (rel.target == .section) { | |
| 1716 | const source_sect = object.sections.items[rel.target.section]; | |
| 1717 | args.source_source_sect_addr = sect.inner.addr; | |
| 1718 | args.source_target_sect_addr = source_sect.inner.addr; | |
| 1719 | } | |
| 1720 | }, | |
| 1721 | .got_page, .got_page_off, .got_load, .got, .pointer_to_got => { | |
| 1722 | const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | |
| 1723 | const got = dc_seg.sections.items[self.got_section_index.?]; | |
| 1724 | const sym = object.symbols.items[rel.target.symbol]; | |
| 1725 | const got_index = sym.got_index orelse { | |
| 1726 | log.err("expected GOT index relocating symbol '{s}'", .{sym.name}); | |
| 1727 | log.err("this is an internal linker error", .{}); | |
| 1728 | return error.FailedToResolveRelocationTarget; | |
| 1729 | }; | |
| 1730 | args.target_addr = got.addr + got_index * @sizeOf(u64); | |
| 1731 | }, | |
| 1732 | else => |tt| { | |
| 1733 | if (tt == .signed and rel.target == .section) { | |
| 1734 | const source_sect = object.sections.items[rel.target.section]; | |
| 1735 | args.source_source_sect_addr = sect.inner.addr; | |
| 1736 | args.source_target_sect_addr = source_sect.inner.addr; | |
| 1737 | } | |
| 1738 | args.target_addr = try self.relocTargetAddr(object, rel.target); | |
| 1739 | }, | |
| 1740 | } | |
| 1741 | ||
| 1742 | try rel.resolve(args); | |
| 1743 | } | |
| 1744 | } | |
| 1745 | } | |
| 1746 | } | |
| 1747 | } | |
| 1748 | ||
| 1749 | 1536 | fn populateMetadata(self: *Zld) !void { |
| 1750 | 1537 | if (self.pagezero_segment_cmd_index == null) { |
| 1751 | 1538 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
src/link/MachO/reloc.zig+130-71| ... | ... | @@ -48,33 +48,24 @@ pub const Relocation = struct { |
| 48 | 48 | /// => * is unreachable |
| 49 | 49 | is_64bit: bool, |
| 50 | 50 | |
| 51 | source_sect_addr: ?u64 = null, | |
| 52 | ||
| 51 | 53 | pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 52 | // const addend = if (unsigned.base.target == .section) | |
| 53 | // unsigned.addend - @intCast(i64, args.source_target_sect_addr.?) | |
| 54 | // else | |
| 55 | // unsigned.addend; | |
| 56 | ||
| 57 | // const result = if (args.subtractor) |subtractor| | |
| 58 | // @intCast(i64, args.target_addr) - @intCast(i64, subtractor) + addend | |
| 59 | // else | |
| 60 | // @intCast(i64, args.target_addr) + addend; | |
| 61 | ||
| 62 | // log.debug(" | calculated addend 0x{x}", .{addend}); | |
| 63 | // log.debug(" | calculated unsigned value 0x{x}", .{result}); | |
| 64 | ||
| 65 | // if (unsigned.is_64bit) { | |
| 66 | // mem.writeIntLittle( | |
| 67 | // u64, | |
| 68 | // unsigned.base.code[0..8], | |
| 69 | // @bitCast(u64, result), | |
| 70 | // ); | |
| 71 | // } else { | |
| 72 | // mem.writeIntLittle( | |
| 73 | // u32, | |
| 74 | // unsigned.base.code[0..4], | |
| 75 | // @truncate(u32, @bitCast(u64, result)), | |
| 76 | // ); | |
| 77 | // } | |
| 54 | const addend = if (self.source_sect_addr) |addr| | |
| 55 | self.addend - addr | |
| 56 | else | |
| 57 | self.addend; | |
| 58 | ||
| 59 | const result = if (self.subtractor) |subtractor| | |
| 60 | @intCast(i64, target_addr) - @intCast(i64, subtractor.payload.regular.address) + addend | |
| 61 | else | |
| 62 | @intCast(i64, target_addr) + addend; | |
| 63 | ||
| 64 | if (self.is_64bit) { | |
| 65 | mem.writeIntLittle(u64, base.block.code[base.offset..][0..8], @bitCast(u64, result)); | |
| 66 | } else { | |
| 67 | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @truncate(u32, @bitCast(u64, result))); | |
| 68 | } | |
| 78 | 69 | } |
| 79 | 70 | |
| 80 | 71 | pub fn format(self: Unsigned, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { |
| ... | ... | @@ -191,56 +182,119 @@ pub const Relocation = struct { |
| 191 | 182 | pub fn resolve(self: PageOff, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 192 | 183 | switch (self.kind) { |
| 193 | 184 | .page => { |
| 194 | // const target_addr = if (page_off.addend) |addend| args.target_addr + addend else args.target_addr; | |
| 195 | // const narrowed = @truncate(u12, target_addr); | |
| 196 | ||
| 197 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | |
| 198 | // log.debug(" | {s} opcode", .{page_off.op_kind}); | |
| 199 | ||
| 200 | // var inst = page_off.inst; | |
| 201 | // if (page_off.op_kind == .arithmetic) { | |
| 202 | // inst.add_subtract_immediate.imm12 = narrowed; | |
| 203 | // } else { | |
| 204 | // const offset: u12 = blk: { | |
| 205 | // if (inst.load_store_register.size == 0) { | |
| 206 | // if (inst.load_store_register.v == 1) { | |
| 207 | // // 128-bit SIMD is scaled by 16. | |
| 208 | // break :blk try math.divExact(u12, narrowed, 16); | |
| 209 | // } | |
| 210 | // // Otherwise, 8-bit SIMD or ldrb. | |
| 211 | // break :blk narrowed; | |
| 212 | // } else { | |
| 213 | // const denom: u4 = try math.powi(u4, 2, inst.load_store_register.size); | |
| 214 | // break :blk try math.divExact(u12, narrowed, denom); | |
| 215 | // } | |
| 216 | // }; | |
| 217 | // inst.load_store_register.offset = offset; | |
| 218 | // } | |
| 219 | ||
| 220 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | |
| 185 | const actual_target_addr = if (self.addend) |addend| target_addr + addend else target_addr; | |
| 186 | const narrowed = @truncate(u12, actual_target_addr); | |
| 187 | ||
| 188 | const op_kind = self.op_kind orelse unreachable; | |
| 189 | var inst: aarch64.Instruction = blk: { | |
| 190 | switch (op_kind) { | |
| 191 | .arithmetic => { | |
| 192 | break :blk .{ | |
| 193 | .add_subtract_immediate = mem.bytesToValue( | |
| 194 | meta.TagPayload( | |
| 195 | aarch64.Instruction, | |
| 196 | aarch64.Instruction.add_subtract_immediate, | |
| 197 | ), | |
| 198 | base.block.code[base.offset..][0..4], | |
| 199 | ), | |
| 200 | }; | |
| 201 | }, | |
| 202 | .load => { | |
| 203 | break :blk .{ | |
| 204 | .load_store_register = mem.bytesToValue( | |
| 205 | meta.TagPayload( | |
| 206 | aarch64.Instruction, | |
| 207 | aarch64.Instruction.load_store_register, | |
| 208 | ), | |
| 209 | base.block.code[base.offset..][0..4], | |
| 210 | ), | |
| 211 | }; | |
| 212 | }, | |
| 213 | } | |
| 214 | }; | |
| 215 | ||
| 216 | if (op_kind == .arithmetic) { | |
| 217 | inst.add_subtract_immediate.imm12 = narrowed; | |
| 218 | } else { | |
| 219 | const offset: u12 = blk: { | |
| 220 | if (inst.load_store_register.size == 0) { | |
| 221 | if (inst.load_store_register.v == 1) { | |
| 222 | // 128-bit SIMD is scaled by 16. | |
| 223 | break :blk try math.divExact(u12, narrowed, 16); | |
| 224 | } | |
| 225 | // Otherwise, 8-bit SIMD or ldrb. | |
| 226 | break :blk narrowed; | |
| 227 | } else { | |
| 228 | const denom: u4 = try math.powi(u4, 2, inst.load_store_register.size); | |
| 229 | break :blk try math.divExact(u12, narrowed, denom); | |
| 230 | } | |
| 231 | }; | |
| 232 | inst.load_store_register.offset = offset; | |
| 233 | } | |
| 221 | 234 | |
| 235 | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); | |
| 222 | 236 | }, |
| 223 | 237 | .got => { |
| 224 | // const narrowed = @truncate(u12, args.target_addr); | |
| 225 | ||
| 226 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | |
| 227 | ||
| 228 | // var inst = page_off.inst; | |
| 229 | // const offset = try math.divExact(u12, narrowed, 8); | |
| 230 | // inst.load_store_register.offset = offset; | |
| 231 | ||
| 232 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | |
| 238 | const narrowed = @truncate(u12, target_addr); | |
| 239 | var inst = mem.bytesToValue( | |
| 240 | meta.TagPayload( | |
| 241 | aarch64.Instruction, | |
| 242 | aarch64.Instruction.load_store_register, | |
| 243 | ), | |
| 244 | base.block.code[base.offset..][0..4], | |
| 245 | ); | |
| 246 | const offset = try math.divExact(u12, narrowed, 8); | |
| 247 | inst.load_store_register.offset = offset; | |
| 248 | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); | |
| 233 | 249 | }, |
| 234 | 250 | .tlvp => { |
| 235 | ||
| 236 | // const narrowed = @truncate(u12, args.target_addr); | |
| 237 | ||
| 238 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | |
| 239 | ||
| 240 | // var inst = page_off.inst; | |
| 241 | // inst.add_subtract_immediate.imm12 = narrowed; | |
| 242 | ||
| 243 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | |
| 251 | const RegInfo = struct { | |
| 252 | rd: u5, | |
| 253 | rn: u5, | |
| 254 | size: u1, | |
| 255 | }; | |
| 256 | const reg_info: RegInfo = blk: { | |
| 257 | if (isArithmeticOp(base.block.code[base.offset..][0..4])) { | |
| 258 | const inst = mem.bytesToValue( | |
| 259 | meta.TagPayload( | |
| 260 | aarch64.Instruction, | |
| 261 | aarch64.Instruction.add_subtract_immediate, | |
| 262 | ), | |
| 263 | base.block.code[base.offset..][0..4], | |
| 264 | ); | |
| 265 | break :blk .{ | |
| 266 | .rd = inst.rd, | |
| 267 | .rn = inst.rn, | |
| 268 | .size = inst.sf, | |
| 269 | }; | |
| 270 | } else { | |
| 271 | const inst = mem.bytesToValue( | |
| 272 | meta.TagPayload( | |
| 273 | aarch64.Instruction, | |
| 274 | aarch64.Instruction.load_store_register, | |
| 275 | ), | |
| 276 | base.block.code[base.offset..][0..4], | |
| 277 | ); | |
| 278 | break :blk .{ | |
| 279 | .rd = inst.rt, | |
| 280 | .rn = inst.rn, | |
| 281 | .size = @truncate(u1, inst.size), | |
| 282 | }; | |
| 283 | } | |
| 284 | }; | |
| 285 | const narrowed = @truncate(u12, target_addr); | |
| 286 | var inst = aarch64.Instruction{ | |
| 287 | .add_subtract_immediate = .{ | |
| 288 | .rd = reg_info.rd, | |
| 289 | .rn = reg_info.rn, | |
| 290 | .imm12 = narrowed, | |
| 291 | .sh = 0, | |
| 292 | .s = 0, | |
| 293 | .op = 0, | |
| 294 | .sf = reg_info.size, | |
| 295 | }, | |
| 296 | }; | |
| 297 | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], inst.toU32()); | |
| 244 | 298 | }, |
| 245 | 299 | } |
| 246 | 300 | } |
| ... | ... | @@ -661,12 +715,17 @@ pub const Parser = struct { |
| 661 | 715 | mem.readIntLittle(i64, self.block.code[parsed.offset..][0..8]) |
| 662 | 716 | else |
| 663 | 717 | mem.readIntLittle(i32, self.block.code[parsed.offset..][0..4]); |
| 718 | const source_sect_addr = if (rel.r_extern == 0) blk: { | |
| 719 | if (parsed.target.payload == .regular) break :blk parsed.target.payload.regular.address; | |
| 720 | break :blk null; | |
| 721 | } else null; | |
| 664 | 722 | |
| 665 | 723 | parsed.payload = .{ |
| 666 | 724 | .unsigned = .{ |
| 667 | 725 | .subtractor = self.subtractor, |
| 668 | 726 | .is_64bit = is_64bit, |
| 669 | 727 | .addend = addend, |
| 728 | .source_sect_addr = source_sect_addr, | |
| 670 | 729 | }, |
| 671 | 730 | }; |
| 672 | 731 |