mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 22:04:21 +00:00
elf: hook up saving object files in an archive
This commit is contained in:
parent
55fa8a04f1
commit
8142925c7e
5 changed files with 61 additions and 27 deletions
|
|
@ -288,7 +288,9 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
|
||||||
const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));
|
const index = @as(File.Index, @intCast(try self.files.addOne(allocator)));
|
||||||
self.files.set(index, .{ .zig_object = .{
|
self.files.set(index, .{ .zig_object = .{
|
||||||
.index = index,
|
.index = index,
|
||||||
.path = options.module.?.main_mod.root_src_path,
|
.path = try std.fmt.allocPrint(self.base.allocator, "{s}.o", .{std.fs.path.stem(
|
||||||
|
options.module.?.main_mod.root_src_path,
|
||||||
|
)}),
|
||||||
} });
|
} });
|
||||||
self.zig_object_index = index;
|
self.zig_object_index = index;
|
||||||
try self.zigObjectPtr().?.init(self);
|
try self.zigObjectPtr().?.init(self);
|
||||||
|
|
@ -1553,6 +1555,9 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
|
||||||
var files = std.ArrayList(File.Index).init(gpa);
|
var files = std.ArrayList(File.Index).init(gpa);
|
||||||
defer files.deinit();
|
defer files.deinit();
|
||||||
try files.ensureTotalCapacityPrecise(self.objects.items.len + 1);
|
try files.ensureTotalCapacityPrecise(self.objects.items.len + 1);
|
||||||
|
// Note to self: we currently must have ZigObject written out first as we write the object
|
||||||
|
// file into the same file descriptor and then re-read its contents.
|
||||||
|
// TODO implement writing ZigObject to a buffer instead of file.
|
||||||
if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index);
|
if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index);
|
||||||
for (self.objects.items) |index| files.appendAssumeCapacity(index);
|
for (self.objects.items) |index| files.appendAssumeCapacity(index);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ const SYMDEFNAME = genSpecialMemberName("__.SYMDEF");
|
||||||
const SYMDEFSORTEDNAME = genSpecialMemberName("__.SYMDEF SORTED");
|
const SYMDEFSORTEDNAME = genSpecialMemberName("__.SYMDEF SORTED");
|
||||||
|
|
||||||
const strtab_delimiter = '\n';
|
const strtab_delimiter = '\n';
|
||||||
|
pub const max_member_name_len = 15;
|
||||||
|
|
||||||
pub const ar_hdr = extern struct {
|
pub const ar_hdr = extern struct {
|
||||||
/// Member file name, sometimes / terminated.
|
/// Member file name, sometimes / terminated.
|
||||||
|
|
@ -248,6 +249,9 @@ pub const ArSymtab = struct {
|
||||||
if (elf_file.zigObjectPtr()) |zig_object| {
|
if (elf_file.zigObjectPtr()) |zig_object| {
|
||||||
offsets.putAssumeCapacityNoClobber(zig_object.index, zig_object.output_ar_state.file_off);
|
offsets.putAssumeCapacityNoClobber(zig_object.index, zig_object.output_ar_state.file_off);
|
||||||
}
|
}
|
||||||
|
for (elf_file.objects.items) |index| {
|
||||||
|
offsets.putAssumeCapacityNoClobber(index, elf_file.file(index).?.object.output_ar_state.file_off);
|
||||||
|
}
|
||||||
|
|
||||||
// Number of symbols
|
// Number of symbols
|
||||||
try writer.writeInt(u64, @as(u64, @intCast(ar.symtab.items.len)), .big);
|
try writer.writeInt(u64, @as(u64, @intCast(ar.symtab.items.len)), .big);
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,36 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
|
||||||
|
const gpa = elf_file.base.allocator;
|
||||||
|
const start = self.first_global orelse self.symtab.items.len;
|
||||||
|
|
||||||
|
try ar_symtab.symtab.ensureUnusedCapacity(gpa, self.symtab.items.len - start);
|
||||||
|
|
||||||
|
for (self.symtab.items[start..]) |sym| {
|
||||||
|
if (sym.st_shndx == elf.SHN_UNDEF) continue;
|
||||||
|
const off = try ar_symtab.strtab.insert(gpa, self.getString(sym.st_name));
|
||||||
|
ar_symtab.symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateArSize(self: *Object) void {
|
||||||
|
self.output_ar_state.size = self.data.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeAr(self: Object, writer: anytype) !void {
|
||||||
|
const name = self.path;
|
||||||
|
const hdr = Archive.setArHdr(.{
|
||||||
|
.name = if (name.len <= Archive.max_member_name_len)
|
||||||
|
.{ .name = name }
|
||||||
|
else
|
||||||
|
.{ .name_off = self.output_ar_state.name_off },
|
||||||
|
.size = @intCast(self.data.len),
|
||||||
|
});
|
||||||
|
try writer.writeAll(mem.asBytes(&hdr));
|
||||||
|
try writer.writeAll(self.data);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locals(self: Object) []const Symbol.Index {
|
pub fn locals(self: Object) []const Symbol.Index {
|
||||||
const end = self.first_global orelse self.symbols.items.len;
|
const end = self.first_global orelse self.symbols.items.len;
|
||||||
return self.symbols.items[0..end];
|
return self.symbols.items[0..end];
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
//! and any relocations that may have been emitted.
|
//! and any relocations that may have been emitted.
|
||||||
//! Think about this as fake in-memory Object file for the Zig module.
|
//! Think about this as fake in-memory Object file for the Zig module.
|
||||||
|
|
||||||
/// Path is owned by Module and lives as long as *Module.
|
|
||||||
path: []const u8,
|
path: []const u8,
|
||||||
index: File.Index,
|
index: File.Index,
|
||||||
|
|
||||||
|
|
@ -78,7 +77,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
|
||||||
try self.atoms.append(gpa, 0); // null input section
|
try self.atoms.append(gpa, 0); // null input section
|
||||||
try self.strtab.buffer.append(gpa, 0);
|
try self.strtab.buffer.append(gpa, 0);
|
||||||
|
|
||||||
const name_off = try self.strtab.insert(gpa, std.fs.path.stem(self.path));
|
const name_off = try self.strtab.insert(gpa, self.path);
|
||||||
const symbol_index = try elf_file.addSymbol();
|
const symbol_index = try elf_file.addSymbol();
|
||||||
try self.local_symbols.append(gpa, symbol_index);
|
try self.local_symbols.append(gpa, symbol_index);
|
||||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||||
|
|
@ -98,6 +97,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||||
|
allocator.free(self.path);
|
||||||
self.local_esyms.deinit(allocator);
|
self.local_esyms.deinit(allocator);
|
||||||
self.global_esyms.deinit(allocator);
|
self.global_esyms.deinit(allocator);
|
||||||
self.strtab.deinit(allocator);
|
self.strtab.deinit(allocator);
|
||||||
|
|
@ -512,25 +512,13 @@ pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *
|
||||||
const global = elf_file.symbol(global_index);
|
const global = elf_file.symbol(global_index);
|
||||||
const file_ptr = global.file(elf_file).?;
|
const file_ptr = global.file(elf_file).?;
|
||||||
assert(file_ptr.index() == self.index);
|
assert(file_ptr.index() == self.index);
|
||||||
if (global.type(elf_file) == elf.SHN_UNDEF) continue;
|
if (global.outputShndx() == null) continue;
|
||||||
|
|
||||||
const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file));
|
const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file));
|
||||||
ar_symtab.symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index });
|
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);
|
|
||||||
if (name.len <= 15) return;
|
|
||||||
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 {
|
pub fn updateArSize(self: *ZigObject, elf_file: *Elf) void {
|
||||||
var end_pos: u64 = elf_file.shdr_table_offset.?;
|
var end_pos: u64 = elf_file.shdr_table_offset.?;
|
||||||
for (elf_file.shdrs.items) |shdr| {
|
for (elf_file.shdrs.items) |shdr| {
|
||||||
|
|
@ -549,11 +537,12 @@ pub fn writeAr(self: ZigObject, elf_file: *Elf, writer: anytype) !void {
|
||||||
const amt = try elf_file.base.file.?.preadAll(contents, 0);
|
const amt = try elf_file.base.file.?.preadAll(contents, 0);
|
||||||
if (amt != self.output_ar_state.size) return error.InputOutput;
|
if (amt != self.output_ar_state.size) return error.InputOutput;
|
||||||
|
|
||||||
const name = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(self.path)});
|
const name = self.path;
|
||||||
defer gpa.free(name);
|
|
||||||
|
|
||||||
const hdr = Archive.setArHdr(.{
|
const hdr = Archive.setArHdr(.{
|
||||||
.name = if (name.len <= 15) .{ .name = name } else .{ .name_off = self.output_ar_state.name_off },
|
.name = if (name.len <= Archive.max_member_name_len)
|
||||||
|
.{ .name = name }
|
||||||
|
else
|
||||||
|
.{ .name_off = self.output_ar_state.name_off },
|
||||||
.size = @intCast(size),
|
.size = @intCast(size),
|
||||||
});
|
});
|
||||||
try writer.writeAll(mem.asBytes(&hdr));
|
try writer.writeAll(mem.asBytes(&hdr));
|
||||||
|
|
|
||||||
|
|
@ -199,23 +199,30 @@ pub const File = union(enum) {
|
||||||
pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
|
pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
|
||||||
return switch (file) {
|
return switch (file) {
|
||||||
.zig_object => |x| x.updateArSymtab(ar_symtab, elf_file),
|
.zig_object => |x| x.updateArSymtab(ar_symtab, elf_file),
|
||||||
.object => @panic("TODO"),
|
.object => |x| x.updateArSymtab(ar_symtab, elf_file),
|
||||||
inline else => unreachable,
|
inline else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void {
|
pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void {
|
||||||
return switch (file) {
|
const path = switch (file) {
|
||||||
.zig_object => |x| x.updateArStrtab(allocator, ar_strtab),
|
.zig_object => |x| x.path,
|
||||||
.object => @panic("TODO"),
|
.object => |x| x.path,
|
||||||
inline else => unreachable,
|
inline else => unreachable,
|
||||||
};
|
};
|
||||||
|
const state = switch (file) {
|
||||||
|
.zig_object => |x| &x.output_ar_state,
|
||||||
|
.object => |x| &x.output_ar_state,
|
||||||
|
inline else => unreachable,
|
||||||
|
};
|
||||||
|
if (path.len <= Archive.max_member_name_len) return;
|
||||||
|
state.name_off = try ar_strtab.insert(allocator, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateArSize(file: File, elf_file: *Elf) void {
|
pub fn updateArSize(file: File, elf_file: *Elf) void {
|
||||||
return switch (file) {
|
return switch (file) {
|
||||||
.zig_object => |x| x.updateArSize(elf_file),
|
.zig_object => |x| x.updateArSize(elf_file),
|
||||||
.object => @panic("TODO"),
|
.object => |x| x.updateArSize(),
|
||||||
inline else => unreachable,
|
inline else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -223,8 +230,7 @@ pub const File = union(enum) {
|
||||||
pub fn writeAr(file: File, elf_file: *Elf, writer: anytype) !void {
|
pub fn writeAr(file: File, elf_file: *Elf, writer: anytype) !void {
|
||||||
return switch (file) {
|
return switch (file) {
|
||||||
.zig_object => |x| x.writeAr(elf_file, writer),
|
.zig_object => |x| x.writeAr(elf_file, writer),
|
||||||
// .object => |x| x.writeAr(elf_file, writer),
|
.object => |x| x.writeAr(writer),
|
||||||
.object => @panic("TODO"),
|
|
||||||
inline else => unreachable,
|
inline else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue