authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-02-25 09:47:26+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-17 19:59:13+01:00
loge825a15b0588d2ae4d3c6ab28fb8d8fd2ae05288
tree2b658a6fd9e32ae3d0132e146b45e1f2d3d301aa
parentf52f23618d51367bfd498403e303090039f3b6b6

zld: replace ldr with add if indivisible


1 files changed, 94 insertions(+), 63 deletions(-)

src/link/MachO/Zld.zig+94-63
...@@ -16,6 +16,7 @@ const CodeSignature = @import("CodeSignature.zig");...@@ -16,6 +16,7 @@ const CodeSignature = @import("CodeSignature.zig");
16const Archive = @import("Archive.zig");16const Archive = @import("Archive.zig");
17const Object = @import("Object.zig");17const Object = @import("Object.zig");
18const Trie = @import("Trie.zig");18const Trie = @import("Trie.zig");
19const aarch64 = @import("../../codegen/aarch64.zig");
1920
20usingnamespace @import("commands.zig");21usingnamespace @import("commands.zig");
21usingnamespace @import("bind.zig");22usingnamespace @import("bind.zig");
...@@ -299,6 +300,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {...@@ -299,6 +300,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
299fn parseObjectFile(self: *Zld, object: *const Object) !void {300fn parseObjectFile(self: *Zld, object: *const Object) !void {
300 const seg_cmd = object.load_commands.items[object.segment_cmd_index.?].Segment;301 const seg_cmd = object.load_commands.items[object.segment_cmd_index.?].Segment;
301 for (seg_cmd.sections.items) |sect| {302 for (seg_cmd.sections.items) |sect| {
303 const segname = parseName(&sect.segname);
302 const sectname = parseName(&sect.sectname);304 const sectname = parseName(&sect.sectname);
303305
304 const seg_index = self.segments_directory.get(sect.segname) orelse {306 const seg_index = self.segments_directory.get(sect.segname) orelse {
...@@ -384,7 +386,7 @@ fn resolveImports(self: *Zld) !void {...@@ -384,7 +386,7 @@ fn resolveImports(self: *Zld) !void {
384 mem.eql(u8, sym_name, "___stack_chk_guard") or386 mem.eql(u8, sym_name, "___stack_chk_guard") or
385 mem.eql(u8, sym_name, "_environ"))387 mem.eql(u8, sym_name, "_environ"))
386 {388 {
387 log.debug("writing nonlazy symbol '{s}'", .{sym_name});389 log.warn("writing nonlazy symbol '{s}'", .{sym_name});
388 const index = @intCast(u32, self.nonlazy_imports.items().len);390 const index = @intCast(u32, self.nonlazy_imports.items().len);
389 try self.nonlazy_imports.putNoClobber(self.allocator, key, .{391 try self.nonlazy_imports.putNoClobber(self.allocator, key, .{
390 .symbol = new_sym,392 .symbol = new_sym,
...@@ -392,7 +394,7 @@ fn resolveImports(self: *Zld) !void {...@@ -392,7 +394,7 @@ fn resolveImports(self: *Zld) !void {
392 .index = index,394 .index = index,
393 });395 });
394 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {396 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
395 log.debug("writing threadlocal symbol '{s}'", .{sym_name});397 log.warn("writing threadlocal symbol '{s}'", .{sym_name});
396 const index = @intCast(u32, self.threadlocal_imports.items().len);398 const index = @intCast(u32, self.threadlocal_imports.items().len);
397 try self.threadlocal_imports.putNoClobber(self.allocator, key, .{399 try self.threadlocal_imports.putNoClobber(self.allocator, key, .{
398 .symbol = new_sym,400 .symbol = new_sym,
...@@ -400,7 +402,7 @@ fn resolveImports(self: *Zld) !void {...@@ -400,7 +402,7 @@ fn resolveImports(self: *Zld) !void {
400 .index = index,402 .index = index,
401 });403 });
402 } else {404 } else {
403 log.debug("writing lazy symbol '{s}'", .{sym_name});405 log.warn("writing lazy symbol '{s}'", .{sym_name});
404 const index = @intCast(u32, self.lazy_imports.items().len);406 const index = @intCast(u32, self.lazy_imports.items().len);
405 try self.lazy_imports.putNoClobber(self.allocator, key, .{407 try self.lazy_imports.putNoClobber(self.allocator, key, .{
406 .symbol = new_sym,408 .symbol = new_sym,
...@@ -412,7 +414,7 @@ fn resolveImports(self: *Zld) !void {...@@ -412,7 +414,7 @@ fn resolveImports(self: *Zld) !void {
412414
413 const n_strx = try self.makeString("dyld_stub_binder");415 const n_strx = try self.makeString("dyld_stub_binder");
414 const name = try self.allocator.dupe(u8, "dyld_stub_binder");416 const name = try self.allocator.dupe(u8, "dyld_stub_binder");
415 log.debug("writing nonlazy symbol 'dyld_stub_binder'", .{});417 log.warn("writing nonlazy symbol 'dyld_stub_binder'", .{});
416 const index = @intCast(u32, self.nonlazy_imports.items().len);418 const index = @intCast(u32, self.nonlazy_imports.items().len);
417 try self.nonlazy_imports.putNoClobber(self.allocator, name, .{419 try self.nonlazy_imports.putNoClobber(self.allocator, name, .{
418 .symbol = .{420 .symbol = .{
...@@ -606,7 +608,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -606,7 +608,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
606 var buf: [@sizeOf(u64)]u8 = undefined;608 var buf: [@sizeOf(u64)]u8 = undefined;
607 mem.writeIntLittle(u64, &buf, end);609 mem.writeIntLittle(u64, &buf, end);
608 const off = la_symbol_ptr.offset + index * @sizeOf(u64);610 const off = la_symbol_ptr.offset + index * @sizeOf(u64);
609 log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });611 log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });
610 try self.file.?.pwriteAll(&buf, off);612 try self.file.?.pwriteAll(&buf, off);
611}613}
612614
...@@ -619,7 +621,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -619,7 +621,7 @@ fn writeStub(self: *Zld, index: u32) !void {
619 const stub_off = stubs.offset + index * stubs.reserved2;621 const stub_off = stubs.offset + index * stubs.reserved2;
620 const stub_addr = stubs.addr + index * stubs.reserved2;622 const stub_addr = stubs.addr + index * stubs.reserved2;
621 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);623 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);
622 log.debug("writing stub at 0x{x}", .{stub_off});624 log.warn("writing stub at 0x{x}", .{stub_off});
623 var code = try self.allocator.alloc(u8, stubs.reserved2);625 var code = try self.allocator.alloc(u8, stubs.reserved2);
624 defer self.allocator.free(code);626 defer self.allocator.free(code);
625 switch (self.arch.?) {627 switch (self.arch.?) {
...@@ -720,7 +722,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -720,7 +722,7 @@ fn resolveSymbols(self: *Zld) !void {
720 const sym_name = object.getString(sym.n_strx);722 const sym_name = object.getString(sym.n_strx);
721723
722 if (isLocal(&sym) and self.locals.get(sym_name) != null) {724 if (isLocal(&sym) and self.locals.get(sym_name) != null) {
723 log.debug("symbol '{s}' already exists; skipping", .{sym_name});725 log.warn("symbol '{s}' already exists; skipping", .{sym_name});
724 continue;726 continue;
725 }727 }
726728
...@@ -734,7 +736,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -734,7 +736,7 @@ fn resolveSymbols(self: *Zld) !void {
734 const n_strx = try self.makeString(sym_name);736 const n_strx = try self.makeString(sym_name);
735 const n_value = sym.n_value - sect.addr + next_address.get(key).?.addr;737 const n_value = sym.n_value - sect.addr + next_address.get(key).?.addr;
736738
737 log.debug("resolving '{s}' as local symbol at 0x{x}", .{ sym_name, n_value });739 log.warn("resolving '{s}' as local symbol at 0x{x}", .{ sym_name, n_value });
738740
739 var n_sect = res.sect_index + 1;741 var n_sect = res.sect_index + 1;
740 for (self.load_commands.items) |sseg, i| {742 for (self.load_commands.items) |sseg, i| {
...@@ -766,8 +768,8 @@ fn doRelocs(self: *Zld) !void {...@@ -766,8 +768,8 @@ fn doRelocs(self: *Zld) !void {
766 defer next_space.deinit();768 defer next_space.deinit();
767769
768 for (self.objects.items) |object| {770 for (self.objects.items) |object| {
769 log.debug("\n\n", .{});771 log.warn("\n\n", .{});
770 log.debug("relocating object {s}", .{object.name});772 log.warn("relocating object {s}", .{object.name});
771773
772 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;774 const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
773775
...@@ -802,9 +804,12 @@ fn doRelocs(self: *Zld) !void {...@@ -802,9 +804,12 @@ fn doRelocs(self: *Zld) !void {
802 };804 };
803 const next = next_space.get(key) orelse continue;805 const next = next_space.get(key) orelse continue;
804806
805 var code = try self.allocator.alloc(u8, sect.size);807 var code = blk: {
806 defer self.allocator.free(code);808 var buf = try self.allocator.alloc(u8, sect.size);
807 _ = try object.file.preadAll(code, sect.offset);809 _ = try object.file.preadAll(buf, sect.offset);
810 break :blk std.ArrayList(u8).fromOwnedSlice(self.allocator, buf);
811 };
812 defer code.deinit();
808813
809 // Parse relocs (if any)814 // Parse relocs (if any)
810 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);815 var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
...@@ -822,34 +827,34 @@ fn doRelocs(self: *Zld) !void {...@@ -822,34 +827,34 @@ fn doRelocs(self: *Zld) !void {
822 switch (self.arch.?) {827 switch (self.arch.?) {
823 .aarch64 => {828 .aarch64 => {
824 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);829 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
825 log.debug("{s}", .{rel_type});830 log.warn("{s}", .{rel_type});
826 log.debug(" | source address 0x{x}", .{this_addr});831 log.warn(" | source address 0x{x}", .{this_addr});
827 log.debug(" | offset 0x{x}", .{off});832 log.warn(" | offset 0x{x}", .{off});
828833
829 if (rel_type == .ARM64_RELOC_ADDEND) {834 if (rel_type == .ARM64_RELOC_ADDEND) {
830 addend = rel.r_symbolnum;835 addend = rel.r_symbolnum;
831 log.debug(" | calculated addend = 0x{x}", .{addend});836 log.warn(" | calculated addend = 0x{x}", .{addend});
832 // TODO followed by either PAGE21 or PAGEOFF12 only.837 // TODO followed by either PAGE21 or PAGEOFF12 only.
833 continue;838 continue;
834 }839 }
835 },840 },
836 .x86_64 => {841 .x86_64 => {
837 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);842 const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type);
838 log.debug("{s}", .{rel_type});843 log.warn("{s}", .{rel_type});
839 log.debug(" | source address 0x{x}", .{this_addr});844 log.warn(" | source address 0x{x}", .{this_addr});
840 log.debug(" | offset 0x{x}", .{off});845 log.warn(" | offset 0x{x}", .{off});
841 },846 },
842 else => {},847 else => {},
843 }848 }
844849
845 const target_addr = try self.relocTargetAddr(object, rel, next_space);850 const target_addr = try self.relocTargetAddr(object, rel, next_space);
846 log.debug(" | target address 0x{x}", .{target_addr});851 log.warn(" | target address 0x{x}", .{target_addr});
847 if (rel.r_extern == 1) {852 if (rel.r_extern == 1) {
848 const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx);853 const target_symname = object.getString(object.symtab.items[rel.r_symbolnum].n_strx);
849 log.debug(" | target symbol '{s}'", .{target_symname});854 log.warn(" | target symbol '{s}'", .{target_symname});
850 } else {855 } else {
851 const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname;856 const target_sectname = seg.sections.items[rel.r_symbolnum - 1].sectname;
852 log.debug(" | target section '{s}'", .{parseName(&target_sectname)});857 log.warn(" | target section '{s}'", .{parseName(&target_sectname)});
853 }858 }
854859
855 switch (self.arch.?) {860 switch (self.arch.?) {
...@@ -862,16 +867,16 @@ fn doRelocs(self: *Zld) !void {...@@ -862,16 +867,16 @@ fn doRelocs(self: *Zld) !void {
862 .X86_64_RELOC_GOT,867 .X86_64_RELOC_GOT,
863 => {868 => {
864 assert(rel.r_length == 2);869 assert(rel.r_length == 2);
865 const inst = code[off..][0..4];870 const inst = code.items[off..][0..4];
866 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));871 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));
867 mem.writeIntLittle(u32, inst, displacement);872 mem.writeIntLittle(u32, inst, displacement);
868 },873 },
869 .X86_64_RELOC_TLV => {874 .X86_64_RELOC_TLV => {
870 assert(rel.r_length == 2);875 assert(rel.r_length == 2);
871 // We need to rewrite the opcode from movq to leaq.876 // We need to rewrite the opcode from movq to leaq.
872 code[off - 2] = 0x8d;877 code.items[off - 2] = 0x8d;
873 // Add displacement.878 // Add displacement.
874 const inst = code[off..][0..4];879 const inst = code.items[off..][0..4];
875 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));880 const displacement = @bitCast(u32, @intCast(i32, @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4));
876 mem.writeIntLittle(u32, inst, displacement);881 mem.writeIntLittle(u32, inst, displacement);
877 },882 },
...@@ -881,7 +886,7 @@ fn doRelocs(self: *Zld) !void {...@@ -881,7 +886,7 @@ fn doRelocs(self: *Zld) !void {
881 .X86_64_RELOC_SIGNED_4,886 .X86_64_RELOC_SIGNED_4,
882 => {887 => {
883 assert(rel.r_length == 2);888 assert(rel.r_length == 2);
884 const inst = code[off..][0..4];889 const inst = code.items[off..][0..4];
885 const offset: i32 = blk: {890 const offset: i32 = blk: {
886 if (rel.r_extern == 1) {891 if (rel.r_extern == 1) {
887 break :blk mem.readIntLittle(i32, inst);892 break :blk mem.readIntLittle(i32, inst);
...@@ -899,7 +904,7 @@ fn doRelocs(self: *Zld) !void {...@@ -899,7 +904,7 @@ fn doRelocs(self: *Zld) !void {
899 break :blk correction;904 break :blk correction;
900 }905 }
901 };906 };
902 log.debug(" | calculated addend 0x{x}", .{offset});907 log.warn(" | calculated addend 0x{x}", .{offset});
903 const result = @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4 + offset;908 const result = @intCast(i64, target_addr) - @intCast(i64, this_addr) - 4 + offset;
904 const displacement = @bitCast(u32, @intCast(i32, result));909 const displacement = @bitCast(u32, @intCast(i32, result));
905 mem.writeIntLittle(u32, inst, displacement);910 mem.writeIntLittle(u32, inst, displacement);
...@@ -910,9 +915,9 @@ fn doRelocs(self: *Zld) !void {...@@ -910,9 +915,9 @@ fn doRelocs(self: *Zld) !void {
910 .X86_64_RELOC_UNSIGNED => {915 .X86_64_RELOC_UNSIGNED => {
911 switch (rel.r_length) {916 switch (rel.r_length) {
912 3 => {917 3 => {
913 const inst = code[off..][0..8];918 const inst = code.items[off..][0..8];
914 const offset = mem.readIntLittle(i64, inst);919 const offset = mem.readIntLittle(i64, inst);
915 log.debug(" | calculated addend 0x{x}", .{offset});920 log.warn(" | calculated addend 0x{x}", .{offset});
916 const result = if (sub) |s|921 const result = if (sub) |s|
917 @intCast(i64, target_addr) - s + offset922 @intCast(i64, target_addr) - s + offset
918 else923 else
...@@ -934,9 +939,9 @@ fn doRelocs(self: *Zld) !void {...@@ -934,9 +939,9 @@ fn doRelocs(self: *Zld) !void {
934 }939 }
935 },940 },
936 2 => {941 2 => {
937 const inst = code[off..][0..4];942 const inst = code.items[off..][0..4];
938 const offset = mem.readIntLittle(i32, inst);943 const offset = mem.readIntLittle(i32, inst);
939 log.debug(" | calculated addend 0x{x}", .{offset});944 log.warn(" | calculated addend 0x{x}", .{offset});
940 const result = if (sub) |s|945 const result = if (sub) |s|
941 @intCast(i64, target_addr) - s + offset946 @intCast(i64, target_addr) - s + offset
942 else947 else
...@@ -958,7 +963,7 @@ fn doRelocs(self: *Zld) !void {...@@ -958,7 +963,7 @@ fn doRelocs(self: *Zld) !void {
958 switch (rel_type) {963 switch (rel_type) {
959 .ARM64_RELOC_BRANCH26 => {964 .ARM64_RELOC_BRANCH26 => {
960 assert(rel.r_length == 2);965 assert(rel.r_length == 2);
961 const inst = code[off..][0..4];966 const inst = code.items[off..][0..4];
962 const displacement = @intCast(i28, @intCast(i64, target_addr) - @intCast(i64, this_addr));967 const displacement = @intCast(i28, @intCast(i64, target_addr) - @intCast(i64, this_addr));
963 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Branch), inst);968 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Branch), inst);
964 parsed.disp = @truncate(u26, @bitCast(u28, displacement) >> 2);969 parsed.disp = @truncate(u26, @bitCast(u28, displacement) >> 2);
...@@ -968,12 +973,18 @@ fn doRelocs(self: *Zld) !void {...@@ -968,12 +973,18 @@ fn doRelocs(self: *Zld) !void {
968 .ARM64_RELOC_TLVP_LOAD_PAGE21,973 .ARM64_RELOC_TLVP_LOAD_PAGE21,
969 => {974 => {
970 assert(rel.r_length == 2);975 assert(rel.r_length == 2);
971 const inst = code[off..][0..4];976 const inst = code.items[off..][0..4];
972 const ta = if (addend) |a| target_addr + a else target_addr;977 const ta = if (addend) |a| target_addr + a else target_addr;
973 const this_page = @intCast(i32, this_addr >> 12);978 const this_page = @intCast(i32, this_addr >> 12);
974 const target_page = @intCast(i32, ta >> 12);979 const target_page = @intCast(i32, ta >> 12);
975 const pages = @bitCast(u21, @intCast(i21, target_page - this_page));980 const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
976 log.debug(" | moving by {} pages", .{pages});981 if (pages == 0) {
982 // No need to execute adrp. Instead, replace with a nop.
983 log.warn(" | replacing ADRP with NOP", .{});
984 mem.writeIntLittle(u32, inst, aarch64.Instruction.nop().toU32());
985 continue;
986 }
987 log.warn(" | moving by {} pages", .{pages});
977 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);988 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);
978 parsed.immhi = @truncate(u19, pages >> 2);989 parsed.immhi = @truncate(u19, pages >> 2);
979 parsed.immlo = @truncate(u2, pages);990 parsed.immlo = @truncate(u2, pages);
...@@ -982,22 +993,42 @@ fn doRelocs(self: *Zld) !void {...@@ -982,22 +993,42 @@ fn doRelocs(self: *Zld) !void {
982 .ARM64_RELOC_PAGEOFF12,993 .ARM64_RELOC_PAGEOFF12,
983 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,994 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
984 => {995 => {
985 const inst = code[off..][0..4];996 const inst = code.items[off..][0..4];
986 if (Arm64.isArithmetic(inst)) {997 if (Arm64.isArithmetic(inst)) {
987 log.debug(" | detected ADD opcode", .{});998 log.warn(" | detected ADD opcode", .{});
988 // add999 // add
989 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);1000 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
990 const ta = if (addend) |a| target_addr + a else target_addr;1001 const ta = if (addend) |a| target_addr + a else target_addr;
991 const narrowed = @truncate(u12, ta);1002 const narrowed = @truncate(u12, ta);
1003 if (narrowed == 0) {
1004 // No need to execute add. Instead, replace with a nop.
1005 log.warn(" | replacing ADD with NOP", .{});
1006 mem.writeIntLittle(u32, inst, aarch64.Instruction.nop().toU32());
1007 continue;
1008 }
992 parsed.offset = narrowed;1009 parsed.offset = narrowed;
993 } else {1010 } else {
994 log.debug(" | detected LDR/STR opcode", .{});1011 log.warn(" | detected LDR/STR opcode", .{});
995 // ldr/str1012 // ldr/str
996 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);1013 var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);
997 const ta = if (addend) |a| target_addr + a else target_addr;1014 const ta = if (addend) |a| target_addr + a else target_addr;
998 const narrowed = @truncate(u12, ta);1015 const narrowed = @truncate(u12, ta);
999 const offset = if (parsed.size == 1) @divExact(narrowed, 8) else @divExact(narrowed, 4);1016 if (narrowed == 0) {
1000 parsed.offset = @truncate(u12, offset);1017 // No need to execute ldr/str. Instead, replace with a nop.
1018 log.warn(" | replacing LDR/STR with NOP", .{});
1019 mem.writeIntLittle(u32, inst, aarch64.Instruction.nop().toU32());
1020 continue;
1021 }
1022 const denom: u12 = if (parsed.size == 1) 8 else 4;
1023 const offset = math.divExact(u12, narrowed, denom) catch |_| {
1024 // If we are here, then this means we are not able to divide the offset
1025 // exactly by the required denominator. Therefore, we will use add instead of
1026 // ldr as we expect ldr to follow this instruction nonetheless.
1027 // TODO I believe ldr/str can only occur for GOT_LOAD_PAGEOFF12.
1028 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rn, parsed.rn, narrowed, parsed.size).toU32());
1029 continue;
1030 };
1031 parsed.offset = offset;
1001 }1032 }
1002 addend = null;1033 addend = null;
1003 },1034 },
...@@ -1008,7 +1039,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1008,7 +1039,7 @@ fn doRelocs(self: *Zld) !void {
1008 rn: u5,1039 rn: u5,
1009 size: u1,1040 size: u1,
1010 };1041 };
1011 const inst = code[off..][0..4];1042 const inst = code.items[off..][0..4];
1012 const parsed: RegInfo = blk: {1043 const parsed: RegInfo = blk: {
1013 if (Arm64.isArithmetic(inst)) {1044 if (Arm64.isArithmetic(inst)) {
1014 const curr = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);1045 const curr = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
...@@ -1020,7 +1051,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1020,7 +1051,7 @@ fn doRelocs(self: *Zld) !void {
1020 };1051 };
1021 const ta = if (addend) |a| target_addr + a else target_addr;1052 const ta = if (addend) |a| target_addr + a else target_addr;
1022 const narrowed = @truncate(u12, ta);1053 const narrowed = @truncate(u12, ta);
1023 log.debug(" | rewriting TLV access to ADD opcode", .{});1054 log.warn(" | rewriting TLV access to ADD opcode", .{});
1024 // For TLV, we always generate an add instruction.1055 // For TLV, we always generate an add instruction.
1025 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());1056 mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());
1026 },1057 },
...@@ -1030,9 +1061,9 @@ fn doRelocs(self: *Zld) !void {...@@ -1030,9 +1061,9 @@ fn doRelocs(self: *Zld) !void {
1030 .ARM64_RELOC_UNSIGNED => {1061 .ARM64_RELOC_UNSIGNED => {
1031 switch (rel.r_length) {1062 switch (rel.r_length) {
1032 3 => {1063 3 => {
1033 const inst = code[off..][0..8];1064 const inst = code.items[off..][0..8];
1034 const offset = mem.readIntLittle(i64, inst);1065 const offset = mem.readIntLittle(i64, inst);
1035 log.debug(" | calculated addend 0x{x}", .{offset});1066 log.warn(" | calculated addend 0x{x}", .{offset});
1036 const result = if (sub) |s|1067 const result = if (sub) |s|
1037 @intCast(i64, target_addr) - s + offset1068 @intCast(i64, target_addr) - s + offset
1038 else1069 else
...@@ -1054,9 +1085,9 @@ fn doRelocs(self: *Zld) !void {...@@ -1054,9 +1085,9 @@ fn doRelocs(self: *Zld) !void {
1054 }1085 }
1055 },1086 },
1056 2 => {1087 2 => {
1057 const inst = code[off..][0..4];1088 const inst = code.items[off..][0..4];
1058 const offset = mem.readIntLittle(i32, inst);1089 const offset = mem.readIntLittle(i32, inst);
1059 log.debug(" | calculated addend 0x{x}", .{offset});1090 log.warn(" | calculated addend 0x{x}", .{offset});
1060 const result = if (sub) |s|1091 const result = if (sub) |s|
1061 @intCast(i64, target_addr) - s + offset1092 @intCast(i64, target_addr) - s + offset
1062 else1093 else
...@@ -1078,7 +1109,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1078,7 +1109,7 @@ fn doRelocs(self: *Zld) !void {
1078 }1109 }
1079 }1110 }
10801111
1081 log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{1112 log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
1082 segname,1113 segname,
1083 sectname,1114 sectname,
1084 object.name,1115 object.name,
...@@ -1096,7 +1127,7 @@ fn doRelocs(self: *Zld) !void {...@@ -1096,7 +1127,7 @@ fn doRelocs(self: *Zld) !void {
1096 mem.set(u8, zeroes, 0);1127 mem.set(u8, zeroes, 0);
1097 try self.file.?.pwriteAll(zeroes, next.offset);1128 try self.file.?.pwriteAll(zeroes, next.offset);
1098 } else {1129 } else {
1099 try self.file.?.pwriteAll(code, next.offset);1130 try self.file.?.pwriteAll(code.items, next.offset);
1100 }1131 }
1101 }1132 }
1102 }1133 }
...@@ -1672,7 +1703,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -1672,7 +1703,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
1672 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));1703 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
1673 seg.inner.filesize += dyld_info.rebase_size;1704 seg.inner.filesize += dyld_info.rebase_size;
16741705
1675 log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });1706 log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
16761707
1677 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);1708 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
1678}1709}
...@@ -1725,7 +1756,7 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -1725,7 +1756,7 @@ fn writeBindInfoTable(self: *Zld) !void {
1725 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));1756 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
1726 seg.inner.filesize += dyld_info.bind_size;1757 seg.inner.filesize += dyld_info.bind_size;
17271758
1728 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });1759 log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
17291760
1730 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);1761 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
1731}1762}
...@@ -1764,7 +1795,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -1764,7 +1795,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
1764 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));1795 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
1765 seg.inner.filesize += dyld_info.lazy_bind_size;1796 seg.inner.filesize += dyld_info.lazy_bind_size;
17661797
1767 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });1798 log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
17681799
1769 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);1800 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
1770 try self.populateLazyBindOffsetsInStubHelper(buffer);1801 try self.populateLazyBindOffsetsInStubHelper(buffer);
...@@ -1866,7 +1897,7 @@ fn writeExportInfo(self: *Zld) !void {...@@ -1866,7 +1897,7 @@ fn writeExportInfo(self: *Zld) !void {
1866 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));1897 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
1867 seg.inner.filesize += dyld_info.export_size;1898 seg.inner.filesize += dyld_info.export_size;
18681899
1869 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });1900 log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
18701901
1871 try self.file.?.pwriteAll(buffer, dyld_info.export_off);1902 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
1872}1903}
...@@ -1995,7 +2026,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -1995,7 +2026,7 @@ fn writeDebugInfo(self: *Zld) !void {
19952026
1996 const stabs_off = symtab.symoff;2027 const stabs_off = symtab.symoff;
1997 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);2028 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);
1998 log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });2029 log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });
1999 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);2030 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
20002031
2001 linkedit.inner.filesize += stabs_size;2032 linkedit.inner.filesize += stabs_size;
...@@ -2044,17 +2075,17 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2044,17 +2075,17 @@ fn writeSymbolTable(self: *Zld) !void {
20442075
2045 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);2076 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
2046 const locals_size = nlocals * @sizeOf(macho.nlist_64);2077 const locals_size = nlocals * @sizeOf(macho.nlist_64);
2047 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });2078 log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
2048 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);2079 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
20492080
2050 const exports_off = locals_off + locals_size;2081 const exports_off = locals_off + locals_size;
2051 const exports_size = nexports * @sizeOf(macho.nlist_64);2082 const exports_size = nexports * @sizeOf(macho.nlist_64);
2052 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });2083 log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
2053 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);2084 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
20542085
2055 const undefs_off = exports_off + exports_size;2086 const undefs_off = exports_off + exports_size;
2056 const undefs_size = nundefs * @sizeOf(macho.nlist_64);2087 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
2057 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });2088 log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
2058 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);2089 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
20592090
2060 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);2091 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
...@@ -2085,7 +2116,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void {...@@ -2085,7 +2116,7 @@ fn writeDynamicSymbolTable(self: *Zld) !void {
2085 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);2116 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
2086 seg.inner.filesize += needed_size;2117 seg.inner.filesize += needed_size;
20872118
2088 log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{2119 log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{
2089 dysymtab.indirectsymoff,2120 dysymtab.indirectsymoff,
2090 dysymtab.indirectsymoff + needed_size,2121 dysymtab.indirectsymoff + needed_size,
2091 });2122 });
...@@ -2124,7 +2155,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2124,7 +2155,7 @@ fn writeStringTable(self: *Zld) !void {
2124 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));2155 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
2125 seg.inner.filesize += symtab.strsize;2156 seg.inner.filesize += symtab.strsize;
21262157
2127 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });2158 log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
21282159
2129 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);2160 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
21302161
...@@ -2150,7 +2181,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -2150,7 +2181,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
2150 seg.inner.filesize += needed_size;2181 seg.inner.filesize += needed_size;
2151 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2182 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
21522183
2153 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });2184 log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
21542185
2155 // Pad out the space. We need to do this to calculate valid hashes for everything in the file2186 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
2156 // except for code signature data.2187 // except for code signature data.
...@@ -2176,7 +2207,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -2176,7 +2207,7 @@ fn writeCodeSignature(self: *Zld) !void {
2176 var stream = std.io.fixedBufferStream(buffer);2207 var stream = std.io.fixedBufferStream(buffer);
2177 try code_sig.write(stream.writer());2208 try code_sig.write(stream.writer());
21782209
2179 log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });2210 log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });
21802211
2181 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);2212 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
2182}2213}
...@@ -2195,7 +2226,7 @@ fn writeLoadCommands(self: *Zld) !void {...@@ -2195,7 +2226,7 @@ fn writeLoadCommands(self: *Zld) !void {
2195 }2226 }
21962227
2197 const off = @sizeOf(macho.mach_header_64);2228 const off = @sizeOf(macho.mach_header_64);
2198 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });2229 log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
2199 try self.file.?.pwriteAll(buffer, off);2230 try self.file.?.pwriteAll(buffer, off);
2200}2231}
22012232
...@@ -2233,7 +2264,7 @@ fn writeHeader(self: *Zld) !void {...@@ -2233,7 +2264,7 @@ fn writeHeader(self: *Zld) !void {
2233 for (self.load_commands.items) |cmd| {2264 for (self.load_commands.items) |cmd| {
2234 header.sizeofcmds += cmd.cmdsize();2265 header.sizeofcmds += cmd.cmdsize();
2235 }2266 }
2236 log.debug("writing Mach-O header {}", .{header});2267 log.warn("writing Mach-O header {}", .{header});
2237 try self.file.?.pwriteAll(mem.asBytes(&header), 0);2268 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
2238}2269}
22392270
...@@ -2247,7 +2278,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -2247,7 +2278,7 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
2247fn makeString(self: *Zld, bytes: []const u8) !u32 {2278fn makeString(self: *Zld, bytes: []const u8) !u32 {
2248 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);2279 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
2249 const offset = @intCast(u32, self.strtab.items.len);2280 const offset = @intCast(u32, self.strtab.items.len);
2250 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });2281 log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
2251 self.strtab.appendSliceAssumeCapacity(bytes);2282 self.strtab.appendSliceAssumeCapacity(bytes);
2252 self.strtab.appendAssumeCapacity(0);2283 self.strtab.appendAssumeCapacity(0);
2253 return offset;2284 return offset;