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 {
811811
812812 if (self.base.gc_sections) {
813813 try gc.gcAtoms(self);
814
815 if (self.base.print_gc_sections) {
816 try gc.dumpPrunedAtoms(self);
817 }
818814 }
819815
820816 self.checkDuplicates() catch |err| switch (err) {
......@@ -3005,7 +3001,7 @@ fn writeAtoms(self: *Elf) !void {
30053001 undefs.deinit();
30063002 }
30073003
3008 var buffer = std.array_list.Managed(u8).init(gpa);
3004 var buffer: std.Io.Writer.Allocating = .init(gpa);
30093005 defer buffer.deinit();
30103006
30113007 const slice = self.sections.slice();
......@@ -3032,9 +3028,9 @@ fn writeAtoms(self: *Elf) !void {
30323028 try buffer.ensureUnusedCapacity(thunk_size);
30333029 const shdr = slice.items(.shdr)[th.output_section_index];
30343030 const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset;
3035 try th.write(self, buffer.writer());
3036 assert(buffer.items.len == thunk_size);
3037 try self.pwriteAll(buffer.items, offset);
3031 try th.write(self, &buffer.writer);
3032 assert(buffer.written().len == thunk_size);
3033 try self.pwriteAll(buffer.written(), offset);
30383034 buffer.clearRetainingCapacity();
30393035 }
30403036 }
......@@ -3166,26 +3162,26 @@ fn writeSyntheticSections(self: *Elf) !void {
31663162
31673163 if (self.section_indexes.verneed) |shndx| {
31683164 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());
31703166 defer buffer.deinit();
3171 try self.verneed.write(buffer.writer());
3172 try self.pwriteAll(buffer.items, shdr.sh_offset);
3167 try self.verneed.write(&buffer.writer);
3168 try self.pwriteAll(buffer.written(), shdr.sh_offset);
31733169 }
31743170
31753171 if (self.section_indexes.dynamic) |shndx| {
31763172 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));
31783174 defer buffer.deinit();
3179 try self.dynamic.write(self, buffer.writer());
3180 try self.pwriteAll(buffer.items, shdr.sh_offset);
3175 try self.dynamic.write(self, &buffer.writer);
3176 try self.pwriteAll(buffer.written(), shdr.sh_offset);
31813177 }
31823178
31833179 if (self.section_indexes.dynsymtab) |shndx| {
31843180 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());
31863182 defer buffer.deinit();
3187 try self.dynsym.write(self, buffer.writer());
3188 try self.pwriteAll(buffer.items, shdr.sh_offset);
3183 try self.dynsym.write(self, &buffer.writer);
3184 try self.pwriteAll(buffer.written(), shdr.sh_offset);
31893185 }
31903186
31913187 if (self.section_indexes.dynstrtab) |shndx| {
......@@ -3201,28 +3197,28 @@ fn writeSyntheticSections(self: *Elf) !void {
32013197 };
32023198 const shdr = slice.items(.shdr)[shndx];
32033199 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));
32053201 defer buffer.deinit();
3206 try eh_frame.writeEhFrame(self, buffer.writer());
3207 assert(buffer.items.len == sh_size - existing_size);
3208 try self.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
3202 try eh_frame.writeEhFrame(self, &buffer.writer);
3203 assert(buffer.written().len == sh_size - existing_size);
3204 try self.pwriteAll(buffer.written(), shdr.sh_offset + existing_size);
32093205 }
32103206
32113207 if (self.section_indexes.eh_frame_hdr) |shndx| {
32123208 const shdr = slice.items(.shdr)[shndx];
32133209 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);
32153211 defer buffer.deinit();
3216 try eh_frame.writeEhFrameHdr(self, buffer.writer());
3217 try self.pwriteAll(buffer.items, shdr.sh_offset);
3212 try eh_frame.writeEhFrameHdr(self, &buffer.writer);
3213 try self.pwriteAll(buffer.written(), shdr.sh_offset);
32183214 }
32193215
32203216 if (self.section_indexes.got) |index| {
32213217 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));
32233219 defer buffer.deinit();
3224 try self.got.write(self, buffer.writer());
3225 try self.pwriteAll(buffer.items, shdr.sh_offset);
3220 try self.got.write(self, &buffer.writer);
3221 try self.pwriteAll(buffer.written(), shdr.sh_offset);
32263222 }
32273223
32283224 if (self.section_indexes.rela_dyn) |shndx| {
......@@ -3235,26 +3231,26 @@ fn writeSyntheticSections(self: *Elf) !void {
32353231
32363232 if (self.section_indexes.plt) |shndx| {
32373233 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));
32393235 defer buffer.deinit();
3240 try self.plt.write(self, buffer.writer());
3241 try self.pwriteAll(buffer.items, shdr.sh_offset);
3236 try self.plt.write(self, &buffer.writer);
3237 try self.pwriteAll(buffer.written(), shdr.sh_offset);
32423238 }
32433239
32443240 if (self.section_indexes.got_plt) |shndx| {
32453241 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));
32473243 defer buffer.deinit();
3248 try self.got_plt.write(self, buffer.writer());
3249 try self.pwriteAll(buffer.items, shdr.sh_offset);
3244 try self.got_plt.write(self, &buffer.writer);
3245 try self.pwriteAll(buffer.written(), shdr.sh_offset);
32503246 }
32513247
32523248 if (self.section_indexes.plt_got) |shndx| {
32533249 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));
32553251 defer buffer.deinit();
3256 try self.plt_got.write(self, buffer.writer());
3257 try self.pwriteAll(buffer.items, shdr.sh_offset);
3252 try self.plt_got.write(self, &buffer.writer);
3253 try self.pwriteAll(buffer.written(), shdr.sh_offset);
32583254 }
32593255
32603256 if (self.section_indexes.rela_plt) |shndx| {
......@@ -3757,7 +3753,7 @@ pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
37573753 const gpa = self.base.comp.gpa;
37583754 const off = @as(u32, @intCast(self.shstrtab.items.len));
37593755 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;
37613757 return off;
37623758}
37633759
......@@ -3770,7 +3766,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 {
37703766 const gpa = self.base.comp.gpa;
37713767 const off = @as(u32, @intCast(self.dynstrtab.items.len));
37723768 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;
37743770 return off;
37753771}
37763772
src/link/Elf/Archive.zig+4-5
......@@ -123,8 +123,7 @@ pub fn setArHdr(opts: struct {
123123 @memcpy(&hdr.ar_fmag, elf.ARFMAG);
124124
125125 {
126 var stream = std.io.fixedBufferStream(&hdr.ar_name);
127 const writer = stream.writer();
126 var writer: std.Io.Writer = .fixed(&hdr.ar_name);
128127 switch (opts.name) {
129128 .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable,
130129 .strtab => writer.print("//", .{}) catch unreachable,
......@@ -133,8 +132,8 @@ pub fn setArHdr(opts: struct {
133132 }
134133 }
135134 {
136 var stream = std.io.fixedBufferStream(&hdr.ar_size);
137 stream.writer().print("{d}", .{opts.size}) catch unreachable;
135 var writer: std.Io.Writer = .fixed(&hdr.ar_size);
136 writer.print("{d}", .{opts.size}) catch unreachable;
138137 }
139138
140139 return hdr;
......@@ -246,7 +245,7 @@ pub const ArStrtab = struct {
246245
247246 pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 {
248247 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 });
250249 return off;
251250 }
252251
src/link/Elf/Atom.zig+113-142
......@@ -621,7 +621,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
621621
622622 const cpu_arch = elf_file.getTarget().cpu.arch;
623623 const file_ptr = self.file(elf_file).?;
624 var stream = std.io.fixedBufferStream(code);
625624
626625 const rels = self.relocs(elf_file);
627626 var it = RelocsIterator{ .relocs = rels };
......@@ -661,20 +660,16 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
661660 target.name(elf_file),
662661 });
663662
664 try stream.seekTo(r_offset);
665
666663 const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP };
667664
668665 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) {
670667 error.RelocFailure,
671668 error.RelaxFailure,
672 error.InvalidInstruction,
673 error.CannotEncode,
674669 => has_reloc_errors = true,
675670 else => |e| return e,
676671 },
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) {
678673 error.RelocFailure,
679674 error.RelaxFailure,
680675 error.UnexpectedRemainder,
......@@ -682,7 +677,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
682677 => has_reloc_errors = true,
683678 else => |e| return e,
684679 },
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) {
686681 error.RelocFailure,
687682 error.RelaxFailure,
688683 => has_reloc_errors = true,
......@@ -701,7 +696,8 @@ fn resolveDynAbsReloc(
701696 rel: elf.Elf64_Rela,
702697 action: RelocAction,
703698 elf_file: *Elf,
704 writer: anytype,
699 code: []u8,
700 r_offset: usize,
705701) !void {
706702 const comp = elf_file.base.comp;
707703 const gpa = comp.gpa;
......@@ -726,7 +722,7 @@ fn resolveDynAbsReloc(
726722 .copyrel,
727723 .cplt,
728724 .none,
729 => try writer.writeInt(i64, S + A, .little),
725 => mem.writeInt(i64, code[r_offset..][0..8], S + A, .little),
730726
731727 .dyn_copyrel => {
732728 if (is_writeable or elf_file.z_nocopyreloc) {
......@@ -737,9 +733,9 @@ fn resolveDynAbsReloc(
737733 .addend = A,
738734 .target = target,
739735 });
740 try applyDynamicReloc(A, elf_file, writer);
736 applyDynamicReloc(A, code, r_offset);
741737 } else {
742 try writer.writeInt(i64, S + A, .little);
738 mem.writeInt(i64, code[r_offset..][0..8], S + A, .little);
743739 }
744740 },
745741
......@@ -752,9 +748,9 @@ fn resolveDynAbsReloc(
752748 .addend = A,
753749 .target = target,
754750 });
755 try applyDynamicReloc(A, elf_file, writer);
751 applyDynamicReloc(A, code, r_offset);
756752 } else {
757 try writer.writeInt(i64, S + A, .little);
753 mem.writeInt(i64, code[r_offset..][0..8], S + A, .little);
758754 }
759755 },
760756
......@@ -766,7 +762,7 @@ fn resolveDynAbsReloc(
766762 .addend = A,
767763 .target = target,
768764 });
769 try applyDynamicReloc(A, elf_file, writer);
765 applyDynamicReloc(A, code, r_offset);
770766 },
771767
772768 .baserel => {
......@@ -776,7 +772,7 @@ fn resolveDynAbsReloc(
776772 .addend = S + A,
777773 .target = target,
778774 });
779 try applyDynamicReloc(S + A, elf_file, writer);
775 applyDynamicReloc(S + A, code, r_offset);
780776 },
781777
782778 .ifunc => {
......@@ -787,16 +783,13 @@ fn resolveDynAbsReloc(
787783 .addend = S_ + A,
788784 .target = target,
789785 });
790 try applyDynamicReloc(S_ + A, elf_file, writer);
786 applyDynamicReloc(S_ + A, code, r_offset);
791787 },
792788 }
793789}
794790
795fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void {
796 _ = elf_file;
797 // if (elf_file.options.apply_dynamic_relocs) {
798 try writer.writeInt(i64, value, .little);
799 // }
791fn applyDynamicReloc(value: i64, code: []u8, r_offset: usize) void {
792 mem.writeInt(i64, code[r_offset..][0..8], value, .little);
800793}
801794
802795pub 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
804797
805798 const cpu_arch = elf_file.getTarget().cpu.arch;
806799 const file_ptr = self.file(elf_file).?;
807 var stream = std.io.fixedBufferStream(code);
808800
809801 const rels = self.relocs(elf_file);
810802 var has_reloc_errors = false;
......@@ -863,18 +855,16 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any
863855 target.name(elf_file),
864856 });
865857
866 try stream.seekTo(r_offset);
867
868858 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) {
870860 error.RelocFailure => has_reloc_errors = true,
871861 else => |e| return e,
872862 },
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) {
874864 error.RelocFailure => has_reloc_errors = true,
875865 else => |e| return e,
876866 },
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) {
878868 error.RelocFailure => has_reloc_errors = true,
879869 else => |e| return e,
880870 },
......@@ -915,7 +905,7 @@ const Format = struct {
915905 atom: Atom,
916906 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 {
919909 const atom = f.atom;
920910 const elf_file = f.elf_file;
921911 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 {
10681058 args: ResolveArgs,
10691059 it: *RelocsIterator,
10701060 code: []u8,
1071 stream: anytype,
1072 ) (error{ InvalidInstruction, CannotEncode } || RelocError)!void {
1061 ) !void {
10731062 dev.check(.x86_64_backend);
10741063 const t = &elf_file.base.comp.root_mod.resolved_target.result;
10751064 const diags = &elf_file.base.comp.link_diags;
10761065 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
10771066 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
10781067
1079 const cwriter = stream.writer();
1080
10811068 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
10821069
10831070 switch (r_type) {
......@@ -1089,58 +1076,60 @@ const x86_64 = struct {
10891076 rel,
10901077 dynAbsRelocAction(target, elf_file),
10911078 elf_file,
1092 cwriter,
1079 code,
1080 r_offset,
10931081 );
10941082 },
10951083
1096 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1097 .PC32 => 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),
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),
1100 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
1101 .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little),
1087 .GOTPCREL => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little),
1088 .GOTPC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(GOT + A - P)), .little),
1089 .GOTPC64 => mem.writeInt(i64, code[r_offset..][0..8], GOT + A - P, .little),
11021090
11031091 .GOTPCRELX => {
11041092 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
11051093 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);
11071095 return;
11081096 }
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);
11101098 },
11111099
11121100 .REX_GOTPCRELX => {
11131101 if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
11141102 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);
11161104 return;
11171105 }
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);
11191107 },
11201108
1121 .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little),
1122 .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little),
1109 .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(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),
1125 .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little),
1112 .TPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(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),
1128 .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little),
1115 .DTPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - DTP)), .little),
1116 .DTPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - DTP, .little),
11291117
11301118 .TLSGD => {
11311119 if (target.flags.has_tlsgd) {
11321120 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);
11341122 } else if (target.flags.has_gottp) {
11351123 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);
11371125 } else {
11381126 try x86_64.relaxTlsGdToLe(
11391127 atom,
11401128 &.{ rel, it.next().? },
11411129 @as(i32, @intCast(S - TP)),
11421130 elf_file,
1143 stream,
1131 code,
1132 r_offset,
11441133 );
11451134 }
11461135 },
......@@ -1149,14 +1138,15 @@ const x86_64 = struct {
11491138 if (elf_file.got.tlsld_index) |entry_index| {
11501139 const tlsld_entry = elf_file.got.entries.items[entry_index];
11511140 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);
11531142 } else {
11541143 try x86_64.relaxTlsLdToLe(
11551144 atom,
11561145 &.{ rel, it.next().? },
11571146 @as(i32, @intCast(TP - elf_file.tlsAddress())),
11581147 elf_file,
1159 stream,
1148 code,
1149 r_offset,
11601150 );
11611151 }
11621152 },
......@@ -1164,7 +1154,7 @@ const x86_64 = struct {
11641154 .GOTPC32_TLSDESC => {
11651155 if (target.flags.has_tlsdesc) {
11661156 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);
11681158 } else {
11691159 x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {
11701160 var err = try diags.addErrorWithNotes(1);
......@@ -1176,26 +1166,26 @@ const x86_64 = struct {
11761166 });
11771167 return error.RelaxFailure;
11781168 };
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);
11801170 }
11811171 },
11821172
11831173 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
11841174 // call -> nop
1185 try cwriter.writeAll(&.{ 0x66, 0x90 });
1175 code[r_offset..][0..2].* = .{ 0x66, 0x90 };
11861176 },
11871177
11881178 .GOTTPOFF => {
11891179 if (target.flags.has_gottp) {
11901180 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);
11921182 } else {
11931183 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);
11951185 }
11961186 },
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
12001190 else => try atom.reportUnhandledRelocError(rel, elf_file),
12011191 }
......@@ -1207,45 +1197,42 @@ const x86_64 = struct {
12071197 rel: elf.Elf64_Rela,
12081198 target: *const Symbol,
12091199 args: ResolveArgs,
1210 it: *RelocsIterator,
12111200 code: []u8,
1212 stream: anytype,
12131201 ) !void {
12141202 dev.check(.x86_64_backend);
1215 _ = code;
1216 _ = it;
12171203 const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
1218 const cwriter = stream.writer();
12191204
12201205 _, const A, const S, const GOT, _, _, const DTP = args;
12211206
1207 var writer: Writer = .fixed(code);
1208
12221209 switch (r_type) {
12231210 .NONE => unreachable,
1224 .@"8" => try cwriter.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),
1226 .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),
1227 .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little),
1211 .@"8" => try writer.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little),
1212 .@"16" => try writer.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little),
1213 .@"32" => try writer.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little),
1214 .@"32S" => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little),
12281215 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1229 try cwriter.writeInt(u64, value, .little)
1216 try writer.writeInt(u64, value, .little)
12301217 else
1231 try cwriter.writeInt(i64, S + A, .little),
1218 try writer.writeInt(i64, S + A, .little),
12321219 .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1233 try cwriter.writeInt(u64, value, .little)
1220 try writer.writeInt(u64, value, .little)
12341221 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),
12361223 .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1237 try cwriter.writeInt(u64, value, .little)
1224 try writer.writeInt(u64, value, .little)
12381225 else
1239 try cwriter.writeInt(i64, S + A - DTP, .little),
1240 .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little),
1241 .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little),
1226 try writer.writeInt(i64, S + A - DTP, .little),
1227 .GOTOFF64 => try writer.writeInt(i64, S + A - GOT, .little),
1228 .GOTPC64 => try writer.writeInt(i64, GOT + A, .little),
12421229 .SIZE32 => {
12431230 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);
12451232 },
12461233 .SIZE64 => {
12471234 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);
12491236 },
12501237 else => try atom.reportUnhandledRelocError(rel, elf_file),
12511238 }
......@@ -1288,12 +1275,12 @@ const x86_64 = struct {
12881275 rels: []const elf.Elf64_Rela,
12891276 value: i32,
12901277 elf_file: *Elf,
1291 stream: anytype,
1278 code: []u8,
1279 r_offset: usize,
12921280 ) !void {
12931281 dev.check(.x86_64_backend);
12941282 assert(rels.len == 2);
12951283 const diags = &elf_file.base.comp.link_diags;
1296 const writer = stream.writer();
12971284 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
12981285 switch (rel) {
12991286 .PC32,
......@@ -1304,8 +1291,7 @@ const x86_64 = struct {
13041291 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax
13051292 };
13061293 std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little);
1307 try stream.seekBy(-4);
1308 try writer.writeAll(&insts);
1294 @memcpy(code[r_offset - 4 ..][0..insts.len], &insts);
13091295 },
13101296
13111297 else => {
......@@ -1329,12 +1315,12 @@ const x86_64 = struct {
13291315 rels: []const elf.Elf64_Rela,
13301316 value: i32,
13311317 elf_file: *Elf,
1332 stream: anytype,
1318 code: []u8,
1319 r_offset: usize,
13331320 ) !void {
13341321 dev.check(.x86_64_backend);
13351322 assert(rels.len == 2);
13361323 const diags = &elf_file.base.comp.link_diags;
1337 const writer = stream.writer();
13381324 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
13391325 switch (rel) {
13401326 .PC32,
......@@ -1346,8 +1332,7 @@ const x86_64 = struct {
13461332 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax
13471333 };
13481334 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1349 try stream.seekBy(-3);
1350 try writer.writeAll(&insts);
1335 @memcpy(code[r_offset - 3 ..][0..insts.len], &insts);
13511336 },
13521337
13531338 .GOTPCREL,
......@@ -1360,8 +1345,7 @@ const x86_64 = struct {
13601345 0x90, // nop
13611346 };
13621347 std.mem.writeInt(i32, insts[8..][0..4], value, .little);
1363 try stream.seekBy(-3);
1364 try writer.writeAll(&insts);
1348 @memcpy(code[r_offset - 3 ..][0..insts.len], &insts);
13651349 },
13661350
13671351 else => {
......@@ -1390,7 +1374,7 @@ const x86_64 = struct {
13901374 // TODO: hack to force imm32s in the assembler
13911375 .{ .imm = .s(-129) },
13921376 }, t) catch return false;
1393 var trash: std.io.Writer.Discarding = .init(&.{});
1377 var trash: Writer.Discarding = .init(&.{});
13941378 inst.encode(&trash.writer, .{}) catch return false;
13951379 return true;
13961380 },
......@@ -1437,12 +1421,12 @@ const x86_64 = struct {
14371421 rels: []const elf.Elf64_Rela,
14381422 value: i32,
14391423 elf_file: *Elf,
1440 stream: anytype,
1424 code: []u8,
1425 r_offset: usize,
14411426 ) !void {
14421427 dev.check(.x86_64_backend);
14431428 assert(rels.len == 2);
14441429 const diags = &elf_file.base.comp.link_diags;
1445 const writer = stream.writer();
14461430 const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type());
14471431 switch (rel) {
14481432 .PC32,
......@@ -1455,8 +1439,7 @@ const x86_64 = struct {
14551439 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax
14561440 };
14571441 std.mem.writeInt(i32, insts[12..][0..4], value, .little);
1458 try stream.seekBy(-4);
1459 try writer.writeAll(&insts);
1442 @memcpy(code[r_offset - 4 ..][0..insts.len], &insts);
14601443 relocs_log.debug(" relaxing {f} and {f}", .{
14611444 relocation.fmtRelocType(rels[0].r_type(), .x86_64),
14621445 relocation.fmtRelocType(rels[1].r_type(), .x86_64),
......@@ -1486,8 +1469,8 @@ const x86_64 = struct {
14861469 }
14871470
14881471 fn encode(insts: []const Instruction, code: []u8) !void {
1489 var stream: std.io.Writer = .fixed(code);
1490 for (insts) |inst| try inst.encode(&stream, .{});
1472 var writer: Writer = .fixed(code);
1473 for (insts) |inst| try inst.encode(&writer, .{});
14911474 }
14921475
14931476 const bits = @import("../../arch/x86_64/bits.zig");
......@@ -1592,14 +1575,12 @@ const aarch64 = struct {
15921575 args: ResolveArgs,
15931576 it: *RelocsIterator,
15941577 code_buffer: []u8,
1595 stream: anytype,
15961578 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
15971579 _ = it;
15981580
15991581 const diags = &elf_file.base.comp.link_diags;
16001582 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
16011583 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1602 const cwriter = stream.writer();
16031584 const code = code_buffer[r_offset..][0..4];
16041585 const file_ptr = atom.file(elf_file).?;
16051586
......@@ -1614,7 +1595,8 @@ const aarch64 = struct {
16141595 rel,
16151596 dynAbsRelocAction(target, elf_file),
16161597 elf_file,
1617 cwriter,
1598 code_buffer,
1599 r_offset,
16181600 );
16191601 },
16201602
......@@ -1782,25 +1764,20 @@ const aarch64 = struct {
17821764 rel: elf.Elf64_Rela,
17831765 target: *const Symbol,
17841766 args: ResolveArgs,
1785 it: *RelocsIterator,
17861767 code: []u8,
1787 stream: anytype,
17881768 ) !void {
1789 _ = it;
1790 _ = code;
1791
17921769 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1793 const cwriter = stream.writer();
17941770
17951771 _, const A, const S, _, _, _, _ = args;
17961772
1773 var writer: Writer = .fixed(code);
17971774 switch (r_type) {
17981775 .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),
18001777 .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
1801 try cwriter.writeInt(u64, value, .little)
1778 try writer.writeInt(u64, value, .little)
18021779 else
1803 try cwriter.writeInt(i64, S + A, .little),
1780 try writer.writeInt(i64, S + A, .little),
18041781 else => try atom.reportUnhandledRelocError(rel, elf_file),
18051782 }
18061783 }
......@@ -1861,12 +1838,10 @@ const riscv = struct {
18611838 args: ResolveArgs,
18621839 it: *RelocsIterator,
18631840 code: []u8,
1864 stream: anytype,
18651841 ) !void {
18661842 const diags = &elf_file.base.comp.link_diags;
18671843 const r_type: elf.R_RISCV = @enumFromInt(rel.r_type());
18681844 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1869 const cwriter = stream.writer();
18701845
18711846 const P, const A, const S, const GOT, const G, const TP, const DTP = args;
18721847 _ = TP;
......@@ -1875,7 +1850,7 @@ const riscv = struct {
18751850 switch (r_type) {
18761851 .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
18801855 .@"64" => {
18811856 try atom.resolveDynAbsReloc(
......@@ -1883,7 +1858,8 @@ const riscv = struct {
18831858 rel,
18841859 dynAbsRelocAction(target, elf_file),
18851860 elf_file,
1886 cwriter,
1861 code,
1862 r_offset,
18871863 );
18881864 },
18891865
......@@ -1997,15 +1973,9 @@ const riscv = struct {
19971973 rel: elf.Elf64_Rela,
19981974 target: *const Symbol,
19991975 args: ResolveArgs,
2000 it: *RelocsIterator,
20011976 code: []u8,
2002 stream: anytype,
20031977 ) !void {
2004 _ = it;
2005
20061978 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
20101980 _, const A, const S, const GOT, _, _, const DTP = args;
20111981 _ = GOT;
......@@ -2014,30 +1984,29 @@ const riscv = struct {
20141984 switch (r_type) {
20151985 .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),
20181988 .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value|
2019 try cwriter.writeInt(u64, value, .little)
1989 mem.writeInt(u64, code[0..8], value, .little)
20201990 else
2021 try cwriter.writeInt(i64, S + A, .little),
2022
2023 .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A),
2024 .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A),
2025 .ADD16 => riscv_util.writeAddend(i16, .add, code[r_offset..][0..2], S + A),
2026 .SUB16 => riscv_util.writeAddend(i16, .sub, code[r_offset..][0..2], S + A),
2027 .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A),
2028 .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A),
2029 .ADD64 => riscv_util.writeAddend(i64, .add, code[r_offset..][0..8], S + A),
2030 .SUB64 => riscv_util.writeAddend(i64, .sub, code[r_offset..][0..8], S + A),
2031
2032 .SET8 => mem.writeInt(i8, code[r_offset..][0..1], @as(i8, @truncate(S + A)), .little),
2033 .SET16 => mem.writeInt(i16, code[r_offset..][0..2], @as(i16, @truncate(S + A)), .little),
2034 .SET32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little),
2035
2036 .SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A),
2037 .SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A),
2038
2039 .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A),
2040 .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A),
1991 mem.writeInt(i64, code[0..8], S + A, .little),
1992 .ADD8 => riscv_util.writeAddend(i8, .add, code[0..1], S + A),
1993 .SUB8 => riscv_util.writeAddend(i8, .sub, code[0..1], S + A),
1994 .ADD16 => riscv_util.writeAddend(i16, .add, code[0..2], S + A),
1995 .SUB16 => riscv_util.writeAddend(i16, .sub, code[0..2], S + A),
1996 .ADD32 => riscv_util.writeAddend(i32, .add, code[0..4], S + A),
1997 .SUB32 => riscv_util.writeAddend(i32, .sub, code[0..4], S + A),
1998 .ADD64 => riscv_util.writeAddend(i64, .add, code[0..8], S + A),
1999 .SUB64 => riscv_util.writeAddend(i64, .sub, code[0..8], S + A),
2000
2001 .SET8 => mem.writeInt(i8, code[0..1], @as(i8, @truncate(S + A)), .little),
2002 .SET16 => mem.writeInt(i16, code[0..2], @as(i16, @truncate(S + A)), .little),
2003 .SET32 => mem.writeInt(i32, code[0..4], @as(i32, @truncate(S + A)), .little),
2004
2005 .SET6 => riscv_util.writeSetSub6(.set, code[0..1], S + A),
2006 .SUB6 => riscv_util.writeSetSub6(.sub, code[0..1], S + A),
2007
2008 .SET_ULEB128 => riscv_util.writeSetUleb(code, S + A),
2009 .SUB_ULEB128 => riscv_util.writeSubUleb(code, S - A),
20412010
20422011 else => try atom.reportUnhandledRelocError(rel, elf_file),
20432012 }
......@@ -2108,14 +2077,16 @@ pub const Extra = struct {
21082077const std = @import("std");
21092078const assert = std.debug.assert;
21102079const elf = std.elf;
2111const eh_frame = @import("eh_frame.zig");
21122080const log = std.log.scoped(.link);
21132081const math = std.math;
21142082const mem = std.mem;
21152083const relocs_log = std.log.scoped(.link_relocs);
2084const Allocator = mem.Allocator;
2085const Writer = std.Io.Writer;
2086
2087const eh_frame = @import("eh_frame.zig");
21162088const relocation = @import("relocation.zig");
21172089
2118const Allocator = mem.Allocator;
21192090const Atom = @This();
21202091const Elf = @import("../Elf.zig");
21212092const Fde = eh_frame.Fde;
src/link/Elf/AtomList.zig+4-5
......@@ -89,7 +89,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void {
8989 list.dirty = false;
9090}
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 {
9393 const gpa = elf_file.base.comp.gpa;
9494 const osec = elf_file.sections.items(.shdr)[list.output_section_index];
9595 assert(osec.sh_type != elf.SHT_NOBITS);
......@@ -98,8 +98,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp
9898 log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)});
9999
100100 const list_size = math.cast(usize, list.size) orelse return error.Overflow;
101 try buffer.ensureUnusedCapacity(list_size);
102 buffer.appendNTimesAssumeCapacity(0, list_size);
101 try buffer.writer.splatByteAll(0, list_size);
103102
104103 for (list.atoms.keys()) |ref| {
105104 const atom_ptr = elf_file.atom(ref).?;
......@@ -113,7 +112,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp
113112 const object = atom_ptr.file(elf_file).?.object;
114113 const code = try object.codeDecompressAlloc(elf_file, ref.index);
115114 defer gpa.free(code);
116 const out_code = buffer.items[off..][0..size];
115 const out_code = buffer.written()[off..][0..size];
117116 @memcpy(out_code, code);
118117
119118 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
122121 try atom_ptr.resolveRelocsAlloc(elf_file, out_code);
123122 }
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));
126125 buffer.clearRetainingCapacity();
127126}
128127
src/link/Elf/Object.zig+1-1
......@@ -952,7 +952,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
952952 const is_tls = sym.type(elf_file) == elf.STT_TLS;
953953 const name = if (is_tls) ".tls_common" else ".common";
954954 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
957957 var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
958958 if (is_tls) sh_flags |= elf.SHF_TLS;
src/link/Elf/gc.zig-16
......@@ -162,22 +162,6 @@ fn prune(elf_file: *Elf) void {
162162 }
163163}
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
181165const Level = struct {
182166 value: usize = 0,
183167
src/link/Elf/relocatable.zig+24-21
......@@ -100,32 +100,33 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
100100 state_log.debug("ar_strtab\n{f}\n", .{ar_strtab});
101101 }
102102
103 var buffer = std.array_list.Managed(u8).init(gpa);
104 defer buffer.deinit();
105 try buffer.ensureTotalCapacityPrecise(total_size);
103 const buffer = try gpa.alloc(u8, total_size);
104 defer gpa.free(buffer);
105
106 var writer: std.Io.Writer = .fixed(buffer);
106107
107108 // Write magic
108 try buffer.writer().writeAll(elf.ARMAG);
109 try writer.writeAll(elf.ARMAG);
109110
110111 // Write symtab
111 try ar_symtab.write(.p64, elf_file, buffer.writer());
112 try ar_symtab.write(.p64, elf_file, &writer);
112113
113114 // Write strtab
114115 if (ar_strtab.size() > 0) {
115 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);
116 try ar_strtab.write(buffer.writer());
116 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
117 try ar_strtab.write(&writer);
117118 }
118119
119120 // Write object files
120121 for (files.items) |index| {
121 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);
122 try elf_file.file(index).?.writeAr(elf_file, buffer.writer());
122 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
123 try elf_file.file(index).?.writeAr(elf_file, &writer);
123124 }
124125
125 assert(buffer.items.len == total_size);
126 assert(writer.buffered().len == total_size);
126127
127128 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
130131 if (diags.hasErrors()) return error.LinkFailure;
131132}
......@@ -407,15 +408,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
407408 };
408409 const shdr = slice.items(.shdr)[shndx];
409410 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 defer buffer.deinit();
412 try eh_frame.writeEhFrameRelocatable(elf_file, buffer.writer());
411 const buffer = try gpa.alloc(u8, @intCast(sh_size - existing_size));
412 defer gpa.free(buffer);
413 var writer: std.Io.Writer = .fixed(buffer);
414 try eh_frame.writeEhFrameRelocatable(elf_file, &writer);
413415 log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{
414416 shdr.sh_offset + existing_size,
415417 shdr.sh_offset + sh_size,
416418 });
417 assert(buffer.items.len == sh_size - existing_size);
418 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
419 assert(writer.buffered().len == sh_size - existing_size);
420 try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset + existing_size);
419421 }
420422 if (elf_file.section_indexes.eh_frame_rela) |shndx| {
421423 const shdr = slice.items(.shdr)[shndx];
......@@ -446,15 +448,16 @@ fn writeGroups(elf_file: *Elf) !void {
446448 for (elf_file.group_sections.items) |cgs| {
447449 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];
448450 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);
450 defer buffer.deinit();
451 try cgs.write(elf_file, buffer.writer());
452 assert(buffer.items.len == sh_size);
451 const buffer = try gpa.alloc(u8, sh_size);
452 defer gpa.free(buffer);
453 var writer: std.Io.Writer = .fixed(buffer);
454 try cgs.write(elf_file, &writer);
455 assert(writer.buffered().len == sh_size);
453456 log.debug("writing group from 0x{x} to 0x{x}", .{
454457 shdr.sh_offset,
455458 shdr.sh_offset + shdr.sh_size,
456459 });
457 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
460 try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset);
458461 }
459462}
460463
src/link/Elf/synthetic_sections.zig+53-51
......@@ -94,134 +94,134 @@ pub const DynamicSection = struct {
9494 return nentries * @sizeOf(elf.Elf64_Dyn);
9595 }
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 {
9898 const shdrs = elf_file.sections.items(.shdr);
9999
100100 // NEEDED
101101 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);
103103 }
104104
105105 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);
107107 }
108108
109109 // RUNPATH
110110 // TODO add option in Options to revert to old RPATH tag
111111 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);
113113 }
114114
115115 // INIT
116116 if (elf_file.sectionByName(".init")) |shndx| {
117117 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);
119119 }
120120
121121 // FINI
122122 if (elf_file.sectionByName(".fini")) |shndx| {
123123 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);
125125 }
126126
127127 // INIT_ARRAY
128128 if (elf_file.sectionByName(".init_array")) |shndx| {
129129 const shdr = shdrs[shndx];
130 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });
131 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });
130 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }), .little);
131 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }), .little);
132132 }
133133
134134 // FINI_ARRAY
135135 if (elf_file.sectionByName(".fini_array")) |shndx| {
136136 const shdr = shdrs[shndx];
137 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });
138 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });
137 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }), .little);
138 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }), .little);
139139 }
140140
141141 // RELA
142142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143143 const shdr = shdrs[shndx];
144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
146 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });
144 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }), .little);
145 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }), .little);
146 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }), .little);
147147 }
148148
149149 // JMPREL
150150 if (elf_file.section_indexes.rela_plt) |shndx| {
151151 const shdr = shdrs[shndx];
152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
154 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });
152 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }), .little);
153 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }), .little);
154 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }), .little);
155155 }
156156
157157 // PLTGOT
158158 if (elf_file.section_indexes.got_plt) |shndx| {
159159 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);
161161 }
162162
163163 {
164164 assert(elf_file.section_indexes.hash != null);
165165 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);
167167 }
168168
169169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170170 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);
172172 }
173173
174174 // TEXTREL
175175 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);
177177 }
178178
179179 // SYMTAB + SYMENT
180180 {
181181 assert(elf_file.section_indexes.dynsymtab != null);
182182 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 });
184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
183 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }), .little);
184 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }), .little);
185185 }
186186
187187 // STRTAB + STRSZ
188188 {
189189 assert(elf_file.section_indexes.dynstrtab != null);
190190 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 });
192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
191 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }), .little);
192 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }), .little);
193193 }
194194
195195 // VERSYM
196196 if (elf_file.section_indexes.versym) |shndx| {
197197 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);
199199 }
200200
201201 // VERNEED + VERNEEDNUM
202202 if (elf_file.section_indexes.verneed) |shndx| {
203203 const addr = shdrs[shndx].sh_addr;
204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
205 try writer.writeStruct(elf.Elf64_Dyn{
204 try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERNEED, .d_val = addr }), .little);
205 try writer.writeStruct(@as(elf.Elf64_Dyn, .{
206206 .d_tag = elf.DT_VERNEEDNUM,
207207 .d_val = elf_file.verneed.verneed.items.len,
208 });
208 }), .little);
209209 }
210210
211211 // FLAGS
212212 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);
214214 }
215215 // FLAGS_1
216216 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);
218218 }
219219
220220 // 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
223223 // 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);
225225 }
226226};
227227
......@@ -360,7 +360,7 @@ pub const GotSection = struct {
360360 return s;
361361 }
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 {
364364 const comp = elf_file.base.comp;
365365 const is_dyn_lib = elf_file.isEffectivelyDynLib();
366366 const apply_relocs = true; // TODO add user option for this
......@@ -666,7 +666,7 @@ pub const PltSection = struct {
666666 };
667667 }
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 {
670670 const cpu_arch = elf_file.getTarget().cpu.arch;
671671 switch (cpu_arch) {
672672 .x86_64 => try x86_64.write(plt, elf_file, writer),
......@@ -763,7 +763,7 @@ pub const PltSection = struct {
763763 }
764764
765765 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 {
767767 const shdrs = elf_file.sections.items(.shdr);
768768 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
769769 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
......@@ -778,7 +778,7 @@ pub const PltSection = struct {
778778 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
779779 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
780780 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
783783 for (plt.symbols.items, 0..) |ref, i| {
784784 const sym = elf_file.symbol(ref).?;
......@@ -798,7 +798,7 @@ pub const PltSection = struct {
798798 };
799799
800800 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 {
802802 {
803803 const shdrs = elf_file.sections.items(.shdr);
804804 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
......@@ -853,7 +853,7 @@ pub const GotPltSection = struct {
853853 return preamble_size + elf_file.plt.symbols.items.len * 8;
854854 }
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 {
857857 _ = got_plt;
858858 {
859859 // [0]: _DYNAMIC
......@@ -904,7 +904,7 @@ pub const PltGotSection = struct {
904904 };
905905 }
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 {
908908 const cpu_arch = elf_file.getTarget().cpu.arch;
909909 switch (cpu_arch) {
910910 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
......@@ -940,7 +940,7 @@ pub const PltGotSection = struct {
940940 }
941941
942942 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 {
944944 for (plt_got.symbols.items) |ref| {
945945 const sym = elf_file.symbol(ref).?;
946946 const target_addr = sym.gotAddress(elf_file);
......@@ -958,7 +958,7 @@ pub const PltGotSection = struct {
958958 };
959959
960960 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 {
962962 for (plt_got.symbols.items) |ref| {
963963 const sym = elf_file.symbol(ref).?;
964964 const target_addr = sym.gotAddress(elf_file);
......@@ -1133,14 +1133,14 @@ pub const DynsymSection = struct {
11331133 return @as(u32, @intCast(dynsym.entries.items.len + 1));
11341134 }
11351135
1136 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void {
1137 try writer.writeStruct(Elf.null_sym);
1136 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: *std.Io.Writer) !void {
1137 try writer.writeStruct(Elf.null_sym, .little);
11381138 for (dynsym.entries.items) |entry| {
11391139 const sym = elf_file.symbol(entry.ref).?;
11401140 var out_sym: elf.Elf64_Sym = Elf.null_sym;
11411141 sym.setOutputSym(elf_file, &out_sym);
11421142 out_sym.st_name = entry.off;
1143 try writer.writeStruct(out_sym);
1143 try writer.writeStruct(out_sym, .little);
11441144 }
11451145 }
11461146};
......@@ -1175,10 +1175,12 @@ pub const HashSection = struct {
11751175 }
11761176
11771177 try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4);
1178 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1179 hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1180 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(buckets)) catch unreachable;
1181 hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(chains)) catch unreachable;
1178 var w: std.Io.Writer = .fixed(hs.buffer.unusedCapacitySlice());
1179 w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1180 w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable;
1181 w.writeAll(@ptrCast(buckets)) catch unreachable;
1182 w.writeAll(@ptrCast(chains)) catch unreachable;
1183 hs.buffer.items.len += w.end;
11821184 }
11831185
11841186 pub inline fn size(hs: HashSection) usize {
......@@ -1439,7 +1441,7 @@ pub const VerneedSection = struct {
14391441 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);
14401442 }
14411443
1442 pub fn write(vern: VerneedSection, writer: anytype) !void {
1444 pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
14431445 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));
14441446 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));
14451447 }
......@@ -1467,7 +1469,7 @@ pub const GroupSection = struct {
14671469 return (members.len + 1) * @sizeOf(u32);
14681470 }
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 {
14711473 const cg = cgs.group(elf_file);
14721474 const object = cg.file(elf_file).object;
14731475 const members = cg.members(elf_file);
......@@ -1495,7 +1497,7 @@ pub const GroupSection = struct {
14951497 }
14961498};
14971499
1498fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
1500fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void {
14991501 const entry_size = elf_file.archPtrWidthBytes();
15001502 const target = elf_file.getTarget();
15011503 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
99 mem.writeInt(u8, code, value, .little);
1010}
1111
12pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void {
13 switch (op) {
14 .set => try overwriteUleb(stream, @intCast(addend)),
15 .sub => {
16 const position = try stream.getPos();
17 const value: u64 = try std.leb.readUleb128(u64, stream.reader());
18 try stream.seekTo(position);
19 try overwriteUleb(stream, value -% @as(u64, @intCast(addend)));
20 },
21 }
12pub fn writeSubUleb(code: []u8, addend: i64) void {
13 var reader: std.Io.Reader = .fixed(code);
14 const value = reader.takeLeb128(u64) catch unreachable;
15 overwriteUleb(code, value -% @as(u64, @intCast(addend)));
16}
17
18pub fn writeSetUleb(code: []u8, addend: i64) void {
19 overwriteUleb(code, @intCast(addend));
2220}
2321
24fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void {
22fn overwriteUleb(code: []u8, addend: u64) void {
2523 var value: u64 = addend;
26 const writer = stream.writer();
24 var i: usize = 0;
2725
2826 while (true) {
29 const byte = stream.buffer[stream.pos];
27 const byte = code[i];
3028 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;
3231 value >>= 7;
3332 }
34 stream.buffer[stream.pos] = @truncate(value & 0x7f);
33 code[i] = @truncate(value & 0x7f);
3534}
3635
3736pub fn writeAddend(