authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-05 23:56:48-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-06 00:04:19-04:00
log25da0f83727e8d04a520474799ee4006e7818508
treeb7f24f1ea396ed0001e9fa0fad0e04c364fdde1d
parent98cf81d51c7c5b5cd6b6840007ce05cd0cc94143

link: support static archives that are linker scripts

Note that `openLoadArchive` already has linker script support. With this change I get a failure parsing a real archive in the self hosted elf linker, rather than the previous behavior of getting an error while trying to parse a pseudo archive that is actually a load script.

1 files changed, 11 insertions(+), 11 deletions(-)

src/link.zig+11-11
......@@ -2294,9 +2294,10 @@ fn resolvePathInputLib(
22942294 const test_path: Path = pq.path;
22952295 // In the case of shared libraries, they might actually be "linker scripts"
22962296 // that contain references to other libraries.
2297 if (pq.query.allow_so_scripts and target.ofmt == .elf and
2298 Compilation.classifyFileExt(test_path.sub_path) == .shared_library)
2299 {
2297 if (pq.query.allow_so_scripts and target.ofmt == .elf and switch (Compilation.classifyFileExt(test_path.sub_path)) {
2298 .static_library, .shared_library => true,
2299 else => false,
2300 }) {
23002301 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
23012302 error.FileNotFound => return .no_match,
23022303 else => |e| fatal("unable to search for {s} library '{'}': {s}", .{
......@@ -2304,14 +2305,13 @@ fn resolvePathInputLib(
23042305 }),
23052306 };
23062307 errdefer file.close();
2307 try ld_script_bytes.resize(gpa, @sizeOf(std.elf.Elf64_Ehdr));
2308 try ld_script_bytes.resize(gpa, @max(std.elf.MAGIC.len, std.elf.ARMAG.len));
23082309 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{'}': {s}", .{
23092310 test_path, @errorName(err),
23102311 });
2311 elf_file: {
2312 if (n != ld_script_bytes.items.len) break :elf_file;
2313 if (!mem.eql(u8, ld_script_bytes.items[0..4], "\x7fELF")) break :elf_file;
2314 // Appears to be an ELF file.
2312 const buf = ld_script_bytes.items[0..n];
2313 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
2314 // Appears to be an ELF or archive file.
23152315 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
23162316 }
23172317 const stat = file.stat() catch |err|
......@@ -2319,10 +2319,10 @@ fn resolvePathInputLib(
23192319 const size = std.math.cast(u32, stat.size) orelse
23202320 fatal("{}: linker script too big", .{test_path});
23212321 try ld_script_bytes.resize(gpa, size);
2322 const buf = ld_script_bytes.items[n..];
2323 const n2 = file.preadAll(buf, n) catch |err|
2322 const buf2 = ld_script_bytes.items[n..];
2323 const n2 = file.preadAll(buf2, n) catch |err|
23242324 fatal("failed to read {}: {s}", .{ test_path, @errorName(err) });
2325 if (n2 != buf.len) fatal("failed to read {}: unexpected end of file", .{test_path});
2325 if (n2 != buf2.len) fatal("failed to read {}: unexpected end of file", .{test_path});
23262326 var diags = Diags.init(gpa);
23272327 defer diags.deinit();
23282328 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);