mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #18486 from castholm/undefined-version
Add support for `--(no-)undefined-version`
This commit is contained in:
commit
7320b24e0e
@ -110,6 +110,9 @@ linker_dynamicbase: bool = true,
|
||||
|
||||
linker_allow_shlib_undefined: ?bool = null,
|
||||
|
||||
/// Allow version scripts to refer to undefined symbols.
|
||||
linker_allow_undefined_version: ?bool = null,
|
||||
|
||||
/// Permit read-only relocations in read-only segments. Disallowed by default.
|
||||
link_z_notext: bool = false,
|
||||
|
||||
@ -1451,6 +1454,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
try zig_args.append("--version-script");
|
||||
try zig_args.append(version_script.getPath(b));
|
||||
}
|
||||
if (self.linker_allow_undefined_version) |x| {
|
||||
try zig_args.append(if (x) "--undefined-version" else "--no-undefined-version");
|
||||
}
|
||||
|
||||
if (self.kind == .@"test") {
|
||||
if (self.exec_cmd_args) |exec_cmd_args| {
|
||||
|
||||
@ -1033,6 +1033,7 @@ pub const CreateOptions = struct {
|
||||
link_emit_relocs: bool = false,
|
||||
linker_script: ?[]const u8 = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
linker_allow_undefined_version: bool = false,
|
||||
soname: ?[]const u8 = null,
|
||||
linker_gc_sections: ?bool = null,
|
||||
linker_allow_shlib_undefined: ?bool = null,
|
||||
@ -1572,6 +1573,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
.stack_size = options.stack_size,
|
||||
.image_base = options.image_base,
|
||||
.version_script = options.version_script,
|
||||
.allow_undefined_version = options.linker_allow_undefined_version,
|
||||
.gc_sections = options.linker_gc_sections,
|
||||
.emit_relocs = options.link_emit_relocs,
|
||||
.soname = options.soname,
|
||||
@ -2458,7 +2460,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
|
||||
/// to remind the programmer to update multiple related pieces of code that
|
||||
/// are in different locations. Bump this number when adding or deleting
|
||||
/// anything from the link cache manifest.
|
||||
pub const link_hash_implementation_version = 10;
|
||||
pub const link_hash_implementation_version = 11;
|
||||
|
||||
fn addNonIncrementalStuffToCacheManifest(
|
||||
comp: *Compilation,
|
||||
@ -2467,7 +2469,7 @@ fn addNonIncrementalStuffToCacheManifest(
|
||||
) !void {
|
||||
const gpa = comp.gpa;
|
||||
|
||||
comptime assert(link_hash_implementation_version == 10);
|
||||
comptime assert(link_hash_implementation_version == 11);
|
||||
|
||||
if (comp.module) |mod| {
|
||||
const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);
|
||||
@ -2541,6 +2543,7 @@ fn addNonIncrementalStuffToCacheManifest(
|
||||
|
||||
try man.addOptionalFile(opts.linker_script);
|
||||
try man.addOptionalFile(opts.version_script);
|
||||
man.hash.add(opts.allow_undefined_version);
|
||||
|
||||
man.hash.addOptional(opts.stack_size);
|
||||
man.hash.addOptional(opts.image_base);
|
||||
|
||||
@ -113,6 +113,7 @@ pub const File = struct {
|
||||
minor_subsystem_version: ?u16,
|
||||
gc_sections: ?bool,
|
||||
allow_shlib_undefined: ?bool,
|
||||
allow_undefined_version: bool,
|
||||
subsystem: ?std.Target.SubSystem,
|
||||
linker_script: ?[]const u8,
|
||||
version_script: ?[]const u8,
|
||||
|
||||
@ -70,7 +70,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)
|
||||
man = comp.cache_parent.obtain();
|
||||
self.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
comptime assert(Compilation.link_hash_implementation_version == 11);
|
||||
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
|
||||
@ -22,6 +22,7 @@ soname: ?[]const u8,
|
||||
bind_global_refs_locally: bool,
|
||||
linker_script: ?[]const u8,
|
||||
version_script: ?[]const u8,
|
||||
allow_undefined_version: bool,
|
||||
print_icf_sections: bool,
|
||||
print_map: bool,
|
||||
entry_name: ?[]const u8,
|
||||
@ -325,6 +326,7 @@ pub fn createEmpty(
|
||||
.bind_global_refs_locally = options.bind_global_refs_locally,
|
||||
.linker_script = options.linker_script,
|
||||
.version_script = options.version_script,
|
||||
.allow_undefined_version = options.allow_undefined_version,
|
||||
.print_icf_sections = options.print_icf_sections,
|
||||
.print_map = options.print_map,
|
||||
};
|
||||
@ -2410,10 +2412,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
|
||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||
self.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
comptime assert(Compilation.link_hash_implementation_version == 11);
|
||||
|
||||
try man.addOptionalFile(self.linker_script);
|
||||
try man.addOptionalFile(self.version_script);
|
||||
man.hash.add(self.allow_undefined_version);
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
man.hash.add(obj.must_link);
|
||||
@ -2789,6 +2792,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
|
||||
try argv.append("-version-script");
|
||||
try argv.append(version_script);
|
||||
}
|
||||
if (self.allow_undefined_version) {
|
||||
try argv.append("--undefined-version");
|
||||
} else {
|
||||
try argv.append("--no-undefined-version");
|
||||
}
|
||||
}
|
||||
|
||||
// Positional arguments to the linker such as object files.
|
||||
|
||||
@ -55,7 +55,7 @@ pub fn linkWithZld(
|
||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||
macho_file.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
comptime assert(Compilation.link_hash_implementation_version == 11);
|
||||
|
||||
for (objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
|
||||
@ -3547,7 +3547,7 @@ fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) lin
|
||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||
wasm.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
comptime assert(Compilation.link_hash_implementation_version == 11);
|
||||
|
||||
for (objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
@ -4633,7 +4633,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !vo
|
||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||
wasm.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
comptime assert(Compilation.link_hash_implementation_version == 11);
|
||||
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
|
||||
12
src/main.zig
12
src/main.zig
@ -500,6 +500,8 @@ const usage_build_generic =
|
||||
\\Global Link Options:
|
||||
\\ -T[script], --script [script] Use a custom linker script
|
||||
\\ --version-script [path] Provide a version .map file
|
||||
\\ --undefined-version Allow version scripts to refer to undefined symbols
|
||||
\\ --no-undefined-version (default) Disallow version scripts from referring to undefined symbols
|
||||
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
|
||||
\\ --sysroot [path] Set the system root directory (usually /)
|
||||
\\ --version [ver] Dynamic library semver
|
||||
@ -826,6 +828,7 @@ fn buildOutputType(
|
||||
var want_compiler_rt: ?bool = null;
|
||||
var linker_script: ?[]const u8 = null;
|
||||
var version_script: ?[]const u8 = null;
|
||||
var linker_allow_undefined_version: bool = false;
|
||||
var disable_c_depfile = false;
|
||||
var linker_sort_section: ?link.File.Elf.SortSection = null;
|
||||
var linker_gc_sections: ?bool = null;
|
||||
@ -1200,6 +1203,10 @@ fn buildOutputType(
|
||||
linker_script = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {
|
||||
version_script = args_iter.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "--undefined-version")) {
|
||||
linker_allow_undefined_version = true;
|
||||
} else if (mem.eql(u8, arg, "--no-undefined-version")) {
|
||||
linker_allow_undefined_version = false;
|
||||
} else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
|
||||
// We don't know whether this library is part of libc
|
||||
// or libc++ until we resolve the target, so we append
|
||||
@ -2153,6 +2160,10 @@ fn buildOutputType(
|
||||
create_module.opts.rdynamic = true;
|
||||
} else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {
|
||||
version_script = linker_args_it.nextOrFatal();
|
||||
} else if (mem.eql(u8, arg, "--undefined-version")) {
|
||||
linker_allow_undefined_version = true;
|
||||
} else if (mem.eql(u8, arg, "--no-undefined-version")) {
|
||||
linker_allow_undefined_version = false;
|
||||
} else if (mem.eql(u8, arg, "-O")) {
|
||||
linker_optimization = linker_args_it.nextOrFatal();
|
||||
} else if (mem.startsWith(u8, arg, "-O")) {
|
||||
@ -3166,6 +3177,7 @@ fn buildOutputType(
|
||||
.hash_style = hash_style,
|
||||
.linker_script = linker_script,
|
||||
.version_script = version_script,
|
||||
.linker_allow_undefined_version = linker_allow_undefined_version,
|
||||
.disable_c_depfile = disable_c_depfile,
|
||||
.soname = resolved_soname,
|
||||
.linker_sort_section = linker_sort_section,
|
||||
|
||||
@ -94,6 +94,8 @@ pub fn testAll(b: *Build) *Step {
|
||||
elf_step.dependOn(testLinkOrder(b, .{ .target = glibc_target }));
|
||||
elf_step.dependOn(testLdScript(b, .{ .target = glibc_target }));
|
||||
elf_step.dependOn(testLdScriptPathError(b, .{ .target = glibc_target }));
|
||||
elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = glibc_target, .use_lld = true }));
|
||||
elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = glibc_target, .use_lld = true }));
|
||||
elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = glibc_target }));
|
||||
// https://github.com/ziglang/zig/issues/17451
|
||||
// elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = glibc_target }));
|
||||
@ -2008,6 +2010,67 @@ fn testLdScriptPathError(b: *Build, opts: Options) *Step {
|
||||
return test_step;
|
||||
}
|
||||
|
||||
fn testLdScriptAllowUndefinedVersion(b: *Build, opts: Options) *Step {
|
||||
const test_step = addTestStep(b, "ld-script-allow-undefined-version", opts);
|
||||
|
||||
const so = addSharedLibrary(b, opts, .{
|
||||
.name = "add",
|
||||
.zig_source_bytes =
|
||||
\\export fn add(a: i32, b: i32) i32 {
|
||||
\\ return a + b;
|
||||
\\}
|
||||
,
|
||||
});
|
||||
const ld = b.addWriteFiles().add("add.ld", "VERSION { ADD_1.0 { global: add; sub; local: *; }; }");
|
||||
so.setLinkerScript(ld);
|
||||
so.linker_allow_undefined_version = true;
|
||||
|
||||
const exe = addExecutable(b, opts, .{
|
||||
.name = "main",
|
||||
.zig_source_bytes =
|
||||
\\const std = @import("std");
|
||||
\\extern fn add(a: i32, b: i32) i32;
|
||||
\\pub fn main() void {
|
||||
\\ std.debug.print("{d}\n", .{add(1, 2)});
|
||||
\\}
|
||||
,
|
||||
});
|
||||
exe.linkLibrary(so);
|
||||
exe.linkLibC();
|
||||
|
||||
const run = addRunArtifact(exe);
|
||||
run.expectStdErrEqual("3\n");
|
||||
test_step.dependOn(&run.step);
|
||||
|
||||
return test_step;
|
||||
}
|
||||
|
||||
fn testLdScriptDisallowUndefinedVersion(b: *Build, opts: Options) *Step {
|
||||
const test_step = addTestStep(b, "ld-script-disallow-undefined-version", opts);
|
||||
|
||||
const so = addSharedLibrary(b, opts, .{
|
||||
.name = "add",
|
||||
.zig_source_bytes =
|
||||
\\export fn add(a: i32, b: i32) i32 {
|
||||
\\ return a + b;
|
||||
\\}
|
||||
,
|
||||
});
|
||||
const ld = b.addWriteFiles().add("add.ld", "VERSION { ADD_1.0 { global: add; sub; local: *; }; }");
|
||||
so.setLinkerScript(ld);
|
||||
so.linker_allow_undefined_version = false;
|
||||
|
||||
expectLinkErrors(
|
||||
so,
|
||||
test_step,
|
||||
.{
|
||||
.contains = "error: ld.lld: version script assignment of 'ADD_1.0' to symbol 'sub' failed: symbol not defined",
|
||||
},
|
||||
);
|
||||
|
||||
return test_step;
|
||||
}
|
||||
|
||||
fn testMismatchedCpuArchitectureError(b: *Build, opts: Options) *Step {
|
||||
const test_step = addTestStep(b, "mismatched-cpu-architecture-error", opts);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user