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(...@@ -865,6 +865,11 @@ pub inline fn writeSliceEndian(
865 slice: []const Elem,865 slice: []const Elem,
866 endian: std.builtin.Endian,866 endian: std.builtin.Endian,
867) Error!void {867) 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 }
868 if (native_endian == endian) {873 if (native_endian == endian) {
869 return writeAll(w, @ptrCast(slice));874 return writeAll(w, @ptrCast(slice));
870 } else {875 } else {
src/link/Coff.zig+36-37
...@@ -1,4 +1,38 @@...@@ -1,4 +1,38 @@
1//! The main driver of the self-hosted COFF linker.1//! 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
3base: link.File,37base: link.File,
4image_base: u64,38image_base: u64,
...@@ -2168,12 +2202,12 @@ fn writeStrtab(coff: *Coff) !void {...@@ -2168,12 +2202,12 @@ fn writeStrtab(coff: *Coff) !void {
21682202
2169fn writeSectionHeaders(coff: *Coff) !void {2203fn writeSectionHeaders(coff: *Coff) !void {
2170 const offset = coff.getSectionHeadersOffset();2204 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);
2172}2206}
21732207
2174fn writeDataDirectoriesHeaders(coff: *Coff) !void {2208fn writeDataDirectoriesHeaders(coff: *Coff) !void {
2175 const offset = coff.getDataDirectoryHeadersOffset();2209 const offset = coff.getDataDirectoryHeadersOffset();
2176 try coff.pwriteAll(mem.sliceAsBytes(&coff.data_directories), offset);2210 try coff.pwriteAll(@ptrCast(&coff.data_directories), offset);
2177}2211}
21782212
2179fn writeHeader(coff: *Coff) !void {2213fn writeHeader(coff: *Coff) !void {
...@@ -3068,41 +3102,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi...@@ -3068,41 +3102,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi
3068 };3102 };
3069}3103}
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
3106/// This is the start of a Portable Executable (PE) file.3105/// This is the start of a Portable Executable (PE) file.
3107/// It starts with a MS-DOS header followed by a MS-DOS stub program.3106/// It starts with a MS-DOS header followed by a MS-DOS stub program.
3108/// This data does not change so we include it as follows in all binaries.3107/// 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 {...@@ -1465,7 +1465,7 @@ pub fn writeShdrTable(self: *Elf) !void {
1465 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);1465 mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
1466 }1466 }
1467 }1467 }
1468 try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);1468 try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
1469 },1469 },
1470 .p64 => {1470 .p64 => {
1471 const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);1471 const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);
...@@ -1478,7 +1478,7 @@ pub fn writeShdrTable(self: *Elf) !void {...@@ -1478,7 +1478,7 @@ pub fn writeShdrTable(self: *Elf) !void {
1478 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);1478 mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
1479 }1479 }
1480 }1480 }
1481 try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);1481 try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
1482 },1482 },
1483 }1483 }
1484}1484}
...@@ -1505,7 +1505,7 @@ fn writePhdrTable(self: *Elf) !void {...@@ -1505,7 +1505,7 @@ fn writePhdrTable(self: *Elf) !void {
1505 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);1505 mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
1506 }1506 }
1507 }1507 }
1508 try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);1508 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
1509 },1509 },
1510 .p64 => {1510 .p64 => {
1511 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);1511 const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
...@@ -1517,7 +1517,7 @@ fn writePhdrTable(self: *Elf) !void {...@@ -1517,7 +1517,7 @@ fn writePhdrTable(self: *Elf) !void {
1517 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);1517 mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
1518 }1518 }
1519 }1519 }
1520 try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);1520 try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
1521 },1521 },
1522 }1522 }
1523}1523}
...@@ -3157,7 +3157,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3157,7 +3157,7 @@ fn writeSyntheticSections(self: *Elf) !void {
31573157
3158 if (self.section_indexes.versym) |shndx| {3158 if (self.section_indexes.versym) |shndx| {
3159 const shdr = slice.items(.shdr)[shndx];3159 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);
3161 }3161 }
31623162
3163 if (self.section_indexes.verneed) |shndx| {3163 if (self.section_indexes.verneed) |shndx| {
...@@ -3226,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3226,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3226 try self.got.addRela(self);3226 try self.got.addRela(self);
3227 try self.copy_rel.addRela(self);3227 try self.copy_rel.addRela(self);
3228 self.sortRelaDyn();3228 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);
3230 }3230 }
32313231
3232 if (self.section_indexes.plt) |shndx| {3232 if (self.section_indexes.plt) |shndx| {
...@@ -3256,7 +3256,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -3256,7 +3256,7 @@ fn writeSyntheticSections(self: *Elf) !void {
3256 if (self.section_indexes.rela_plt) |shndx| {3256 if (self.section_indexes.rela_plt) |shndx| {
3257 const shdr = slice.items(.shdr)[shndx];3257 const shdr = slice.items(.shdr)[shndx];
3258 try self.plt.addRela(self);3258 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);
3260 }3260 }
32613261
3262 try self.writeSymtab();3262 try self.writeSymtab();
...@@ -3364,13 +3364,13 @@ pub fn writeSymtab(self: *Elf) !void {...@@ -3364,13 +3364,13 @@ pub fn writeSymtab(self: *Elf) !void {
3364 };3364 };
3365 if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);3365 if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
3366 }3366 }
3367 try self.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset);3367 try self.pwriteAll(@ptrCast(buf), symtab_shdr.sh_offset);
3368 },3368 },
3369 .p64 => {3369 .p64 => {
3370 if (foreign_endian) {3370 if (foreign_endian) {
3371 for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);3371 for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
3372 }3372 }
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);
3374 },3374 },
3375 }3375 }
33763376
src/link/Elf/eh_frame.zig+2-2
...@@ -482,7 +482,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {...@@ -482,7 +482,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
482 );482 );
483 try writer.writeInt(u32, num_fdes, .little);483 try writer.writeInt(u32, num_fdes, .little);
484484
485 const Entry = struct {485 const Entry = extern struct {
486 init_addr: u32,486 init_addr: u32,
487 fde_addr: u32,487 fde_addr: u32,
488488
...@@ -520,7 +520,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {...@@ -520,7 +520,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
520 }520 }
521521
522 std.mem.sort(Entry, entries.items, {}, Entry.lessThan);522 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);
524}524}
525525
526const eh_frame_hdr_header_size: usize = 12;526const eh_frame_hdr_header_size: usize = 12;
src/link/Elf/relocatable.zig+2-2
...@@ -397,7 +397,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -397,7 +397,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
397 shdr.sh_offset + shdr.sh_size,397 shdr.sh_offset + shdr.sh_size,
398 });398 });
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);
401 }401 }
402402
403 if (elf_file.section_indexes.eh_frame) |shndx| {403 if (elf_file.section_indexes.eh_frame) |shndx| {
...@@ -435,7 +435,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -435,7 +435,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
435 shdr.sh_offset,435 shdr.sh_offset,
436 shdr.sh_offset + shdr.sh_size,436 shdr.sh_offset + shdr.sh_size,
437 });437 });
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);
439 }439 }
440440
441 try writeGroups(elf_file);441 try writeGroups(elf_file);
src/link/Elf/synthetic_sections.zig+5-5
...@@ -1265,7 +1265,7 @@ pub const GnuHashSection = struct {...@@ -1265,7 +1265,7 @@ pub const GnuHashSection = struct {
1265 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));1265 bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
1266 }1266 }
12671267
1268 try writer.writeAll(mem.sliceAsBytes(bloom));1268 try writer.writeSliceEndian(u64, bloom, .little);
12691269
1270 // Fill in the hash bucket indices1270 // Fill in the hash bucket indices
1271 const buckets = try gpa.alloc(u32, hash.num_buckets);1271 const buckets = try gpa.alloc(u32, hash.num_buckets);
...@@ -1278,7 +1278,7 @@ pub const GnuHashSection = struct {...@@ -1278,7 +1278,7 @@ pub const GnuHashSection = struct {
1278 }1278 }
1279 }1279 }
12801280
1281 try writer.writeAll(mem.sliceAsBytes(buckets));1281 try writer.writeSliceEndian(u32, buckets, .little);
12821282
1283 // Finally, write the hash table1283 // Finally, write the hash table
1284 const table = try gpa.alloc(u32, hash.num_exports);1284 const table = try gpa.alloc(u32, hash.num_exports);
...@@ -1294,7 +1294,7 @@ pub const GnuHashSection = struct {...@@ -1294,7 +1294,7 @@ pub const GnuHashSection = struct {
1294 }1294 }
1295 }1295 }
12961296
1297 try writer.writeAll(mem.sliceAsBytes(table));1297 try writer.writeSliceEndian(u32, table, .little);
1298 }1298 }
12991299
1300 pub fn hasher(name: [:0]const u8) u32 {1300 pub fn hasher(name: [:0]const u8) u32 {
...@@ -1442,8 +1442,8 @@ pub const VerneedSection = struct {...@@ -1442,8 +1442,8 @@ pub const VerneedSection = struct {
1442 }1442 }
14431443
1444 pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {1444 pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
1445 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));1445 try writer.writeSliceEndian(elf.Elf64_Verneed, vern.verneed.items, .little);
1446 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));1446 try writer.writeSliceEndian(elf.Vernaux, vern.vernaux.items, .little);
1447 }1447 }
1448};1448};
14491449
src/link/MachO.zig+1-1
...@@ -2711,7 +2711,7 @@ pub fn writeSymtabToFile(self: *MachO) !void {...@@ -2711,7 +2711,7 @@ pub fn writeSymtabToFile(self: *MachO) !void {
2711 const tracy = trace(@src());2711 const tracy = trace(@src());
2712 defer tracy.end();2712 defer tracy.end();
2713 const cmd = self.symtab_cmd;2713 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);
2715 try self.pwriteAll(self.strtab.items, cmd.stroff);2715 try self.pwriteAll(self.strtab.items, cmd.stroff);
2716}2716}
27172717
src/link/MachO/DebugSymbols.zig+1-1
...@@ -403,7 +403,7 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {...@@ -403,7 +403,7 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
403 internal.writeSymtab(macho_file, self);403 internal.writeSymtab(macho_file, self);
404 }404 }
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
408 return off + cmd.nsyms * @sizeOf(macho.nlist_64);408 return off + cmd.nsyms * @sizeOf(macho.nlist_64);
409}409}
src/link/MachO/UnwindInfo.zig+1-1
...@@ -311,7 +311,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {...@@ -311,7 +311,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
311 .indexCount = indexes_count,311 .indexCount = indexes_count,
312 }), .little);312 }), .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
316 for (info.personalities[0..info.personalities_count]) |ref| {316 for (info.personalities[0..info.personalities_count]) |ref| {
317 const sym = ref.getSymbol(macho_file).?;317 const sym = ref.getSymbol(macho_file).?;
src/link/MachO/relocatable.zig+2-2
...@@ -676,11 +676,11 @@ fn writeSectionsToFile(macho_file: *MachO) !void {...@@ -676,11 +676,11 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
676 const slice = macho_file.sections.slice();676 const slice = macho_file.sections.slice();
677 for (slice.items(.header), slice.items(.out), slice.items(.relocs)) |header, out, relocs| {677 for (slice.items(.header), slice.items(.out), slice.items(.relocs)) |header, out, relocs| {
678 try macho_file.pwriteAll(out.items, header.offset);678 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);
680 }680 }
681681
682 try macho_file.writeDataInCode();682 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);
684 try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);684 try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
685}685}
686686
src/link/SpirV.zig+2-1
...@@ -285,7 +285,8 @@ pub fn flush(...@@ -285,7 +285,8 @@ pub fn flush(
285 else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),285 else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),
286 };286 };
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|
289 return diags.fail("failed to write: {s}", .{@errorName(err)});290 return diags.fail("failed to write: {s}", .{@errorName(err)});
290}291}
291292