elf: store ar state per input object file

This commit is contained in:
Jakub Konka 2023-11-03 23:08:48 +01:00
parent ed2984f335
commit acd700ac6b
4 changed files with 354 additions and 250 deletions

View File

@ -186,12 +186,6 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}
/// such as `resolver` and `comdat_groups_table`.
strings: StringTable = .{},
/// Static archive state.
/// TODO it may be wise to move it somewhere else, but for the time being, it
/// is far easier to pollute global state.
ar_symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .{},
ar_strtab: StringTable = .{},
/// When allocating, the ideal_capacity is calculated by
/// actual_capacity + (actual_capacity / ideal_factor)
const ideal_factor = 3;
@ -398,9 +392,6 @@ pub fn deinit(self: *Elf) void {
self.copy_rel.deinit(gpa);
self.rela_dyn.deinit(gpa);
self.rela_plt.deinit(gpa);
self.ar_symtab.deinit(gpa);
self.ar_strtab.deinit(gpa);
}
pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 {
@ -1553,175 +1544,74 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
try self.writeSymtab();
try self.writeShStrtab();
try self.writeElfHeader();
// Update ar symbol table.
try zig_object.asFile().updateArSymtab(self);
}
// TODO parse positionals that we want to make part of the archive
mem.sort(ArSymtabEntry, self.ar_symtab.items, {}, ArSymtabEntry.lessThan);
// TODO update ar symtab from parsed positionals
if (build_options.enable_logging) {
state_log.debug("{}", .{self.dumpState()});
var ar_symtab: Archive.ArSymtab = .{};
defer ar_symtab.deinit(gpa);
if (self.zigObjectPtr()) |zig_object| {
try zig_object.updateArSymtab(&ar_symtab, self);
}
ar_symtab.sort();
// Save object paths in filenames strtab.
var ar_strtab = std.ArrayList(u8).init(gpa);
defer ar_strtab.deinit();
var files = std.AutoHashMap(File.Index, struct { u32, u64, u64 }).init(gpa);
defer files.deinit();
try files.ensureUnusedCapacity(@intCast(self.objects.items.len + 1));
var ar_strtab: Archive.ArStrtab = .{};
defer ar_strtab.deinit(gpa);
if (self.zigObjectPtr()) |zig_object| {
const off = @as(u32, @intCast(ar_strtab.items.len));
try ar_strtab.writer().print("{s}/\n", .{zig_object.path});
files.putAssumeCapacityNoClobber(zig_object.index, .{ off, 0, 0 });
try zig_object.updateArStrtab(gpa, &ar_strtab);
zig_object.updateArSize(self);
}
// Align to even byte boundary
{
const end = ar_strtab.items.len;
const aligned = mem.alignForward(usize, end, 2);
try ar_strtab.writer().writeByteNTimes(0, aligned - end);
}
// Update file offsets of contributing objects.
const total_size: u64 = blk: {
var pos: u64 = Archive.SARMAG;
pos += @sizeOf(Archive.ar_hdr) + ar_symtab.size(.p64);
pos = mem.alignForward(u64, pos, 2);
pos += @sizeOf(Archive.ar_hdr) + ar_strtab.size();
// Encode ar symtab in 64bit format.
var ar_symtab = std.ArrayList(u8).init(gpa);
defer ar_symtab.deinit();
try ar_symtab.ensureUnusedCapacity(8 * (self.ar_symtab.items.len + 1));
// Number of symbols
ar_symtab.writer().writeInt(u64, @as(u64, @intCast(self.ar_symtab.items.len)), .big) catch unreachable;
// Offsets which we will relocate later.
for (0..self.ar_symtab.items.len) |_| {
ar_symtab.writer().writeInt(u64, 0, .big) catch unreachable;
}
// ASCII offsets into the strtab.
for (self.ar_symtab.items) |entry| {
const name = self.ar_strtab.getAssumeExists(entry.off);
try ar_symtab.writer().print("{s}\x00", .{name});
}
// Align to 8 bytes if required
{
const end = ar_symtab.items.len;
const aligned = mem.alignForward(usize, end, 8);
try ar_symtab.writer().writeByteNTimes(0, aligned - end);
}
assert(mem.isAligned(ar_symtab.items.len, 8));
// Calculate required size for headers before ZigObject pos in file.
if (self.zigObjectPtr()) |zig_object| {
var file_off: u64 = 0;
// Magic
file_off += Archive.SARMAG;
// Symtab
file_off += @sizeOf(Archive.ar_hdr) + @as(u64, @intCast(ar_symtab.items.len));
// Strtab
file_off += @sizeOf(Archive.ar_hdr) + @as(u64, @intCast(ar_strtab.items.len));
const files_ptr = files.getPtr(zig_object.index).?;
files_ptr[1] = file_off;
// Move ZigObject into place.
{
var end_pos: u64 = self.shdr_table_offset.?;
for (self.shdrs.items) |shdr| {
end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size);
}
const contents = try gpa.alloc(u8, end_pos);
defer gpa.free(contents);
const amt = try self.base.file.?.preadAll(contents, 0);
if (amt != end_pos) return error.InputOutput;
try self.base.file.?.pwriteAll(contents, file_off + @sizeOf(Archive.ar_hdr));
files_ptr[2] = end_pos;
if (self.zigObjectPtr()) |zig_object| {
pos = mem.alignForward(u64, pos, 2);
zig_object.output_ar_state.file_off = pos;
pos += @sizeOf(Archive.ar_hdr) + zig_object.output_ar_state.size;
}
}
// Fixup file offsets in the symtab.
for (self.ar_symtab.items, 1..) |entry, i| {
const file_off = files.get(entry.file_index).?[1];
mem.writeInt(u64, ar_symtab.items[8 * i ..][0..8], file_off, .big);
}
var pos: usize = Archive.SARMAG;
// Write symtab.
{
const hdr = setArHdr(.{ .kind = .symtab, .name_off = 0, .size = @intCast(ar_symtab.items.len) });
try self.base.file.?.pwriteAll(mem.asBytes(&hdr), pos);
pos += @sizeOf(Archive.ar_hdr);
try self.base.file.?.pwriteAll(ar_symtab.items, pos);
pos += ar_symtab.items.len;
}
// Write strtab.
{
const hdr = setArHdr(.{
.kind = .strtab,
.name_off = 0,
.size = @intCast(ar_strtab.items.len),
});
try self.base.file.?.pwriteAll(mem.asBytes(&hdr), pos);
pos += @sizeOf(Archive.ar_hdr);
try self.base.file.?.pwriteAll(ar_strtab.items, pos);
pos += ar_strtab.items.len;
}
// Zig object if defined
if (self.zigObjectPtr()) |zig_object| {
const entry = files.get(zig_object.index).?;
const hdr = setArHdr(.{ .kind = .object, .name_off = entry[0], .size = @intCast(entry[2]) });
try self.base.file.?.pwriteAll(mem.asBytes(&hdr), entry[1]);
pos += @sizeOf(Archive.ar_hdr) + entry[2];
}
// TODO parsed positionals
// Magic bytes.
{
try self.base.file.?.pwriteAll(Archive.ARMAG, 0);
}
}
fn setArHdr(opts: struct {
kind: enum { symtab, strtab, object },
name_off: u32,
size: u32,
}) Archive.ar_hdr {
var hdr: Archive.ar_hdr = .{
.ar_name = undefined,
.ar_date = undefined,
.ar_uid = undefined,
.ar_gid = undefined,
.ar_mode = undefined,
.ar_size = undefined,
.ar_fmag = undefined,
break :blk pos;
};
@memset(mem.asBytes(&hdr), 0x20);
@memcpy(&hdr.ar_fmag, Archive.ARFMAG);
{
var stream = std.io.fixedBufferStream(&hdr.ar_name);
const writer = stream.writer();
switch (opts.kind) {
.symtab => writer.print("{s}", .{Archive.SYM64NAME}) catch unreachable,
.strtab => writer.print("//", .{}) catch unreachable,
.object => writer.print("/{d}", .{opts.name_off}) catch unreachable,
}
}
{
var stream = std.io.fixedBufferStream(&hdr.ar_size);
stream.writer().print("{d}", .{opts.size}) catch unreachable;
if (build_options.enable_logging) {
state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(self)});
state_log.debug("ar_strtab\n{}\n", .{ar_strtab});
}
return hdr;
var buffer = std.ArrayList(u8).init(gpa);
defer buffer.deinit();
try buffer.ensureTotalCapacityPrecise(total_size);
// Write magic
try buffer.writer().writeAll(Archive.ARMAG);
// Write symtab
try ar_symtab.write(.p64, self, buffer.writer());
if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);
// Write strtab
try ar_strtab.write(buffer.writer());
if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);
// Write object files
if (self.zigObjectPtr()) |zig_object| {
try zig_object.writeAr(self, buffer.writer());
}
assert(buffer.items.len == total_size);
try self.base.file.?.pwriteAll(buffer.items, 0);
}
pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void {
@ -5822,18 +5712,6 @@ fn fmtDumpState(
try writer.print("{}\n", .{self.got.fmt(self)});
try writer.print("{}\n", .{self.zig_got.fmt(self)});
if (self.isStaticLib()) {
try writer.writeAll("ar symtab\n");
for (self.ar_symtab.items, 0..) |entry, i| {
try writer.print(" {d} : {s} in file({d})\n", .{
i,
self.ar_strtab.getAssumeExists(entry.off),
entry.file_index,
});
}
try writer.writeByte('\n');
}
try writer.writeAll("Output shdrs\n");
for (self.shdrs.items, 0..) |shdr, shndx| {
try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{
@ -5966,19 +5844,6 @@ const LastAtomAndFreeList = struct {
const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList);
const ArSymtabEntry = struct {
off: u32,
file_index: File.Index,
pub fn lessThan(ctx: void, lhs: ArSymtabEntry, rhs: ArSymtabEntry) bool {
_ = ctx;
if (lhs.off == rhs.off) {
return lhs.file_index < rhs.file_index;
}
return lhs.off < rhs.off;
}
};
pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1;
pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2;

View File

@ -4,69 +4,11 @@ data: []const u8,
objects: std.ArrayListUnmanaged(Object) = .{},
strtab: []const u8 = &[0]u8{},
// Archive files start with the ARMAG identifying string. Then follows a
// `struct ar_hdr', and as many bytes of member file data as its `ar_size'
// member indicates, for each member file.
/// String that begins an archive file.
pub const ARMAG: *const [SARMAG:0]u8 = "!<arch>\n";
/// Size of that string.
pub const SARMAG = 8;
/// String in ar_fmag at the end of each header.
pub const ARFMAG: *const [2:0]u8 = "`\n";
pub const SYM64NAME: *const [7:0]u8 = "/SYM64/";
pub const ar_hdr = extern struct {
/// Member file name, sometimes / terminated.
ar_name: [16]u8,
/// File date, decimal seconds since Epoch.
ar_date: [12]u8,
/// User ID, in ASCII format.
ar_uid: [6]u8,
/// Group ID, in ASCII format.
ar_gid: [6]u8,
/// File mode, in ASCII octal.
ar_mode: [8]u8,
/// File size, in ASCII decimal.
ar_size: [10]u8,
/// Always contains ARFMAG.
ar_fmag: [2]u8,
fn date(self: ar_hdr) !u64 {
const value = getValue(&self.ar_date);
return std.fmt.parseInt(u64, value, 10);
}
fn size(self: ar_hdr) !u32 {
const value = getValue(&self.ar_size);
return std.fmt.parseInt(u32, value, 10);
}
fn getValue(raw: []const u8) []const u8 {
return mem.trimRight(u8, raw, &[_]u8{@as(u8, 0x20)});
}
fn isStrtab(self: ar_hdr) bool {
return mem.eql(u8, getValue(&self.ar_name), "//");
}
fn isSymtab(self: ar_hdr) bool {
return mem.eql(u8, getValue(&self.ar_name), "/") or mem.eql(u8, getValue(&self.ar_name), SYM64NAME);
}
};
pub fn isArchive(path: []const u8) !bool {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
const reader = file.reader();
const magic = reader.readBytesNoEof(Archive.SARMAG) catch return false;
const magic = reader.readBytesNoEof(SARMAG) catch return false;
if (!mem.eql(u8, &magic, ARMAG)) return false;
return true;
}
@ -140,9 +82,267 @@ pub fn parse(self: *Archive, elf_file: *Elf) !void {
fn getString(self: Archive, off: u32) []const u8 {
assert(off < self.strtab.len);
return mem.sliceTo(@as([*:'\n']const u8, @ptrCast(self.strtab.ptr + off)), 0);
return mem.sliceTo(@as([*:strtab_delimiter]const u8, @ptrCast(self.strtab.ptr + off)), 0);
}
pub fn setArHdr(opts: struct {
kind: enum { symtab, strtab, object },
name_off: u32,
size: u32,
}) ar_hdr {
var hdr: ar_hdr = .{
.ar_name = undefined,
.ar_date = undefined,
.ar_uid = undefined,
.ar_gid = undefined,
.ar_mode = undefined,
.ar_size = undefined,
.ar_fmag = undefined,
};
@memset(mem.asBytes(&hdr), 0x20);
@memcpy(&hdr.ar_fmag, Archive.ARFMAG);
{
var stream = std.io.fixedBufferStream(&hdr.ar_name);
const writer = stream.writer();
switch (opts.kind) {
.symtab => writer.print("{s}", .{Archive.SYM64NAME}) catch unreachable,
.strtab => writer.print("//", .{}) catch unreachable,
.object => writer.print("/{d}", .{opts.name_off}) catch unreachable,
}
}
{
var stream = std.io.fixedBufferStream(&hdr.ar_size);
stream.writer().print("{d}", .{opts.size}) catch unreachable;
}
return hdr;
}
// Archive files start with the ARMAG identifying string. Then follows a
// `struct ar_hdr', and as many bytes of member file data as its `ar_size'
// member indicates, for each member file.
/// String that begins an archive file.
pub const ARMAG: *const [SARMAG:0]u8 = "!<arch>\n";
/// Size of that string.
pub const SARMAG = 8;
/// String in ar_fmag at the end of each header.
const ARFMAG: *const [2:0]u8 = "`\n";
/// Strtab identifier
const STRNAME: *const [2:0]u8 = "//";
/// 32-bit symtab identifier
const SYMNAME: *const [1:0]u8 = "/";
/// 64-bit symtab identifier
const SYM64NAME: *const [7:0]u8 = "/SYM64/";
const strtab_delimiter = '\n';
pub const ar_hdr = extern struct {
/// Member file name, sometimes / terminated.
ar_name: [16]u8,
/// File date, decimal seconds since Epoch.
ar_date: [12]u8,
/// User ID, in ASCII format.
ar_uid: [6]u8,
/// Group ID, in ASCII format.
ar_gid: [6]u8,
/// File mode, in ASCII octal.
ar_mode: [8]u8,
/// File size, in ASCII decimal.
ar_size: [10]u8,
/// Always contains ARFMAG.
ar_fmag: [2]u8,
fn date(self: ar_hdr) !u64 {
const value = getValue(&self.ar_date);
return std.fmt.parseInt(u64, value, 10);
}
fn size(self: ar_hdr) !u32 {
const value = getValue(&self.ar_size);
return std.fmt.parseInt(u32, value, 10);
}
fn getValue(raw: []const u8) []const u8 {
return mem.trimRight(u8, raw, &[_]u8{@as(u8, 0x20)});
}
fn isStrtab(self: ar_hdr) bool {
return mem.eql(u8, getValue(&self.ar_name), STRNAME);
}
fn isSymtab(self: ar_hdr) bool {
return mem.eql(u8, getValue(&self.ar_name), SYMNAME) or mem.eql(u8, getValue(&self.ar_name), SYM64NAME);
}
};
pub const ArSymtab = struct {
symtab: std.ArrayListUnmanaged(Entry) = .{},
strtab: StringTable = .{},
pub fn deinit(ar: *ArSymtab, allocator: Allocator) void {
ar.symtab.deinit(allocator);
ar.strtab.deinit(allocator);
}
pub fn sort(ar: *ArSymtab) void {
mem.sort(Entry, ar.symtab.items, {}, Entry.lessThan);
}
pub fn size(ar: ArSymtab, kind: enum { p32, p64 }) usize {
const ptr_size: usize = switch (kind) {
.p32 => 4,
.p64 => 8,
};
var ss: usize = ptr_size + ar.symtab.items.len * ptr_size;
for (ar.symtab.items) |entry| {
ss += ar.strtab.getAssumeExists(entry.off).len + 1;
}
return ss;
}
pub fn write(ar: ArSymtab, kind: enum { p32, p64 }, elf_file: *Elf, writer: anytype) !void {
assert(kind == .p64); // TODO p32
const hdr = setArHdr(.{ .kind = .symtab, .name_off = 0, .size = @intCast(ar.size(.p64)) });
try writer.writeAll(mem.asBytes(&hdr));
const gpa = elf_file.base.allocator;
var offsets = std.AutoHashMap(File.Index, u64).init(gpa);
defer offsets.deinit();
try offsets.ensureUnusedCapacity(@intCast(elf_file.objects.items.len + 1));
if (elf_file.zigObjectPtr()) |zig_object| {
offsets.putAssumeCapacityNoClobber(zig_object.index, zig_object.output_ar_state.file_off);
}
// Number of symbols
try writer.writeInt(u64, @as(u64, @intCast(ar.symtab.items.len)), .big);
// Offsets to files
for (ar.symtab.items) |entry| {
const off = offsets.get(entry.file_index).?;
try writer.writeInt(u64, off, .big);
}
// Strings
for (ar.symtab.items) |entry| {
try writer.print("{s}\x00", .{ar.strtab.getAssumeExists(entry.off)});
}
}
pub fn format(
ar: ArSymtab,
comptime unused_fmt_string: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = ar;
_ = unused_fmt_string;
_ = options;
_ = writer;
@compileError("do not format ar symtab directly; use fmt instead");
}
const FormatContext = struct {
ar: ArSymtab,
elf_file: *Elf,
};
pub fn fmt(ar: ArSymtab, elf_file: *Elf) std.fmt.Formatter(format2) {
return .{ .data = .{
.ar = ar,
.elf_file = elf_file,
} };
}
fn format2(
ctx: FormatContext,
comptime unused_fmt_string: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = unused_fmt_string;
_ = options;
const ar = ctx.ar;
const elf_file = ctx.elf_file;
for (ar.symtab.items, 0..) |entry, i| {
const name = ar.strtab.getAssumeExists(entry.off);
const file = elf_file.file(entry.file_index).?;
try writer.print(" {d}: {s} in file({d})({})\n", .{ i, name, entry.file_index, file.fmtPath() });
}
}
const Entry = struct {
/// Offset into the string table.
off: u32,
/// Index of the file defining the global.
file_index: File.Index,
pub fn lessThan(ctx: void, lhs: Entry, rhs: Entry) bool {
_ = ctx;
if (lhs.off == rhs.off) return lhs.file_index < rhs.file_index;
return lhs.off < rhs.off;
}
};
};
pub const ArStrtab = struct {
buffer: std.ArrayListUnmanaged(u8) = .{},
pub fn deinit(ar: *ArStrtab, allocator: Allocator) void {
ar.buffer.deinit(allocator);
}
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 });
return off;
}
pub fn size(ar: ArStrtab) usize {
return ar.buffer.items.len;
}
pub fn write(ar: ArStrtab, writer: anytype) !void {
const hdr = setArHdr(.{ .kind = .strtab, .name_off = 0, .size = @intCast(ar.size()) });
try writer.writeAll(mem.asBytes(&hdr));
try writer.writeAll(ar.buffer.items);
}
pub fn format(
ar: ArStrtab,
comptime unused_fmt_string: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = unused_fmt_string;
_ = options;
try writer.print("{s}", .{std.fmt.fmtSliceEscapeLower(ar.buffer.items)});
}
};
pub const ArState = struct {
/// Name offset in the string table.
name_off: u32 = 0,
/// File offset of the ar_hdr describing the contributing
/// object in the archive.
file_off: u64 = 0,
/// Total size of the contributing object (excludes ar_hdr).
size: u64 = 0,
};
const std = @import("std");
const assert = std.debug.assert;
const elf = std.elf;
@ -153,4 +353,6 @@ const mem = std.mem;
const Allocator = mem.Allocator;
const Archive = @This();
const Elf = @import("../Elf.zig");
const File = @import("file.zig").File;
const Object = @import("Object.zig");
const StringTable = @import("../StringTable.zig");

View File

@ -20,6 +20,7 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
num_dynrelocs: u32 = 0,
output_symtab_size: Elf.SymtabSize = .{},
output_ar_state: Archive.ArState = .{},
dwarf: ?Dwarf = null,
@ -502,10 +503,10 @@ fn sortSymbols(self: *ZigObject, elf_file: *Elf) error{OutOfMemory}!void {
// mem.sort(Entry, sorted_globals, elf_file, Entry.lessThan);
}
pub fn updateArSymtab(self: ZigObject, elf_file: *Elf) !void {
pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) error{OutOfMemory}!void {
const gpa = elf_file.base.allocator;
try elf_file.ar_symtab.ensureUnusedCapacity(gpa, self.globals().len);
try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.globals().len);
for (self.globals()) |global_index| {
const global = elf_file.symbol(global_index);
@ -513,11 +514,45 @@ pub fn updateArSymtab(self: ZigObject, elf_file: *Elf) !void {
assert(file_ptr.index() == self.index);
if (global.type(elf_file) == elf.SHN_UNDEF) continue;
const off = try elf_file.ar_strtab.insert(gpa, global.name(elf_file));
elf_file.ar_symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index });
const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file));
ar_symtab.symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index });
}
}
pub fn updateArStrtab(
self: *ZigObject,
allocator: Allocator,
ar_strtab: *Archive.ArStrtab,
) error{OutOfMemory}!void {
const name = try std.fmt.allocPrint(allocator, "{s}.o", .{std.fs.path.stem(self.path)});
defer allocator.free(name);
const name_off = try ar_strtab.insert(allocator, name);
self.output_ar_state.name_off = name_off;
}
pub fn updateArSize(self: *ZigObject, elf_file: *Elf) void {
var end_pos: u64 = elf_file.shdr_table_offset.?;
for (elf_file.shdrs.items) |shdr| {
end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size);
}
self.output_ar_state.size = end_pos;
}
pub fn writeAr(self: ZigObject, elf_file: *Elf, writer: anytype) !void {
const gpa = elf_file.base.allocator;
const contents = try gpa.alloc(u8, self.output_ar_state.size);
defer gpa.free(contents);
const amt = try elf_file.base.file.?.preadAll(contents, 0);
if (amt != self.output_ar_state.size) return error.InputOutput;
const hdr = Archive.setArHdr(.{
.kind = .object,
.name_off = self.output_ar_state.name_off,
.size = @intCast(self.output_ar_state.size),
});
try writer.writeAll(mem.asBytes(&hdr));
try writer.writeAll(contents);
}
pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
_ = self;
@ -1533,6 +1568,7 @@ const std = @import("std");
const Air = @import("../../Air.zig");
const Allocator = std.mem.Allocator;
const Archive = @import("Archive.zig");
const Atom = @import("Atom.zig");
const Dwarf = @import("../Dwarf.zig");
const Elf = @import("../Elf.zig");

View File

@ -196,9 +196,9 @@ pub const File = union(enum) {
}
}
pub fn updateArSymtab(file: File, elf_file: *Elf) !void {
pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
return switch (file) {
.zig_object => |x| x.updateArSymtab(elf_file),
.zig_object => |x| x.updateArSymtab(ar_symtab, elf_file),
.object => @panic("TODO"),
inline else => unreachable,
};
@ -219,6 +219,7 @@ const std = @import("std");
const elf = std.elf;
const Allocator = std.mem.Allocator;
const Archive = @import("Archive.zig");
const Atom = @import("Atom.zig");
const Cie = @import("eh_frame.zig").Cie;
const Elf = @import("../Elf.zig");