diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-08-16 20:01:30 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-08-28 18:30:57 -0700 |
| commit | 6713745ec4f76d133eb0d5066c40bba666d0a194 (patch) | |
| tree | e8cb329a553013770558429031ba7b03d9c444f5 | |
| parent | cc931660eb3e5b7251944c727808aa36e72c1e52 (diff) | |
| download | zig-6713745ec4f76d133eb0d5066c40bba666d0a194.tar.gz zig-6713745ec4f76d133eb0d5066c40bba666d0a194.zip | |
link.Elf: update to not use GenericWriter
| -rw-r--r-- | src/link/Elf.zig | 72 | ||||
| -rw-r--r-- | src/link/Elf/Archive.zig | 9 | ||||
| -rw-r--r-- | src/link/Elf/Atom.zig | 255 | ||||
| -rw-r--r-- | src/link/Elf/AtomList.zig | 9 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/gc.zig | 16 | ||||
| -rw-r--r-- | src/link/Elf/relocatable.zig | 45 | ||||
| -rw-r--r-- | src/link/Elf/synthetic_sections.zig | 104 | ||||
| -rw-r--r-- | src/link/riscv.zig | 29 |
9 files changed, 247 insertions, 294 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 0ebbb9f27e..9cf2b0e074 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -811,10 +811,6 @@ fn flushInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void { if (self.base.gc_sections) { try gc.gcAtoms(self); - - if (self.base.print_gc_sections) { - try gc.dumpPrunedAtoms(self); - } } self.checkDuplicates() catch |err| switch (err) { @@ -3005,7 +3001,7 @@ fn writeAtoms(self: *Elf) !void { undefs.deinit(); } - var buffer = std.array_list.Managed(u8).init(gpa); + var buffer: std.Io.Writer.Allocating = .init(gpa); defer buffer.deinit(); const slice = self.sections.slice(); @@ -3032,9 +3028,9 @@ fn writeAtoms(self: *Elf) !void { try buffer.ensureUnusedCapacity(thunk_size); const shdr = slice.items(.shdr)[th.output_section_index]; const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; - try th.write(self, buffer.writer()); - assert(buffer.items.len == thunk_size); - try self.pwriteAll(buffer.items, offset); + try th.write(self, &buffer.writer); + assert(buffer.written().len == thunk_size); + try self.pwriteAll(buffer.written(), offset); buffer.clearRetainingCapacity(); } } @@ -3166,26 +3162,26 @@ fn writeSyntheticSections(self: *Elf) !void { if (self.section_indexes.verneed) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.verneed.size()); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.verneed.size()); defer buffer.deinit(); - try self.verneed.write(buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.verneed.write(&buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.dynamic) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynamic.size(self)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynamic.size(self)); defer buffer.deinit(); - try self.dynamic.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.dynamic.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.dynsymtab) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.dynsym.size()); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.dynsym.size()); defer buffer.deinit(); - try self.dynsym.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.dynsym.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.dynstrtab) |shndx| { @@ -3201,28 +3197,28 @@ fn writeSyntheticSections(self: *Elf) !void { }; const shdr = slice.items(.shdr)[shndx]; const sh_size = try self.cast(usize, shdr.sh_size); - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, @intCast(sh_size - existing_size)); defer buffer.deinit(); - try eh_frame.writeEhFrame(self, buffer.writer()); - assert(buffer.items.len == sh_size - existing_size); - try self.pwriteAll(buffer.items, shdr.sh_offset + existing_size); + try eh_frame.writeEhFrame(self, &buffer.writer); + assert(buffer.written().len == sh_size - existing_size); + try self.pwriteAll(buffer.written(), shdr.sh_offset + existing_size); } if (self.section_indexes.eh_frame_hdr) |shndx| { const shdr = slice.items(.shdr)[shndx]; const sh_size = try self.cast(usize, shdr.sh_size); - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, sh_size); defer buffer.deinit(); - try eh_frame.writeEhFrameHdr(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try eh_frame.writeEhFrameHdr(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.got) |index| { const shdr = slice.items(.shdr)[index]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got.size(self)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got.size(self)); defer buffer.deinit(); - try self.got.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.got.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.rela_dyn) |shndx| { @@ -3235,26 +3231,26 @@ fn writeSyntheticSections(self: *Elf) !void { if (self.section_indexes.plt) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt.size(self)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt.size(self)); defer buffer.deinit(); - try self.plt.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.plt.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.got_plt) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.got_plt.size(self)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.got_plt.size(self)); defer buffer.deinit(); - try self.got_plt.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.got_plt.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.plt_got) |shndx| { const shdr = slice.items(.shdr)[shndx]; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.plt_got.size(self)); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.plt_got.size(self)); defer buffer.deinit(); - try self.plt_got.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, shdr.sh_offset); + try self.plt_got.write(self, &buffer.writer); + try self.pwriteAll(buffer.written(), shdr.sh_offset); } if (self.section_indexes.rela_plt) |shndx| { @@ -3757,7 +3753,7 @@ pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { const gpa = self.base.comp.gpa; const off = @as(u32, @intCast(self.shstrtab.items.len)); try self.shstrtab.ensureUnusedCapacity(gpa, name.len + 1); - self.shstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; + self.shstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable; return off; } @@ -3770,7 +3766,7 @@ pub fn insertDynString(self: *Elf, name: []const u8) error{OutOfMemory}!u32 { const gpa = self.base.comp.gpa; const off = @as(u32, @intCast(self.dynstrtab.items.len)); try self.dynstrtab.ensureUnusedCapacity(gpa, name.len + 1); - self.dynstrtab.writer(gpa).print("{s}\x00", .{name}) catch unreachable; + self.dynstrtab.print(gpa, "{s}\x00", .{name}) catch unreachable; return off; } diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index 2243dc4781..b0f7ca2971 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -123,8 +123,7 @@ pub fn setArHdr(opts: struct { @memcpy(&hdr.ar_fmag, elf.ARFMAG); { - var stream = std.io.fixedBufferStream(&hdr.ar_name); - const writer = stream.writer(); + var writer: std.Io.Writer = .fixed(&hdr.ar_name); switch (opts.name) { .symtab => writer.print("{s}", .{elf.SYM64NAME}) catch unreachable, .strtab => writer.print("//", .{}) catch unreachable, @@ -133,8 +132,8 @@ pub fn setArHdr(opts: struct { } } { - var stream = std.io.fixedBufferStream(&hdr.ar_size); - stream.writer().print("{d}", .{opts.size}) catch unreachable; + var writer: std.Io.Writer = .fixed(&hdr.ar_size); + writer.print("{d}", .{opts.size}) catch unreachable; } return hdr; @@ -246,7 +245,7 @@ pub const ArStrtab = struct { pub fn insert(ar: *ArStrtab, allocator: Allocator, name: []const u8) error{OutOfMemory}!u32 { const off = @as(u32, @intCast(ar.buffer.items.len)); - try ar.buffer.writer(allocator).print("{s}/{c}", .{ name, strtab_delimiter }); + try ar.buffer.print(allocator, "{s}/{c}", .{ name, strtab_delimiter }); return off; } diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 28899838b1..6bfaddea97 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -621,7 +621,6 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi const cpu_arch = elf_file.getTarget().cpu.arch; const file_ptr = self.file(elf_file).?; - var stream = std.io.fixedBufferStream(code); const rels = self.relocs(elf_file); var it = RelocsIterator{ .relocs = rels }; @@ -661,20 +660,16 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi target.name(elf_file), }); - try stream.seekTo(r_offset); - const args = ResolveArgs{ P, A, S, GOT, G, TP, DTP }; switch (cpu_arch) { - .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .x86_64 => x86_64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { error.RelocFailure, error.RelaxFailure, - error.InvalidInstruction, - error.CannotEncode, => has_reloc_errors = true, else => |e| return e, }, - .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .aarch64, .aarch64_be => aarch64.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { error.RelocFailure, error.RelaxFailure, error.UnexpectedRemainder, @@ -682,7 +677,7 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi => has_reloc_errors = true, else => |e| return e, }, - .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .riscv64, .riscv64be => riscv.resolveRelocAlloc(self, elf_file, rel, target, args, &it, code) catch |err| switch (err) { error.RelocFailure, error.RelaxFailure, => has_reloc_errors = true, @@ -701,7 +696,8 @@ fn resolveDynAbsReloc( rel: elf.Elf64_Rela, action: RelocAction, elf_file: *Elf, - writer: anytype, + code: []u8, + r_offset: usize, ) !void { const comp = elf_file.base.comp; const gpa = comp.gpa; @@ -726,7 +722,7 @@ fn resolveDynAbsReloc( .copyrel, .cplt, .none, - => try writer.writeInt(i64, S + A, .little), + => mem.writeInt(i64, code[r_offset..][0..8], S + A, .little), .dyn_copyrel => { if (is_writeable or elf_file.z_nocopyreloc) { @@ -737,9 +733,9 @@ fn resolveDynAbsReloc( .addend = A, .target = target, }); - try applyDynamicReloc(A, elf_file, writer); + applyDynamicReloc(A, code, r_offset); } else { - try writer.writeInt(i64, S + A, .little); + mem.writeInt(i64, code[r_offset..][0..8], S + A, .little); } }, @@ -752,9 +748,9 @@ fn resolveDynAbsReloc( .addend = A, .target = target, }); - try applyDynamicReloc(A, elf_file, writer); + applyDynamicReloc(A, code, r_offset); } else { - try writer.writeInt(i64, S + A, .little); + mem.writeInt(i64, code[r_offset..][0..8], S + A, .little); } }, @@ -766,7 +762,7 @@ fn resolveDynAbsReloc( .addend = A, .target = target, }); - try applyDynamicReloc(A, elf_file, writer); + applyDynamicReloc(A, code, r_offset); }, .baserel => { @@ -776,7 +772,7 @@ fn resolveDynAbsReloc( .addend = S + A, .target = target, }); - try applyDynamicReloc(S + A, elf_file, writer); + applyDynamicReloc(S + A, code, r_offset); }, .ifunc => { @@ -787,16 +783,13 @@ fn resolveDynAbsReloc( .addend = S_ + A, .target = target, }); - try applyDynamicReloc(S_ + A, elf_file, writer); + applyDynamicReloc(S_ + A, code, r_offset); }, } } -fn applyDynamicReloc(value: i64, elf_file: *Elf, writer: anytype) !void { - _ = elf_file; - // if (elf_file.options.apply_dynamic_relocs) { - try writer.writeInt(i64, value, .little); - // } +fn applyDynamicReloc(value: i64, code: []u8, r_offset: usize) void { + mem.writeInt(i64, code[r_offset..][0..8], value, .little); } pub 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 const cpu_arch = elf_file.getTarget().cpu.arch; const file_ptr = self.file(elf_file).?; - var stream = std.io.fixedBufferStream(code); const rels = self.relocs(elf_file); var has_reloc_errors = false; @@ -863,18 +855,16 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any target.name(elf_file), }); - try stream.seekTo(r_offset); - switch (cpu_arch) { - .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .x86_64 => x86_64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .aarch64, .aarch64_be => aarch64.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, - .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, &it, code, &stream) catch |err| switch (err) { + .riscv64, .riscv64be => riscv.resolveRelocNonAlloc(self, elf_file, rel, target, args, code[r_offset..]) catch |err| switch (err) { error.RelocFailure => has_reloc_errors = true, else => |e| return e, }, @@ -915,7 +905,7 @@ const Format = struct { atom: Atom, elf_file: *Elf, - fn default(f: Format, w: *std.io.Writer) std.io.Writer.Error!void { + fn default(f: Format, w: *Writer) Writer.Error!void { const atom = f.atom; const elf_file = f.elf_file; 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 { args: ResolveArgs, it: *RelocsIterator, code: []u8, - stream: anytype, - ) (error{ InvalidInstruction, CannotEncode } || RelocError)!void { + ) !void { dev.check(.x86_64_backend); const t = &elf_file.base.comp.root_mod.resolved_target.result; const diags = &elf_file.base.comp.link_diags; const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; - const cwriter = stream.writer(); - const P, const A, const S, const GOT, const G, const TP, const DTP = args; switch (r_type) { @@ -1089,58 +1076,60 @@ const x86_64 = struct { rel, dynAbsRelocAction(target, elf_file), elf_file, - cwriter, + code, + r_offset, ); }, - .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), - .PC32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), + .PLT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little), + .PC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little), - .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), - .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), - .GOTPC64 => try cwriter.writeInt(i64, GOT + A - P, .little), + .GOTPCREL => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little), + .GOTPC32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(GOT + A - P)), .little), + .GOTPC64 => mem.writeInt(i64, code[r_offset..][0..8], GOT + A - P, .little), .GOTPCRELX => { if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk; - try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little); return; } - try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little); }, .REX_GOTPCRELX => { if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: { x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk; - try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S + A - P)), .little); return; } - try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + GOT + A - P)), .little); }, - .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), - .@"32S" => try cwriter.writeInt(i32, @as(i32, @truncate(S + A)), .little), + .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), + .@"32S" => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little), - .TPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - TP)), .little), - .TPOFF64 => try cwriter.writeInt(i64, S + A - TP, .little), + .TPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - TP)), .little), + .TPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - TP, .little), - .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @truncate(S + A - DTP)), .little), - .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), + .DTPOFF32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A - DTP)), .little), + .DTPOFF64 => mem.writeInt(i64, code[r_offset..][0..8], S + A - DTP, .little), .TLSGD => { if (target.flags.has_tlsgd) { const S_ = target.tlsGdAddress(elf_file); - try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); } else if (target.flags.has_gottp) { const S_ = target.gotTpAddress(elf_file); - try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream); + try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, code, r_offset); } else { try x86_64.relaxTlsGdToLe( atom, &.{ rel, it.next().? }, @as(i32, @intCast(S - TP)), elf_file, - stream, + code, + r_offset, ); } }, @@ -1149,14 +1138,15 @@ const x86_64 = struct { if (elf_file.got.tlsld_index) |entry_index| { const tlsld_entry = elf_file.got.entries.items[entry_index]; const S_ = tlsld_entry.address(elf_file); - try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); } else { try x86_64.relaxTlsLdToLe( atom, &.{ rel, it.next().? }, @as(i32, @intCast(TP - elf_file.tlsAddress())), elf_file, - stream, + code, + r_offset, ); } }, @@ -1164,7 +1154,7 @@ const x86_64 = struct { .GOTPC32_TLSDESC => { if (target.flags.has_tlsdesc) { const S_ = target.tlsDescAddress(elf_file); - try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); } else { x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch { var err = try diags.addErrorWithNotes(1); @@ -1176,26 +1166,26 @@ const x86_64 = struct { }); return error.RelaxFailure; }; - try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little); } }, .TLSDESC_CALL => if (!target.flags.has_tlsdesc) { // call -> nop - try cwriter.writeAll(&.{ 0x66, 0x90 }); + code[r_offset..][0..2].* = .{ 0x66, 0x90 }; }, .GOTTPOFF => { if (target.flags.has_gottp) { const S_ = target.gotTpAddress(elf_file); - try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S_ + A - P)), .little); } else { x86_64.relaxGotTpOff(code[r_offset - 3 ..], t); - try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little); + mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(S - TP)), .little); } }, - .GOT32 => try cwriter.writeInt(i32, @as(i32, @intCast(G + A)), .little), + .GOT32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @intCast(G + A)), .little), else => try atom.reportUnhandledRelocError(rel, elf_file), } @@ -1207,45 +1197,42 @@ const x86_64 = struct { rel: elf.Elf64_Rela, target: *const Symbol, args: ResolveArgs, - it: *RelocsIterator, code: []u8, - stream: anytype, ) !void { dev.check(.x86_64_backend); - _ = code; - _ = it; const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type()); - const cwriter = stream.writer(); _, const A, const S, const GOT, _, _, const DTP = args; + var writer: Writer = .fixed(code); + switch (r_type) { .NONE => unreachable, - .@"8" => try cwriter.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), - .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), - .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), - .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), + .@"8" => try writer.writeInt(u8, @as(u8, @bitCast(@as(i8, @intCast(S + A)))), .little), + .@"16" => try writer.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), + .@"32" => try writer.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), + .@"32S" => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little), .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| - try cwriter.writeInt(u64, value, .little) + try writer.writeInt(u64, value, .little) else - try cwriter.writeInt(i64, S + A, .little), + try writer.writeInt(i64, S + A, .little), .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| - try cwriter.writeInt(u64, value, .little) + try writer.writeInt(u64, value, .little) else - try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), + try writer.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| - try cwriter.writeInt(u64, value, .little) + try writer.writeInt(u64, value, .little) else - try cwriter.writeInt(i64, S + A - DTP, .little), - .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), - .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), + try writer.writeInt(i64, S + A - DTP, .little), + .GOTOFF64 => try writer.writeInt(i64, S + A - GOT, .little), + .GOTPC64 => try writer.writeInt(i64, GOT + A, .little), .SIZE32 => { const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); - try cwriter.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little); + try writer.writeInt(u32, @bitCast(@as(i32, @intCast(size + A))), .little); }, .SIZE64 => { const size = @as(i64, @intCast(target.elfSym(elf_file).st_size)); - try cwriter.writeInt(i64, @intCast(size + A), .little); + try writer.writeInt(i64, @intCast(size + A), .little); }, else => try atom.reportUnhandledRelocError(rel, elf_file), } @@ -1288,12 +1275,12 @@ const x86_64 = struct { rels: []const elf.Elf64_Rela, value: i32, elf_file: *Elf, - stream: anytype, + code: []u8, + r_offset: usize, ) !void { dev.check(.x86_64_backend); assert(rels.len == 2); const diags = &elf_file.base.comp.link_diags; - const writer = stream.writer(); const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); switch (rel) { .PC32, @@ -1304,8 +1291,7 @@ const x86_64 = struct { 0x48, 0x03, 0x05, 0, 0, 0, 0, // add foo@gottpoff(%rip), %rax }; std.mem.writeInt(i32, insts[12..][0..4], value - 12, .little); - try stream.seekBy(-4); - try writer.writeAll(&insts); + @memcpy(code[r_offset - 4 ..][0..insts.len], &insts); }, else => { @@ -1329,12 +1315,12 @@ const x86_64 = struct { rels: []const elf.Elf64_Rela, value: i32, elf_file: *Elf, - stream: anytype, + code: []u8, + r_offset: usize, ) !void { dev.check(.x86_64_backend); assert(rels.len == 2); const diags = &elf_file.base.comp.link_diags; - const writer = stream.writer(); const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); switch (rel) { .PC32, @@ -1346,8 +1332,7 @@ const x86_64 = struct { 0x48, 0x2d, 0, 0, 0, 0, // sub $tls_size, %rax }; std.mem.writeInt(i32, insts[8..][0..4], value, .little); - try stream.seekBy(-3); - try writer.writeAll(&insts); + @memcpy(code[r_offset - 3 ..][0..insts.len], &insts); }, .GOTPCREL, @@ -1360,8 +1345,7 @@ const x86_64 = struct { 0x90, // nop }; std.mem.writeInt(i32, insts[8..][0..4], value, .little); - try stream.seekBy(-3); - try writer.writeAll(&insts); + @memcpy(code[r_offset - 3 ..][0..insts.len], &insts); }, else => { @@ -1390,7 +1374,7 @@ const x86_64 = struct { // TODO: hack to force imm32s in the assembler .{ .imm = .s(-129) }, }, t) catch return false; - var trash: std.io.Writer.Discarding = .init(&.{}); + var trash: Writer.Discarding = .init(&.{}); inst.encode(&trash.writer, .{}) catch return false; return true; }, @@ -1437,12 +1421,12 @@ const x86_64 = struct { rels: []const elf.Elf64_Rela, value: i32, elf_file: *Elf, - stream: anytype, + code: []u8, + r_offset: usize, ) !void { dev.check(.x86_64_backend); assert(rels.len == 2); const diags = &elf_file.base.comp.link_diags; - const writer = stream.writer(); const rel: elf.R_X86_64 = @enumFromInt(rels[1].r_type()); switch (rel) { .PC32, @@ -1455,8 +1439,7 @@ const x86_64 = struct { 0x48, 0x81, 0xc0, 0, 0, 0, 0, // add $tp_offset, %rax }; std.mem.writeInt(i32, insts[12..][0..4], value, .little); - try stream.seekBy(-4); - try writer.writeAll(&insts); + @memcpy(code[r_offset - 4 ..][0..insts.len], &insts); relocs_log.debug(" relaxing {f} and {f}", .{ relocation.fmtRelocType(rels[0].r_type(), .x86_64), relocation.fmtRelocType(rels[1].r_type(), .x86_64), @@ -1486,8 +1469,8 @@ const x86_64 = struct { } fn encode(insts: []const Instruction, code: []u8) !void { - var stream: std.io.Writer = .fixed(code); - for (insts) |inst| try inst.encode(&stream, .{}); + var writer: Writer = .fixed(code); + for (insts) |inst| try inst.encode(&writer, .{}); } const bits = @import("../../arch/x86_64/bits.zig"); @@ -1592,14 +1575,12 @@ const aarch64 = struct { args: ResolveArgs, it: *RelocsIterator, code_buffer: []u8, - stream: anytype, ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { _ = it; const diags = &elf_file.base.comp.link_diags; const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; - const cwriter = stream.writer(); const code = code_buffer[r_offset..][0..4]; const file_ptr = atom.file(elf_file).?; @@ -1614,7 +1595,8 @@ const aarch64 = struct { rel, dynAbsRelocAction(target, elf_file), elf_file, - cwriter, + code_buffer, + r_offset, ); }, @@ -1782,25 +1764,20 @@ const aarch64 = struct { rel: elf.Elf64_Rela, target: *const Symbol, args: ResolveArgs, - it: *RelocsIterator, code: []u8, - stream: anytype, ) !void { - _ = it; - _ = code; - const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); - const cwriter = stream.writer(); _, const A, const S, _, _, _, _ = args; + var writer: Writer = .fixed(code); switch (r_type) { .NONE => unreachable, - .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), + .ABS32 => try writer.writeInt(i32, @as(i32, @intCast(S + A)), .little), .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| - try cwriter.writeInt(u64, value, .little) + try writer.writeInt(u64, value, .little) else - try cwriter.writeInt(i64, S + A, .little), + try writer.writeInt(i64, S + A, .little), else => try atom.reportUnhandledRelocError(rel, elf_file), } } @@ -1861,12 +1838,10 @@ const riscv = struct { args: ResolveArgs, it: *RelocsIterator, code: []u8, - stream: anytype, ) !void { const diags = &elf_file.base.comp.link_diags; const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; - const cwriter = stream.writer(); const P, const A, const S, const GOT, const G, const TP, const DTP = args; _ = TP; @@ -1875,7 +1850,7 @@ const riscv = struct { switch (r_type) { .NONE => unreachable, - .@"32" => try cwriter.writeInt(u32, @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), + .@"32" => mem.writeInt(u32, code[r_offset..][0..4], @as(u32, @truncate(@as(u64, @intCast(S + A)))), .little), .@"64" => { try atom.resolveDynAbsReloc( @@ -1883,7 +1858,8 @@ const riscv = struct { rel, dynAbsRelocAction(target, elf_file), elf_file, - cwriter, + code, + r_offset, ); }, @@ -1997,15 +1973,9 @@ const riscv = struct { rel: elf.Elf64_Rela, target: *const Symbol, args: ResolveArgs, - it: *RelocsIterator, code: []u8, - stream: anytype, ) !void { - _ = it; - const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); - const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; - const cwriter = stream.writer(); _, const A, const S, const GOT, _, _, const DTP = args; _ = GOT; @@ -2014,30 +1984,29 @@ const riscv = struct { switch (r_type) { .NONE => unreachable, - .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), + .@"32" => mem.writeInt(i32, code[0..4], @intCast(S + A), .little), .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| - try cwriter.writeInt(u64, value, .little) + mem.writeInt(u64, code[0..8], value, .little) else - try cwriter.writeInt(i64, S + A, .little), - - .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A), - .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A), - .ADD16 => riscv_util.writeAddend(i16, .add, code[r_offset..][0..2], S + A), - .SUB16 => riscv_util.writeAddend(i16, .sub, code[r_offset..][0..2], S + A), - .ADD32 => riscv_util.writeAddend(i32, .add, code[r_offset..][0..4], S + A), - .SUB32 => riscv_util.writeAddend(i32, .sub, code[r_offset..][0..4], S + A), - .ADD64 => riscv_util.writeAddend(i64, .add, code[r_offset..][0..8], S + A), - .SUB64 => riscv_util.writeAddend(i64, .sub, code[r_offset..][0..8], S + A), - - .SET8 => mem.writeInt(i8, code[r_offset..][0..1], @as(i8, @truncate(S + A)), .little), - .SET16 => mem.writeInt(i16, code[r_offset..][0..2], @as(i16, @truncate(S + A)), .little), - .SET32 => mem.writeInt(i32, code[r_offset..][0..4], @as(i32, @truncate(S + A)), .little), - - .SET6 => riscv_util.writeSetSub6(.set, code[r_offset..][0..1], S + A), - .SUB6 => riscv_util.writeSetSub6(.sub, code[r_offset..][0..1], S + A), - - .SET_ULEB128 => try riscv_util.writeSetSubUleb(.set, stream, S + A), - .SUB_ULEB128 => try riscv_util.writeSetSubUleb(.sub, stream, S - A), + mem.writeInt(i64, code[0..8], S + A, .little), + .ADD8 => riscv_util.writeAddend(i8, .add, code[0..1], S + A), + .SUB8 => riscv_util.writeAddend(i8, .sub, code[0..1], S + A), + .ADD16 => riscv_util.writeAddend(i16, .add, code[0..2], S + A), + .SUB16 => riscv_util.writeAddend(i16, .sub, code[0..2], S + A), + .ADD32 => riscv_util.writeAddend(i32, .add, code[0..4], S + A), + .SUB32 => riscv_util.writeAddend(i32, .sub, code[0..4], S + A), + .ADD64 => riscv_util.writeAddend(i64, .add, code[0..8], S + A), + .SUB64 => riscv_util.writeAddend(i64, .sub, code[0..8], S + A), + + .SET8 => mem.writeInt(i8, code[0..1], @as(i8, @truncate(S + A)), .little), + .SET16 => mem.writeInt(i16, code[0..2], @as(i16, @truncate(S + A)), .little), + .SET32 => mem.writeInt(i32, code[0..4], @as(i32, @truncate(S + A)), .little), + + .SET6 => riscv_util.writeSetSub6(.set, code[0..1], S + A), + .SUB6 => riscv_util.writeSetSub6(.sub, code[0..1], S + A), + + .SET_ULEB128 => riscv_util.writeSetUleb(code, S + A), + .SUB_ULEB128 => riscv_util.writeSubUleb(code, S - A), else => try atom.reportUnhandledRelocError(rel, elf_file), } @@ -2108,14 +2077,16 @@ pub const Extra = struct { const std = @import("std"); const assert = std.debug.assert; const elf = std.elf; -const eh_frame = @import("eh_frame.zig"); const log = std.log.scoped(.link); const math = std.math; const mem = std.mem; const relocs_log = std.log.scoped(.link_relocs); +const Allocator = mem.Allocator; +const Writer = std.Io.Writer; + +const eh_frame = @import("eh_frame.zig"); const relocation = @import("relocation.zig"); -const Allocator = mem.Allocator; const Atom = @This(); const Elf = @import("../Elf.zig"); const Fde = eh_frame.Fde; diff --git a/src/link/Elf/AtomList.zig b/src/link/Elf/AtomList.zig index 0caa69ca90..900a6e32c7 100644 --- a/src/link/Elf/AtomList.zig +++ b/src/link/Elf/AtomList.zig @@ -89,7 +89,7 @@ pub fn allocate(list: *AtomList, elf_file: *Elf) !void { list.dirty = false; } -pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytype, elf_file: *Elf) !void { +pub fn write(list: AtomList, buffer: *std.Io.Writer.Allocating, undefs: anytype, elf_file: *Elf) !void { const gpa = elf_file.base.comp.gpa; const osec = elf_file.sections.items(.shdr)[list.output_section_index]; assert(osec.sh_type != elf.SHT_NOBITS); @@ -98,8 +98,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)}); const list_size = math.cast(usize, list.size) orelse return error.Overflow; - try buffer.ensureUnusedCapacity(list_size); - buffer.appendNTimesAssumeCapacity(0, list_size); + try buffer.writer.splatByteAll(0, list_size); for (list.atoms.keys()) |ref| { const atom_ptr = elf_file.atom(ref).?; @@ -113,7 +112,7 @@ pub fn write(list: AtomList, buffer: *std.array_list.Managed(u8), undefs: anytyp const object = atom_ptr.file(elf_file).?.object; const code = try object.codeDecompressAlloc(elf_file, ref.index); defer gpa.free(code); - const out_code = buffer.items[off..][0..size]; + const out_code = buffer.written()[off..][0..size]; @memcpy(out_code, code); 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 try atom_ptr.resolveRelocsAlloc(elf_file, out_code); } - try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file)); + try elf_file.base.file.?.pwriteAll(buffer.written(), list.offset(elf_file)); buffer.clearRetainingCapacity(); } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 921b5eb733..88e484fcd5 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -952,7 +952,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { const is_tls = sym.type(elf_file) == elf.STT_TLS; const name = if (is_tls) ".tls_common" else ".common"; const name_offset = @as(u32, @intCast(self.strtab.items.len)); - try self.strtab.writer(gpa).print("{s}\x00", .{name}); + try self.strtab.print(gpa, "{s}\x00", .{name}); var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE; if (is_tls) sh_flags |= elf.SHF_TLS; diff --git a/src/link/Elf/gc.zig b/src/link/Elf/gc.zig index 92d80580b8..8778a0846c 100644 --- a/src/link/Elf/gc.zig +++ b/src/link/Elf/gc.zig @@ -162,22 +162,6 @@ fn prune(elf_file: *Elf) void { } } -pub fn dumpPrunedAtoms(elf_file: *Elf) !void { - const stderr = std.fs.File.stderr().deprecatedWriter(); - for (elf_file.objects.items) |index| { - const file = elf_file.file(index).?; - for (file.atoms()) |atom_index| { - const atom = file.atom(atom_index) orelse continue; - if (!atom.alive) - // TODO should we simply print to stderr? - try stderr.print("link: removing unused section '{s}' in file '{f}'\n", .{ - atom.name(elf_file), - atom.file(elf_file).?.fmtPath(), - }); - } - } -} - const Level = struct { value: usize = 0, diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 58f18bd08b..4dd6e0370d 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -100,32 +100,33 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { state_log.debug("ar_strtab\n{f}\n", .{ar_strtab}); } - var buffer = std.array_list.Managed(u8).init(gpa); - defer buffer.deinit(); - try buffer.ensureTotalCapacityPrecise(total_size); + const buffer = try gpa.alloc(u8, total_size); + defer gpa.free(buffer); + + var writer: std.Io.Writer = .fixed(buffer); // Write magic - try buffer.writer().writeAll(elf.ARMAG); + try writer.writeAll(elf.ARMAG); // Write symtab - try ar_symtab.write(.p64, elf_file, buffer.writer()); + try ar_symtab.write(.p64, elf_file, &writer); // Write strtab if (ar_strtab.size() > 0) { - if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); - try ar_strtab.write(buffer.writer()); + if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); + try ar_strtab.write(&writer); } // Write object files for (files.items) |index| { - if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); - try elf_file.file(index).?.writeAr(elf_file, buffer.writer()); + if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); + try elf_file.file(index).?.writeAr(elf_file, &writer); } - assert(buffer.items.len == total_size); + assert(writer.buffered().len == total_size); try elf_file.base.file.?.setEndPos(total_size); - try elf_file.base.file.?.pwriteAll(buffer.items, 0); + try elf_file.base.file.?.pwriteAll(writer.buffered(), 0); if (diags.hasErrors()) return error.LinkFailure; } @@ -407,15 +408,16 @@ fn writeSyntheticSections(elf_file: *Elf) !void { }; const shdr = slice.items(.shdr)[shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); - defer buffer.deinit(); - try eh_frame.writeEhFrameRelocatable(elf_file, buffer.writer()); + const buffer = try gpa.alloc(u8, @intCast(sh_size - existing_size)); + defer gpa.free(buffer); + var writer: std.Io.Writer = .fixed(buffer); + try eh_frame.writeEhFrameRelocatable(elf_file, &writer); log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ shdr.sh_offset + existing_size, shdr.sh_offset + sh_size, }); - assert(buffer.items.len == sh_size - existing_size); - try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); + assert(writer.buffered().len == sh_size - existing_size); + try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset + existing_size); } if (elf_file.section_indexes.eh_frame_rela) |shndx| { const shdr = slice.items(.shdr)[shndx]; @@ -446,15 +448,16 @@ fn writeGroups(elf_file: *Elf) !void { for (elf_file.group_sections.items) |cgs| { const shdr = elf_file.sections.items(.shdr)[cgs.shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, sh_size); - defer buffer.deinit(); - try cgs.write(elf_file, buffer.writer()); - assert(buffer.items.len == sh_size); + const buffer = try gpa.alloc(u8, sh_size); + defer gpa.free(buffer); + var writer: std.Io.Writer = .fixed(buffer); + try cgs.write(elf_file, &writer); + assert(writer.buffered().len == sh_size); log.debug("writing group from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size, }); - try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); + try elf_file.base.file.?.pwriteAll(writer.buffered(), shdr.sh_offset); } } diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index be45937ffe..f0b3798d29 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -94,134 +94,134 @@ pub const DynamicSection = struct { return nentries * @sizeOf(elf.Elf64_Dyn); } - pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(dt: DynamicSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const shdrs = elf_file.sections.items(.shdr); // NEEDED for (dt.needed.items) |off| { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NEEDED, .d_val = off }), .little); } if (dt.soname) |off| { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SONAME, .d_val = off }), .little); } // RUNPATH // TODO add option in Options to revert to old RPATH tag if (dt.rpath > 0) { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath }), .little); } // INIT if (elf_file.sectionByName(".init")) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT, .d_val = addr }), .little); } // FINI if (elf_file.sectionByName(".fini")) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI, .d_val = addr }), .little); } // INIT_ARRAY if (elf_file.sectionByName(".init_array")) |shndx| { const shdr = shdrs[shndx]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }), .little); } // FINI_ARRAY if (elf_file.sectionByName(".fini_array")) |shndx| { const shdr = shdrs[shndx]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }), .little); } // RELA if (elf_file.section_indexes.rela_dyn) |shndx| { const shdr = shdrs[shndx]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }), .little); } // JMPREL if (elf_file.section_indexes.rela_plt) |shndx| { const shdr = shdrs[shndx]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }), .little); } // PLTGOT if (elf_file.section_indexes.got_plt) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_PLTGOT, .d_val = addr }), .little); } { assert(elf_file.section_indexes.hash != null); const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_HASH, .d_val = addr }), .little); } if (elf_file.section_indexes.gnu_hash) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }), .little); } // TEXTREL if (elf_file.has_text_reloc) { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_TEXTREL, .d_val = 0 }), .little); } // SYMTAB + SYMENT { assert(elf_file.section_indexes.dynsymtab != null); const shdr = shdrs[elf_file.section_indexes.dynsymtab.?]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }), .little); } // STRTAB + STRSZ { assert(elf_file.section_indexes.dynstrtab != null); const shdr = shdrs[elf_file.section_indexes.dynstrtab.?]; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }); - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }), .little); } // VERSYM if (elf_file.section_indexes.versym) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERSYM, .d_val = addr }), .little); } // VERNEED + VERNEEDNUM if (elf_file.section_indexes.verneed) |shndx| { const addr = shdrs[shndx].sh_addr; - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); - try writer.writeStruct(elf.Elf64_Dyn{ + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERNEED, .d_val = addr }), .little); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_VERNEEDNUM, .d_val = elf_file.verneed.verneed.items.len, - }); + }), .little); } // FLAGS if (dt.getFlags(elf_file)) |flags| { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS, .d_val = flags }), .little); } // FLAGS_1 if (dt.getFlags1(elf_file)) |flags_1| { - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 }), .little); } // DEBUG - if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 }); + if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_DEBUG, .d_val = 0 }), .little); // NULL - try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 }); + try writer.writeStruct(@as(elf.Elf64_Dyn, .{ .d_tag = elf.DT_NULL, .d_val = 0 }), .little); } }; @@ -360,7 +360,7 @@ pub const GotSection = struct { return s; } - pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(got: GotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const comp = elf_file.base.comp; const is_dyn_lib = elf_file.isEffectivelyDynLib(); const apply_relocs = true; // TODO add user option for this @@ -666,7 +666,7 @@ pub const PltSection = struct { }; } - pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const cpu_arch = elf_file.getTarget().cpu.arch; switch (cpu_arch) { .x86_64 => try x86_64.write(plt, elf_file, writer), @@ -763,7 +763,7 @@ pub const PltSection = struct { } const x86_64 = struct { - fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { + fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const shdrs = elf_file.sections.items(.shdr); const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr; const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr; @@ -778,7 +778,7 @@ pub const PltSection = struct { disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4; mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little); try writer.writeAll(&preamble); - try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len); + try writer.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len); for (plt.symbols.items, 0..) |ref, i| { const sym = elf_file.symbol(ref).?; @@ -798,7 +798,7 @@ pub const PltSection = struct { }; const aarch64 = struct { - fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { + fn write(plt: PltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { { const shdrs = elf_file.sections.items(.shdr); const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr); @@ -853,7 +853,7 @@ pub const GotPltSection = struct { return preamble_size + elf_file.plt.symbols.items.len * 8; } - pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: *std.Io.Writer) !void { _ = got_plt; { // [0]: _DYNAMIC @@ -904,7 +904,7 @@ pub const PltGotSection = struct { }; } - pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const cpu_arch = elf_file.getTarget().cpu.arch; switch (cpu_arch) { .x86_64 => try x86_64.write(plt_got, elf_file, writer), @@ -940,7 +940,7 @@ pub const PltGotSection = struct { } const x86_64 = struct { - pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { for (plt_got.symbols.items) |ref| { const sym = elf_file.symbol(ref).?; const target_addr = sym.gotAddress(elf_file); @@ -958,7 +958,7 @@ pub const PltGotSection = struct { }; const aarch64 = struct { - fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { + fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *std.Io.Writer) !void { for (plt_got.symbols.items) |ref| { const sym = elf_file.symbol(ref).?; const target_addr = sym.gotAddress(elf_file); @@ -1133,14 +1133,14 @@ pub const DynsymSection = struct { return @as(u32, @intCast(dynsym.entries.items.len + 1)); } - pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: anytype) !void { - try writer.writeStruct(Elf.null_sym); + pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: *std.Io.Writer) !void { + try writer.writeStruct(Elf.null_sym, .little); for (dynsym.entries.items) |entry| { const sym = elf_file.symbol(entry.ref).?; var out_sym: elf.Elf64_Sym = Elf.null_sym; sym.setOutputSym(elf_file, &out_sym); out_sym.st_name = entry.off; - try writer.writeStruct(out_sym); + try writer.writeStruct(out_sym, .little); } } }; @@ -1175,10 +1175,12 @@ pub const HashSection = struct { } try hs.buffer.ensureTotalCapacityPrecise(gpa, (2 + nsyms * 2) * 4); - hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; - hs.buffer.writer(gpa).writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; - hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(buckets)) catch unreachable; - hs.buffer.writer(gpa).writeAll(mem.sliceAsBytes(chains)) catch unreachable; + var w: std.Io.Writer = .fixed(hs.buffer.unusedCapacitySlice()); + w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; + w.writeInt(u32, @as(u32, @intCast(nsyms)), .little) catch unreachable; + w.writeAll(@ptrCast(buckets)) catch unreachable; + w.writeAll(@ptrCast(chains)) catch unreachable; + hs.buffer.items.len += w.end; } pub inline fn size(hs: HashSection) usize { @@ -1439,7 +1441,7 @@ pub const VerneedSection = struct { return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux); } - pub fn write(vern: VerneedSection, writer: anytype) !void { + pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void { try writer.writeAll(mem.sliceAsBytes(vern.verneed.items)); try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items)); } @@ -1467,7 +1469,7 @@ pub const GroupSection = struct { return (members.len + 1) * @sizeOf(u32); } - pub fn write(cgs: GroupSection, elf_file: *Elf, writer: anytype) !void { + pub fn write(cgs: GroupSection, elf_file: *Elf, writer: *std.Io.Writer) !void { const cg = cgs.group(elf_file); const object = cg.file(elf_file).object; const members = cg.members(elf_file); @@ -1495,7 +1497,7 @@ pub const GroupSection = struct { } }; -fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void { +fn writeInt(value: anytype, elf_file: *Elf, writer: *std.Io.Writer) !void { const entry_size = elf_file.archPtrWidthBytes(); const target = elf_file.getTarget(); const endian = target.cpu.arch.endian(); diff --git a/src/link/riscv.zig b/src/link/riscv.zig index 31f26b7287..85cc491603 100644 --- a/src/link/riscv.zig +++ b/src/link/riscv.zig @@ -9,29 +9,28 @@ pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytyp mem.writeInt(u8, code, value, .little); } -pub fn writeSetSubUleb(comptime op: enum { set, sub }, stream: *std.io.FixedBufferStream([]u8), addend: i64) !void { - switch (op) { - .set => try overwriteUleb(stream, @intCast(addend)), - .sub => { - const position = try stream.getPos(); - const value: u64 = try std.leb.readUleb128(u64, stream.reader()); - try stream.seekTo(position); - try overwriteUleb(stream, value -% @as(u64, @intCast(addend))); - }, - } +pub fn writeSubUleb(code: []u8, addend: i64) void { + var reader: std.Io.Reader = .fixed(code); + const value = reader.takeLeb128(u64) catch unreachable; + overwriteUleb(code, value -% @as(u64, @intCast(addend))); +} + +pub fn writeSetUleb(code: []u8, addend: i64) void { + overwriteUleb(code, @intCast(addend)); } -fn overwriteUleb(stream: *std.io.FixedBufferStream([]u8), addend: u64) !void { +fn overwriteUleb(code: []u8, addend: u64) void { var value: u64 = addend; - const writer = stream.writer(); + var i: usize = 0; while (true) { - const byte = stream.buffer[stream.pos]; + const byte = code[i]; if (byte & 0x80 == 0) break; - try writer.writeByte(0x80 | @as(u8, @truncate(value & 0x7f))); + code[i] = 0x80 | @as(u8, @truncate(value & 0x7f)); + i += 1; value >>= 7; } - stream.buffer[stream.pos] = @truncate(value & 0x7f); + code[i] = @truncate(value & 0x7f); } pub fn writeAddend( |
