mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge pull request #25191 from ziglang/fix-linker-undef-memory
fix linker writing undefined memory to output file
This commit is contained in:
commit
f63cd9194c
11 changed files with 66 additions and 61 deletions
|
|
@ -865,6 +865,11 @@ pub inline fn writeSliceEndian(
|
||||||
slice: []const Elem,
|
slice: []const Elem,
|
||||||
endian: std.builtin.Endian,
|
endian: std.builtin.Endian,
|
||||||
) Error!void {
|
) Error!void {
|
||||||
|
switch (@typeInfo(Elem)) {
|
||||||
|
.@"struct" => |info| comptime assert(info.layout != .auto),
|
||||||
|
.int, .@"enum" => {},
|
||||||
|
else => @compileError("ill-defined memory layout"),
|
||||||
|
}
|
||||||
if (native_endian == endian) {
|
if (native_endian == endian) {
|
||||||
return writeAll(w, @ptrCast(slice));
|
return writeAll(w, @ptrCast(slice));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,38 @@
|
||||||
//! The main driver of the self-hosted COFF linker.
|
//! The main driver of the self-hosted COFF linker.
|
||||||
|
const Coff = @This();
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const build_options = @import("build_options");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const coff_util = std.coff;
|
||||||
|
const fmt = std.fmt;
|
||||||
|
const fs = std.fs;
|
||||||
|
const log = std.log.scoped(.link);
|
||||||
|
const math = std.math;
|
||||||
|
const mem = std.mem;
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
const Path = std.Build.Cache.Path;
|
||||||
|
const Directory = std.Build.Cache.Directory;
|
||||||
|
const Cache = std.Build.Cache;
|
||||||
|
|
||||||
|
const aarch64_util = link.aarch64;
|
||||||
|
const allocPrint = std.fmt.allocPrint;
|
||||||
|
const codegen = @import("../codegen.zig");
|
||||||
|
const link = @import("../link.zig");
|
||||||
|
const target_util = @import("../target.zig");
|
||||||
|
const trace = @import("../tracy.zig").trace;
|
||||||
|
|
||||||
|
const Compilation = @import("../Compilation.zig");
|
||||||
|
const Zcu = @import("../Zcu.zig");
|
||||||
|
const InternPool = @import("../InternPool.zig");
|
||||||
|
const TableSection = @import("table_section.zig").TableSection;
|
||||||
|
const StringTable = @import("StringTable.zig");
|
||||||
|
const Type = @import("../Type.zig");
|
||||||
|
const Value = @import("../Value.zig");
|
||||||
|
const AnalUnit = InternPool.AnalUnit;
|
||||||
|
const dev = @import("../dev.zig");
|
||||||
|
|
||||||
base: link.File,
|
base: link.File,
|
||||||
image_base: u64,
|
image_base: u64,
|
||||||
|
|
@ -2168,12 +2202,12 @@ fn writeStrtab(coff: *Coff) !void {
|
||||||
|
|
||||||
fn writeSectionHeaders(coff: *Coff) !void {
|
fn writeSectionHeaders(coff: *Coff) !void {
|
||||||
const offset = coff.getSectionHeadersOffset();
|
const offset = coff.getSectionHeadersOffset();
|
||||||
try coff.pwriteAll(mem.sliceAsBytes(coff.sections.items(.header)), offset);
|
try coff.pwriteAll(@ptrCast(coff.sections.items(.header)), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeDataDirectoriesHeaders(coff: *Coff) !void {
|
fn writeDataDirectoriesHeaders(coff: *Coff) !void {
|
||||||
const offset = coff.getDataDirectoryHeadersOffset();
|
const offset = coff.getDataDirectoryHeadersOffset();
|
||||||
try coff.pwriteAll(mem.sliceAsBytes(&coff.data_directories), offset);
|
try coff.pwriteAll(@ptrCast(&coff.data_directories), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeHeader(coff: *Coff) !void {
|
fn writeHeader(coff: *Coff) !void {
|
||||||
|
|
@ -3068,41 +3102,6 @@ fn pwriteAll(coff: *Coff, bytes: []const u8, offset: u64) error{LinkFailure}!voi
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Coff = @This();
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const build_options = @import("build_options");
|
|
||||||
const builtin = @import("builtin");
|
|
||||||
const assert = std.debug.assert;
|
|
||||||
const coff_util = std.coff;
|
|
||||||
const fmt = std.fmt;
|
|
||||||
const fs = std.fs;
|
|
||||||
const log = std.log.scoped(.link);
|
|
||||||
const math = std.math;
|
|
||||||
const mem = std.mem;
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const Path = std.Build.Cache.Path;
|
|
||||||
const Directory = std.Build.Cache.Directory;
|
|
||||||
const Cache = std.Build.Cache;
|
|
||||||
|
|
||||||
const aarch64_util = link.aarch64;
|
|
||||||
const allocPrint = std.fmt.allocPrint;
|
|
||||||
const codegen = @import("../codegen.zig");
|
|
||||||
const link = @import("../link.zig");
|
|
||||||
const target_util = @import("../target.zig");
|
|
||||||
const trace = @import("../tracy.zig").trace;
|
|
||||||
|
|
||||||
const Compilation = @import("../Compilation.zig");
|
|
||||||
const Zcu = @import("../Zcu.zig");
|
|
||||||
const InternPool = @import("../InternPool.zig");
|
|
||||||
const TableSection = @import("table_section.zig").TableSection;
|
|
||||||
const StringTable = @import("StringTable.zig");
|
|
||||||
const Type = @import("../Type.zig");
|
|
||||||
const Value = @import("../Value.zig");
|
|
||||||
const AnalUnit = InternPool.AnalUnit;
|
|
||||||
const dev = @import("../dev.zig");
|
|
||||||
|
|
||||||
/// This is the start of a Portable Executable (PE) file.
|
/// This is the start of a Portable Executable (PE) file.
|
||||||
/// It starts with a MS-DOS header followed by a MS-DOS stub program.
|
/// It starts with a MS-DOS header followed by a MS-DOS stub program.
|
||||||
/// This data does not change so we include it as follows in all binaries.
|
/// This data does not change so we include it as follows in all binaries.
|
||||||
|
|
|
||||||
|
|
@ -1465,7 +1465,7 @@ pub fn writeShdrTable(self: *Elf) !void {
|
||||||
mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
|
mem.byteSwapAllFields(elf.Elf32_Shdr, shdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
|
try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
|
||||||
},
|
},
|
||||||
.p64 => {
|
.p64 => {
|
||||||
const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);
|
const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len);
|
||||||
|
|
@ -1478,7 +1478,7 @@ pub fn writeShdrTable(self: *Elf) !void {
|
||||||
mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
|
mem.byteSwapAllFields(elf.Elf64_Shdr, shdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
|
try self.pwriteAll(@ptrCast(buf), self.shdr_table_offset.?);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1505,7 +1505,7 @@ fn writePhdrTable(self: *Elf) !void {
|
||||||
mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
|
mem.byteSwapAllFields(elf.Elf32_Phdr, phdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
|
try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
|
||||||
},
|
},
|
||||||
.p64 => {
|
.p64 => {
|
||||||
const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
|
const buf = try gpa.alloc(elf.Elf64_Phdr, self.phdrs.items.len);
|
||||||
|
|
@ -1517,7 +1517,7 @@ fn writePhdrTable(self: *Elf) !void {
|
||||||
mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
|
mem.byteSwapAllFields(elf.Elf64_Phdr, phdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset);
|
try self.pwriteAll(@ptrCast(buf), phdr_table.p_offset);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3157,7 +3157,7 @@ fn writeSyntheticSections(self: *Elf) !void {
|
||||||
|
|
||||||
if (self.section_indexes.versym) |shndx| {
|
if (self.section_indexes.versym) |shndx| {
|
||||||
const shdr = slice.items(.shdr)[shndx];
|
const shdr = slice.items(.shdr)[shndx];
|
||||||
try self.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);
|
try self.pwriteAll(@ptrCast(self.versym.items), shdr.sh_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.section_indexes.verneed) |shndx| {
|
if (self.section_indexes.verneed) |shndx| {
|
||||||
|
|
@ -3226,7 +3226,7 @@ fn writeSyntheticSections(self: *Elf) !void {
|
||||||
try self.got.addRela(self);
|
try self.got.addRela(self);
|
||||||
try self.copy_rel.addRela(self);
|
try self.copy_rel.addRela(self);
|
||||||
self.sortRelaDyn();
|
self.sortRelaDyn();
|
||||||
try self.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
|
try self.pwriteAll(@ptrCast(self.rela_dyn.items), shdr.sh_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.section_indexes.plt) |shndx| {
|
if (self.section_indexes.plt) |shndx| {
|
||||||
|
|
@ -3256,7 +3256,7 @@ fn writeSyntheticSections(self: *Elf) !void {
|
||||||
if (self.section_indexes.rela_plt) |shndx| {
|
if (self.section_indexes.rela_plt) |shndx| {
|
||||||
const shdr = slice.items(.shdr)[shndx];
|
const shdr = slice.items(.shdr)[shndx];
|
||||||
try self.plt.addRela(self);
|
try self.plt.addRela(self);
|
||||||
try self.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);
|
try self.pwriteAll(@ptrCast(self.rela_plt.items), shdr.sh_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.writeSymtab();
|
try self.writeSymtab();
|
||||||
|
|
@ -3364,13 +3364,13 @@ pub fn writeSymtab(self: *Elf) !void {
|
||||||
};
|
};
|
||||||
if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
|
if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset);
|
try self.pwriteAll(@ptrCast(buf), symtab_shdr.sh_offset);
|
||||||
},
|
},
|
||||||
.p64 => {
|
.p64 => {
|
||||||
if (foreign_endian) {
|
if (foreign_endian) {
|
||||||
for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
|
for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
|
||||||
}
|
}
|
||||||
try self.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset);
|
try self.pwriteAll(@ptrCast(self.symtab.items), symtab_shdr.sh_offset);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
|
||||||
);
|
);
|
||||||
try writer.writeInt(u32, num_fdes, .little);
|
try writer.writeInt(u32, num_fdes, .little);
|
||||||
|
|
||||||
const Entry = struct {
|
const Entry = extern struct {
|
||||||
init_addr: u32,
|
init_addr: u32,
|
||||||
fde_addr: u32,
|
fde_addr: u32,
|
||||||
|
|
||||||
|
|
@ -520,7 +520,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
std.mem.sort(Entry, entries.items, {}, Entry.lessThan);
|
std.mem.sort(Entry, entries.items, {}, Entry.lessThan);
|
||||||
try writer.writeAll(std.mem.sliceAsBytes(entries.items));
|
try writer.writeSliceEndian(Entry, entries.items, .little);
|
||||||
}
|
}
|
||||||
|
|
||||||
const eh_frame_hdr_header_size: usize = 12;
|
const eh_frame_hdr_header_size: usize = 12;
|
||||||
|
|
|
||||||
|
|
@ -397,7 +397,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
|
||||||
shdr.sh_offset + shdr.sh_size,
|
shdr.sh_offset + shdr.sh_size,
|
||||||
});
|
});
|
||||||
|
|
||||||
try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
|
try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_file.section_indexes.eh_frame) |shndx| {
|
if (elf_file.section_indexes.eh_frame) |shndx| {
|
||||||
|
|
@ -435,7 +435,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
|
||||||
shdr.sh_offset,
|
shdr.sh_offset,
|
||||||
shdr.sh_offset + shdr.sh_size,
|
shdr.sh_offset + shdr.sh_size,
|
||||||
});
|
});
|
||||||
try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
|
try elf_file.base.file.?.pwriteAll(@ptrCast(relocs.items), shdr.sh_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
try writeGroups(elf_file);
|
try writeGroups(elf_file);
|
||||||
|
|
|
||||||
|
|
@ -1265,7 +1265,7 @@ pub const GnuHashSection = struct {
|
||||||
bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
|
bloom[idx] |= @as(u64, 1) << @as(u6, @intCast((h >> bloom_shift) % 64));
|
||||||
}
|
}
|
||||||
|
|
||||||
try writer.writeAll(mem.sliceAsBytes(bloom));
|
try writer.writeSliceEndian(u64, bloom, .little);
|
||||||
|
|
||||||
// Fill in the hash bucket indices
|
// Fill in the hash bucket indices
|
||||||
const buckets = try gpa.alloc(u32, hash.num_buckets);
|
const buckets = try gpa.alloc(u32, hash.num_buckets);
|
||||||
|
|
@ -1278,7 +1278,7 @@ pub const GnuHashSection = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try writer.writeAll(mem.sliceAsBytes(buckets));
|
try writer.writeSliceEndian(u32, buckets, .little);
|
||||||
|
|
||||||
// Finally, write the hash table
|
// Finally, write the hash table
|
||||||
const table = try gpa.alloc(u32, hash.num_exports);
|
const table = try gpa.alloc(u32, hash.num_exports);
|
||||||
|
|
@ -1294,7 +1294,7 @@ pub const GnuHashSection = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try writer.writeAll(mem.sliceAsBytes(table));
|
try writer.writeSliceEndian(u32, table, .little);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasher(name: [:0]const u8) u32 {
|
pub fn hasher(name: [:0]const u8) u32 {
|
||||||
|
|
@ -1442,8 +1442,8 @@ pub const VerneedSection = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
|
pub fn write(vern: VerneedSection, writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));
|
try writer.writeSliceEndian(elf.Elf64_Verneed, vern.verneed.items, .little);
|
||||||
try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));
|
try writer.writeSliceEndian(elf.Vernaux, vern.vernaux.items, .little);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2711,7 +2711,7 @@ pub fn writeSymtabToFile(self: *MachO) !void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
const cmd = self.symtab_cmd;
|
const cmd = self.symtab_cmd;
|
||||||
try self.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
|
try self.pwriteAll(@ptrCast(self.symtab.items), cmd.symoff);
|
||||||
try self.pwriteAll(self.strtab.items, cmd.stroff);
|
try self.pwriteAll(self.strtab.items, cmd.stroff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -403,7 +403,7 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 {
|
||||||
internal.writeSymtab(macho_file, self);
|
internal.writeSymtab(macho_file, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff);
|
try self.file.?.pwriteAll(@ptrCast(self.symtab.items), cmd.symoff);
|
||||||
|
|
||||||
return off + cmd.nsyms * @sizeOf(macho.nlist_64);
|
return off + cmd.nsyms * @sizeOf(macho.nlist_64);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
|
||||||
.indexCount = indexes_count,
|
.indexCount = indexes_count,
|
||||||
}), .little);
|
}), .little);
|
||||||
|
|
||||||
try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
|
try writer.writeSliceEndian(Encoding, info.common_encodings[0..info.common_encodings_count], .little);
|
||||||
|
|
||||||
for (info.personalities[0..info.personalities_count]) |ref| {
|
for (info.personalities[0..info.personalities_count]) |ref| {
|
||||||
const sym = ref.getSymbol(macho_file).?;
|
const sym = ref.getSymbol(macho_file).?;
|
||||||
|
|
|
||||||
|
|
@ -676,11 +676,11 @@ fn writeSectionsToFile(macho_file: *MachO) !void {
|
||||||
const slice = macho_file.sections.slice();
|
const slice = macho_file.sections.slice();
|
||||||
for (slice.items(.header), slice.items(.out), slice.items(.relocs)) |header, out, relocs| {
|
for (slice.items(.header), slice.items(.out), slice.items(.relocs)) |header, out, relocs| {
|
||||||
try macho_file.pwriteAll(out.items, header.offset);
|
try macho_file.pwriteAll(out.items, header.offset);
|
||||||
try macho_file.pwriteAll(mem.sliceAsBytes(relocs.items), header.reloff);
|
try macho_file.pwriteAll(@ptrCast(relocs.items), header.reloff);
|
||||||
}
|
}
|
||||||
|
|
||||||
try macho_file.writeDataInCode();
|
try macho_file.writeDataInCode();
|
||||||
try macho_file.pwriteAll(mem.sliceAsBytes(macho_file.symtab.items), macho_file.symtab_cmd.symoff);
|
try macho_file.pwriteAll(@ptrCast(macho_file.symtab.items), macho_file.symtab_cmd.symoff);
|
||||||
try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
|
try macho_file.pwriteAll(macho_file.strtab.items, macho_file.symtab_cmd.stroff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,8 @@ pub fn flush(
|
||||||
else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),
|
else => |other| return diags.fail("error while linking: {s}", .{@errorName(other)}),
|
||||||
};
|
};
|
||||||
|
|
||||||
linker.base.file.?.writeAll(std.mem.sliceAsBytes(linked_module)) catch |err|
|
// TODO endianness bug. use file writer and call writeSliceEndian instead
|
||||||
|
linker.base.file.?.writeAll(@ptrCast(linked_module)) catch |err|
|
||||||
return diags.fail("failed to write: {s}", .{@errorName(err)});
|
return diags.fail("failed to write: {s}", .{@errorName(err)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue