authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-16 20:01:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-28 18:30:57-07:00
log6713745ec4f76d133eb0d5066c40bba666d0a194
treee8cb329a553013770558429031ba7b03d9c444f5
parentcc931660eb3e5b7251944c727808aa36e72c1e52

link.Elf: update to not use GenericWriter


9 files changed, 247 insertions(+), 294 deletions(-)

src/link/Elf.zig+34-38
...@@ -811,10 +811,6 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -811,10 +811,6 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
811811
812 if (self.base.gc_sections) {812 if (self.base.gc_sections) {
813 try gc.gcAtoms(self);813 try gc.gcAtoms(self);
814
815 if (self.base.print_gc_sections) {
816 try gc.dumpPrunedAtoms(self);
817 }
818 }814 }
819815
820 self.checkDuplicates() catch |err| switch (err) {816 self.checkDuplicates() catch |err| switch (err) {
...@@ -3005,7 +3001,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -3005,7 +3001,7 @@ fn writeAtoms(self: *Elf) !void {
3005 undefs.deinit();3001 undefs.deinit();
3006 }3002 }
30073003
3008 var buffer = std.array_list.Managed(u8).init(gpa);3004 var buffer: std.Io.Writer.Allocating = .init(gpa);
3009 defer buffer.deinit();3005 defer buffer.deinit();
30103006
3011 const slice = self.sections.slice();3007 const slice = self.sections.slice();
...@@ -3032,9 +3028,9 @@ fn writeAtoms(self: *Elf) !void {...@@ -3032,9 +3028,9 @@ fn writeAtoms(self: *Elf) !void {
3032 try buffer.ensureUnusedCapacity(thunk_size);3028 try buffer.ensureUnusedCapacity(thunk_size);
3033 const shdr = slice.items(.shdr)[th.output_section_index];3029 const shdr = slice.items(.shdr)[th.output_section_index];
3034 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;3030 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
3035 try th.write(self, buffer.writer());3031 try th.write(self, &buffer.writer);
3036 assert(buffer.items.len == thunk_size);3032 assert(buffer.written().len == thunk_size);
3037 try self.pwriteAll(buffer.items, offset);3033 try self.pwriteAll(buffer.written(), offset);
3038 buffer.clearRetainingCapacity();3034 buffer.clearRetainingCapacity();
3039 }3035 }
3040 }3036 }
...@@ -3166,26 +3162,26 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3166,26 +3162,26 @@ fn writeSyntheticSections(self: *Elf) !void {
31663162
3167 if (self.section_indexes.verneed) |shndx| {3163 if (self.section_indexes.verneed) |shndx| {
3168 const shdr = slice.items(.shdr)[shndx];3164 const shdr = slice.items(.shdr)[shndx];
3169 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.verneed.size());3165 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.verneed.size());
3170 defer buffer.deinit();3166 defer buffer.deinit();
3171 try self.verneed.write(buffer.writer());3167 try self.verneed.write(&buffer.writer);
3172 try self.pwriteAll(buffer.items, shdr.sh_offset);3168 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3173 }3169 }
31743170
3175 if (self.section_indexes.dynamic) |shndx| {3171 if (self.section_indexes.dynamic) |shndx| {
3176 const shdr = slice.items(.shdr)[shndx];3172 const shdr = slice.items(.shdr)[shndx];
3177 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynamic.size(self));3173 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynamic.size(self));
3178 defer buffer.deinit();3174 defer buffer.deinit();
3179 try self.dynamic.write(self, buffer.writer());3175 try self.dynamic.write(self, &buffer.writer);
3180 try self.pwriteAll(buffer.items, shdr.sh_offset);3176 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3181 }3177 }
31823178
3183 if (self.section_indexes.dynsymtab) |shndx| {3179 if (self.section_indexes.dynsymtab) |shndx| {
3184 const shdr = slice.items(.shdr)[shndx];3180 const shdr = slice.items(.shdr)[shndx];
3185 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynsym.size());3181 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynsym.size());
3186 defer buffer.deinit();3182 defer buffer.deinit();
3187 try self.dynsym.write(self, buffer.writer());3183 try self.dynsym.write(self, &buffer.writer);
3188 try self.pwriteAll(buffer.items, shdr.sh_offset);3184 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3189 }3185 }
31903186
3191 if (self.section_indexes.dynstrtab) |shndx| {3187 if (self.section_indexes.dynstrtab) |shndx| {
...@@ -3201,28 +3197,28 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3201,28 +3197,28 @@ fn writeSyntheticSections(self: *Elf) !void {
3201 };3197 };
3202 const shdr = slice.items(.shdr)[shndx];3198 const shdr = slice.items(.shdr)[shndx];
3203 const sh_size = try self.cast(usize, shdr.sh_size);3199 const sh_size = try self.cast(usize, shdr.sh_size);
3204 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size));3200 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, @intCast(sh_size - existing_size));
3205 defer buffer.deinit();3201 defer buffer.deinit();
3206 try eh_frame.writeEhFrame(self, buffer.writer());3202 try eh_frame.writeEhFrame(self, &buffer.writer);
3207 assert(buffer.items.len == sh_size - existing_size);3203 assert(buffer.written().len == sh_size - existing_size);
3208 try self.pwriteAll(buffer.items, shdr.sh_offset + existing_size);3204 try self.pwriteAll(buffer.written(), shdr.sh_offset + existing_size);
3209 }3205 }
32103206
3211 if (self.section_indexes.eh_frame_hdr) |shndx| {3207 if (self.section_indexes.eh_frame_hdr) |shndx| {
3212 const shdr = slice.items(.shdr)[shndx];3208 const shdr = slice.items(.shdr)[shndx];
3213 const sh_size = try self.cast(usize, shdr.sh_size);3209 const sh_size = try self.cast(usize, shdr.sh_size);
3214 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size);3210 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, sh_size);
3215 defer buffer.deinit();3211 defer buffer.deinit();
3216 try eh_frame.writeEhFrameHdr(self, buffer.writer());3212 try eh_frame.writeEhFrameHdr(self, &buffer.writer);
3217 try self.pwriteAll(buffer.items, shdr.sh_offset);3213 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3218 }3214 }
32193215
3220 if (self.section_indexes.got) |index| {3216 if (self.section_indexes.got) |index| {
3221 const shdr = slice.items(.shdr)[index];3217 const shdr = slice.items(.shdr)[index];
3222 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got.size(self));3218 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got.size(self));
3223 defer buffer.deinit();3219 defer buffer.deinit();
3224 try self.got.write(self, buffer.writer());3220 try self.got.write(self, &buffer.writer);
3225 try self.pwriteAll(buffer.items, shdr.sh_offset);3221 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3226 }3222 }
32273223
3228 if (self.section_indexes.rela_dyn) |shndx| {3224 if (self.section_indexes.rela_dyn) |shndx| {
...@@ -3235,26 +3231,26 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3235,26 +3231,26 @@ fn writeSyntheticSections(self: *Elf) !void {
32353231
3236 if (self.section_indexes.plt) |shndx| {3232 if (self.section_indexes.plt) |shndx| {
3237 const shdr = slice.items(.shdr)[shndx];3233 const shdr = slice.items(.shdr)[shndx];
3238 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt.size(self));3234 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt.size(self));
3239 defer buffer.deinit();3235 defer buffer.deinit();
3240 try self.plt.write(self, buffer.writer());3236 try self.plt.write(self, &buffer.writer);
3241 try self.pwriteAll(buffer.items, shdr.sh_offset);3237 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3242 }3238 }
32433239
3244 if (self.section_indexes.got_plt) |shndx| {3240 if (self.section_indexes.got_plt) |shndx| {
3245 const shdr = slice.items(.shdr)[shndx];3241 const shdr = slice.items(.shdr)[shndx];
3246 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got_plt.size(self));3242 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got_plt.size(self));
3247 defer buffer.deinit();3243 defer buffer.deinit();
3248 try self.got_plt.write(self, buffer.writer());3244 try self.got_plt.write(self, &buffer.writer);
3249 try self.pwriteAll(buffer.items, shdr.sh_offset);3245 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3250 }3246 }
32513247
3252 if (self.section_indexes.plt_got) |shndx| {3248 if (self.section_indexes.plt_got) |shndx| {
3253 const shdr = slice.items(.shdr)[shndx];3249 const shdr = slice.items(.shdr)[shndx];
3254 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt_got.size(self));3250 var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt_got.size(self));
3255 defer buffer.deinit();3251 defer buffer.deinit();
3256 try self.plt_got.write(self, buffer.writer());3252 try self.plt_got.write(self, &buffer.writer);
3257 try self.pwriteAll(buffer.items, shdr.sh_offset);3253 try self.pwriteAll(buffer.written(), shdr.sh_offset);
3258 }3254 }
32593255
3260 if (self.section_indexes.rela_plt) |shndx| {3256 if (self.section_indexes.rela_plt) |shndx| {
...@@ -3757,7 +3753,7 @@ pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {...@@ -3757,7 +3753,7 @@ pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
3757 const gpa = self.base.comp.gpa;3753 const gpa = self.base.comp.gpa;
3758 const off = @as(u32, @intCast(self.shstrtab.items.len));3754 const off = @as(u32, @intCast(self.shstrtab.items.len));
3759 try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1);3755 try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1);
3760 self.shstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable;3756 self.shstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable;
3761 return off;3757 return off;
3762}3758}
37633759
...@@ -3770,7 +3766,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {...@@ -3770,7 +3766,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
3770 const gpa = self.base.comp.gpa;3766 const gpa = self.base.comp.gpa;
3771 const off = @as(u32, @intCast(self.dynstrtab.items.len));3767 const off = @as(u32, @intCast(self.dynstrtab.items.len));
3772 try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1);3768 try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1);
3773 self.dynstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable;3769 self.dynstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable;
3774 return off;3770 return off;
3775}3771}
37763772
src/link/Elf/Archive.zig+4-5
...@@ -123,8 +123,7 @@ pub fn setArHdr(opts: struct {...@@ -123,8 +123,7 @@ pub fn setArHdr(opts: struct {
123 @memcpy(&hdr.ar_fmag, elf.ARFMAG);123 @memcpy(&hdr.ar_fmag, elf.ARFMAG);
124124
125 {125 {
126 var stream = std.io.fixedBufferStream(&hdr.ar_name);126 var writer: std.Io.Writer = .fixed(&hdr.ar_name);
127 const writer = stream.writer();
128 switch (opts.name) {127 switch (opts.name) {
129 .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable,128 .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable,
130 .strtab => writer.print("//", .{}) catch unreachable,129 .strtab => writer.print("//", .{}) catch unreachable,
...@@ -133,8 +132,8 @@ pub fn setArHdr(opts: struct {...@@ -133,8 +132,8 @@ pub fn setArHdr(opts: struct {
133 }132 }
134 }133 }
135 {134 {
136 var stream = std.io.fixedBufferStream(&hdr.ar_size);135 var writer: std.Io.Writer = .fixed(&hdr.ar_size);
137 stream.writer().print("{d}", .{opts.size}) catch unreachable;136 writer.print("{d}", .{opts.size}) catch unreachable;
138 }137 }
139138
140 return hdr;139 return hdr;
...@@ -246,7 +245,7 @@ pub const ArStrtab = struct {...@@ -246,7 +245,7 @@ pub const ArStrtab = struct {
246245
247 pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 {246 pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 {
248 const off = @as(u32, @intCast(ar.buffer.items.len));247 const off = @as(u32, @intCast(ar.buffer.items.len));
249 try ar.buffer.writer(allocator).print("{s}/{c}", .{ name, strtab_delimiter });248 try ar.buffer.print(allocator, "{s}/{c}", .{ name, strtab_delimiter });
250 return off;249 return off;
251 }250 }
252251
src/link/Elf/Atom.zig+113-142
...@@ -621,7 +621,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -621,7 +621,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
621621
622 const cpu_arch = elf_file.getTarget().cpu.arch;622 const cpu_arch = elf_file.getTarget().cpu.arch;
623 const file_ptr = self.file(elf_file).?;623 const file_ptr = self.file(elf_file).?;
624 var stream = std.io.fixedBufferStream(code);
625624
626 const rels = self.relocs(elf_file);625 const rels = self.relocs(elf_file);
627 var it = RelocsIterator{ .relocs = rels };626 var it = RelocsIterator{ .relocs = rels };
...@@ -661,20 +660,16 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -661,20 +660,16 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
661 target.name(elf_file),660 target.name(elf_file),
662 });661 });
663662
664 try stream.seekTo(r_offset);
665
666 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };663 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };
667664
668 switch (cpu_arch) {665 switch (cpu_arch) {
669 .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {666 .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) {
670 error.RelocFailure,667 error.RelocFailure,
671 error.RelaxFailure,668 error.RelaxFailure,
672 error.InvalidInstruction,
673 error.CannotEncode,
674 => has_reloc_errors = true,669 => has_reloc_errors = true,
675 else => |e| return e,670 else => |e| return e,
676 },671 },
677 .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {672 .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) {
678 error.RelocFailure,673 error.RelocFailure,
679 error.RelaxFailure,674 error.RelaxFailure,
680 error.UnexpectedRemainder,675 error.UnexpectedRemainder,
...@@ -682,7 +677,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi...@@ -682,7 +677,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
682 => has_reloc_errors = true,677 => has_reloc_errors = true,
683 else => |e| return e,678 else => |e| return e,
684 },679 },
685 .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {680 .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) {
686 error.RelocFailure,681 error.RelocFailure,
687 error.RelaxFailure,682 error.RelaxFailure,
688 => has_reloc_errors = true,683 => has_reloc_errors = true,
...@@ -701,7 +696,8 @@ fn resolveDynAbsReloc(...@@ -701,7 +696,8 @@ fn resolveDynAbsReloc(
701 rel: elf.Elf64_Rela,696 rel: elf.Elf64_Rela,
702 action: RelocAction,697 action: RelocAction,
703 elf_file: *Elf,698 elf_file: *Elf,
704 writer: anytype,699 code: []u8,
700 r_offset: usize,
705) !void {701) !void {
706 const comp = elf_file.base.comp;702 const comp = elf_file.base.comp;
707 const gpa = comp.gpa;703 const gpa = comp.gpa;
...@@ -726,7 +722,7 @@ fn resolveDynAbsReloc(...@@ -726,7 +722,7 @@ fn resolveDynAbsReloc(
726 .copyrel,722 .copyrel,
727 .cplt,723 .cplt,
728 .none,724 .none,
729 => try writer.writeInt(i64, S + A, .little),725 => mem.writeInt(i64, code[r_offset..][0..8], S + A, .little),
730726
731 .dyn_copyrel => {727 .dyn_copyrel => {
732 if (is_writeable or elf_file.z_nocopyreloc) {728 if (is_writeable or elf_file.z_nocopyreloc) {
...@@ -737,9 +733,9 @@ fn resolveDynAbsReloc(...@@ -737,9 +733,9 @@ fn resolveDynAbsReloc(
737 .addend = A,733 .addend = A,
738 .target = target,734 .target = target,
739 });735 });
740 try applyDynamicReloc(A, elf_file, writer);736 applyDynamicReloc(A, code, r_offset);
741 } else {737 } else {
742 try writer.writeInt(i64, S + A, .little);738 mem.writeInt(i64, code[r_offset..][0..8], S + A, .little);
743 }739 }
744 },740 },
745741
...@@ -752,9 +748,9 @@ fn resolveDynAbsReloc(...@@ -752,9 +748,9 @@ fn resolveDynAbsReloc(
752 .addend = A,748 .addend = A,
753 .target = target,749 .target = target,
754 });750 });
755 try applyDynamicReloc(A, elf_file, writer);751 applyDynamicReloc(A, code, r_offset);
756 } else {752 } else {
757 try writer.writeInt(i64, S + A, .little);753 mem.writeInt(i64, code[r_offset..][0..8], S + A, .little);
758 }754 }
759 },755 },
760756
...@@ -766,7 +762,7 @@ fn resolveDynAbsReloc(...@@ -766,7 +762,7 @@ fn resolveDynAbsReloc(
766 .addend = A,762 .addend = A,
767 .target = target,763 .target = target,
768 });764 });
769 try applyDynamicReloc(A, elf_file, writer);765 applyDynamicReloc(A, code, r_offset);
770 },766 },
771767
772 .baserel => {768 .baserel => {
...@@ -776,7 +772,7 @@ fn resolveDynAbsReloc(...@@ -776,7 +772,7 @@ fn resolveDynAbsReloc(
776 .addend = S + A,772 .addend = S + A,
777 .target = target,773 .target = target,
778 });774 });
779 try applyDynamicReloc(S + A, elf_file, writer);775 applyDynamicReloc(S + A, code, r_offset);
780 },776 },
781777
782 .ifunc => {778 .ifunc => {
...@@ -787,16 +783,13 @@ fn resolveDynAbsReloc(...@@ -787,16 +783,13 @@ fn resolveDynAbsReloc(
787 .addend = S_ + A,783 .addend = S_ + A,
788 .target = target,784 .target = target,
789 });785 });
790 try applyDynamicReloc(S_ + A, elf_file, writer);786 applyDynamicReloc(S_ + A, code, r_offset);
791 },787 },
792 }788 }
793}789}
794790
795fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void {791fn applyDynamicReloc(value: i64, code: []u8, r_offset: usize) void {
796 _ = elf_file;792 mem.writeInt(i64, code[r_offset..][0..8], value, .little);
797 // if (elf_file.options.apply_dynamic_relocs) {
798 try writer.writeInt(i64, value, .little);
799 // }
800}793}
801794
802pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void {795pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: anytype) !void {
...@@ -804,7 +797,6 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -804,7 +797,6 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
804797
805 const cpu_arch = elf_file.getTarget().cpu.arch;798 const cpu_arch = elf_file.getTarget().cpu.arch;
806 const file_ptr = self.file(elf_file).?;799 const file_ptr = self.file(elf_file).?;
807 var stream = std.io.fixedBufferStream(code);
808800
809 const rels = self.relocs(elf_file);801 const rels = self.relocs(elf_file);
810 var has_reloc_errors = false;802 var has_reloc_errors = false;
...@@ -863,18 +855,16 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any...@@ -863,18 +855,16 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
863 target.name(elf_file),855 target.name(elf_file),
864 });856 });
865857
866 try stream.seekTo(r_offset);
867
868 switch (cpu_arch) {858 switch (cpu_arch) {
869 .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {859 .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) {
870 error.RelocFailure => has_reloc_errors = true,860 error.RelocFailure => has_reloc_errors = true,
871 else => |e| return e,861 else => |e| return e,
872 },862 },
873 .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {863 .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) {
874 error.RelocFailure => has_reloc_errors = true,864 error.RelocFailure => has_reloc_errors = true,
875 else => |e| return e,865 else => |e| return e,
876 },866 },
877 .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) {867 .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) {
878 error.RelocFailure => has_reloc_errors = true,868 error.RelocFailure => has_reloc_errors = true,
879 else => |e| return e,869 else => |e| return e,
880 },870 },
...@@ -915,7 +905,7 @@ const Format = struct {...@@ -915,7 +905,7 @@ const Format = struct {
915 atom: Atom,905 atom: Atom,
916 elf_file: *Elf,906 elf_file: *Elf,
917907
918 fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void {908 fn default(f: Format, w: *Writer) Writer.Error!void {
919 const atom = f.atom;909 const atom = f.atom;
920 const elf_file = f.elf_file;910 const elf_file = f.elf_file;
921 try w.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{911 try w.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({f}) : next({f})", .{
...@@ -1068,16 +1058,13 @@ const x86_64 = struct {...@@ -1068,16 +1058,13 @@ const x86_64 = struct {
1068 args: ResolveArgs,1058 args: ResolveArgs,
1069 it: *RelocsIterator,1059 it: *RelocsIterator,
1070 code: []u8,1060 code: []u8,
1071 stream: anytype,1061 ) !void {
1072 ) (error{ InvalidInstruction, CannotEncode } || RelocError)!void {
1073 dev.check(.x86_64_backend);1062 dev.check(.x86_64_backend);
1074 const t = &elf_file.base.comp.root_mod.resolved_target.result;1063 const t = &elf_file.base.comp.root_mod.resolved_target.result;
1075 const diags = &elf_file.base.comp.link_diags;1064 const diags = &elf_file.base.comp.link_diags;
1076 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());1065 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1077 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1066 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
10781067
1079 const cwriter = stream.writer();
1080
1081 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1068 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
10821069
1083 switch (r_type) {1070 switch (r_type) {
...@@ -1089,58 +1076,60 @@ const x86_64 = struct {...@@ -1089,58 +1076,60 @@ const x86_64 = struct {
1089 rel,1076 rel,
1090 dynAbsRelocAction(target, elf_file),1077 dynAbsRelocAction(target, elf_file),
1091 elf_file,1078 elf_file,
1092 cwriter,1079 code,
1080 r_offset,
1093 );1081 );
1094 },1082 },
10951083
1096 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),1084 .PLT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little),
1097 .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),1085 .PC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little),
10981086
1099 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),1087 .GOTPCREL => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little),
1100 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),1088 .GOTPC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(GOT + A - P)), .little),
1101 .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little),1089 .GOTPC64 => mem.writeInt(i64, code[r_offset..][0..8], GOT + A - P, .little),
11021090
1103 .GOTPCRELX => {1091 .GOTPCRELX => {
1104 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1092 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1105 x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk;1093 x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk;
1106 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1094 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little);
1107 return;1095 return;
1108 }1096 }
1109 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);1097 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little);
1110 },1098 },
11111099
1112 .REX_GOTPCRELX => {1100 .REX_GOTPCRELX => {
1113 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {1101 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
1114 x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk;1102 x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk;
1115 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);1103 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little);
1116 return;1104 return;
1117 }1105 }
1118 try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little);1106 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little);
1119 },1107 },
11201108
1121 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),1109 .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
1122 .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),1110 .@"32S" => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little),
11231111
1124 .TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little),1112 .TPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - TP)), .little),
1125 .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little),1113 .TPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - TP, .little),
11261114
1127 .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little),1115 .DTPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - DTP)), .little),
1128 .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),1116 .DTPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - DTP, .little),
11291117
1130 .TLSGD => {1118 .TLSGD => {
1131 if (target.flags.has_tlsgd) {1119 if (target.flags.has_tlsgd) {
1132 const S_ = target.tlsGdAddress(elf_file);1120 const S_ = target.tlsGdAddress(elf_file);
1133 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1121 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little);
1134 } else if (target.flags.has_gottp) {1122 } else if (target.flags.has_gottp) {
1135 const S_ = target.gotTpAddress(elf_file);1123 const S_ = target.gotTpAddress(elf_file);
1136 try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream);1124 try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, code, r_offset);
1137 } else {1125 } else {
1138 try x86_64.relaxTlsGdToLe(1126 try x86_64.relaxTlsGdToLe(
1139 atom,1127 atom,
1140 &.{ rel, it.next().? },1128 &.{ rel, it.next().? },
1141 @as(i32, @intCast(S - TP)),1129 @as(i32, @intCast(S - TP)),
1142 elf_file,1130 elf_file,
1143 stream,1131 code,
1132 r_offset,
1144 );1133 );
1145 }1134 }
1146 },1135 },
...@@ -1149,14 +1138,15 @@ const x86_64 = struct {...@@ -1149,14 +1138,15 @@ const x86_64 = struct {
1149 if (elf_file.got.tlsld_index) |entry_index| {1138 if (elf_file.got.tlsld_index) |entry_index| {
1150 const tlsld_entry = elf_file.got.entries.items[entry_index];1139 const tlsld_entry = elf_file.got.entries.items[entry_index];
1151 const S_ = tlsld_entry.address(elf_file);1140 const S_ = tlsld_entry.address(elf_file);
1152 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1141 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little);
1153 } else {1142 } else {
1154 try x86_64.relaxTlsLdToLe(1143 try x86_64.relaxTlsLdToLe(
1155 atom,1144 atom,
1156 &.{ rel, it.next().? },1145 &.{ rel, it.next().? },
1157 @as(i32, @intCast(TP - elf_file.tlsAddress())),1146 @as(i32, @intCast(TP - elf_file.tlsAddress())),
1158 elf_file,1147 elf_file,
1159 stream,1148 code,
1149 r_offset,
1160 );1150 );
1161 }1151 }
1162 },1152 },
...@@ -1164,7 +1154,7 @@ const x86_64 = struct {...@@ -1164,7 +1154,7 @@ const x86_64 = struct {
1164 .GOTPC32_TLSDESC => {1154 .GOTPC32_TLSDESC => {
1165 if (target.flags.has_tlsdesc) {1155 if (target.flags.has_tlsdesc) {
1166 const S_ = target.tlsDescAddress(elf_file);1156 const S_ = target.tlsDescAddress(elf_file);
1167 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1157 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little);
1168 } else {1158 } else {
1169 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {1159 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {
1170 var err = try diags.addErrorWithNotes(1);1160 var err = try diags.addErrorWithNotes(1);
...@@ -1176,26 +1166,26 @@ const x86_64 = struct {...@@ -1176,26 +1166,26 @@ const x86_64 = struct {
1176 });1166 });
1177 return error.RelaxFailure;1167 return error.RelaxFailure;
1178 };1168 };
1179 try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little);1169 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little);
1180 }1170 }
1181 },1171 },
11821172
1183 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {1173 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1184 // call -> nop1174 // call -> nop
1185 try cwriter.writeAll(&.{ 0x66, 0x90 });1175 code[r_offset..][0..2].* = .{ 0x66, 0x90 };
1186 },1176 },
11871177
1188 .GOTTPOFF => {1178 .GOTTPOFF => {
1189 if (target.flags.has_gottp) {1179 if (target.flags.has_gottp) {
1190 const S_ = target.gotTpAddress(elf_file);1180 const S_ = target.gotTpAddress(elf_file);
1191 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);1181 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little);
1192 } else {1182 } else {
1193 x86_64.relaxGotTpOff(code[r_offset - 3 ..], t);1183 x86_64.relaxGotTpOff(code[r_offset - 3 ..], t);
1194 try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little);1184 mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little);
1195 }1185 }
1196 },1186 },
11971187
1198 .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + A)), .little),1188 .GOT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + A)), .little),
11991189
1200 else => try atom.reportUnhandledRelocError(rel, elf_file),1190 else => try atom.reportUnhandledRelocError(rel, elf_file),
1201 }1191 }
...@@ -1207,45 +1197,42 @@ const x86_64 = struct {...@@ -1207,45 +1197,42 @@ const x86_64 = struct {
1207 rel: elf.Elf64_Rela,1197 rel: elf.Elf64_Rela,
1208 target: *const Symbol,1198 target: *const Symbol,
1209 args: ResolveArgs,1199 args: ResolveArgs,
1210 it: *RelocsIterator,
1211 code: []u8,1200 code: []u8,
1212 stream: anytype,
1213 ) !void {1201 ) !void {
1214 dev.check(.x86_64_backend);1202 dev.check(.x86_64_backend);
1215 _ = code;
1216 _ = it;
1217 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());1203 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1218 const cwriter = stream.writer();
12191204
1220 _, const A, const S, const GOT, _, _, const DTP = args;1205 _, const A, const S, const GOT, _, _, const DTP = args;
12211206
1207 var writer: Writer = .fixed(code);
1208
1222 switch (r_type) {1209 switch (r_type) {
1223 .NONE => unreachable,1210 .NONE => unreachable,
1224 .@"8" => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),1211 .@"8" => try writer.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),
1225 .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),1212 .@"16" => try writer.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),
1226 .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),1213 .@"32" => try writer.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),
1227 .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1214 .@"32S" => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1228 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1215 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1229 try cwriter.writeInt(u64, value, .little)1216 try writer.writeInt(u64, value, .little)
1230 else1217 else
1231 try cwriter.writeInt(i64, S + A, .little),1218 try writer.writeInt(i64, S + A, .little),
1232 .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1219 .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1233 try cwriter.writeInt(u64, value, .little)1220 try writer.writeInt(u64, value, .little)
1234 else1221 else
1235 try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),1222 try writer.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little),
1236 .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1223 .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1237 try cwriter.writeInt(u64, value, .little)1224 try writer.writeInt(u64, value, .little)
1238 else1225 else
1239 try cwriter.writeInt(i64, S + A - DTP, .little),1226 try writer.writeInt(i64, S + A - DTP, .little),
1240 .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little),1227 .GOTOFF64 => try writer.writeInt(i64, S + A - GOT, .little),
1241 .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),1228 .GOTPC64 => try writer.writeInt(i64, GOT + A, .little),
1242 .SIZE32 => {1229 .SIZE32 => {
1243 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1230 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1244 try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little);1231 try writer.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little);
1245 },1232 },
1246 .SIZE64 => {1233 .SIZE64 => {
1247 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));1234 const size = @as(i64, @intCast(target.elfSym(elf_file).st_size));
1248 try cwriter.writeInt(i64, @intCast(size + A), .little);1235 try writer.writeInt(i64, @intCast(size + A), .little);
1249 },1236 },
1250 else => try atom.reportUnhandledRelocError(rel, elf_file),1237 else => try atom.reportUnhandledRelocError(rel, elf_file),
1251 }1238 }
...@@ -1288,12 +1275,12 @@ const x86_64 = struct {...@@ -1288,12 +1275,12 @@ const x86_64 = struct {
1288 rels: []const elf.Elf64_Rela,1275 rels: []const elf.Elf64_Rela,
1289 value: i32,1276 value: i32,
1290 elf_file: *Elf,1277 elf_file: *Elf,
1291 stream: anytype,1278 code: []u8,
1279 r_offset: usize,
1292 ) !void {1280 ) !void {
1293 dev.check(.x86_64_backend);1281 dev.check(.x86_64_backend);
1294 assert(rels.len == 2);1282 assert(rels.len == 2);
1295 const diags = &elf_file.base.comp.link_diags;1283 const diags = &elf_file.base.comp.link_diags;
1296 const writer = stream.writer();
1297 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1284 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1298 switch (rel) {1285 switch (rel) {
1299 .PC32,1286 .PC32,
...@@ -1304,8 +1291,7 @@ const x86_64 = struct {...@@ -1304,8 +1291,7 @@ const x86_64 = struct {
1304 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax1291 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax
1305 };1292 };
1306 std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little);1293 std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little);
1307 try stream.seekBy(-4);1294 @memcpy(code[r_offset - 4 ..][0..insts.len], &insts);
1308 try writer.writeAll(&insts);
1309 },1295 },
13101296
1311 else => {1297 else => {
...@@ -1329,12 +1315,12 @@ const x86_64 = struct {...@@ -1329,12 +1315,12 @@ const x86_64 = struct {
1329 rels: []const elf.Elf64_Rela,1315 rels: []const elf.Elf64_Rela,
1330 value: i32,1316 value: i32,
1331 elf_file: *Elf,1317 elf_file: *Elf,
1332 stream: anytype,1318 code: []u8,
1319 r_offset: usize,
1333 ) !void {1320 ) !void {
1334 dev.check(.x86_64_backend);1321 dev.check(.x86_64_backend);
1335 assert(rels.len == 2);1322 assert(rels.len == 2);
1336 const diags = &elf_file.base.comp.link_diags;1323 const diags = &elf_file.base.comp.link_diags;
1337 const writer = stream.writer();
1338 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1324 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1339 switch (rel) {1325 switch (rel) {
1340 .PC32,1326 .PC32,
...@@ -1346,8 +1332,7 @@ const x86_64 = struct {...@@ -1346,8 +1332,7 @@ const x86_64 = struct {
1346 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax1332 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax
1347 };1333 };
1348 std.mem.writeInt(i32, insts[8..][0..4], value, .little);1334 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1349 try stream.seekBy(-3);1335 @memcpy(code[r_offset - 3 ..][0..insts.len], &insts);
1350 try writer.writeAll(&insts);
1351 },1336 },
13521337
1353 .GOTPCREL,1338 .GOTPCREL,
...@@ -1360,8 +1345,7 @@ const x86_64 = struct {...@@ -1360,8 +1345,7 @@ const x86_64 = struct {
1360 0x90, // nop1345 0x90, // nop
1361 };1346 };
1362 std.mem.writeInt(i32, insts[8..][0..4], value, .little);1347 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1363 try stream.seekBy(-3);1348 @memcpy(code[r_offset - 3 ..][0..insts.len], &insts);
1364 try writer.writeAll(&insts);
1365 },1349 },
13661350
1367 else => {1351 else => {
...@@ -1390,7 +1374,7 @@ const x86_64 = struct {...@@ -1390,7 +1374,7 @@ const x86_64 = struct {
1390 // TODO: hack to force imm32s in the assembler1374 // TODO: hack to force imm32s in the assembler
1391 .{ .imm = .s(-129) },1375 .{ .imm = .s(-129) },
1392 }, t) catch return false;1376 }, t) catch return false;
1393 var trash: std.io.Writer.Discarding = .init(&.{});1377 var trash: Writer.Discarding = .init(&.{});
1394 inst.encode(&trash.writer, .{}) catch return false;1378 inst.encode(&trash.writer, .{}) catch return false;
1395 return true;1379 return true;
1396 },1380 },
...@@ -1437,12 +1421,12 @@ const x86_64 = struct {...@@ -1437,12 +1421,12 @@ const x86_64 = struct {
1437 rels: []const elf.Elf64_Rela,1421 rels: []const elf.Elf64_Rela,
1438 value: i32,1422 value: i32,
1439 elf_file: *Elf,1423 elf_file: *Elf,
1440 stream: anytype,1424 code: []u8,
1425 r_offset: usize,
1441 ) !void {1426 ) !void {
1442 dev.check(.x86_64_backend);1427 dev.check(.x86_64_backend);
1443 assert(rels.len == 2);1428 assert(rels.len == 2);
1444 const diags = &elf_file.base.comp.link_diags;1429 const diags = &elf_file.base.comp.link_diags;
1445 const writer = stream.writer();
1446 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());1430 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
1447 switch (rel) {1431 switch (rel) {
1448 .PC32,1432 .PC32,
...@@ -1455,8 +1439,7 @@ const x86_64 = struct {...@@ -1455,8 +1439,7 @@ const x86_64 = struct {
1455 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax1439 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax
1456 };1440 };
1457 std.mem.writeInt(i32, insts[12..][0..4], value, .little);1441 std.mem.writeInt(i32, insts[12..][0..4], value, .little);
1458 try stream.seekBy(-4);1442 @memcpy(code[r_offset - 4 ..][0..insts.len], &insts);
1459 try writer.writeAll(&insts);
1460 relocs_log.debug(" relaxing {f} and {f}", .{1443 relocs_log.debug(" relaxing {f} and {f}", .{
1461 relocation.fmtRelocType(rels[0].r_type(), .x86_64),1444 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
1462 relocation.fmtRelocType(rels[1].r_type(), .x86_64),1445 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
...@@ -1486,8 +1469,8 @@ const x86_64 = struct {...@@ -1486,8 +1469,8 @@ const x86_64 = struct {
1486 }1469 }
14871470
1488 fn encode(insts: []const Instruction, code: []u8) !void {1471 fn encode(insts: []const Instruction, code: []u8) !void {
1489 var stream: std.io.Writer = .fixed(code);1472 var writer: Writer = .fixed(code);
1490 for (insts) |inst| try inst.encode(&stream, .{});1473 for (insts) |inst| try inst.encode(&writer, .{});
1491 }1474 }
14921475
1493 const bits = @import("../../arch/x86_64/bits.zig");1476 const bits = @import("../../arch/x86_64/bits.zig");
...@@ -1592,14 +1575,12 @@ const aarch64 = struct {...@@ -1592,14 +1575,12 @@ const aarch64 = struct {
1592 args: ResolveArgs,1575 args: ResolveArgs,
1593 it: *RelocsIterator,1576 it: *RelocsIterator,
1594 code_buffer: []u8,1577 code_buffer: []u8,
1595 stream: anytype,
1596 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {1578 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
1597 _ = it;1579 _ = it;
15981580
1599 const diags = &elf_file.base.comp.link_diags;1581 const diags = &elf_file.base.comp.link_diags;
1600 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1582 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1601 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1583 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1602 const cwriter = stream.writer();
1603 const code = code_buffer[r_offset..][0..4];1584 const code = code_buffer[r_offset..][0..4];
1604 const file_ptr = atom.file(elf_file).?;1585 const file_ptr = atom.file(elf_file).?;
16051586
...@@ -1614,7 +1595,8 @@ const aarch64 = struct {...@@ -1614,7 +1595,8 @@ const aarch64 = struct {
1614 rel,1595 rel,
1615 dynAbsRelocAction(target, elf_file),1596 dynAbsRelocAction(target, elf_file),
1616 elf_file,1597 elf_file,
1617 cwriter,1598 code_buffer,
1599 r_offset,
1618 );1600 );
1619 },1601 },
16201602
...@@ -1782,25 +1764,20 @@ const aarch64 = struct {...@@ -1782,25 +1764,20 @@ const aarch64 = struct {
1782 rel: elf.Elf64_Rela,1764 rel: elf.Elf64_Rela,
1783 target: *const Symbol,1765 target: *const Symbol,
1784 args: ResolveArgs,1766 args: ResolveArgs,
1785 it: *RelocsIterator,
1786 code: []u8,1767 code: []u8,
1787 stream: anytype,
1788 ) !void {1768 ) !void {
1789 _ = it;
1790 _ = code;
1791
1792 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1769 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1793 const cwriter = stream.writer();
17941770
1795 _, const A, const S, _, _, _, _ = args;1771 _, const A, const S, _, _, _, _ = args;
17961772
1773 var writer: Writer = .fixed(code);
1797 switch (r_type) {1774 switch (r_type) {
1798 .NONE => unreachable,1775 .NONE => unreachable,
1799 .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1776 .ABS32 => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1800 .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1777 .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1801 try cwriter.writeInt(u64, value, .little)1778 try writer.writeInt(u64, value, .little)
1802 else1779 else
1803 try cwriter.writeInt(i64, S + A, .little),1780 try writer.writeInt(i64, S + A, .little),
1804 else => try atom.reportUnhandledRelocError(rel, elf_file),1781 else => try atom.reportUnhandledRelocError(rel, elf_file),
1805 }1782 }
1806 }1783 }
...@@ -1861,12 +1838,10 @@ const riscv = struct {...@@ -1861,12 +1838,10 @@ const riscv = struct {
1861 args: ResolveArgs,1838 args: ResolveArgs,
1862 it: *RelocsIterator,1839 it: *RelocsIterator,
1863 code: []u8,1840 code: []u8,
1864 stream: anytype,
1865 ) !void {1841 ) !void {
1866 const diags = &elf_file.base.comp.link_diags;1842 const diags = &elf_file.base.comp.link_diags;
1867 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());1843 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
1868 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1844 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1869 const cwriter = stream.writer();
18701845
1871 const P, const A, const S, const GOT, const G, const TP, const DTP = args;1846 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
1872 _ = TP;1847 _ = TP;
...@@ -1875,7 +1850,7 @@ const riscv = struct {...@@ -1875,7 +1850,7 @@ const riscv = struct {
1875 switch (r_type) {1850 switch (r_type) {
1876 .NONE => unreachable,1851 .NONE => unreachable,
18771852
1878 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),1853 .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
18791854
1880 .@"64" => {1855 .@"64" => {
1881 try atom.resolveDynAbsReloc(1856 try atom.resolveDynAbsReloc(
...@@ -1883,7 +1858,8 @@ const riscv = struct {...@@ -1883,7 +1858,8 @@ const riscv = struct {
1883 rel,1858 rel,
1884 dynAbsRelocAction(target, elf_file),1859 dynAbsRelocAction(target, elf_file),
1885 elf_file,1860 elf_file,
1886 cwriter,1861 code,
1862 r_offset,
1887 );1863 );
1888 },1864 },
18891865
...@@ -1997,15 +1973,9 @@ const riscv = struct {...@@ -1997,15 +1973,9 @@ const riscv = struct {
1997 rel: elf.Elf64_Rela,1973 rel: elf.Elf64_Rela,
1998 target: *const Symbol,1974 target: *const Symbol,
1999 args: ResolveArgs,1975 args: ResolveArgs,
2000 it: *RelocsIterator,
2001 code: []u8,1976 code: []u8,
2002 stream: anytype,
2003 ) !void {1977 ) !void {
2004 _ = it;
2005
2006 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());1978 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
2007 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
2008 const cwriter = stream.writer();
20091979
2010 _, const A, const S, const GOT, _, _, const DTP = args;1980 _, const A, const S, const GOT, _, _, const DTP = args;
2011 _ = GOT;1981 _ = GOT;
...@@ -2014,30 +1984,29 @@ const riscv = struct {...@@ -2014,30 +1984,29 @@ const riscv = struct {
2014 switch (r_type) {1984 switch (r_type) {
2015 .NONE => unreachable,1985 .NONE => unreachable,
20161986
2017 .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),1987 .@"32" => mem.writeInt(i32, code[0..4], @intCast(S + A), .little),
2018 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|1988 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
2019 try cwriter.writeInt(u64, value, .little)1989 mem.writeInt(u64, code[0..8], value, .little)
2020 else1990 else
2021 try cwriter.writeInt(i64, S + A, .little),1991 mem.writeInt(i64, code[0..8], S + A, .little),
20221992 .ADD8 => riscv_util.writeAddend(i8, .add, code[0..1], S + A),
2023 .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A),1993 .SUB8 => riscv_util.writeAddend(i8, .sub, code[0..1], S + A),
2024 .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A),1994 .ADD16 => riscv_util.writeAddend(i16, .add, code[0..2], S + A),
2025 .ADD16 => riscv_util.writeAddend(i16, .add, code[r_offset..][0..2], S + A),1995 .SUB16 => riscv_util.writeAddend(i16, .sub, code[0..2], S + A),
2026 .SUB16 => riscv_util.writeAddend(i16, .sub, code[r_offset..][0..2], S + A),1996 .ADD32 => riscv_util.writeAddend(i32, .add, code[0..4], S + A),
2027 .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A),1997 .SUB32 => riscv_util.writeAddend(i32, .sub, code[0..4], S + A),
2028 .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A),1998 .ADD64 => riscv_util.writeAddend(i64, .add, code[0..8], S + A),
2029 .ADD64 => riscv_util.writeAddend(i64, .add, code[r_offset..][0..8], S + A),1999 .SUB64 => riscv_util.writeAddend(i64, .sub, code[0..8], S + A),
2030 .SUB64 => riscv_util.writeAddend(i64, .sub, code[r_offset..][0..8], S + A),2000
20312001 .SET8 => mem.writeInt(i8, code[0..1], @as(i8, @truncate(S + A)), .little),
2032 .SET8 => mem.writeInt(i8, code[r_offset..][0..1], @as(i8, @truncate(S + A)), .little),2002 .SET16 => mem.writeInt(i16, code[0..2], @as(i16, @truncate(S + A)), .little),
2033 .SET16 => mem.writeInt(i16, code[r_offset..][0..2], @as(i16, @truncate(S + A)), .little),2003 .SET32 => mem.writeInt(i32, code[0..4], @as(i32, @truncate(S + A)), .little),
2034 .SET32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little),2004
20352005 .SET6 => riscv_util.writeSetSub6(.set, code[0..1], S + A),
2036 .SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A),2006 .SUB6 => riscv_util.writeSetSub6(.sub, code[0..1], S + A),
2037 .SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A),2007
20382008 .SET_ULEB128 => riscv_util.writeSetUleb(code, S + A),
2039 .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A),2009 .SUB_ULEB128 => riscv_util.writeSubUleb(code, S - A),
2040 .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A),
20412010
2042 else => try atom.reportUnhandledRelocError(rel, elf_file),2011 else => try atom.reportUnhandledRelocError(rel, elf_file),
2043 }2012 }
...@@ -2108,14 +2077,16 @@ pub const Extra = struct {...@@ -2108,14 +2077,16 @@ pub const Extra = struct {
2108const std = @import("std");2077const std = @import("std");
2109const assert = std.debug.assert;2078const assert = std.debug.assert;
2110const elf = std.elf;2079const elf = std.elf;
2111const eh_frame = @import("eh_frame.zig");
2112const log = std.log.scoped(.link);2080const log = std.log.scoped(.link);
2113const math = std.math;2081const math = std.math;
2114const mem = std.mem;2082const mem = std.mem;
2115const relocs_log = std.log.scoped(.link_relocs);2083const relocs_log = std.log.scoped(.link_relocs);
2084const Allocator = mem.Allocator;
2085const Writer = std.Io.Writer;
2086
2087const eh_frame = @import("eh_frame.zig");
2116const relocation = @import("relocation.zig");2088const relocation = @import("relocation.zig");
21172089
2118const Allocator = mem.Allocator;
2119const Atom = @This();2090const Atom = @This();
2120const Elf = @import("../Elf.zig");2091const Elf = @import("../Elf.zig");
2121const Fde = eh_frame.Fde;2092const Fde = eh_frame.Fde;
src/link/Elf/AtomList.zig+4-5
...@@ -89,7 +89,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {...@@ -89,7 +89,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
89 list.dirty = false;89 list.dirty = false;
90}90}
9191
92pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytype, elf_file: *Elf) !void {92pub fn write(list: AtomList, buffer: *std.Io.Writer.Allocating, undefs: anytype, elf_file: *Elf) !void {
93 const gpa = elf_file.base.comp.gpa;93 const gpa = elf_file.base.comp.gpa;
94 const osec = elf_file.sections.items(.shdr)[list.output_section_index];94 const osec = elf_file.sections.items(.shdr)[list.output_section_index];
95 assert(osec.sh_type != elf.SHT_NOBITS);95 assert(osec.sh_type != elf.SHT_NOBITS);
...@@ -98,8 +98,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp...@@ -98,8 +98,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp
98 log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)});98 log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)});
9999
100 const list_size = math.cast(usize, list.size) orelse return error.Overflow;100 const list_size = math.cast(usize, list.size) orelse return error.Overflow;
101 try buffer.ensureUnusedCapacity(list_size);101 try buffer.writer.splatByteAll(0, list_size);
102 buffer.appendNTimesAssumeCapacity(0, list_size);
103102
104 for (list.atoms.keys()) |ref| {103 for (list.atoms.keys()) |ref| {
105 const atom_ptr = elf_file.atom(ref).?;104 const atom_ptr = elf_file.atom(ref).?;
...@@ -113,7 +112,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp...@@ -113,7 +112,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp
113 const object = atom_ptr.file(elf_file).?.object;112 const object = atom_ptr.file(elf_file).?.object;
114 const code = try object.codeDecompressAlloc(elf_file, ref.index);113 const code = try object.codeDecompressAlloc(elf_file, ref.index);
115 defer gpa.free(code);114 defer gpa.free(code);
116 const out_code = buffer.items[off..][0..size];115 const out_code = buffer.written()[off..][0..size];
117 @memcpy(out_code, code);116 @memcpy(out_code, code);
118117
119 if (osec.sh_flags & elf.SHF_ALLOC == 0)118 if (osec.sh_flags & elf.SHF_ALLOC == 0)
...@@ -122,7 +121,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp...@@ -122,7 +121,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp
122 try atom_ptr.resolveRelocsAlloc(elf_file, out_code);121 try atom_ptr.resolveRelocsAlloc(elf_file, out_code);
123 }122 }
124123
125 try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file));124 try elf_file.base.file.?.pwriteAll(buffer.written(), list.offset(elf_file));
126 buffer.clearRetainingCapacity();125 buffer.clearRetainingCapacity();
127}126}
128127
src/link/Elf/Object.zig+1-1
...@@ -952,7 +952,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -952,7 +952,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
952 const is_tls = sym.type(elf_file) == elf.STT_TLS;952 const is_tls = sym.type(elf_file) == elf.STT_TLS;
953 const name = if (is_tls) ".tls_common" else ".common";953 const name = if (is_tls) ".tls_common" else ".common";
954 const name_offset = @as(u32, @intCast(self.strtab.items.len));954 const name_offset = @as(u32, @intCast(self.strtab.items.len));
955 try self.strtab.writer(gpa).print("{s}\x00", .{name});955 try self.strtab.print(gpa, "{s}\x00", .{name});
956956
957 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;957 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
958 if (is_tls) sh_flags |= elf.SHF_TLS;958 if (is_tls) sh_flags |= elf.SHF_TLS;
src/link/Elf/gc.zig-16
...@@ -162,22 +162,6 @@ fn prune(elf_file: *Elf) void {...@@ -162,22 +162,6 @@ fn prune(elf_file: *Elf) void {
162 }162 }
163}163}
164164
165pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
166 const stderr = std.fs.File.stderr().deprecatedWriter();
167 for (elf_file.objects.items) |index| {
168 const file = elf_file.file(index).?;
169 for (file.atoms()) |atom_index| {
170 const atom = file.atom(atom_index) orelse continue;
171 if (!atom.alive)
172 // TODO should we simply print to stderr?
173 try stderr.print("link: removing unused section '{s}' in file '{f}'\n", .{
174 atom.name(elf_file),
175 atom.file(elf_file).?.fmtPath(),
176 });
177 }
178 }
179}
180
181const Level = struct {165const Level = struct {
182 value: usize = 0,166 value: usize = 0,
183167
src/link/Elf/relocatable.zig+24-21
...@@ -100,32 +100,33 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -100,32 +100,33 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
101 }101 }
102102
103 var buffer = std.array_list.Managed(u8).init(gpa);103 const buffer = try gpa.alloc(u8, total_size);
104 defer buffer.deinit();104 defer gpa.free(buffer);
105 try buffer.ensureTotalCapacityPrecise(total_size);105
106 var writer: std.Io.Writer = .fixed(buffer);
106107
107 // Write magic108 // Write magic
108 try buffer.writer().writeAll(elf.ARMAG);109 try writer.writeAll(elf.ARMAG);
109110
110 // Write symtab111 // Write symtab
111 try ar_symtab.write(.p64, elf_file, buffer.writer());112 try ar_symtab.write(.p64, elf_file, &writer);
112113
113 // Write strtab114 // Write strtab
114 if (ar_strtab.size() > 0) {115 if (ar_strtab.size() > 0) {
115 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);116 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
116 try ar_strtab.write(buffer.writer());117 try ar_strtab.write(&writer);
117 }118 }
118119
119 // Write object files120 // Write object files
120 for (files.items) |index| {121 for (files.items) |index| {
121 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);122 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
122 try elf_file.file(index).?.writeAr(elf_file, buffer.writer());123 try elf_file.file(index).?.writeAr(elf_file, &writer);
123 }124 }
124125
125 assert(buffer.items.len == total_size);126 assert(writer.buffered().len == total_size);
126127
127 try elf_file.base.file.?.setEndPos(total_size);128 try elf_file.base.file.?.setEndPos(total_size);
128 try elf_file.base.file.?.pwriteAll(buffer.items, 0);129 try elf_file.base.file.?.pwriteAll(writer.buffered(), 0);
129130
130 if (diags.hasErrors()) return error.LinkFailure;131 if (diags.hasErrors()) return error.LinkFailure;
131}132}
...@@ -407,15 +408,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -407,15 +408,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
407 };408 };
408 const shdr = slice.items(.shdr)[shndx];409 const shdr = slice.items(.shdr)[shndx];
409 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;410 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
410 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size));411 const buffer = try gpa.alloc(u8, @intCast(sh_size - existing_size));
411 defer buffer.deinit();412 defer gpa.free(buffer);
412 try eh_frame.writeEhFrameRelocatable(elf_file, buffer.writer());413 var writer: std.Io.Writer = .fixed(buffer);
414 try eh_frame.writeEhFrameRelocatable(elf_file, &writer);
413 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{415 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{
414 shdr.sh_offset + existing_size,416 shdr.sh_offset + existing_size,
415 shdr.sh_offset + sh_size,417 shdr.sh_offset + sh_size,
416 });418 });
417 assert(buffer.items.len == sh_size - existing_size);419 assert(writer.buffered().len == sh_size - existing_size);
418 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);420 try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset + existing_size);
419 }421 }
420 if (elf_file.section_indexes.eh_frame_rela) |shndx| {422 if (elf_file.section_indexes.eh_frame_rela) |shndx| {
421 const shdr = slice.items(.shdr)[shndx];423 const shdr = slice.items(.shdr)[shndx];
...@@ -446,15 +448,16 @@ fn writeGroups(elf_file: *Elf) !void {...@@ -446,15 +448,16 @@ fn writeGroups(elf_file: *Elf) !void {
446 for (elf_file.group_sections.items) |cgs| {448 for (elf_file.group_sections.items) |cgs| {
447 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];449 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];
448 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;450 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
449 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size);451 const buffer = try gpa.alloc(u8, sh_size);
450 defer buffer.deinit();452 defer gpa.free(buffer);
451 try cgs.write(elf_file, buffer.writer());453 var writer: std.Io.Writer = .fixed(buffer);
452 assert(buffer.items.len == sh_size);454 try cgs.write(elf_file, &writer);
455 assert(writer.buffered().len == sh_size);
453 log.debug("writing group from 0x{x} to 0x{x}", .{456 log.debug("writing group from 0x{x} to 0x{x}", .{
454 shdr.sh_offset,457 shdr.sh_offset,
455 shdr.sh_offset + shdr.sh_size,458 shdr.sh_offset + shdr.sh_size,
456 });459 });
457 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);460 try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset);
458 }461 }
459}462}
460463
src/link/Elf/synthetic_sections.zig+53-51
...@@ -94,134 +94,134 @@ pub const DynamicSection = struct {...@@ -94,134 +94,134 @@ pub const DynamicSection = struct {
94 return nentries * @sizeOf(elf.Elf64_Dyn);94 return nentries * @sizeOf(elf.Elf64_Dyn);
95 }95 }
9696
97 pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void {97 pub fn write(dt: DynamicSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
98 const shdrs = elf_file.sections.items(.shdr);98 const shdrs = elf_file.sections.items(.shdr);
9999
100 // NEEDED100 // NEEDED
101 for (dt.needed.items) |off| {101 for (dt.needed.items) |off| {
102 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });102 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NEEDED, .d_val = off }), .little);
103 }103 }
104104
105 if (dt.soname) |off| {105 if (dt.soname) |off| {
106 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off });106 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SONAME, .d_val = off }), .little);
107 }107 }
108108
109 // RUNPATH109 // RUNPATH
110 // TODO add option in Options to revert to old RPATH tag110 // TODO add option in Options to revert to old RPATH tag
111 if (dt.rpath > 0) {111 if (dt.rpath > 0) {
112 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath });112 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath }), .little);
113 }113 }
114114
115 // INIT115 // INIT
116 if (elf_file.sectionByName(".init")) |shndx| {116 if (elf_file.sectionByName(".init")) |shndx| {
117 const addr = shdrs[shndx].sh_addr;117 const addr = shdrs[shndx].sh_addr;
118 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });118 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT, .d_val = addr }), .little);
119 }119 }
120120
121 // FINI121 // FINI
122 if (elf_file.sectionByName(".fini")) |shndx| {122 if (elf_file.sectionByName(".fini")) |shndx| {
123 const addr = shdrs[shndx].sh_addr;123 const addr = shdrs[shndx].sh_addr;
124 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });124 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little);
125 }125 }
126126
127 // INIT_ARRAY127 // INIT_ARRAY
128 if (elf_file.sectionByName(".init_array")) |shndx| {128 if (elf_file.sectionByName(".init_array")) |shndx| {
129 const shdr = shdrs[shndx];129 const shdr = shdrs[shndx];
130 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });130 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }), .little);
131 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });131 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }), .little);
132 }132 }
133133
134 // FINI_ARRAY134 // FINI_ARRAY
135 if (elf_file.sectionByName(".fini_array")) |shndx| {135 if (elf_file.sectionByName(".fini_array")) |shndx| {
136 const shdr = shdrs[shndx];136 const shdr = shdrs[shndx];
137 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });137 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }), .little);
138 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });138 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }), .little);
139 }139 }
140140
141 // RELA141 // RELA
142 if (elf_file.section_indexes.rela_dyn) |shndx| {142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143 const shdr = shdrs[shndx];143 const shdr = shdrs[shndx];
144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });144 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }), .little);
145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });145 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }), .little);
146 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });146 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }), .little);
147 }147 }
148148
149 // JMPREL149 // JMPREL
150 if (elf_file.section_indexes.rela_plt) |shndx| {150 if (elf_file.section_indexes.rela_plt) |shndx| {
151 const shdr = shdrs[shndx];151 const shdr = shdrs[shndx];
152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });152 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }), .little);
153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });153 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }), .little);
154 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });154 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }), .little);
155 }155 }
156156
157 // PLTGOT157 // PLTGOT
158 if (elf_file.section_indexes.got_plt) |shndx| {158 if (elf_file.section_indexes.got_plt) |shndx| {
159 const addr = shdrs[shndx].sh_addr;159 const addr = shdrs[shndx].sh_addr;
160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });160 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTGOT, .d_val = addr }), .little);
161 }161 }
162162
163 {163 {
164 assert(elf_file.section_indexes.hash != null);164 assert(elf_file.section_indexes.hash != null);
165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;
166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });166 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_HASH, .d_val = addr }), .little);
167 }167 }
168168
169 if (elf_file.section_indexes.gnu_hash) |shndx| {169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170 const addr = shdrs[shndx].sh_addr;170 const addr = shdrs[shndx].sh_addr;
171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });171 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }), .little);
172 }172 }
173173
174 // TEXTREL174 // TEXTREL
175 if (elf_file.has_text_reloc) {175 if (elf_file.has_text_reloc) {
176 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 });176 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }), .little);
177 }177 }
178178
179 // SYMTAB + SYMENT179 // SYMTAB + SYMENT
180 {180 {
181 assert(elf_file.section_indexes.dynsymtab != null);181 assert(elf_file.section_indexes.dynsymtab != null);
182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];
183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });183 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }), .little);
184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });184 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }), .little);
185 }185 }
186186
187 // STRTAB + STRSZ187 // STRTAB + STRSZ
188 {188 {
189 assert(elf_file.section_indexes.dynstrtab != null);189 assert(elf_file.section_indexes.dynstrtab != null);
190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];
191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });191 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }), .little);
192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });192 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }), .little);
193 }193 }
194194
195 // VERSYM195 // VERSYM
196 if (elf_file.section_indexes.versym) |shndx| {196 if (elf_file.section_indexes.versym) |shndx| {
197 const addr = shdrs[shndx].sh_addr;197 const addr = shdrs[shndx].sh_addr;
198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });198 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERSYM, .d_val = addr }), .little);
199 }199 }
200200
201 // VERNEED + VERNEEDNUM201 // VERNEED + VERNEEDNUM
202 if (elf_file.section_indexes.verneed) |shndx| {202 if (elf_file.section_indexes.verneed) |shndx| {
203 const addr = shdrs[shndx].sh_addr;203 const addr = shdrs[shndx].sh_addr;
204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });204 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERNEED, .d_val = addr }), .little);
205 try writer.writeStruct(elf.Elf64_Dyn{205 try writer.writeStruct(@as(elf.Elf64_Dyn, .{
206 .d_tag = elf.DT_VERNEEDNUM,206 .d_tag = elf.DT_VERNEEDNUM,
207 .d_val = elf_file.verneed.verneed.items.len,207 .d_val = elf_file.verneed.verneed.items.len,
208 });208 }), .little);
209 }209 }
210210
211 // FLAGS211 // FLAGS
212 if (dt.getFlags(elf_file)) |flags| {212 if (dt.getFlags(elf_file)) |flags| {
213 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags });213 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS, .d_val = flags }), .little);
214 }214 }
215 // FLAGS_1215 // FLAGS_1
216 if (dt.getFlags1(elf_file)) |flags_1| {216 if (dt.getFlags1(elf_file)) |flags_1| {
217 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 });217 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 }), .little);
218 }218 }
219219
220 // DEBUG220 // DEBUG
221 if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });221 if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_DEBUG, .d_val = 0 }), .little);
222222
223 // NULL223 // NULL
224 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });224 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NULL, .d_val = 0 }), .little);
225 }225 }
226};226};
227227
...@@ -360,7 +360,7 @@ pub const GotSection = struct {...@@ -360,7 +360,7 @@ pub const GotSection = struct {
360 return s;360 return s;
361 }361 }
362362
363 pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {363 pub fn write(got: GotSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
364 const comp = elf_file.base.comp;364 const comp = elf_file.base.comp;
365 const is_dyn_lib = elf_file.isEffectivelyDynLib();365 const is_dyn_lib = elf_file.isEffectivelyDynLib();
366 const apply_relocs = true; // TODO add user option for this366 const apply_relocs = true; // TODO add user option for this
...@@ -666,7 +666,7 @@ pub const PltSection = struct {...@@ -666,7 +666,7 @@ pub const PltSection = struct {
666 };666 };
667 }667 }
668668
669 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {669 pub fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
670 const cpu_arch = elf_file.getTarget().cpu.arch;670 const cpu_arch = elf_file.getTarget().cpu.arch;
671 switch (cpu_arch) {671 switch (cpu_arch) {
672 .x86_64 => try x86_64.write(plt, elf_file, writer),672 .x86_64 => try x86_64.write(plt, elf_file, writer),
...@@ -763,7 +763,7 @@ pub const PltSection = struct {...@@ -763,7 +763,7 @@ pub const PltSection = struct {
763 }763 }
764764
765 const x86_64 = struct {765 const x86_64 = struct {
766 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {766 fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
767 const shdrs = elf_file.sections.items(.shdr);767 const shdrs = elf_file.sections.items(.shdr);
768 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;768 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
769 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;769 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
...@@ -778,7 +778,7 @@ pub const PltSection = struct {...@@ -778,7 +778,7 @@ pub const PltSection = struct {
778 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;778 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
779 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);779 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
780 try writer.writeAll(&preamble);780 try writer.writeAll(&preamble);
781 try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len);781 try writer.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len);
782782
783 for (plt.symbols.items, 0..) |ref, i| {783 for (plt.symbols.items, 0..) |ref, i| {
784 const sym = elf_file.symbol(ref).?;784 const sym = elf_file.symbol(ref).?;
...@@ -798,7 +798,7 @@ pub const PltSection = struct {...@@ -798,7 +798,7 @@ pub const PltSection = struct {
798 };798 };
799799
800 const aarch64 = struct {800 const aarch64 = struct {
801 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {801 fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
802 {802 {
803 const shdrs = elf_file.sections.items(.shdr);803 const shdrs = elf_file.sections.items(.shdr);
804 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);804 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
...@@ -853,7 +853,7 @@ pub const GotPltSection = struct {...@@ -853,7 +853,7 @@ pub const GotPltSection = struct {
853 return preamble_size + elf_file.plt.symbols.items.len * 8;853 return preamble_size + elf_file.plt.symbols.items.len * 8;
854 }854 }
855855
856 pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: anytype) !void {856 pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
857 _ = got_plt;857 _ = got_plt;
858 {858 {
859 // [0]: _DYNAMIC859 // [0]: _DYNAMIC
...@@ -904,7 +904,7 @@ pub const PltGotSection = struct {...@@ -904,7 +904,7 @@ pub const PltGotSection = struct {
904 };904 };
905 }905 }
906906
907 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {907 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
908 const cpu_arch = elf_file.getTarget().cpu.arch;908 const cpu_arch = elf_file.getTarget().cpu.arch;
909 switch (cpu_arch) {909 switch (cpu_arch) {
910 .x86_64 => try x86_64.write(plt_got, elf_file, writer),910 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
...@@ -940,7 +940,7 @@ pub const PltGotSection = struct {...@@ -940,7 +940,7 @@ pub const PltGotSection = struct {
940 }940 }
941941
942 const x86_64 = struct {942 const x86_64 = struct {
943 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {943 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
944 for (plt_got.symbols.items) |ref| {944 for (plt_got.symbols.items) |ref| {
945 const sym = elf_file.symbol(ref).?;945 const sym = elf_file.symbol(ref).?;
946 const target_addr = sym.gotAddress(elf_file);946 const target_addr = sym.gotAddress(elf_file);
...@@ -958,7 +958,7 @@ pub const PltGotSection = struct {...@@ -958,7 +958,7 @@ pub const PltGotSection = struct {
958 };958 };
959959
960 const aarch64 = struct {960 const aarch64 = struct {
961 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {961 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
962 for (plt_got.symbols.items) |ref| {962 for (plt_got.symbols.items) |ref| {
963 const sym = elf_file.symbol(ref).?;963 const sym = elf_file.symbol(ref).?;
964 const target_addr = sym.gotAddress(elf_file);964 const target_addr = sym.gotAddress(elf_file);
...@@ -1133,14 +1133,14 @@ pub const DynsymSection = struct {...@@ -1133,14 +1133,14 @@ pub const DynsymSection = struct {
1133 return @as(u32, @intCast(dynsym.entries.items.len + 1));1133 return @as(u32, @intCast(dynsym.entries.items.len + 1));
1134 }1134 }
11351135
1136 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void {1136 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
1137 try writer.writeStruct(Elf.null_sym);1137 try writer.writeStruct(Elf.null_sym, .little);
1138 for (dynsym.entries.items) |entry| {1138 for (dynsym.entries.items) |entry| {
1139 const sym = elf_file.symbol(entry.ref).?;1139 const sym = elf_file.symbol(entry.ref).?;
1140 var out_sym: elf.Elf64_Sym = Elf.null_sym;1140 var out_sym: elf.Elf64_Sym = Elf.null_sym;
1141 sym.setOutputSym(elf_file, &out_sym);1141 sym.setOutputSym(elf_file, &out_sym);
1142 out_sym.st_name = entry.off;1142 out_sym.st_name = entry.off;
1143 try writer.writeStruct(out_sym);1143 try writer.writeStruct(out_sym, .little);
1144 }1144 }
1145 }1145 }
1146};1146};
...@@ -1175,10 +1175,12 @@ pub const HashSection = struct {...@@ -1175,10 +1175,12 @@ pub const HashSection = struct {
1175 }1175 }
11761176
1177 try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4);1177 try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4);
1178 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;1178 var w: std.Io.Writer = .fixed(hs.buffer.unusedCapacitySlice());
1179 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;1179 w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1180 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(buckets)) catch unreachable;1180 w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1181 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(chains)) catch unreachable;1181 w.writeAll(@ptrCast(buckets)) catch unreachable;
1182 w.writeAll(@ptrCast(chains)) catch unreachable;
1183 hs.buffer.items.len += w.end;
1182 }1184 }
11831185
1184 pub inline fn size(hs: HashSection) usize {1186 pub inline fn size(hs: HashSection) usize {
...@@ -1439,7 +1441,7 @@ pub const VerneedSection = struct {...@@ -1439,7 +1441,7 @@ pub const VerneedSection = struct {
1439 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);1441 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);
1440 }1442 }
14411443
1442 pub fn write(vern: VerneedSection, writer: anytype) !void {1444 pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
1443 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));1445 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));
1444 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));1446 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));
1445 }1447 }
...@@ -1467,7 +1469,7 @@ pub const GroupSection = struct {...@@ -1467,7 +1469,7 @@ pub const GroupSection = struct {
1467 return (members.len + 1) * @sizeOf(u32);1469 return (members.len + 1) * @sizeOf(u32);
1468 }1470 }
14691471
1470 pub fn write(cgs: GroupSection, elf_file: *Elf, writer: anytype) !void {1472 pub fn write(cgs: GroupSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
1471 const cg = cgs.group(elf_file);1473 const cg = cgs.group(elf_file);
1472 const object = cg.file(elf_file).object;1474 const object = cg.file(elf_file).object;
1473 const members = cg.members(elf_file);1475 const members = cg.members(elf_file);
...@@ -1495,7 +1497,7 @@ pub const GroupSection = struct {...@@ -1495,7 +1497,7 @@ pub const GroupSection = struct {
1495 }1497 }
1496};1498};
14971499
1498fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {1500fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void {
1499 const entry_size = elf_file.archPtrWidthBytes();1501 const entry_size = elf_file.archPtrWidthBytes();
1500 const target = elf_file.getTarget();1502 const target = elf_file.getTarget();
1501 const endian = target.cpu.arch.endian();1503 const endian = target.cpu.arch.endian();
src/link/riscv.zig+14-15
...@@ -9,29 +9,28 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytyp...@@ -9,29 +9,28 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytyp
9 mem.writeInt(u8, code, value, .little);9 mem.writeInt(u8, code, value, .little);
10}10}
1111
12pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void {12pub fn writeSubUleb(code: []u8, addend: i64) void {
13 switch (op) {13 var reader: std.Io.Reader = .fixed(code);
14 .set => try overwriteUleb(stream, @intCast(addend)),14 const value = reader.takeLeb128(u64) catch unreachable;
15 .sub => {15 overwriteUleb(code, value -% @as(u64, @intCast(addend)));
16 const position = try stream.getPos();16}
17 const value: u64 = try std.leb.readUleb128(u64, stream.reader());17
18 try stream.seekTo(position);18pub fn writeSetUleb(code: []u8, addend: i64) void {
19 try overwriteUleb(stream, value -% @as(u64, @intCast(addend)));19 overwriteUleb(code, @intCast(addend));
20 },
21 }
22}20}
2321
24fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void {22fn overwriteUleb(code: []u8, addend: u64) void {
25 var value: u64 = addend;23 var value: u64 = addend;
26 const writer = stream.writer();24 var i: usize = 0;
2725
28 while (true) {26 while (true) {
29 const byte = stream.buffer[stream.pos];27 const byte = code[i];
30 if (byte & 0x80 == 0) break;28 if (byte & 0x80 == 0) break;
31 try writer.writeByte(0x80 | @as(u8, @truncate(value & 0x7f)));29 code[i] = 0x80 | @as(u8, @truncate(value & 0x7f));
30 i += 1;
32 value >>= 7;31 value >>= 7;
33 }32 }
34 stream.buffer[stream.pos] = @truncate(value & 0x7f);33 code[i] = @truncate(value & 0x7f);
35}34}
3635
37pub fn writeAddend(36pub fn writeAddend(