authorgravatar for goon.pri.low@gmail.comKendall Condon <goon.pri.low@gmail.com> 2025-11-02 09:57:15-05:00
committergravatar for goon.pri.low@gmail.comKendall Condon <goon.pri.low@gmail.com> 2026-02-13 17:58:09-05:00
logaf1e196db3bca66c29979c685b1c9c896c275211
tree03ab8aa21c4fd56ad91561f8efc48ef6b9a88946
parent3c9024be08f34d2bb38693df38e5b4b334c74f90

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.

2 files changed, 11 insertions(+), 5 deletions(-)

lib/std/Build/Step/CheckObject.zig+5-1
......@@ -1702,6 +1702,10 @@ const ElfDumper = struct {
17021702 return error.InvalidArchiveMagicNumber;
17031703 }
17041704
1705 if (!mem.isAligned(bytes.len, 2)) {
1706 return error.InvalidArchivePadding;
1707 }
1708
17051709 var ctx = ArchiveContext{
17061710 .gpa = gpa,
17071711 .data = bytes,
......@@ -1715,8 +1719,8 @@ const ElfDumper = struct {
17151719 }
17161720
17171721 while (true) {
1718 if (reader.seek >= ctx.data.len) break;
17191722 if (!mem.isAligned(reader.seek, 2)) reader.seek += 1;
1723 if (reader.seek >= ctx.data.len) break;
17201724
17211725 const hdr = try reader.takeStruct(elf.ar_hdr, .little);
17221726
src/link/Elf/relocatable.zig+6-4
......@@ -95,10 +95,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
9595 const total_size: usize = blk: {
9696 var pos: usize = elf.ARMAG.len;
9797 pos += @sizeOf(elf.ar_hdr) + ar_symtab.size(.p64);
98 pos = mem.alignForward(usize, pos, 2);
9899
99100 if (ar_strtab.size() > 0) {
100 pos = mem.alignForward(usize, pos, 2);
101101 pos += @sizeOf(elf.ar_hdr) + ar_strtab.size();
102 pos = mem.alignForward(usize, pos, 2);
102103 }
103104
104105 for (files.items) |index| {
......@@ -108,9 +109,9 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
108109 .object => |x| &x.output_ar_state,
109110 else => unreachable,
110111 };
111 pos = mem.alignForward(usize, pos, 2);
112112 state.file_off = pos;
113113 pos += @sizeOf(elf.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow);
114 pos = mem.alignForward(usize, pos, 2);
114115 }
115116
116117 break :blk pos;
......@@ -131,17 +132,18 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
131132
132133 // Write symtab
133134 try ar_symtab.write(.p64, elf_file, &writer);
135 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
134136
135137 // Write strtab
136138 if (ar_strtab.size() > 0) {
137 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
138139 try ar_strtab.write(&writer);
140 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
139141 }
140142
141143 // Write object files
142144 for (files.items) |index| {
143 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
144145 try elf_file.file(index).?.writeAr(elf_file, &writer);
146 if (!mem.isAligned(writer.end, 2)) try writer.writeByte(0);
145147 }
146148
147149 assert(writer.buffered().len == total_size);