authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-09 00:04:37-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-09-09 00:04:37-07:00
logf63cd9194c81459d113a57dc7e8ce357f8029728
tree361f0305050a9049b06da4899a03eaf1c70988f6
parent3071ba4272c2a89e892c6a48090496ec0ba46d8c
parent877d6df8f75a7fcfacea572d38f74ac66d045f32
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #25191 from ziglang/fix-linker-undef-memory

fix linker writing undefined memory to output file

11 files changed, 66 insertions(+), 61 deletions(-)

lib/std/Io/Writer.zig+5
......@@ -865,6 +865,11 @@ pub inline fn writeSliceEndian(
865865 slice: []const Elem,
866866 endian: std.builtin.Endian,
867867) Error!void {
868 switch (@typeInfo(Elem)) {
869 .@"struct" => |info| comptime assert(info.layout != .auto),
870 .int, .@"enum" => {},
871 else => @compileError("ill-defined memory layout"),
872 }
868873 if (native_endian == endian) {
869874 return writeAll(w, @ptrCast(slice));
870875 } else {
src/link/Coff.zig+36-37
......@@ -1,4 +1,38 @@
11//! The main driver of the self-hosted COFF linker.
2const Coff = @This();
3
4const std = @import("std");
5const build_options = @import("build_options");
6const builtin = @import("builtin");
7const assert = std.debug.assert;
8const coff_util = std.coff;
9const fmt = std.fmt;
10const fs = std.fs;
11const log = std.log.scoped(.link);
12const math = std.math;
13const mem = std.mem;
14
15const Allocator = std.mem.Allocator;
16const Path = std.Build.Cache.Path;
17const Directory = std.Build.Cache.Directory;
18const Cache = std.Build.Cache;
19
20const aarch64_util = link.aarch64;
21const allocPrint = std.fmt.allocPrint;
22const codegen = @import("../codegen.zig");
23const link = @import("../link.zig");
24const target_util = @import("../target.zig");
25const trace = @import("../tracy.zig").trace;
26
27const Compilation = @import("../Compilation.zig");
28const Zcu = @import("../Zcu.zig");
29const InternPool = @import("../InternPool.zig");
30const TableSection = @import("table_section.zig").TableSection;
31const StringTable = @import("StringTable.zig");
32const Type = @import("../Type.zig");
33const Value = @import("../Value.zig");
34const AnalUnit = InternPool.AnalUnit;
35const dev = @import("../dev.zig");
236
337base: link.File,
438image_base: u64,
......@@ -2168,12 +2202,12 @@ fn writeStrtab(coff: *Coff) !void {
21682202
21692203fn writeSectionHeaders(coff: *Coff) !void {
21702204 const offset = coff.getSectionHeadersOffset();
2171 try coff.pwriteAll(mem.sliceAsBytes(coff.sections.items(.header)), offset);
2205 try coff.pwriteAll(@ptrCast(coff.sections.items(.header)), offset);
21722206}
21732207
21742208fn writeDataDirectoriesHeaders(coff: *Coff) !void {
21752209 const offset = coff.getDataDirectoryHeadersOffset();
2176 try coff.pwriteAll(mem.sliceAsBytes(&coff.data_directories), offset);
2210 try coff.pwriteAll(@ptrCast(&coff.data_directories), offset);
21772211}
21782212
21792213fn writeHeader(coff: *Coff) !void {
......@@ -3068,41 +3102,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi
30683102 };
30693103}
30703104
3071const Coff = @This();
3072
3073const std = @import("std");
3074const build_options = @import("build_options");
3075const builtin = @import("builtin");
3076const assert = std.debug.assert;
3077const coff_util = std.coff;
3078const fmt = std.fmt;
3079const fs = std.fs;
3080const log = std.log.scoped(.link);
3081const math = std.math;
3082const mem = std.mem;
3083
3084const Allocator = std.mem.Allocator;
3085const Path = std.Build.Cache.Path;
3086const Directory = std.Build.Cache.Directory;
3087const Cache = std.Build.Cache;
3088
3089const aarch64_util = link.aarch64;
3090const allocPrint = std.fmt.allocPrint;
3091const codegen = @import("../codegen.zig");
3092const link = @import("../link.zig");
3093const target_util = @import("../target.zig");
3094const trace = @import("../tracy.zig").trace;
3095
3096const Compilation = @import("../Compilation.zig");
3097const Zcu = @import("../Zcu.zig");
3098const InternPool = @import("../InternPool.zig");
3099const TableSection = @import("table_section.zig").TableSection;
3100const StringTable = @import("StringTable.zig");
3101const Type = @import("../Type.zig");
3102const Value = @import("../Value.zig");
3103const AnalUnit = InternPool.AnalUnit;
3104const dev = @import("../dev.zig");
3105
31063105/// This is the start of a Portable Executable (PE) file.
31073106/// It starts with a MS-DOS header followed by a MS-DOS stub program.
31083107/// This data does not change so we include it as follows in all binaries.
src/link/Elf.zig+9-9
......@@ -1465,7 +1465,7 @@ pub fn writeShdrTable(self: *Elf) !void {
14651465 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
14661466 }
14671467 }
1468 try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
1468 try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
14691469 },
14701470 .p64 => {
14711471 const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);
......@@ -1478,7 +1478,7 @@ pub fn writeShdrTable(self: *Elf) !void {
14781478 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
14791479 }
14801480 }
1481 try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
1481 try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
14821482 },
14831483 }
14841484}
......@@ -1505,7 +1505,7 @@ fn writePhdrTable(self: *Elf) !void {
15051505 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
15061506 }
15071507 }
1508 try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1508 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
15091509 },
15101510 .p64 => {
15111511 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
......@@ -1517,7 +1517,7 @@ fn writePhdrTable(self: *Elf) !void {
15171517 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
15181518 }
15191519 }
1520 try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
1520 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
15211521 },
15221522 }
15231523}
......@@ -3157,7 +3157,7 @@ fn writeSyntheticSections(self: *Elf) !void {
31573157
31583158 if (self.section_indexes.versym) |shndx| {
31593159 const shdr = slice.items(.shdr)[shndx];
3160 try self.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);
3160 try self.pwriteAll(@ptrCast(self.versym.items), shdr.sh_offset);
31613161 }
31623162
31633163 if (self.section_indexes.verneed) |shndx| {
......@@ -3226,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {
32263226 try self.got.addRela(self);
32273227 try self.copy_rel.addRela(self);
32283228 self.sortRelaDyn();
3229 try self.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
3229 try self.pwriteAll(@ptrCast(self.rela_dyn.items), shdr.sh_offset);
32303230 }
32313231
32323232 if (self.section_indexes.plt) |shndx| {
......@@ -3256,7 +3256,7 @@ fn writeSyntheticSections(self: *Elf) !void {
32563256 if (self.section_indexes.rela_plt) |shndx| {
32573257 const shdr = slice.items(.shdr)[shndx];
32583258 try self.plt.addRela(self);
3259 try self.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);
3259 try self.pwriteAll(@ptrCast(self.rela_plt.items), shdr.sh_offset);
32603260 }
32613261
32623262 try self.writeSymtab();
......@@ -3364,13 +3364,13 @@ pub fn writeSymtab(self: *Elf) !void {
33643364 };
33653365 if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
33663366 }
3367 try self.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset);
3367 try self.pwriteAll(@ptrCast(buf), symtab_shdr.sh_offset);
33683368 },
33693369 .p64 => {
33703370 if (foreign_endian) {
33713371 for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
33723372 }
3373 try self.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset);
3373 try self.pwriteAll(@ptrCast(self.symtab.items), symtab_shdr.sh_offset);
33743374 },
33753375 }
33763376
src/link/Elf/eh_frame.zig+2-2
......@@ -482,7 +482,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
482482 );
483483 try writer.writeInt(u32, num_fdes, .little);
484484
485 const Entry = struct {
485 const Entry = extern struct {
486486 init_addr: u32,
487487 fde_addr: u32,
488488
......@@ -520,7 +520,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
520520 }
521521
522522 std.mem.sort(Entry, entries.items, {}, Entry.lessThan);
523 try writer.writeAll(std.mem.sliceAsBytes(entries.items));
523 try writer.writeSliceEndian(Entry, entries.items, .little);
524524}
525525
526526const eh_frame_hdr_header_size: usize = 12;
src/link/Elf/relocatable.zig+2-2
......@@ -397,7 +397,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
397397 shdr.sh_offset + shdr.sh_size,
398398 });
399399
400 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
400 try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset);
401401 }
402402
403403 if (elf_file.section_indexes.eh_frame) |shndx| {
......@@ -435,7 +435,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
435435 shdr.sh_offset,
436436 shdr.sh_offset + shdr.sh_size,
437437 });
438 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
438 try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset);
439439 }
440440
441441 try writeGroups(elf_file);
src/link/Elf/synthetic_sections.zig+5-5
......@@ -1265,7 +1265,7 @@ pub const GnuHashSection = struct {
12651265 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
12661266 }
12671267
1268 try writer.writeAll(mem.sliceAsBytes(bloom));
1268 try writer.writeSliceEndian(u64, bloom, .little);
12691269
12701270 // Fill in the hash bucket indices
12711271 const buckets = try gpa.alloc(u32, hash.num_buckets);
......@@ -1278,7 +1278,7 @@ pub const GnuHashSection = struct {
12781278 }
12791279 }
12801280
1281 try writer.writeAll(mem.sliceAsBytes(buckets));
1281 try writer.writeSliceEndian(u32, buckets, .little);
12821282
12831283 // Finally, write the hash table
12841284 const table = try gpa.alloc(u32, hash.num_exports);
......@@ -1294,7 +1294,7 @@ pub const GnuHashSection = struct {
12941294 }
12951295 }
12961296
1297 try writer.writeAll(mem.sliceAsBytes(table));
1297 try writer.writeSliceEndian(u32, table, .little);
12981298 }
12991299
13001300 pub fn hasher(name: [:0]const u8) u32 {
......@@ -1442,8 +1442,8 @@ pub const VerneedSection = struct {
14421442 }
14431443
14441444 pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
1445 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));
1446 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));
1445 try writer.writeSliceEndian(elf.Elf64_Verneed, vern.verneed.items, .little);
1446 try writer.writeSliceEndian(elf.Vernaux, vern.vernaux.items, .little);
14471447 }
14481448};
14491449
src/link/MachO.zig+1-1
......@@ -2711,7 +2711,7 @@ pub fn writeSymtabToFile(self: *MachO) !void {
27112711 const tracy = trace(@src());
27122712 defer tracy.end();
27132713 const cmd = self.symtab_cmd;
2714 try self.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
2714 try self.pwriteAll(@ptrCast(self.symtab.items), cmd.symoff);
27152715 try self.pwriteAll(self.strtab.items, cmd.stroff);
27162716}
27172717
src/link/MachO/DebugSymbols.zig+1-1
......@@ -403,7 +403,7 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
403403 internal.writeSymtab(macho_file, self);
404404 }
405405
406 try self.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
406 try self.file.?.pwriteAll(@ptrCast(self.symtab.items), cmd.symoff);
407407
408408 return off + cmd.nsyms * @sizeOf(macho.nlist_64);
409409}
src/link/MachO/UnwindInfo.zig+1-1
......@@ -311,7 +311,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
311311 .indexCount = indexes_count,
312312 }), .little);
313313
314 try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
314 try writer.writeSliceEndian(Encoding, info.common_encodings[0..info.common_encodings_count], .little);
315315
316316 for (info.personalities[0..info.personalities_count]) |ref| {
317317 const sym = ref.getSymbol(macho_file).?;
src/link/MachO/relocatable.zig+2-2
......@@ -676,11 +676,11 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
676676 const slice = macho_file.sections.slice();
677677 for (slice.items(.header), slice.items(.out), slice.items(.relocs)) |header, out, relocs| {
678678 try macho_file.pwriteAll(out.items, header.offset);
679 try macho_file.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
679 try macho_file.pwriteAll(@ptrCast(relocs.items), header.reloff);
680680 }
681681
682682 try macho_file.writeDataInCode();
683 try macho_file.pwriteAll(mem.sliceAsBytes(macho_file.symtab.items), macho_file.symtab_cmd.symoff);
683 try macho_file.pwriteAll(@ptrCast(macho_file.symtab.items), macho_file.symtab_cmd.symoff);
684684 try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
685685}
686686
src/link/SpirV.zig+2-1
......@@ -285,7 +285,8 @@ pub fn flush(
285285 else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),
286286 };
287287
288 linker.base.file.?.writeAll(std.mem.sliceAsBytes(linked_module)) catch |err|
288 // TODO endianness bug. use file writer and call writeSliceEndian instead
289 linker.base.file.?.writeAll(@ptrCast(linked_module)) catch |err|
289290 return diags.fail("failed to write: {s}", .{@errorName(err)});
290291}
291292