| 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,8 +48,6 @@ dwarf_debug_ranges_index: ?u16 = null, |
| 48 | 48 | ||
| 49 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 49 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 50 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 50 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 51 | |||
| 52 | initializers: std.ArrayListUnmanaged(u32) = .{}, | ||
| 53 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | 51 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, |
| 54 | 52 | ||
| 55 | symbols: std.ArrayListUnmanaged(*Symbol) = .{}, | 53 | symbols: std.ArrayListUnmanaged(*Symbol) = .{}, |
| ... | @@ -157,7 +155,6 @@ pub fn deinit(self: *Object) void { | ... | @@ -157,7 +155,6 @@ pub fn deinit(self: *Object) void { |
| 157 | } | 155 | } |
| 158 | self.load_commands.deinit(self.allocator); | 156 | self.load_commands.deinit(self.allocator); |
| 159 | self.data_in_code_entries.deinit(self.allocator); | 157 | self.data_in_code_entries.deinit(self.allocator); |
| 160 | self.initializers.deinit(self.allocator); | ||
| 161 | self.symtab.deinit(self.allocator); | 158 | self.symtab.deinit(self.allocator); |
| 162 | self.strtab.deinit(self.allocator); | 159 | self.strtab.deinit(self.allocator); |
| 163 | self.symbols.deinit(self.allocator); | 160 | self.symbols.deinit(self.allocator); |
| ... | @@ -573,6 +570,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { | ... | @@ -573,6 +570,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void { |
| 573 | symbol.payload = .{ | 570 | symbol.payload = .{ |
| 574 | .regular = .{ | 571 | .regular = .{ |
| 575 | .linkage = .translation_unit, | 572 | .linkage = .translation_unit, |
| 573 | .address = sect.addr, | ||
| 576 | .segment_id = match.seg, | 574 | .segment_id = match.seg, |
| 577 | .section_id = match.sect, | 575 | .section_id = match.sect, |
| 578 | .file = self, | 576 | .file = self, |
| ... | @@ -657,6 +655,13 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { | ... | @@ -657,6 +655,13 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { |
| 657 | }); | 655 | }); |
| 658 | defer self.allocator.free(name); | 656 | defer self.allocator.free(name); |
| 659 | const symbol = try Symbol.new(self.allocator, name); | 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 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); | 665 | try self.sections_as_symbols.putNoClobber(self.allocator, sect_id, symbol); |
| 661 | break :symbol symbol; | 666 | break :symbol symbol; |
| 662 | }; | 667 | }; |
| ... | @@ -666,22 +671,6 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { | ... | @@ -666,22 +671,6 @@ pub fn symbolFromReloc(self: *Object, rel: macho.relocation_info) !*Symbol { |
| 666 | return symbol; | 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 | fn parseSymtab(self: *Object) !void { | 674 | fn parseSymtab(self: *Object) !void { |
| 686 | const index = self.symtab_cmd_index orelse return; | 675 | const index = self.symtab_cmd_index orelse return; |
| 687 | const symtab_cmd = self.load_commands.items[index].Symtab; | 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,16 +120,6 @@ pub const Output = struct { |
| 120 | install_name: ?[]const u8 = null, | 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 | pub const TextBlock = struct { | 123 | pub const TextBlock = struct { |
| 134 | local_sym_index: u32, | 124 | local_sym_index: u32, |
| 135 | aliases: ?[]u32 = null, | 125 | aliases: ?[]u32 = null, |
| ... | @@ -274,12 +264,11 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg | ... | @@ -274,12 +264,11 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 274 | try self.parseLibs(args.libs, args.syslibroot); | 264 | try self.parseLibs(args.libs, args.syslibroot); |
| 275 | try self.resolveSymbols(); | 265 | try self.resolveSymbols(); |
| 276 | try self.parseTextBlocks(); | 266 | try self.parseTextBlocks(); |
| 267 | try self.sortSections(); | ||
| 268 | try self.addRpaths(args.rpaths); | ||
| 269 | try self.addDataInCodeLC(); | ||
| 270 | try self.addCodeSignatureLC(); | ||
| 277 | return error.TODO; | 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 | // try self.allocateTextSegment(); | 272 | // try self.allocateTextSegment(); |
| 284 | // try self.allocateDataConstSegment(); | 273 | // try self.allocateDataConstSegment(); |
| 285 | // try self.allocateDataSegment(); | 274 | // try self.allocateDataSegment(); |
| ... | @@ -343,106 +332,6 @@ fn parseLibs(self: *Zld, libs: []const []const u8, syslibroot: ?[]const u8) !voi | ... | @@ -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 | pub const MatchingSection = struct { | 335 | pub const MatchingSection = struct { |
| 447 | seg: u16, | 336 | seg: u16, |
| 448 | sect: u16, | 337 | sect: u16, |
| ... | @@ -946,36 +835,6 @@ fn sortSections(self: *Zld) !void { | ... | @@ -946,36 +835,6 @@ fn sortSections(self: *Zld) !void { |
| 946 | maybe_index.* = new_index; | 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 | fn allocateTextSegment(self: *Zld) !void { | 840 | fn allocateTextSegment(self: *Zld) !void { |
| ... | @@ -1431,6 +1290,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { | ... | @@ -1431,6 +1290,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1431 | symbol.payload = .{ | 1290 | symbol.payload = .{ |
| 1432 | .regular = .{ | 1291 | .regular = .{ |
| 1433 | .linkage = .translation_unit, | 1292 | .linkage = .translation_unit, |
| 1293 | .address = sym.n_value, | ||
| 1434 | .weak_ref = Symbol.isWeakRef(sym), | 1294 | .weak_ref = Symbol.isWeakRef(sym), |
| 1435 | .file = object, | 1295 | .file = object, |
| 1436 | .local_sym_index = @intCast(u32, self.locals.items.len), | 1296 | .local_sym_index = @intCast(u32, self.locals.items.len), |
| ... | @@ -1470,6 +1330,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { | ... | @@ -1470,6 +1330,7 @@ fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1470 | symbol.payload = .{ | 1330 | symbol.payload = .{ |
| 1471 | .regular = .{ | 1331 | .regular = .{ |
| 1472 | .linkage = linkage, | 1332 | .linkage = linkage, |
| 1333 | .address = sym.n_value, | ||
| 1473 | .weak_ref = Symbol.isWeakRef(sym), | 1334 | .weak_ref = Symbol.isWeakRef(sym), |
| 1474 | .file = object, | 1335 | .file = object, |
| 1475 | }, | 1336 | }, |
| ... | @@ -1672,80 +1533,6 @@ fn parseTextBlocks(self: *Zld) !void { | ... | @@ -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 | fn populateMetadata(self: *Zld) !void { | 1536 | fn populateMetadata(self: *Zld) !void { |
| 1750 | if (self.pagezero_segment_cmd_index == null) { | 1537 | if (self.pagezero_segment_cmd_index == null) { |
| 1751 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); | 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,33 +48,24 @@ pub const Relocation = struct { |
| 48 | /// => * is unreachable | 48 | /// => * is unreachable |
| 49 | is_64bit: bool, | 49 | is_64bit: bool, |
| 50 | 50 | ||
| 51 | source_sect_addr: ?u64 = null, | ||
| 52 | |||
| 51 | pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void { | 53 | pub fn resolve(self: Unsigned, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 52 | // const addend = if (unsigned.base.target == .section) | 54 | const addend = if (self.source_sect_addr) |addr| |
| 53 | // unsigned.addend - @intCast(i64, args.source_target_sect_addr.?) | 55 | self.addend - addr |
| 54 | // else | 56 | else |
| 55 | // unsigned.addend; | 57 | self.addend; |
| 56 | 58 | ||
| 57 | // const result = if (args.subtractor) |subtractor| | 59 | const result = if (self.subtractor) |subtractor| |
| 58 | // @intCast(i64, args.target_addr) - @intCast(i64, subtractor) + addend | 60 | @intCast(i64, target_addr) - @intCast(i64, subtractor.payload.regular.address) + addend |
| 59 | // else | 61 | else |
| 60 | // @intCast(i64, args.target_addr) + addend; | 62 | @intCast(i64, target_addr) + addend; |
| 61 | 63 | ||
| 62 | // log.debug(" | calculated addend 0x{x}", .{addend}); | 64 | if (self.is_64bit) { |
| 63 | // log.debug(" | calculated unsigned value 0x{x}", .{result}); | 65 | mem.writeIntLittle(u64, base.block.code[base.offset..][0..8], @bitCast(u64, result)); |
| 64 | 66 | } else { | |
| 65 | // if (unsigned.is_64bit) { | 67 | mem.writeIntLittle(u32, base.block.code[base.offset..][0..4], @truncate(u32, @bitCast(u64, result))); |
| 66 | // mem.writeIntLittle( | 68 | } |
| 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 | // } | ||
| 78 | } | 69 | } |
| 79 | 70 | ||
| 80 | pub fn format(self: Unsigned, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | 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,56 +182,119 @@ pub const Relocation = struct { |
| 191 | pub fn resolve(self: PageOff, base: Relocation, source_addr: u64, target_addr: u64) !void { | 182 | pub fn resolve(self: PageOff, base: Relocation, source_addr: u64, target_addr: u64) !void { |
| 192 | switch (self.kind) { | 183 | switch (self.kind) { |
| 193 | .page => { | 184 | .page => { |
| 194 | // const target_addr = if (page_off.addend) |addend| args.target_addr + addend else args.target_addr; | 185 | const actual_target_addr = if (self.addend) |addend| target_addr + addend else target_addr; |
| 195 | // const narrowed = @truncate(u12, target_addr); | 186 | const narrowed = @truncate(u12, actual_target_addr); |
| 196 | 187 | ||
| 197 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | 188 | const op_kind = self.op_kind orelse unreachable; |
| 198 | // log.debug(" | {s} opcode", .{page_off.op_kind}); | 189 | var inst: aarch64.Instruction = blk: { |
| 199 | 190 | switch (op_kind) { | |
| 200 | // var inst = page_off.inst; | 191 | .arithmetic => { |
| 201 | // if (page_off.op_kind == .arithmetic) { | 192 | break :blk .{ |
| 202 | // inst.add_subtract_immediate.imm12 = narrowed; | 193 | .add_subtract_immediate = mem.bytesToValue( |
| 203 | // } else { | 194 | meta.TagPayload( |
| 204 | // const offset: u12 = blk: { | 195 | aarch64.Instruction, |
| 205 | // if (inst.load_store_register.size == 0) { | 196 | aarch64.Instruction.add_subtract_immediate, |
| 206 | // if (inst.load_store_register.v == 1) { | 197 | ), |
| 207 | // // 128-bit SIMD is scaled by 16. | 198 | base.block.code[base.offset..][0..4], |
| 208 | // break :blk try math.divExact(u12, narrowed, 16); | 199 | ), |
| 209 | // } | 200 | }; |
| 210 | // // Otherwise, 8-bit SIMD or ldrb. | 201 | }, |
| 211 | // break :blk narrowed; | 202 | .load => { |
| 212 | // } else { | 203 | break :blk .{ |
| 213 | // const denom: u4 = try math.powi(u4, 2, inst.load_store_register.size); | 204 | .load_store_register = mem.bytesToValue( |
| 214 | // break :blk try math.divExact(u12, narrowed, denom); | 205 | meta.TagPayload( |
| 215 | // } | 206 | aarch64.Instruction, |
| 216 | // }; | 207 | aarch64.Instruction.load_store_register, |
| 217 | // inst.load_store_register.offset = offset; | 208 | ), |
| 218 | // } | 209 | base.block.code[base.offset..][0..4], |
| 219 | 210 | ), | |
| 220 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | 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 | .got => { | 237 | .got => { |
| 224 | // const narrowed = @truncate(u12, args.target_addr); | 238 | const narrowed = @truncate(u12, target_addr); |
| 225 | 239 | var inst = mem.bytesToValue( | |
| 226 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | 240 | meta.TagPayload( |
| 227 | 241 | aarch64.Instruction, | |
| 228 | // var inst = page_off.inst; | 242 | aarch64.Instruction.load_store_register, |
| 229 | // const offset = try math.divExact(u12, narrowed, 8); | 243 | ), |
| 230 | // inst.load_store_register.offset = offset; | 244 | base.block.code[base.offset..][0..4], |
| 231 | 245 | ); | |
| 232 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | 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 | .tlvp => { | 250 | .tlvp => { |
| 235 | 251 | const RegInfo = struct { | |
| 236 | // const narrowed = @truncate(u12, args.target_addr); | 252 | rd: u5, |
| 237 | 253 | rn: u5, | |
| 238 | // log.debug(" | narrowed address within the page 0x{x}", .{narrowed}); | 254 | size: u1, |
| 239 | 255 | }; | |
| 240 | // var inst = page_off.inst; | 256 | const reg_info: RegInfo = blk: { |
| 241 | // inst.add_subtract_immediate.imm12 = narrowed; | 257 | if (isArithmeticOp(base.block.code[base.offset..][0..4])) { |
| 242 | 258 | const inst = mem.bytesToValue( | |
| 243 | // mem.writeIntLittle(u32, page_off.base.code[0..4], inst.toU32()); | 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,12 +715,17 @@ pub const Parser = struct { |
| 661 | mem.readIntLittle(i64, self.block.code[parsed.offset..][0..8]) | 715 | mem.readIntLittle(i64, self.block.code[parsed.offset..][0..8]) |
| 662 | else | 716 | else |
| 663 | mem.readIntLittle(i32, self.block.code[parsed.offset..][0..4]); | 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 | parsed.payload = .{ | 723 | parsed.payload = .{ |
| 666 | .unsigned = .{ | 724 | .unsigned = .{ |
| 667 | .subtractor = self.subtractor, | 725 | .subtractor = self.subtractor, |
| 668 | .is_64bit = is_64bit, | 726 | .is_64bit = is_64bit, |
| 669 | .addend = addend, | 727 | .addend = addend, |
| 728 | .source_sect_addr = source_sect_addr, | ||
| 670 | }, | 729 | }, |
| 671 | }; | 730 | }; |
| 672 | 731 |