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.
This commit is contained in:
Kendall Condon 2025-11-02 09:57:15 -05:00
parent 3c9024be08
commit af1e196db3
2 changed files with 11 additions and 5 deletions

View file

@ -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);

View file

@ -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);