diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-05 12:56:17 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-05 12:56:17 +0100 |
| commit | 55fa8a04f1853deb473339cdc610cbf012ae0d61 (patch) | |
| tree | e614530b5be669123ed4278d532d7827ae982589 /src | |
| parent | 5c482361034a0b1575ecb719724c942b5709b449 (diff) | |
| download | zig-55fa8a04f1853deb473339cdc610cbf012ae0d61.tar.gz zig-55fa8a04f1853deb473339cdc610cbf012ae0d61.zip | |
elf: add hooks for archiving Objects
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 43 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf/file.zig | 25 |
3 files changed, 51 insertions, 19 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 862f9ba088..6d73e9bf2c 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -939,12 +939,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } else null; const gc_sections = self.base.options.gc_sections orelse false; - if (self.isRelocatable() and self.zig_object_index == null) { - if (self.isStaticLib()) { - var err = try self.addErrorWithNotes(0); - try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{}); - return; - } + if (self.isObject() and self.zig_object_index == null) { // TODO this will become -r route I guess. For now, just copy the object file. assert(self.base.file == null); // TODO uncomment once we implement -r const the_object_path = blk: { @@ -1555,15 +1550,18 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void try self.writeElfHeader(); } - // TODO parse positionals that we want to make part of the archive - - // TODO update ar symtab from parsed positionals + var files = std.ArrayList(File.Index).init(gpa); + defer files.deinit(); + try files.ensureTotalCapacityPrecise(self.objects.items.len + 1); + if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index); + for (self.objects.items) |index| files.appendAssumeCapacity(index); + // Update ar symtab from parsed objects var ar_symtab: Archive.ArSymtab = .{}; defer ar_symtab.deinit(gpa); - if (self.zigObjectPtr()) |zig_object| { - try zig_object.updateArSymtab(&ar_symtab, self); + for (files.items) |index| { + try self.file(index).?.updateArSymtab(&ar_symtab, self); } ar_symtab.sort(); @@ -1572,9 +1570,10 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void var ar_strtab: Archive.ArStrtab = .{}; defer ar_strtab.deinit(gpa); - if (self.zigObjectPtr()) |zig_object| { - try zig_object.updateArStrtab(gpa, &ar_strtab); - zig_object.updateArSize(self); + for (files.items) |index| { + const file_ptr = self.file(index).?; + try file_ptr.updateArStrtab(gpa, &ar_strtab); + file_ptr.updateArSize(self); } // Update file offsets of contributing objects. @@ -1587,10 +1586,16 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void pos += @sizeOf(Archive.ar_hdr) + ar_strtab.size(); } - if (self.zigObjectPtr()) |zig_object| { + for (files.items) |index| { + const file_ptr = self.file(index).?; + const state = switch (file_ptr) { + .zig_object => |x| &x.output_ar_state, + .object => |x| &x.output_ar_state, + else => unreachable, + }; pos = mem.alignForward(usize, pos, 2); - zig_object.output_ar_state.file_off = pos; - pos += @sizeOf(Archive.ar_hdr) + (math.cast(usize, zig_object.output_ar_state.size) orelse return error.Overflow); + state.file_off = pos; + pos += @sizeOf(Archive.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow); } break :blk pos; @@ -1618,9 +1623,9 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void } // Write object files - if (self.zigObjectPtr()) |zig_object| { + for (files.items) |index| { if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); - try zig_object.writeAr(self, buffer.writer()); + try self.file(index).?.writeAr(self, buffer.writer()); } assert(buffer.items.len == total_size); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 8c3c851dbe..673bf08247 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -20,6 +20,7 @@ alive: bool = true, num_dynrelocs: u32 = 0, output_symtab_size: Elf.SymtabSize = .{}, +output_ar_state: Archive.ArState = .{}, pub fn isObject(path: []const u8) !bool { const file = try std.fs.cwd().openFile(path, .{}); @@ -924,6 +925,7 @@ const math = std.math; const mem = std.mem; const Allocator = mem.Allocator; +const Archive = @import("Archive.zig"); const Atom = @import("Atom.zig"); const Cie = eh_frame.Cie; const Elf = @import("../Elf.zig"); diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index e31170a178..ed15ff93f3 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -204,6 +204,31 @@ pub const File = union(enum) { }; } + pub fn updateArStrtab(file: File, allocator: Allocator, ar_strtab: *Archive.ArStrtab) !void { + return switch (file) { + .zig_object => |x| x.updateArStrtab(allocator, ar_strtab), + .object => @panic("TODO"), + inline else => unreachable, + }; + } + + pub fn updateArSize(file: File, elf_file: *Elf) void { + return switch (file) { + .zig_object => |x| x.updateArSize(elf_file), + .object => @panic("TODO"), + inline else => unreachable, + }; + } + + pub fn writeAr(file: File, elf_file: *Elf, writer: anytype) !void { + return switch (file) { + .zig_object => |x| x.writeAr(elf_file, writer), + // .object => |x| x.writeAr(elf_file, writer), + .object => @panic("TODO"), + inline else => unreachable, + }; + } + pub const Index = u32; pub const Entry = union(enum) { |
