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(...@@ -2294,9 +2294,10 @@ fn resolvePathInputLib(
2294 const test_path: Path = pq.path;2294 const test_path: Path = pq.path;
2295 // In the case of shared libraries, they might actually be "linker scripts"2295 // In the case of shared libraries, they might actually be "linker scripts"
2296 // that contain references to other libraries.2296 // that contain references to other libraries.
2297 if (pq.query.allow_so_scripts and target.ofmt == .elf and2297 if (pq.query.allow_so_scripts and target.ofmt == .elf and switch (Compilation.classifyFileExt(test_path.sub_path)) {
2298 Compilation.classifyFileExt(test_path.sub_path) == .shared_library)2298 .static_library, .shared_library => true,
2299 {2299 else => false,
2300 }) {
2300 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {2301 var file = test_path.root_dir.handle.openFile(test_path.sub_path, .{}) catch |err| switch (err) {
2301 error.FileNotFound => return .no_match,2302 error.FileNotFound => return .no_match,
2302 else => |e| fatal("unable to search for {s} library '{'}': {s}", .{2303 else => |e| fatal("unable to search for {s} library '{'}': {s}", .{
...@@ -2304,14 +2305,13 @@ fn resolvePathInputLib(...@@ -2304,14 +2305,13 @@ fn resolvePathInputLib(
2304 }),2305 }),
2305 };2306 };
2306 errdefer file.close();2307 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));
2308 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{'}': {s}", .{2309 const n = file.preadAll(ld_script_bytes.items, 0) catch |err| fatal("failed to read '{'}': {s}", .{
2309 test_path, @errorName(err),2310 test_path, @errorName(err),
2310 });2311 });
2311 elf_file: {2312 const buf = ld_script_bytes.items[0..n];
2312 if (n != ld_script_bytes.items.len) break :elf_file;2313 if (mem.startsWith(u8, buf, std.elf.MAGIC) or mem.startsWith(u8, buf, std.elf.ARMAG)) {
2313 if (!mem.eql(u8, ld_script_bytes.items[0..4], "\x7fELF")) break :elf_file;2314 // Appears to be an ELF or archive file.
2314 // Appears to be an ELF file.
2315 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);2315 return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query);
2316 }2316 }
2317 const stat = file.stat() catch |err|2317 const stat = file.stat() catch |err|
...@@ -2319,10 +2319,10 @@ fn resolvePathInputLib(...@@ -2319,10 +2319,10 @@ fn resolvePathInputLib(
2319 const size = std.math.cast(u32, stat.size) orelse2319 const size = std.math.cast(u32, stat.size) orelse
2320 fatal("{}: linker script too big", .{test_path});2320 fatal("{}: linker script too big", .{test_path});
2321 try ld_script_bytes.resize(gpa, size);2321 try ld_script_bytes.resize(gpa, size);
2322 const buf = ld_script_bytes.items[n..];2322 const buf2 = ld_script_bytes.items[n..];
2323 const n2 = file.preadAll(buf, n) catch |err|2323 const n2 = file.preadAll(buf2, n) catch |err|
2324 fatal("failed to read {}: {s}", .{ test_path, @errorName(err) });2324 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});
2326 var diags = Diags.init(gpa);2326 var diags = Diags.init(gpa);
2327 defer diags.deinit();2327 defer diags.deinit();
2328 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);2328 const ld_script_result = LdScript.parse(gpa, &diags, test_path, ld_script_bytes.items);