From a69f55a7cc3980f4d4dfcce6cb9d21a597975c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Mon, 19 Aug 2024 13:25:08 +0200 Subject: [PATCH 1/2] std.{coff,elf}: Remove the {MachineType,EM}.toTargetCpuArch() functions. These are fundamentally incapable of producing accurate information for reasons I've laid out in #20771. Since our only use of these functions is to check that object files have the correct machine type, and since #21020 made `std.Target.to{Coff,Elf}Machine()` more accurate, just switch these checks over to that and compare the machine type tags instead. Closes #20771. --- lib/std/coff.zig | 17 ---------------- lib/std/elf.zig | 38 ----------------------------------- src/link/Elf/Object.zig | 8 ++++---- src/link/Elf/SharedObject.zig | 8 ++++---- test/link/elf.zig | 2 +- 5 files changed, 9 insertions(+), 64 deletions(-) diff --git a/lib/std/coff.zig b/lib/std/coff.zig index ca05ce3cf918..da7dc0bcda32 100644 --- a/lib/std/coff.zig +++ b/lib/std/coff.zig @@ -1060,23 +1060,6 @@ pub const MachineType = enum(u16) { WCEMIPSV2 = 0x169, _, - - pub fn toTargetCpuArch(machine_type: MachineType) ?std.Target.Cpu.Arch { - return switch (machine_type) { - .ARM => .arm, - .POWERPC => .powerpc, - .RISCV32 => .riscv32, - .THUMB => .thumb, - .I386 => .x86, - .ARM64 => .aarch64, - .RISCV64 => .riscv64, - .X64 => .x86_64, - .LOONGARCH32 => .loongarch32, - .LOONGARCH64 => .loongarch64, - // there's cases we don't (yet) handle - else => null, - }; - } }; pub const CoffError = error{ diff --git a/lib/std/elf.zig b/lib/std/elf.zig index af3f1813e29d..aefaca4bef83 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -1646,44 +1646,6 @@ pub const EM = enum(u16) { FRV = 0x5441, _, - - pub fn toTargetCpuArch(em: EM) ?std.Target.Cpu.Arch { - return switch (em) { - .AVR => .avr, - .MSP430 => .msp430, - .ARC => .arc, - .ARM => .arm, - .HEXAGON => .hexagon, - .@"68K" => .m68k, - .MIPS => .mips, - .MIPS_RS3_LE => .mipsel, - .PPC => .powerpc, - .SPARC => .sparc, - .@"386" => .x86, - .XCORE => .xcore, - .CSR_KALIMBA => .kalimba, - .LANAI => .lanai, - .AARCH64 => .aarch64, - .PPC64 => .powerpc64, - .RISCV => .riscv64, - .X86_64 => .x86_64, - .BPF => .bpfel, - .SPARCV9 => .sparc64, - .S390 => .s390x, - .SPU_2 => .spu_2, - // FIXME: - // No support for .loongarch32 yet so it is safe to assume we are on .loongarch64. - // - // However, when e_machine is .LOONGARCH, we should check - // ei_class's value to decide the CPU architecture. - // - ELFCLASS32 => .loongarch32 - // - ELFCLASS64 => .loongarch64 - .LOONGARCH => .loongarch64, - // there's many cases we don't (yet) handle, or will never have a - // zig target cpu arch equivalent (such as null). - else => null, - }; - } }; pub const GRP_COMDAT = 1; diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index a6f9c4ac1874..d329218b8d8b 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -105,12 +105,12 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil defer allocator.free(header_buffer); self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*; - const target = elf_file.base.comp.root_mod.resolved_target.result; - if (target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { + const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); + if (em != self.header.?.e_machine) { try elf_file.reportParseError2( self.index, - "invalid cpu architecture: {s}", - .{@tagName(self.header.?.e_machine.toTargetCpuArch().?)}, + "invalid ELF machine type: {s}", + .{@tagName(self.header.?.e_machine)}, ); return error.InvalidCpuArch; } diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index b33853d23c18..7fdf9116b5f1 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -56,12 +56,12 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { defer gpa.free(header_buffer); self.header = @as(*align(1) const elf.Elf64_Ehdr, @ptrCast(header_buffer)).*; - const target = elf_file.base.comp.root_mod.resolved_target.result; - if (target.cpu.arch != self.header.?.e_machine.toTargetCpuArch().?) { + const em = elf_file.base.comp.root_mod.resolved_target.result.toElfMachine(); + if (em != self.header.?.e_machine) { try elf_file.reportParseError2( self.index, - "invalid cpu architecture: {s}", - .{@tagName(self.header.?.e_machine.toTargetCpuArch().?)}, + "invalid ELF machine type: {s}", + .{@tagName(self.header.?.e_machine)}, ); return error.InvalidCpuArch; } diff --git a/test/link/elf.zig b/test/link/elf.zig index 98253811b24d..6abf596ab7e7 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -2257,7 +2257,7 @@ fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step { exe.linkLibC(); expectLinkErrors(exe, test_step, .{ .exact = &.{ - "invalid cpu architecture: aarch64", + "invalid ELF machine type: AARCH64", "note: while parsing /?/a.o", } }); From fb6f5a30b2d6334d0f1415446849d39fe00d3af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 23 Aug 2024 10:40:35 +0200 Subject: [PATCH 2/2] link: Rename InvalidCpuArch error to InvalidMachineType. --- src/link/Elf.zig | 10 +++++----- src/link/Elf/Object.zig | 2 +- src/link/Elf/SharedObject.zig | 2 +- src/link/Elf/relocatable.zig | 4 ++-- src/link/MachO.zig | 2 +- src/link/MachO/Dylib.zig | 4 ++-- src/link/MachO/Object.zig | 8 ++++---- src/link/MachO/relocatable.zig | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 333e490d1751..088485a78d9b 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1100,7 +1100,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod error.MalformedObject, error.MalformedArchive, error.MismatchedEflags, - error.InvalidCpuArch, + error.InvalidMachineType, => continue, // already reported else => |e| try self.reportParseError( obj.path, @@ -1187,7 +1187,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod for (system_libs.items) |lib| { self.parseLibrary(lib, false) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, error.MalformedArchive, error.InvalidMachineType => continue, // already reported else => |e| try self.reportParseError( lib.path, "unexpected error: parsing library failed with error {s}", @@ -1213,7 +1213,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod error.MalformedObject, error.MalformedArchive, error.MismatchedEflags, - error.InvalidCpuArch, + error.InvalidMachineType, => continue, // already reported else => |e| try self.reportParseError( obj.path, @@ -1642,7 +1642,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { pub const ParseError = error{ MalformedObject, MalformedArchive, - InvalidCpuArch, + InvalidMachineType, MismatchedEflags, OutOfMemory, Overflow, @@ -1813,7 +1813,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { .needed = scr_obj.needed, .path = full_path, }, false) catch |err| switch (err) { - error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported + error.MalformedObject, error.MalformedArchive, error.InvalidMachineType => continue, // already reported else => |e| try self.reportParseError( full_path, "unexpected error: parsing library failed with error {s}", diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index d329218b8d8b..584e5ad6d3e6 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -112,7 +112,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil "invalid ELF machine type: {s}", .{@tagName(self.header.?.e_machine)}, ); - return error.InvalidCpuArch; + return error.InvalidMachineType; } try elf_file.validateEFlags(self.index, self.header.?.e_flags); diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 7fdf9116b5f1..9463cad75a73 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -63,7 +63,7 @@ pub fn parse(self: *SharedObject, elf_file: *Elf, handle: std.fs.File) !void { "invalid ELF machine type: {s}", .{@tagName(self.header.?.e_machine)}, ); - return error.InvalidCpuArch; + return error.InvalidMachineType; } const shoff = std.math.cast(usize, self.header.?.e_shoff) orelse return error.Overflow; diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 50b9b562d12c..06850f87ac7b 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -21,7 +21,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co parsePositional(elf_file, obj.path) catch |err| switch (err) { error.MalformedObject, error.MalformedArchive, - error.InvalidCpuArch, + error.InvalidMachineType, error.MismatchedEflags, => continue, // already reported error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}), @@ -178,7 +178,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { error.MalformedObject, error.MalformedArchive, - error.InvalidCpuArch, + error.InvalidMachineType, error.MismatchedEflags, => continue, // already reported else => |e| try elf_file.reportParseError( diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d99fc2185e6e..cfcf6b79653a 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -921,7 +921,7 @@ fn parseInputFileWorker(self: *MachO, file: File) void { error.MalformedObject, error.MalformedDylib, error.MalformedTbd, - error.InvalidCpuArch, + error.InvalidMachineType, error.InvalidTarget, => {}, // already reported else => |e| self.reportParseError2(file.getIndex(), "unexpected error: parsing input file failed with error {s}", .{@errorName(e)}) catch {}, diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index ce12397be45b..7c52f6937681 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -75,12 +75,12 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { macho.CPU_TYPE_X86_64 => .x86_64, else => |x| { try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x}); - return error.InvalidCpuArch; + return error.InvalidMachineType; }, }; if (macho_file.getTarget().cpu.arch != this_cpu_arch) { try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)}); - return error.InvalidCpuArch; + return error.InvalidMachineType; } const lc_buffer = try gpa.alloc(u8, header.sizeofcmds); diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 38cb82e858ff..ad83777906a7 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -91,12 +91,12 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { macho.CPU_TYPE_X86_64 => .x86_64, else => |x| { try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x}); - return error.InvalidCpuArch; + return error.InvalidMachineType; }, }; if (cpu_arch != this_cpu_arch) { try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)}); - return error.InvalidCpuArch; + return error.InvalidMachineType; } const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); @@ -1648,12 +1648,12 @@ pub fn parseAr(self: *Object, macho_file: *MachO) !void { macho.CPU_TYPE_X86_64 => .x86_64, else => |x| { try macho_file.reportParseError2(self.index, "unknown cpu architecture: {d}", .{x}); - return error.InvalidCpuArch; + return error.InvalidMachineType; }, }; if (macho_file.getTarget().cpu.arch != this_cpu_arch) { try macho_file.reportParseError2(self.index, "invalid cpu architecture: {s}", .{@tagName(this_cpu_arch)}); - return error.InvalidCpuArch; + return error.InvalidMachineType; } const lc_buffer = try gpa.alloc(u8, self.header.?.sizeofcmds); diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index e18442b6c2d7..e231360928bf 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -232,7 +232,7 @@ fn parseInputFilesAr(macho_file: *MachO) !void { for (macho_file.objects.items) |index| { macho_file.getFile(index).?.parseAr(macho_file) catch |err| switch (err) { - error.InvalidCpuArch => {}, // already reported + error.InvalidMachineType => {}, // already reported else => |e| try macho_file.reportParseError2(index, "unexpected error: parsing input file failed with error {s}", .{@errorName(e)}), }; }