From e3b82eaa661bc964f62a9481ac9ebfe35cf3bb87 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sat, 4 Nov 2023 00:08:55 +0100 Subject: elf: do not store filename in strtab unless longer than 15 chars --- src/link/Elf.zig | 16 +++++++++++----- src/link/Elf/Archive.zig | 24 +++++++++++++++--------- src/link/Elf/ZigObject.zig | 10 ++++++++-- 3 files changed, 34 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 75df6ce40a..b2ac2b687a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1572,8 +1572,11 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void 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(); + + if (ar_strtab.size() > 0) { + pos = mem.alignForward(u64, pos, 2); + pos += @sizeOf(Archive.ar_hdr) + ar_strtab.size(); + } if (self.zigObjectPtr()) |zig_object| { pos = mem.alignForward(u64, pos, 2); @@ -1598,19 +1601,22 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void // 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); + if (ar_strtab.size() > 0) { + if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); + try ar_strtab.write(buffer.writer()); + } // Write object files if (self.zigObjectPtr()) |zig_object| { + if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); try zig_object.writeAr(self, buffer.writer()); } assert(buffer.items.len == total_size); + try self.base.file.?.setEndPos(total_size); try self.base.file.?.pwriteAll(buffer.items, 0); } diff --git a/src/link/Elf/Archive.zig b/src/link/Elf/Archive.zig index 59576312e8..58a9e541a7 100644 --- a/src/link/Elf/Archive.zig +++ b/src/link/Elf/Archive.zig @@ -61,14 +61,15 @@ pub fn parse(self: *Archive, elf_file: *Elf) !void { const object_name = blk: { if (name[0] == '/') { const off = try std.fmt.parseInt(u32, name[1..], 10); - break :blk self.getString(off); + const object_name = self.getString(off); + break :blk try gpa.dupe(u8, object_name[0 .. object_name.len - 1]); // To account for trailing '/' } - break :blk name; + break :blk try gpa.dupe(u8, name); }; const object = Object{ .archive = try gpa.dupe(u8, self.path), - .path = try gpa.dupe(u8, object_name[0 .. object_name.len - 1]), // To account for trailing '/' + .path = object_name, .data = try gpa.dupe(u8, self.data[stream.pos..][0..size]), .index = undefined, .alive = false, @@ -86,8 +87,12 @@ fn getString(self: Archive, off: u32) []const u8 { } pub fn setArHdr(opts: struct { - kind: enum { symtab, strtab, object }, - name_off: u32, + name: union(enum) { + symtab: void, + strtab: void, + name: []const u8, + name_off: u32, + }, size: u32, }) ar_hdr { var hdr: ar_hdr = .{ @@ -105,10 +110,11 @@ pub fn setArHdr(opts: struct { { var stream = std.io.fixedBufferStream(&hdr.ar_name); const writer = stream.writer(); - switch (opts.kind) { + switch (opts.name) { .symtab => writer.print("{s}", .{Archive.SYM64NAME}) catch unreachable, .strtab => writer.print("//", .{}) catch unreachable, - .object => writer.print("/{d}", .{opts.name_off}) catch unreachable, + .name => |x| writer.print("{s}", .{x}) catch unreachable, + .name_off => |x| writer.print("/{d}", .{x}) catch unreachable, } } { @@ -213,7 +219,7 @@ pub const ArSymtab = struct { 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)) }); + const hdr = setArHdr(.{ .name = .symtab, .size = @intCast(ar.size(.p64)) }); try writer.writeAll(mem.asBytes(&hdr)); const gpa = elf_file.base.allocator; @@ -314,7 +320,7 @@ pub const ArStrtab = struct { } pub fn write(ar: ArStrtab, writer: anytype) !void { - const hdr = setArHdr(.{ .kind = .strtab, .name_off = 0, .size = @intCast(ar.size()) }); + const hdr = setArHdr(.{ .name = .strtab, .size = @intCast(ar.size()) }); try writer.writeAll(mem.asBytes(&hdr)); try writer.writeAll(ar.buffer.items); } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index bd5ba04834..5442d9a4bb 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -526,6 +526,7 @@ pub fn updateArStrtab( ) 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; } @@ -540,13 +541,18 @@ pub fn updateArSize(self: *ZigObject, elf_file: *Elf) void { 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 name = try std.fmt.allocPrint(gpa, "{s}.o", .{std.fs.path.stem(self.path)}); + defer gpa.free(name); + const hdr = Archive.setArHdr(.{ - .kind = .object, - .name_off = self.output_ar_state.name_off, + .name = if (name.len <= 15) .{ .name = name } else .{ .name_off = self.output_ar_state.name_off }, .size = @intCast(self.output_ar_state.size), }); try writer.writeAll(mem.asBytes(&hdr)); -- cgit v1.2.3