From af1e196db3bca66c29979c685b1c9c896c275211 Mon Sep 17 00:00:00 2001 From: Kendall Condon Date: Sun, 2 Nov 2025 09:57:15 -0500 Subject: [PATCH] align end of elf archives The end of the archive needs to also be aligned to a two-byte boundary, not just the start of records. This was causing lld to reject archives. Notably, this was happening with compiler_rt when rebuilding in fuzz mode, which is why this commit is included in this patchset. --- lib/std/Build/Step/CheckObject.zig | 6 +++++- src/link/Elf/relocatable.zig | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index ac8fafaa3fc965e808466c4573a7a6746c683097..ad44138f3128db3391b2822ffc91263068009d93 100644 --- a/lib/std/Build/Step/CheckObject.zig +++ b/lib/std/Build/Step/CheckObject.zig @@ -1702,6 +1702,10 @@ const ElfDumper = struct { return error.InvalidArchiveMagicNumber; } + if (!mem.isAligned(bytes.len, 2)) { + return error.InvalidArchivePadding; + } + var ctx = ArchiveContext{ .gpa = gpa, .data = bytes, @@ -1715,8 +1719,8 @@ const ElfDumper = struct { } while (true) { - if (reader.seek >= ctx.data.len) break; if (!mem.isAligned(reader.seek, 2)) reader.seek += 1; + if (reader.seek >= ctx.data.len) break; const hdr = try reader.takeStruct(elf.ar_hdr, .little); diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 74ea71ce9d063b73880582335a45178a418f1366..864f7bf4185e88847f7072337d5abf84f0e1df42 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -95,10 +95,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { const total_size: usize = blk: { var pos: usize = elf.ARMAG.len; pos += @sizeOf(elf.ar_hdr) + ar_symtab.size(.p64); + pos = mem.alignForward(usize, pos, 2); if (ar_strtab.size() > 0) { - pos = mem.alignForward(usize, pos, 2); pos += @sizeOf(elf.ar_hdr) + ar_strtab.size(); + pos = mem.alignForward(usize, pos, 2); } for (files.items) |index| { @@ -108,9 +109,9 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { .object => |x| &x.output_ar_state, else => unreachable, }; - pos = mem.alignForward(usize, pos, 2); state.file_off = pos; pos += @sizeOf(elf.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow); + pos = mem.alignForward(usize, pos, 2); } break :blk pos; @@ -131,17 +132,18 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void { // Write symtab try ar_symtab.write(.p64, elf_file, &writer); + if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); // Write strtab if (ar_strtab.size() > 0) { - if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); try ar_strtab.write(&writer); + if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); } // Write object files for (files.items) |index| { - if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); try elf_file.file(index).?.writeAr(elf_file, &writer); + if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0); } assert(writer.buffered().len == total_size); -- 2.54.0