authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-05 12:56:17+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-05 12:56:17+01:00
log55fa8a04f1853deb473339cdc610cbf012ae0d61
treee614530b5be669123ed4278d532d7827ae982589
parent5c482361034a0b1575ecb719724c942b5709b449

elf: add hooks for archiving Objects


3 files changed, 51 insertions(+), 19 deletions(-)

src/link/Elf.zig+24-19
......@@ -939,12 +939,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
939939 } else null;
940940 const gc_sections = self.base.options.gc_sections orelse false;
941941
942 if (self.isRelocatable() and self.zig_object_index == null) {
943 if (self.isStaticLib()) {
944 var err = try self.addErrorWithNotes(0);
945 try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{});
946 return;
947 }
942 if (self.isObject() and self.zig_object_index == null) {
948943 // TODO this will become -r route I guess. For now, just copy the object file.
949944 assert(self.base.file == null); // TODO uncomment once we implement -r
950945 const the_object_path = blk: {
......@@ -1555,15 +1550,18 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
15551550 try self.writeElfHeader();
15561551 }
15571552
1558 // TODO parse positionals that we want to make part of the archive
1559
1560 // TODO update ar symtab from parsed positionals
1553 var files = std.ArrayList(File.Index).init(gpa);
1554 defer files.deinit();
1555 try files.ensureTotalCapacityPrecise(self.objects.items.len + 1);
1556 if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index);
1557 for (self.objects.items) |index| files.appendAssumeCapacity(index);
15611558
1559 // Update ar symtab from parsed objects
15621560 var ar_symtab: Archive.ArSymtab = .{};
15631561 defer ar_symtab.deinit(gpa);
15641562
1565 if (self.zigObjectPtr()) |zig_object| {
1566 try zig_object.updateArSymtab(&ar_symtab, self);
1563 for (files.items) |index| {
1564 try self.file(index).?.updateArSymtab(&ar_symtab, self);
15671565 }
15681566
15691567 ar_symtab.sort();
......@@ -1572,9 +1570,10 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
15721570 var ar_strtab: Archive.ArStrtab = .{};
15731571 defer ar_strtab.deinit(gpa);
15741572
1575 if (self.zigObjectPtr()) |zig_object| {
1576 try zig_object.updateArStrtab(gpa, &ar_strtab);
1577 zig_object.updateArSize(self);
1573 for (files.items) |index| {
1574 const file_ptr = self.file(index).?;
1575 try file_ptr.updateArStrtab(gpa, &ar_strtab);
1576 file_ptr.updateArSize(self);
15781577 }
15791578
15801579 // Update file offsets of contributing objects.
......@@ -1587,10 +1586,16 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
15871586 pos += @sizeOf(Archive.ar_hdr) + ar_strtab.size();
15881587 }
15891588
1590 if (self.zigObjectPtr()) |zig_object| {
1589 for (files.items) |index| {
1590 const file_ptr = self.file(index).?;
1591 const state = switch (file_ptr) {
1592 .zig_object => |x| &x.output_ar_state,
1593 .object => |x| &x.output_ar_state,
1594 else => unreachable,
1595 };
15911596 pos = mem.alignForward(usize, pos, 2);
1592 zig_object.output_ar_state.file_off = pos;
1593 pos += @sizeOf(Archive.ar_hdr) + (math.cast(usize, zig_object.output_ar_state.size) orelse return error.Overflow);
1597 state.file_off = pos;
1598 pos += @sizeOf(Archive.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow);
15941599 }
15951600
15961601 break :blk pos;
......@@ -1618,9 +1623,9 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
16181623 }
16191624
16201625 // Write object files
1621 if (self.zigObjectPtr()) |zig_object| {
1626 for (files.items) |index| {
16221627 if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0);
1623 try zig_object.writeAr(self, buffer.writer());
1628 try self.file(index).?.writeAr(self, buffer.writer());
16241629 }
16251630
16261631 assert(buffer.items.len == total_size);
src/link/Elf/Object.zig+2
......@@ -20,6 +20,7 @@ alive: bool = true,
2020num_dynrelocs: u32 = 0,
2121
2222output_symtab_size: Elf.SymtabSize = .{},
23output_ar_state: Archive.ArState = .{},
2324
2425pub fn isObject(path: []const u8) !bool {
2526 const file = try std.fs.cwd().openFile(path, .{});
......@@ -924,6 +925,7 @@ const math = std.math;
924925const mem = std.mem;
925926
926927const Allocator = mem.Allocator;
928const Archive = @import("Archive.zig");
927929const Atom = @import("Atom.zig");
928930const Cie = eh_frame.Cie;
929931const Elf = @import("../Elf.zig");
src/link/Elf/file.zig+25
......@@ -204,6 +204,31 @@ pub const File = union(enum) {
204204 };
205205 }
206206
207 pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void {
208 return switch (file) {
209 .zig_object => |x| x.updateArStrtab(allocator, ar_strtab),
210 .object => @panic("TODO"),
211 inline else => unreachable,
212 };
213 }
214
215 pub fn updateArSize(file: File, elf_file: *Elf) void {
216 return switch (file) {
217 .zig_object => |x| x.updateArSize(elf_file),
218 .object => @panic("TODO"),
219 inline else => unreachable,
220 };
221 }
222
223 pub fn writeAr(file: File, elf_file: *Elf, writer: anytype) !void {
224 return switch (file) {
225 .zig_object => |x| x.writeAr(elf_file, writer),
226 // .object => |x| x.writeAr(elf_file, writer),
227 .object => @panic("TODO"),
228 inline else => unreachable,
229 };
230 }
231
207232 pub const Index = u32;
208233
209234 pub const Entry = union(enum) {