Commit 6713745ec4
Changed files (9)
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;
}
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;
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();
}
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,
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;
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);
}
}
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();
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;
}
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(