mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
glibc sometimes makes archives be ld scripts
it is incredible how many bad ideas glibc is bundled into one project.
This commit is contained in:
parent
ccac11196b
commit
336466c9df
78
src/link.zig
78
src/link.zig
@ -1009,11 +1009,25 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
/// Opens a path as a static library and parses it into the linker.
|
||||
fn openLoadArchive(base: *File, path: Path) anyerror!void {
|
||||
const diags = &base.comp.link_diags;
|
||||
const input = try openArchiveInput(diags, path, false, false);
|
||||
errdefer input.archive.file.close();
|
||||
try loadInput(base, input);
|
||||
/// If `query` is non-null, allows GNU ld scripts.
|
||||
fn openLoadArchive(base: *File, path: Path, opt_query: ?UnresolvedInput.Query) anyerror!void {
|
||||
if (opt_query) |query| {
|
||||
const archive = try openObject(path, query.must_link, query.hidden);
|
||||
errdefer archive.file.close();
|
||||
loadInput(base, .{ .archive = archive }) catch |err| switch (err) {
|
||||
error.BadMagic, error.UnexpectedEndOfFile => {
|
||||
if (base.tag != .elf) return err;
|
||||
try loadGnuLdScript(base, path, query, archive.file);
|
||||
archive.file.close();
|
||||
return;
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
} else {
|
||||
const archive = try openObject(path, false, false);
|
||||
errdefer archive.file.close();
|
||||
try loadInput(base, .{ .archive = archive });
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens a path as a shared library and parses it into the linker.
|
||||
@ -1060,7 +1074,7 @@ pub const File = struct {
|
||||
switch (Compilation.classifyFileExt(arg.path)) {
|
||||
.shared_library => try openLoadDso(base, new_path, query),
|
||||
.object => try openLoadObject(base, new_path),
|
||||
.static_library => try openLoadArchive(base, new_path),
|
||||
.static_library => try openLoadArchive(base, new_path, query),
|
||||
else => diags.addParseError(path, "GNU ld script references file with unrecognized extension: {s}", .{arg.path}),
|
||||
}
|
||||
} else {
|
||||
@ -1408,33 +1422,51 @@ pub const File = struct {
|
||||
assert(mem.startsWith(u8, flag, "-l"));
|
||||
const lib_name = flag["-l".len..];
|
||||
switch (comp.config.link_mode) {
|
||||
.dynamic => d: {
|
||||
const path = Path.initCwd(
|
||||
.dynamic => {
|
||||
const dso_path = Path.initCwd(
|
||||
std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{
|
||||
crt_dir, target.libPrefix(), lib_name, target.dynamicLibSuffix(),
|
||||
}) catch return diags.setAllocFailure(),
|
||||
);
|
||||
base.openLoadDso(path, .{
|
||||
base.openLoadDso(dso_path, .{
|
||||
.preferred_mode = .dynamic,
|
||||
.search_strategy = .paths_first,
|
||||
}) catch |err| switch (err) {
|
||||
error.FileNotFound => break :d, // also try static
|
||||
error.FileNotFound => {
|
||||
// Also try static.
|
||||
const archive_path = Path.initCwd(
|
||||
std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{
|
||||
crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(),
|
||||
}) catch return diags.setAllocFailure(),
|
||||
);
|
||||
base.openLoadArchive(archive_path, .{
|
||||
.preferred_mode = .dynamic,
|
||||
.search_strategy = .paths_first,
|
||||
}) catch |archive_err| switch (archive_err) {
|
||||
error.LinkFailure => return, // error reported via diags
|
||||
else => |e| diags.addParseError(dso_path, "failed to parse archive {}: {s}", .{ archive_path, @errorName(e) }),
|
||||
};
|
||||
},
|
||||
error.LinkFailure => return, // error reported via diags
|
||||
else => |e| diags.addParseError(path, "failed to parse shared library: {s}", .{@errorName(e)}),
|
||||
else => |e| diags.addParseError(dso_path, "failed to parse shared library: {s}", .{@errorName(e)}),
|
||||
};
|
||||
},
|
||||
.static => {
|
||||
const path = Path.initCwd(
|
||||
std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{
|
||||
crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(),
|
||||
}) catch return diags.setAllocFailure(),
|
||||
);
|
||||
// glibc sometimes makes even archive files GNU ld scripts.
|
||||
base.openLoadArchive(path, .{
|
||||
.preferred_mode = .static,
|
||||
.search_strategy = .no_fallback,
|
||||
}) catch |err| switch (err) {
|
||||
error.LinkFailure => return, // error reported via diags
|
||||
else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
|
||||
};
|
||||
continue;
|
||||
},
|
||||
.static => {},
|
||||
}
|
||||
const path = Path.initCwd(
|
||||
std.fmt.allocPrint(comp.arena, "{s}" ++ sep ++ "{s}{s}{s}", .{
|
||||
crt_dir, target.libPrefix(), lib_name, target.staticLibSuffix(),
|
||||
}) catch return diags.setAllocFailure(),
|
||||
);
|
||||
base.openLoadArchive(path) catch |err| switch (err) {
|
||||
error.LinkFailure => return, // error reported via diags
|
||||
else => |e| diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
},
|
||||
.load_object => |path| {
|
||||
@ -1444,7 +1476,7 @@ pub const File = struct {
|
||||
};
|
||||
},
|
||||
.load_archive => |path| {
|
||||
base.openLoadArchive(path) catch |err| switch (err) {
|
||||
base.openLoadArchive(path, null) catch |err| switch (err) {
|
||||
error.LinkFailure => return, // error reported via link_diags
|
||||
else => |e| comp.link_diags.addParseError(path, "failed to parse archive: {s}", .{@errorName(e)}),
|
||||
};
|
||||
|
||||
@ -1098,20 +1098,6 @@ fn dumpArgvInit(self: *Elf, arena: Allocator) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub const ParseError = error{
|
||||
/// Indicates the error is already reported on `Compilation.link_diags`.
|
||||
LinkFailure,
|
||||
|
||||
OutOfMemory,
|
||||
Overflow,
|
||||
InputOutput,
|
||||
EndOfStream,
|
||||
FileSystem,
|
||||
NotSupported,
|
||||
InvalidCharacter,
|
||||
UnknownFileType,
|
||||
} || fs.Dir.AccessError || fs.File.SeekError || fs.File.OpenError || fs.File.ReadError;
|
||||
|
||||
pub fn openParseObjectReportingFailure(self: *Elf, path: Path) void {
|
||||
const diags = &self.base.comp.link_diags;
|
||||
const obj = link.openObject(path, false, false) catch |err| {
|
||||
@ -1130,7 +1116,7 @@ fn parseObjectReportingFailure(self: *Elf, obj: link.Input.Object) void {
|
||||
};
|
||||
}
|
||||
|
||||
fn parseObject(self: *Elf, obj: link.Input.Object) ParseError!void {
|
||||
fn parseObject(self: *Elf, obj: link.Input.Object) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@ -1175,7 +1161,7 @@ fn parseArchive(
|
||||
objects: *std.ArrayListUnmanaged(File.Index),
|
||||
obj: link.Input.Object,
|
||||
is_static_lib: bool,
|
||||
) ParseError!void {
|
||||
) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
|
||||
@ -16,6 +16,15 @@ pub fn parse(
|
||||
handle_index: File.HandleIndex,
|
||||
) !Archive {
|
||||
const handle = file_handles.items[handle_index];
|
||||
var pos: usize = 0;
|
||||
{
|
||||
var magic_buffer: [elf.ARMAG.len]u8 = undefined;
|
||||
const n = try handle.preadAll(&magic_buffer, pos);
|
||||
if (n != magic_buffer.len) return error.BadMagic;
|
||||
if (!mem.eql(u8, &magic_buffer, elf.ARMAG)) return error.BadMagic;
|
||||
pos += magic_buffer.len;
|
||||
}
|
||||
|
||||
const size = (try handle.stat()).size;
|
||||
|
||||
var objects: std.ArrayListUnmanaged(Object) = .empty;
|
||||
@ -24,17 +33,14 @@ pub fn parse(
|
||||
var strtab: std.ArrayListUnmanaged(u8) = .empty;
|
||||
defer strtab.deinit(gpa);
|
||||
|
||||
var pos: usize = elf.ARMAG.len;
|
||||
while (true) {
|
||||
if (pos >= size) break;
|
||||
if (!mem.isAligned(pos, 2)) pos += 1;
|
||||
while (pos < size) {
|
||||
pos = mem.alignForward(usize, pos, 2);
|
||||
|
||||
var hdr_buffer: [@sizeOf(elf.ar_hdr)]u8 = undefined;
|
||||
var hdr: elf.ar_hdr = undefined;
|
||||
{
|
||||
const amt = try handle.preadAll(&hdr_buffer, pos);
|
||||
if (amt != @sizeOf(elf.ar_hdr)) return error.InputOutput;
|
||||
const n = try handle.preadAll(mem.asBytes(&hdr), pos);
|
||||
if (n != @sizeOf(elf.ar_hdr)) return error.UnexpectedEndOfFile;
|
||||
}
|
||||
const hdr = @as(*align(1) const elf.ar_hdr, @ptrCast(&hdr_buffer)).*;
|
||||
pos += @sizeOf(elf.ar_hdr);
|
||||
|
||||
if (!mem.eql(u8, &hdr.ar_fmag, elf.ARFMAG)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user