aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-10-14 22:57:12 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-10-23 16:27:38 -0700
commit4706ec81d4f864bc08804d9600937848ff9e4290 (patch)
tree2771856f2b8da6be686fd81e2d8c76c7b7d51a84 /src
parent5b016e290a5ba335b295afeae104af6b3396a425 (diff)
downloadzig-4706ec81d4f864bc08804d9600937848ff9e4290.tar.gz
zig-4706ec81d4f864bc08804d9600937848ff9e4290.zip
introduce a CLI flag to enable .so scripts; default off
The compiler defaults this value to off so that users whose system shared libraries are all ELF files don't have to pay the cost of checking every file to find out if it is a text file instead. When a GNU ld script is encountered, the error message instructs users about the CLI flag that will immediately solve their problem.
Diffstat (limited to 'src')
-rw-r--r--src/link/Elf.zig6
-rw-r--r--src/main.zig10
2 files changed, 15 insertions, 1 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 4f96e10d87..35b5a30349 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1337,6 +1337,12 @@ pub fn parseInputReportingFailure(self: *Elf, path: Path, needed: bool, must_lin
.needed = needed,
}, &self.shared_objects, &self.files, target) catch |err| switch (err) {
error.LinkFailure => return, // already reported
+ error.BadMagic, error.UnexpectedEndOfFile => {
+ var notes = diags.addErrorWithNotes(2) catch return diags.setAllocFailure();
+ notes.addMsg("failed to parse shared object: {s}", .{@errorName(err)}) catch return diags.setAllocFailure();
+ notes.addNote("while parsing {}", .{path}) catch return diags.setAllocFailure();
+ notes.addNote("{s}", .{@as([]const u8, "the file may be a GNU ld script, in which case it is not an ELF file but a text file referencing other libraries to link. In this case, avoid depending on the library, convince your system administrators to refrain from using this kind of file, or pass -fallow-so-scripts to force the compiler to check every shared library in case it is an ld script.")}) catch return diags.setAllocFailure();
+ },
else => |e| diags.addParseError(path, "failed to parse shared object: {s}", .{@errorName(e)}),
},
.static_library => parseArchive(self, path, must_link) catch |err| switch (err) {
diff --git a/src/main.zig b/src/main.zig
index 1ec9548883..c68e4b7562 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -555,6 +555,8 @@ const usage_build_generic =
\\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library
\\ -fallow-shlib-undefined Allows undefined symbols in shared libraries
\\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries
+ \\ -fallow-so-scripts Allows .so files to be GNU ld scripts
+ \\ -fno-allow-so-scripts (default) .so files must be ELF files
\\ --build-id[=style] At a minor link-time expense, coordinates stripped binaries
\\ fast, uuid, sha1, md5 with debug symbols via a '.note.gnu.build-id' section
\\ 0x[hexstring] Maximum 32 bytes
@@ -1003,6 +1005,7 @@ fn buildOutputType(
.libc_paths_file = try EnvVar.ZIG_LIBC.get(arena),
.link_objects = .{},
.native_system_include_paths = &.{},
+ .allow_so_scripts = false,
};
// before arg parsing, check for the NO_COLOR and CLICOLOR_FORCE environment variables
@@ -1573,6 +1576,10 @@ fn buildOutputType(
linker_allow_shlib_undefined = true;
} else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) {
linker_allow_shlib_undefined = false;
+ } else if (mem.eql(u8, arg, "-fallow-so-scripts")) {
+ create_module.allow_so_scripts = true;
+ } else if (mem.eql(u8, arg, "-fno-allow-so-scripts")) {
+ create_module.allow_so_scripts = false;
} else if (mem.eql(u8, arg, "-z")) {
const z_arg = args_iter.nextOrFatal();
if (mem.eql(u8, z_arg, "nodelete")) {
@@ -3679,6 +3686,7 @@ const CreateModule = struct {
each_lib_rpath: ?bool,
libc_paths_file: ?[]const u8,
link_objects: std.ArrayListUnmanaged(Compilation.LinkObject),
+ allow_so_scripts: bool,
};
fn createModule(
@@ -6950,7 +6958,7 @@ fn accessLibPath(
// In the case of .so files, they might actually be "linker scripts"
// that contain references to other libraries.
- if (target.ofmt == .elf and mem.endsWith(u8, test_path.items, ".so")) {
+ if (create_module.allow_so_scripts and target.ofmt == .elf and mem.endsWith(u8, test_path.items, ".so")) {
var file = fs.cwd().openFile(test_path.items, .{}) catch |err| switch (err) {
error.FileNotFound => break :main_check,
else => |e| fatal("unable to search for {s} library '{s}': {s}", .{