Coff: delete

This commit is contained in:
Jacob Young 2025-10-01 15:21:49 -04:00
parent e1f3fc6ce2
commit 1fa11e0954
9 changed files with 85 additions and 3294 deletions

View File

@ -561,7 +561,6 @@ set(ZIG_STAGE2_SOURCES
src/libs/libunwind.zig
src/link.zig
src/link/C.zig
src/link/Coff.zig
src/link/Dwarf.zig
src/link/Elf.zig
src/link/Elf/Archive.zig

View File

@ -3226,7 +3226,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE
.root_dir = comp.dirs.local_cache,
.sub_path = try fs.path.join(arena, &.{ o_sub_path, comp.emit_bin.? }),
};
const result: link.File.OpenError!void = switch (need_writable_dance) {
const result: (link.File.OpenError || error{HotSwapUnavailableOnHostOperatingSystem})!void = switch (need_writable_dance) {
.no => {},
.lf_only => lf.makeWritable(),
.lf_and_debug => res: {

View File

@ -438,8 +438,6 @@ pub fn resolve(options: Options) ResolveError!Config {
if (options.use_new_linker) |x| break :b x;
if (target.ofmt == .coff) break :b true;
break :b options.incremental;
};

View File

@ -978,21 +978,6 @@ pub fn genNavRef(
},
.link_once => unreachable,
}
} else if (lf.cast(.coff)) |coff_file| {
// TODO audit this
switch (linkage) {
.internal => {
const atom_index = try coff_file.getOrCreateAtomForNav(nav_index);
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
return .{ .sym_index = sym_index };
},
.strong, .weak => {
const global_index = try coff_file.getGlobalSymbol(nav.name.toSlice(ip), lib_name.toSlice(ip));
try coff_file.need_got_table.put(zcu.gpa, global_index, {}); // needs GOT
return .{ .sym_index = global_index };
},
.link_once => unreachable,
}
} else if (lf.cast(.coff2)) |coff| {
return .{ .sym_index = @intFromEnum(try coff.navSymbol(zcu, nav_index)) };
} else {

View File

@ -135,11 +135,6 @@ pub fn emit(
else if (lf.cast(.macho)) |mf|
mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err|
return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
else if (lf.cast(.coff)) |cf|
if (cf.getOrCreateAtomForLazySymbol(pt, lazy_reloc.symbol)) |atom|
cf.getAtom(atom).getSymbolIndex().?
else |err|
return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
else
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
mir.body[lazy_reloc.reloc.label],
@ -154,8 +149,6 @@ pub fn emit(
try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null)
else if (lf.cast(.macho)) |mf|
try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null)
else if (lf.cast(.coff)) |cf|
try cf.getGlobalSymbol(std.mem.span(global_reloc.name), "compiler_rt")
else
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
mir.body[global_reloc.reloc.label],

View File

@ -170,11 +170,6 @@ pub fn emitMir(emit: *Emit) Error!void {
else if (emit.bin_file.cast(.macho)) |macho_file|
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else if (emit.bin_file.cast(.coff)) |coff_file|
if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom|
coff_file.getAtom(atom).getSymbolIndex().?
else |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else if (emit.bin_file.cast(.coff2)) |elf|
@intFromEnum(try elf.lazySymbol(lazy_sym))
else
@ -190,8 +185,6 @@ pub fn emitMir(emit: *Emit) Error!void {
.type = .FUNC,
})) else if (emit.bin_file.cast(.macho)) |macho_file|
try macho_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, null)
else if (emit.bin_file.cast(.coff)) |coff_file|
try coff_file.getGlobalSymbol(extern_func.toSlice(&emit.lower.mir).?, "compiler_rt")
else if (emit.bin_file.cast(.coff2)) |coff| @intFromEnum(try coff.globalSymbol(
extern_func.toSlice(&emit.lower.mir).?,
switch (comp.compiler_rt_strat) {
@ -211,9 +204,7 @@ pub fn emitMir(emit: *Emit) Error!void {
switch (lowered_inst.encoding.mnemonic) {
.call => {
reloc.target.type = .branch;
if (emit.bin_file.cast(.coff)) |_| try emit.encodeInst(try .new(.none, .call, &.{
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info) else try emit.encodeInst(lowered_inst, reloc_info);
try emit.encodeInst(lowered_inst, reloc_info);
continue :lowered_inst;
},
else => {},
@ -290,37 +281,6 @@ pub fn emitMir(emit: *Emit) Error!void {
}, emit.lower.target), reloc_info),
else => unreachable,
}
} else if (emit.bin_file.cast(.coff)) |_| {
if (reloc.target.is_extern) switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info),
.mov => {
const dst_reg = lowered_inst.ops[0].reg.to64();
try emit.encodeInst(try .new(.none, .mov, &.{
.{ .reg = dst_reg },
.{ .mem = .initRip(.ptr, 0) },
}, emit.lower.target), reloc_info);
try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initSib(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, .{ .base = .{
.reg = dst_reg,
} }) },
}, emit.lower.target), &.{});
},
else => unreachable,
} else switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(.none, 0) },
}, emit.lower.target), reloc_info),
.mov => try emit.encodeInst(try .new(.none, .mov, &.{
lowered_inst.ops[0],
.{ .mem = .initRip(lowered_inst.ops[reloc.op_index].mem.sib.ptr_size, 0) },
}, emit.lower.target), reloc_info),
else => unreachable,
}
} else if (emit.bin_file.cast(.coff2)) |_| {
switch (lowered_inst.encoding.mnemonic) {
.lea => try emit.encodeInst(try .new(.none, .lea, &.{
@ -820,22 +780,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
@enumFromInt(reloc.target.index),
reloc.off,
.{ .X86_64 = .@"32" },
) else if (emit.bin_file.cast(.coff)) |coff_file| {
const atom_index = coff_file.getAtomIndexForSymbol(
.{ .sym_index = emit.atom_index, .file = null },
).?;
try coff_file.addRelocation(atom_index, .{
.type = if (reloc.target.is_extern) .got else .direct,
.target = if (reloc.target.is_extern)
coff_file.getGlobalByIndex(reloc.target.index)
else
.{ .sym_index = reloc.target.index, .file = null },
.offset = end_offset - 4,
.addend = @intCast(reloc.off),
.pcrel = true,
.length = 2,
});
} else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc(
) else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc(
@enumFromInt(emit.atom_index),
end_offset - 4,
@enumFromInt(reloc.target.index),
@ -873,21 +818,6 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
.symbolnum = @intCast(reloc.target.index),
},
});
} else if (emit.bin_file.cast(.coff)) |coff_file| {
const atom_index = coff_file.getAtomIndexForSymbol(
.{ .sym_index = emit.atom_index, .file = null },
).?;
try coff_file.addRelocation(atom_index, .{
.type = if (reloc.target.is_extern) .import else .got,
.target = if (reloc.target.is_extern)
coff_file.getGlobalByIndex(reloc.target.index)
else
.{ .sym_index = reloc.target.index, .file = null },
.offset = end_offset - 4,
.addend = @intCast(reloc.off),
.pcrel = true,
.length = 2,
});
} else if (emit.bin_file.cast(.coff2)) |coff| try coff.addReloc(
@enumFromInt(emit.atom_index),
end_offset - 4,

View File

@ -574,16 +574,13 @@ pub const File = struct {
const gpa = comp.gpa;
switch (base.tag) {
.lld => assert(base.file == null),
.coff, .elf, .macho, .wasm, .goff, .xcoff => {
.elf, .macho, .wasm, .goff, .xcoff => {
if (base.file != null) return;
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
const emit = base.emit;
if (base.child_pid) |pid| {
if (builtin.os.tag == .windows) {
const coff_file = base.cast(.coff).?;
coff_file.ptraceAttach(pid) catch |err| {
log.warn("attaching failed with error: {s}", .{@errorName(err)});
};
return error.HotSwapUnavailableOnHostOperatingSystem;
} else {
// If we try to open the output file in write mode while it is running,
// it will return ETXTBSY. So instead, we copy the file, atomically rename it
@ -671,7 +668,7 @@ pub const File = struct {
}
}
},
.coff, .macho, .wasm, .goff, .xcoff => if (base.file) |f| {
.macho, .wasm, .goff, .xcoff => if (base.file) |f| {
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
f.close();
base.file = null;
@ -684,10 +681,6 @@ pub const File = struct {
log.warn("detaching failed with error: {s}", .{@errorName(err)});
};
},
.windows => {
const coff_file = base.cast(.coff).?;
coff_file.ptraceDetach(pid);
},
else => return error.HotSwapUnavailableOnHostOperatingSystem,
}
}
@ -1157,7 +1150,6 @@ pub const File = struct {
}
pub const Tag = enum {
coff,
coff2,
elf,
elf2,
@ -1172,7 +1164,6 @@ pub const File = struct {
pub fn Type(comptime tag: Tag) type {
return switch (tag) {
.coff => Coff,
.coff2 => Coff2,
.elf => Elf,
.elf2 => Elf2,
@ -1189,7 +1180,7 @@ pub const File = struct {
fn fromObjectFormat(ofmt: std.Target.ObjectFormat, use_new_linker: bool) Tag {
return switch (ofmt) {
.coff => if (use_new_linker) .coff2 else .coff,
.coff => .coff2,
.elf => if (use_new_linker) .elf2 else .elf,
.macho => .macho,
.wasm => .wasm,
@ -1274,7 +1265,6 @@ pub const File = struct {
pub const Lld = @import("link/Lld.zig");
pub const C = @import("link/C.zig");
pub const Coff = @import("link/Coff.zig");
pub const Coff2 = @import("link/Coff2.zig");
pub const Elf = @import("link/Elf.zig");
pub const Elf2 = @import("link/Elf2.zig");

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,73 @@ relocs: std.ArrayList(Reloc),
/// This is hiding actual bugs with global symbols! Reconsider once they are implemented correctly.
entry_hack: Symbol.Index,
pub const default_file_alignment: u16 = 0x200;
pub const default_size_of_stack_reserve: u32 = 0x1000000;
pub const default_size_of_stack_commit: u32 = 0x1000;
pub const default_size_of_heap_reserve: u32 = 0x100000;
pub const default_size_of_heap_commit: u32 = 0x1000;
/// This is the start of a Portable Executable (PE) file.
/// 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.
///
/// In this context,
/// A "paragraph" is 16 bytes.
/// A "page" is 512 bytes.
/// A "long" is 4 bytes.
/// A "word" is 2 bytes.
pub const msdos_stub: [120]u8 = .{
'M', 'Z', // Magic number. Stands for Mark Zbikowski (designer of the MS-DOS executable format).
0x78, 0x00, // Number of bytes in the last page. This matches the size of this entire MS-DOS stub.
0x01, 0x00, // Number of pages.
0x00, 0x00, // Number of entries in the relocation table.
0x04, 0x00, // The number of paragraphs taken up by the header. 4 * 16 = 64, which matches the header size (all bytes before the MS-DOS stub program).
0x00, 0x00, // The number of paragraphs required by the program.
0x00, 0x00, // The number of paragraphs requested by the program.
0x00, 0x00, // Initial value for SS (relocatable segment address).
0x00, 0x00, // Initial value for SP.
0x00, 0x00, // Checksum.
0x00, 0x00, // Initial value for IP.
0x00, 0x00, // Initial value for CS (relocatable segment address).
0x40, 0x00, // Absolute offset to relocation table. 64 matches the header size (all bytes before the MS-DOS stub program).
0x00, 0x00, // Overlay number. Zero means this is the main executable.
}
// Reserved words.
++ .{ 0x00, 0x00 } ** 4
// OEM-related fields.
++ .{
0x00, 0x00, // OEM identifier.
0x00, 0x00, // OEM information.
}
// Reserved words.
++ .{ 0x00, 0x00 } ** 10
// Address of the PE header (a long). This matches the size of this entire MS-DOS stub, so that's the address of what's after this MS-DOS stub.
++ .{ 0x78, 0x00, 0x00, 0x00 }
// What follows is a 16-bit x86 MS-DOS program of 7 instructions that prints the bytes after these instructions and then exits.
++ .{
// Set the value of the data segment to the same value as the code segment.
0x0e, // push cs
0x1f, // pop ds
// Set the DX register to the address of the message.
// If you count all bytes of these 7 instructions you get 14, so that's the address of what's after these instructions.
0xba, 14, 0x00, // mov dx, 14
// Set AH to the system call code for printing a message.
0xb4, 0x09, // mov ah, 0x09
// Perform the system call to print the message.
0xcd, 0x21, // int 0x21
// Set AH to 0x4c which is the system call code for exiting, and set AL to 0x01 which is the exit code.
0xb8, 0x01, 0x4c, // mov ax, 0x4c01
// Peform the system call to exit the program with exit code 1.
0xcd, 0x21, // int 0x21
}
// Message to print.
++ "This program cannot be run in DOS mode.".*
// Message terminators.
++ .{
'$', // We do not pass a length to the print system call; the string is terminated by this character.
0x00, 0x00, // Terminating zero bytes.
};
pub const Node = union(enum) {
file,
header,
@ -613,8 +680,7 @@ fn initHeaders(
) !void {
const comp = coff.base.comp;
const gpa = comp.gpa;
const file_align: std.mem.Alignment =
comptime .fromByteUnits(link.File.Coff.default_file_alignment);
const file_align: std.mem.Alignment = comptime .fromByteUnits(default_file_alignment);
const target_endian = coff.targetEndian();
const optional_header_size: u16 = if (is_image) switch (magic) {
@ -639,15 +705,14 @@ fn initHeaders(
const signature_ni = Node.known.signature;
assert(signature_ni == try coff.mf.addOnlyChildNode(gpa, header_ni, .{
.size = (if (is_image) link.File.Coff.msdos_stub.len else 0) + "PE\x00\x00".len,
.size = (if (is_image) msdos_stub.len else 0) + "PE\x00\x00".len,
.alignment = .@"4",
.fixed = true,
}));
coff.nodes.appendAssumeCapacity(.signature);
{
const signature_slice = signature_ni.slice(&coff.mf);
if (is_image)
@memcpy(signature_slice[0..link.File.Coff.msdos_stub.len], &link.File.Coff.msdos_stub);
if (is_image) @memcpy(signature_slice[0..msdos_stub.len], &msdos_stub);
@memcpy(signature_slice[signature_slice.len - 4 ..], "PE\x00\x00");
}
@ -730,10 +795,10 @@ fn initHeaders(
.TERMINAL_SERVER_AWARE = true,
.NX_COMPAT = true,
},
.size_of_stack_reserve = link.File.Coff.default_size_of_stack_reserve,
.size_of_stack_commit = link.File.Coff.default_size_of_stack_commit,
.size_of_heap_reserve = link.File.Coff.default_size_of_heap_reserve,
.size_of_heap_commit = link.File.Coff.default_size_of_heap_commit,
.size_of_stack_reserve = default_size_of_stack_reserve,
.size_of_stack_commit = default_size_of_stack_commit,
.size_of_heap_reserve = default_size_of_heap_reserve,
.size_of_heap_commit = default_size_of_heap_commit,
.loader_flags = 0,
.number_of_rva_and_sizes = data_directories_len,
};
@ -781,10 +846,10 @@ fn initHeaders(
.TERMINAL_SERVER_AWARE = true,
.NX_COMPAT = true,
},
.size_of_stack_reserve = link.File.Coff.default_size_of_stack_reserve,
.size_of_stack_commit = link.File.Coff.default_size_of_stack_commit,
.size_of_heap_reserve = link.File.Coff.default_size_of_heap_reserve,
.size_of_heap_commit = link.File.Coff.default_size_of_heap_commit,
.size_of_stack_reserve = default_size_of_stack_reserve,
.size_of_stack_commit = default_size_of_stack_commit,
.size_of_heap_reserve = default_size_of_heap_reserve,
.size_of_heap_commit = default_size_of_heap_commit,
.loader_flags = 0,
.number_of_rva_and_sizes = data_directories_len,
};