authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-22 18:01:26-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-22 18:01:26-07:00
log782a9d16c7e5a2023b3cd7bc763c0cb210b86412
tree224a66287a19dc2b0158aeda93a16739879c099b
parentfcff82feb2565b427349927624da85089f5e3601
signaturelock-open Commit is signed but in an unrecognized format.

elf: add riscv eflag collisions


4 files changed, 83 insertions(+), 8 deletions(-)

src/link/Elf.zig+58-6
......@@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}
229229/// such as `resolver` and `comdat_groups_table`.
230230strings: StringTable = .{},
231231
232first_eflags: ?elf.Elf64_Word = null,
233
232234/// When allocating, the ideal_capacity is calculated by
233235/// actual_capacity + (actual_capacity / ideal_factor)
234236const ideal_factor = 3;
......@@ -553,7 +555,7 @@ pub fn lowerAnonDecl(
553555 pt: Zcu.PerThread,
554556 decl_val: InternPool.Index,
555557 explicit_alignment: InternPool.Alignment,
556 src_loc: Module.LazySrcLoc,
558 src_loc: Zcu.LazySrcLoc,
557559) !codegen.Result {
558560 return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc);
559561}
......@@ -1158,7 +1160,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
11581160
11591161 for (positionals.items) |obj| {
11601162 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1161 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
1163 error.MalformedObject,
1164 error.MalformedArchive,
1165 error.MismatchedEflags,
1166 error.InvalidCpuArch,
1167 => continue, // already reported
11621168 else => |e| try self.reportParseError(
11631169 obj.path,
11641170 "unexpected error: parsing input file failed with error {s}",
......@@ -1267,7 +1273,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
12671273
12681274 for (positionals.items) |obj| {
12691275 self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
1270 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
1276 error.MalformedObject,
1277 error.MalformedArchive,
1278 error.MismatchedEflags,
1279 error.InvalidCpuArch,
1280 => continue, // already reported
12711281 else => |e| try self.reportParseError(
12721282 obj.path,
12731283 "unexpected error: parsing input file failed with error {s}",
......@@ -1693,6 +1703,7 @@ pub const ParseError = error{
16931703 MalformedObject,
16941704 MalformedArchive,
16951705 InvalidCpuArch,
1706 MismatchedEflags,
16961707 OutOfMemory,
16971708 Overflow,
16981709 InputOutput,
......@@ -1872,6 +1883,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
18721883 }
18731884}
18741885
1886pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void {
1887 const target = self.base.comp.root_mod.resolved_target.result;
1888
1889 if (self.first_eflags == null) {
1890 self.first_eflags = e_flags;
1891 return; // there isn't anything to conflict with yet
1892 }
1893 const self_eflags: *elf.Elf64_Word = &self.first_eflags.?;
1894
1895 switch (target.cpu.arch) {
1896 .riscv64 => {
1897 if (e_flags != self_eflags.*) {
1898 const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
1899 const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
1900
1901 self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
1902 self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
1903
1904 var is_error: bool = false;
1905 if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
1906 is_error = true;
1907 _ = try self.reportParseError2(
1908 file_index,
1909 "cannot link object files with different float-point ABIs",
1910 .{},
1911 );
1912 }
1913 if (self_riscv_eflags.rve != riscv_eflags.rve) {
1914 is_error = true;
1915 _ = try self.reportParseError2(
1916 file_index,
1917 "cannot link object files with different RVEs",
1918 .{},
1919 );
1920 }
1921 if (is_error) return error.MismatchedEflags;
1922 }
1923 },
1924 else => {},
1925 }
1926}
1927
18751928fn accessLibPath(
18761929 self: *Elf,
18771930 arena: Allocator,
......@@ -3013,7 +3066,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index:
30133066pub fn updateExports(
30143067 self: *Elf,
30153068 pt: Zcu.PerThread,
3016 exported: Module.Exported,
3069 exported: Zcu.Exported,
30173070 export_indices: []const u32,
30183071) link.File.UpdateExportsError!void {
30193072 if (build_options.skip_non_native and builtin.object_format != .elf) {
......@@ -6471,8 +6524,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
64716524const MergeSection = merge_section.MergeSection;
64726525const MergeSubsection = merge_section.MergeSubsection;
64736526const Zcu = @import("../Zcu.zig");
6474/// Deprecated.
6475const Module = Zcu;
64766527const Object = @import("Elf/Object.zig");
64776528const InternPool = @import("../InternPool.zig");
64786529const PltSection = synthetic_sections.PltSection;
......@@ -6485,3 +6536,4 @@ const Value = @import("../Value.zig");
64856536const VerneedSection = synthetic_sections.VerneedSection;
64866537const ZigGotSection = synthetic_sections.ZigGotSection;
64876538const ZigObject = @import("Elf/ZigObject.zig");
6539const riscv = @import("riscv.zig");
src/link/Elf/Object.zig+1
......@@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
9393 );
9494 return error.InvalidCpuArch;
9595 }
96 try elf_file.validateEFlags(self.index, self.header.?.e_flags);
9697
9798 if (self.header.?.e_shnum == 0) return;
9899
src/link/Elf/relocatable.zig+10-2
......@@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
1919
2020 for (positionals.items) |obj| {
2121 parsePositional(elf_file, obj.path) catch |err| switch (err) {
22 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
22 error.MalformedObject,
23 error.MalformedArchive,
24 error.InvalidCpuArch,
25 error.MismatchedEflags,
26 => continue, // already reported
2327 error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
2428 else => |e| try elf_file.reportParseError(
2529 obj.path,
......@@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
168172
169173 for (positionals.items) |obj| {
170174 elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
171 error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
175 error.MalformedObject,
176 error.MalformedArchive,
177 error.InvalidCpuArch,
178 error.MismatchedEflags,
179 => continue, // already reported
172180 else => |e| try elf_file.reportParseError(
173181 obj.path,
174182 "unexpected error: parsing input file failed with error {s}",
src/link/riscv.zig+14
......@@ -95,6 +95,20 @@ fn bitSlice(
9595 return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
9696}
9797
98pub const RiscvEflags = packed struct(u32) {
99 rvc: bool,
100 fabi: enum(u2) {
101 soft = 0b00,
102 single = 0b01,
103 double = 0b10,
104 quad = 0b11,
105 },
106 rve: bool,
107 tso: bool,
108 _reserved: u19,
109 _unused: u8,
110};
111
98112const encoder = @import("../arch/riscv64/encoder.zig");
99113const Encoding = @import("../arch/riscv64/Encoding.zig");
100114const mem = std.mem;