Skip to content

Commit

Permalink
elf: add riscv eflag collisions
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexicon226 committed Jul 23, 2024
1 parent fcff82f commit 782a9d1
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 8 deletions.
64 changes: 58 additions & 6 deletions src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{}
/// such as `resolver` and `comdat_groups_table`.
strings: StringTable = .{},

first_eflags: ?elf.Elf64_Word = null,

/// When allocating, the ideal_capacity is calculated by
/// actual_capacity + (actual_capacity / ideal_factor)
const ideal_factor = 3;
Expand Down Expand Up @@ -553,7 +555,7 @@ pub fn lowerAnonDecl(
pt: Zcu.PerThread,
decl_val: InternPool.Index,
explicit_alignment: InternPool.Alignment,
src_loc: Module.LazySrcLoc,
src_loc: Zcu.LazySrcLoc,
) !codegen.Result {
return self.zigObjectPtr().?.lowerAnonDecl(self, pt, decl_val, explicit_alignment, src_loc);
}
Expand Down Expand Up @@ -1158,7 +1160,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod

for (positionals.items) |obj| {
self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
error.MalformedObject,
error.MalformedArchive,
error.MismatchedEflags,
error.InvalidCpuArch,
=> continue, // already reported
else => |e| try self.reportParseError(
obj.path,
"unexpected error: parsing input file failed with error {s}",
Expand Down Expand Up @@ -1267,7 +1273,11 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod

for (positionals.items) |obj| {
self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
error.MalformedObject,
error.MalformedArchive,
error.MismatchedEflags,
error.InvalidCpuArch,
=> continue, // already reported
else => |e| try self.reportParseError(
obj.path,
"unexpected error: parsing input file failed with error {s}",
Expand Down Expand Up @@ -1693,6 +1703,7 @@ pub const ParseError = error{
MalformedObject,
MalformedArchive,
InvalidCpuArch,
MismatchedEflags,
OutOfMemory,
Overflow,
InputOutput,
Expand Down Expand Up @@ -1872,6 +1883,48 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
}
}

pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void {
const target = self.base.comp.root_mod.resolved_target.result;

if (self.first_eflags == null) {
self.first_eflags = e_flags;
return; // there isn't anything to conflict with yet
}
const self_eflags: *elf.Elf64_Word = &self.first_eflags.?;

switch (target.cpu.arch) {
.riscv64 => {
if (e_flags != self_eflags.*) {
const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);

self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;

var is_error: bool = false;
if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
is_error = true;
_ = try self.reportParseError2(
file_index,
"cannot link object files with different float-point ABIs",
.{},
);
}
if (self_riscv_eflags.rve != riscv_eflags.rve) {
is_error = true;
_ = try self.reportParseError2(
file_index,
"cannot link object files with different RVEs",
.{},
);
}
if (is_error) return error.MismatchedEflags;
}
},
else => {},
}
}

fn accessLibPath(
self: *Elf,
arena: Allocator,
Expand Down Expand Up @@ -3013,7 +3066,7 @@ pub fn lowerUnnamedConst(self: *Elf, pt: Zcu.PerThread, val: Value, decl_index:
pub fn updateExports(
self: *Elf,
pt: Zcu.PerThread,
exported: Module.Exported,
exported: Zcu.Exported,
export_indices: []const u32,
) link.File.UpdateExportsError!void {
if (build_options.skip_non_native and builtin.object_format != .elf) {
Expand Down Expand Up @@ -6471,8 +6524,6 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
const MergeSection = merge_section.MergeSection;
const MergeSubsection = merge_section.MergeSubsection;
const Zcu = @import("../Zcu.zig");
/// Deprecated.
const Module = Zcu;
const Object = @import("Elf/Object.zig");
const InternPool = @import("../InternPool.zig");
const PltSection = synthetic_sections.PltSection;
Expand All @@ -6485,3 +6536,4 @@ const Value = @import("../Value.zig");
const VerneedSection = synthetic_sections.VerneedSection;
const ZigGotSection = synthetic_sections.ZigGotSection;
const ZigObject = @import("Elf/ZigObject.zig");
const riscv = @import("riscv.zig");
1 change: 1 addition & 0 deletions src/link/Elf/Object.zig
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
);
return error.InvalidCpuArch;
}
try elf_file.validateEFlags(self.index, self.header.?.e_flags);

if (self.header.?.e_shnum == 0) return;

Expand Down
12 changes: 10 additions & 2 deletions src/link/Elf/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co

for (positionals.items) |obj| {
parsePositional(elf_file, obj.path) catch |err| switch (err) {
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
error.MalformedObject,
error.MalformedArchive,
error.InvalidCpuArch,
error.MismatchedEflags,
=> continue, // already reported
error.UnknownFileType => try elf_file.reportParseError(obj.path, "unknown file type for an object file", .{}),
else => |e| try elf_file.reportParseError(
obj.path,
Expand Down Expand Up @@ -168,7 +172,11 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const

for (positionals.items) |obj| {
elf_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported
error.MalformedObject,
error.MalformedArchive,
error.InvalidCpuArch,
error.MismatchedEflags,
=> continue, // already reported
else => |e| try elf_file.reportParseError(
obj.path,
"unexpected error: parsing input file failed with error {s}",
Expand Down
14 changes: 14 additions & 0 deletions src/link/riscv.zig
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ fn bitSlice(
return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
}

pub const RiscvEflags = packed struct(u32) {
rvc: bool,
fabi: enum(u2) {
soft = 0b00,
single = 0b01,
double = 0b10,
quad = 0b11,
},
rve: bool,
tso: bool,
_reserved: u19,
_unused: u8,
};

const encoder = @import("../arch/riscv64/encoder.zig");
const Encoding = @import("../arch/riscv64/Encoding.zig");
const mem = std.mem;
Expand Down

0 comments on commit 782a9d1

Please sign in to comment.