mirror of
https://github.com/ziglang/zig.git
synced 2026-01-30 11:13:38 +00:00
linkers: update references to "options" field
This commit is contained in:
parent
3b6cb257df
commit
0789e91eeb
@ -76,6 +76,7 @@ framework_dirs: []const []const u8,
|
||||
system_libs: std.StringArrayHashMapUnmanaged(SystemLib),
|
||||
version: ?std.SemanticVersion,
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
skip_linker_dependencies: bool,
|
||||
|
||||
c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
|
||||
win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =
|
||||
@ -940,7 +941,7 @@ pub const InitOptions = struct {
|
||||
/// * getpid
|
||||
/// * mman
|
||||
/// * signal
|
||||
wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{},
|
||||
wasi_emulated_libs: []const wasi_libc.CRTFile = &.{},
|
||||
/// This means that if the output mode is an executable it will be a
|
||||
/// Position Independent Executable. If the output mode is not an
|
||||
/// executable this field is ignored.
|
||||
@ -1238,7 +1239,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
const sysroot = options.sysroot orelse libc_dirs.sysroot;
|
||||
|
||||
const include_compiler_rt = options.want_compiler_rt orelse
|
||||
(!options.skip_linker_dependencies and is_exe_or_dyn_lib);
|
||||
(!comp.skip_linker_dependencies and is_exe_or_dyn_lib);
|
||||
|
||||
if (include_compiler_rt and output_mode == .Obj) {
|
||||
// For objects, this mechanism relies on essentially `_ = @import("compiler-rt");`
|
||||
@ -1639,6 +1640,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.objects = options.link_objects,
|
||||
.framework_dirs = options.framework_dirs,
|
||||
.llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
|
||||
.skip_linker_dependencies = options.skip_linker_dependencies,
|
||||
};
|
||||
|
||||
if (bin_file_emit) |emit| {
|
||||
@ -1695,7 +1697,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.soname = options.soname,
|
||||
.compatibility_version = options.compatibility_version,
|
||||
.dll_export_fns = dll_export_fns,
|
||||
.skip_linker_dependencies = options.skip_linker_dependencies,
|
||||
.parent_compilation_link_libc = options.parent_compilation_link_libc,
|
||||
.each_lib_rpath = each_lib_rpath,
|
||||
.build_id = build_id,
|
||||
@ -1765,9 +1766,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
}
|
||||
}
|
||||
|
||||
const have_bin_emit = comp.bin_file.options.emit != null or comp.whole_bin_sub_path != null;
|
||||
const have_bin_emit = comp.bin_file != null or comp.whole_bin_sub_path != null;
|
||||
|
||||
if (have_bin_emit and !comp.bin_file.options.skip_linker_dependencies and target.ofmt != .c) {
|
||||
if (have_bin_emit and !comp.skip_linker_dependencies and target.ofmt != .c) {
|
||||
if (target.isDarwin()) {
|
||||
switch (target.abi) {
|
||||
.none,
|
||||
@ -1808,27 +1809,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
.{ .musl_crt_file = .crt1_o },
|
||||
.{ .musl_crt_file = .scrt1_o },
|
||||
.{ .musl_crt_file = .rcrt1_o },
|
||||
switch (comp.bin_file.options.link_mode) {
|
||||
switch (comp.config.link_mode) {
|
||||
.Static => .{ .musl_crt_file = .libc_a },
|
||||
.Dynamic => .{ .musl_crt_file = .libc_so },
|
||||
},
|
||||
});
|
||||
}
|
||||
if (comp.wantBuildWasiLibcFromSource()) {
|
||||
if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
|
||||
|
||||
const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs;
|
||||
try comp.work_queue.ensureUnusedCapacity(wasi_emulated_libs.len + 2); // worst-case we need all components
|
||||
for (wasi_emulated_libs) |crt_file| {
|
||||
comp.work_queue.writeItemAssumeCapacity(.{
|
||||
.wasi_libc_crt_file = crt_file,
|
||||
});
|
||||
if (comp.bin_file) |lf| {
|
||||
if (lf.cast(link.File.Wasm)) |wasm| {
|
||||
if (comp.wantBuildWasiLibcFromSource()) {
|
||||
if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
|
||||
|
||||
// worst-case we need all components
|
||||
try comp.work_queue.ensureUnusedCapacity(wasm.wasi_emulated_libs.len + 2);
|
||||
|
||||
for (wasm.wasi_emulated_libs) |crt_file| {
|
||||
comp.work_queue.writeItemAssumeCapacity(.{
|
||||
.wasi_libc_crt_file = crt_file,
|
||||
});
|
||||
}
|
||||
comp.work_queue.writeAssumeCapacity(&[_]Job{
|
||||
.{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) },
|
||||
.{ .wasi_libc_crt_file = .libc_a },
|
||||
});
|
||||
}
|
||||
}
|
||||
comp.work_queue.writeAssumeCapacity(&[_]Job{
|
||||
.{ .wasi_libc_crt_file = wasi_libc.execModelCrtFile(options.config.wasi_exec_model) },
|
||||
.{ .wasi_libc_crt_file = .libc_a },
|
||||
});
|
||||
}
|
||||
|
||||
if (comp.wantBuildMinGWFromSource()) {
|
||||
if (!target_util.canBuildLibC(target)) return error.LibCUnavailable;
|
||||
|
||||
@ -1863,27 +1871,29 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
if (comp.wantBuildLibUnwindFromSource()) {
|
||||
try comp.work_queue.writeItem(.{ .libunwind = {} });
|
||||
}
|
||||
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.bin_file.options.link_libcpp) {
|
||||
if (build_options.have_llvm and is_exe_or_dyn_lib and comp.config.link_libcpp) {
|
||||
try comp.work_queue.writeItem(.libcxx);
|
||||
try comp.work_queue.writeItem(.libcxxabi);
|
||||
}
|
||||
if (build_options.have_llvm and comp.bin_file.options.tsan) {
|
||||
if (build_options.have_llvm and comp.config.any_sanitize_thread) {
|
||||
try comp.work_queue.writeItem(.libtsan);
|
||||
}
|
||||
|
||||
if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) {
|
||||
// LLD might drop some symbols as unused during LTO and GCing, therefore,
|
||||
// we force mark them for resolution here.
|
||||
if (comp.bin_file) |lf| {
|
||||
if (comp.getTarget().isMinGW() and comp.config.any_non_single_threaded) {
|
||||
// LLD might drop some symbols as unused during LTO and GCing, therefore,
|
||||
// we force mark them for resolution here.
|
||||
|
||||
const tls_index_sym = switch (comp.getTarget().cpu.arch) {
|
||||
.x86 => "__tls_index",
|
||||
else => "_tls_index",
|
||||
};
|
||||
const tls_index_sym = switch (comp.getTarget().cpu.arch) {
|
||||
.x86 => "__tls_index",
|
||||
else => "_tls_index",
|
||||
};
|
||||
|
||||
try comp.bin_file.options.force_undefined_symbols.put(comp.gpa, tls_index_sym, {});
|
||||
try lf.force_undefined_symbols.put(comp.gpa, tls_index_sym, {});
|
||||
}
|
||||
}
|
||||
|
||||
if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
|
||||
if (comp.include_compiler_rt and capable_of_building_compiler_rt) {
|
||||
if (is_exe_or_dyn_lib) {
|
||||
log.debug("queuing a job to build compiler_rt_lib", .{});
|
||||
comp.job_queued_compiler_rt_lib = true;
|
||||
@ -1895,8 +1905,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
||||
}
|
||||
}
|
||||
|
||||
if (!comp.bin_file.options.skip_linker_dependencies and is_exe_or_dyn_lib and
|
||||
!comp.bin_file.options.link_libc and capable_of_building_zig_libc)
|
||||
if (!comp.skip_linker_dependencies and is_exe_or_dyn_lib and
|
||||
!comp.config.link_libc and capable_of_building_zig_libc)
|
||||
{
|
||||
try comp.work_queue.writeItem(.{ .zig_libc = {} });
|
||||
}
|
||||
@ -2425,7 +2435,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
||||
man.hash.add(comp.test_evented_io);
|
||||
man.hash.addOptionalBytes(comp.test_filter);
|
||||
man.hash.addOptionalBytes(comp.test_name_prefix);
|
||||
man.hash.add(comp.bin_file.options.skip_linker_dependencies);
|
||||
man.hash.add(comp.skip_linker_dependencies);
|
||||
man.hash.add(comp.formatted_panics);
|
||||
man.hash.add(mod.emit_h != null);
|
||||
man.hash.add(mod.error_limit);
|
||||
@ -2477,7 +2487,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
||||
man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());
|
||||
man.hash.add(comp.bin_file.options.each_lib_rpath);
|
||||
man.hash.add(comp.bin_file.build_id);
|
||||
man.hash.add(comp.bin_file.options.skip_linker_dependencies);
|
||||
man.hash.add(comp.skip_linker_dependencies);
|
||||
man.hash.add(comp.bin_file.options.z_nodelete);
|
||||
man.hash.add(comp.bin_file.options.z_notext);
|
||||
man.hash.add(comp.bin_file.options.z_defs);
|
||||
@ -2489,7 +2499,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
||||
man.hash.add(comp.bin_file.options.z_max_page_size orelse 0);
|
||||
man.hash.add(comp.bin_file.options.hash_style);
|
||||
man.hash.add(comp.bin_file.options.compress_debug_sections);
|
||||
man.hash.add(comp.bin_file.options.include_compiler_rt);
|
||||
man.hash.add(comp.include_compiler_rt);
|
||||
man.hash.add(comp.bin_file.options.sort_section);
|
||||
if (comp.config.link_libc) {
|
||||
man.hash.add(comp.bin_file.options.libc_installation != null);
|
||||
@ -3836,7 +3846,7 @@ pub fn obtainCObjectCacheManifest(comp: *const Compilation) Cache.Manifest {
|
||||
// Also nothing that applies only to compiling .zig code.
|
||||
man.hash.add(comp.sanitize_c);
|
||||
man.hash.addListOfBytes(comp.clang_argv);
|
||||
man.hash.add(comp.bin_file.options.link_libcpp);
|
||||
man.hash.add(comp.config.link_libcpp);
|
||||
|
||||
// When libc_installation is null it means that Zig generated this dir list
|
||||
// based on the zig library directory alone. The zig lib directory file
|
||||
@ -4909,7 +4919,7 @@ pub fn addCCArgs(
|
||||
try argv.append("-fno-builtin");
|
||||
}
|
||||
|
||||
if (comp.bin_file.options.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
const libcxx_include_path = try std.fs.path.join(arena, &[_][]const u8{
|
||||
comp.zig_lib_directory.path.?, "libcxx", "include",
|
||||
});
|
||||
@ -4954,7 +4964,7 @@ pub fn addCCArgs(
|
||||
try argv.append(libunwind_include_path);
|
||||
}
|
||||
|
||||
if (comp.bin_file.options.link_libc and target.isGnuLibC()) {
|
||||
if (comp.config.link_libc and target.isGnuLibC()) {
|
||||
const target_version = target.os.version_range.linux.glibc;
|
||||
const glibc_minor_define = try std.fmt.allocPrint(arena, "-D__GLIBC_MINOR__={d}", .{
|
||||
target_version.minor,
|
||||
@ -5944,7 +5954,7 @@ fn wantBuildLibCFromSource(comp: Compilation) bool {
|
||||
.Lib => comp.bin_file.options.link_mode == .Dynamic,
|
||||
.Exe => true,
|
||||
};
|
||||
return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and
|
||||
return comp.config.link_libc and is_exe_or_dyn_lib and
|
||||
comp.bin_file.options.libc_installation == null and
|
||||
comp.bin_file.options.target.ofmt != .c;
|
||||
}
|
||||
@ -6164,6 +6174,7 @@ fn buildOutputFromZig(
|
||||
.have_zcu = true,
|
||||
.emit_bin = true,
|
||||
.root_optimize_mode = comp.compilerRtOptMode(),
|
||||
.link_libc = comp.config.link_libc,
|
||||
});
|
||||
|
||||
const root_mod = Package.Module.create(.{
|
||||
@ -6224,7 +6235,6 @@ fn buildOutputFromZig(
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.link_libc = comp.bin_file.options.link_libc,
|
||||
.want_structured_cfg = comp.bin_file.options.want_structured_cfg,
|
||||
});
|
||||
defer sub_compilation.destroy();
|
||||
@ -6305,7 +6315,6 @@ pub fn build_crt_file(
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.link_libc = comp.bin_file.options.link_libc,
|
||||
.want_structured_cfg = comp.bin_file.options.want_structured_cfg,
|
||||
});
|
||||
defer sub_compilation.destroy();
|
||||
@ -6327,7 +6336,7 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void {
|
||||
// This can happen when the user uses `build-exe foo.obj -lkernel32` and
|
||||
// then when we create a sub-Compilation for zig libc, it also tries to
|
||||
// build kernel32.lib.
|
||||
if (comp.bin_file.options.skip_linker_dependencies) return;
|
||||
if (comp.skip_linker_dependencies) return;
|
||||
|
||||
// This happens when an `extern "foo"` function is referenced.
|
||||
// If we haven't seen this library yet and we're targeting Windows, we need
|
||||
|
||||
@ -335,7 +335,7 @@ pub fn resolve(options: Options) !Config {
|
||||
break :b .Static;
|
||||
};
|
||||
|
||||
const import_memory = options.import_memory orelse false;
|
||||
const import_memory = options.import_memory orelse (options.output_mode == .Obj);
|
||||
const export_memory = b: {
|
||||
if (link_mode == .Dynamic) {
|
||||
if (options.export_memory == true) return error.ExportMemoryAndDynamicIncompatible;
|
||||
|
||||
27
src/Sema.zig
27
src/Sema.zig
@ -5742,7 +5742,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
const msg = try sema.errMsg(&child_block, src, "C import failed", .{});
|
||||
errdefer msg.destroy(gpa);
|
||||
|
||||
if (!comp.bin_file.options.link_libc)
|
||||
if (!comp.config.link_libc)
|
||||
try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});
|
||||
|
||||
const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index);
|
||||
@ -9058,7 +9058,7 @@ fn resolveGenericBody(
|
||||
|
||||
/// Given a library name, examines if the library name should end up in
|
||||
/// `link.File.Options.system_libs` table (for example, libc is always
|
||||
/// specified via dedicated flag `link.File.Options.link_libc` instead),
|
||||
/// specified via dedicated flag `link_libc` instead),
|
||||
/// and puts it there if it doesn't exist.
|
||||
/// It also dupes the library name which can then be saved as part of the
|
||||
/// respective `Decl` (either `ExternFn` or `Var`).
|
||||
@ -9076,7 +9076,7 @@ fn handleExternLibName(
|
||||
const target = mod.getTarget();
|
||||
log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
|
||||
if (target.is_libc_lib_name(lib_name)) {
|
||||
if (!comp.bin_file.options.link_libc) {
|
||||
if (!comp.config.link_libc) {
|
||||
return sema.fail(
|
||||
block,
|
||||
src_loc,
|
||||
@ -9087,18 +9087,21 @@ fn handleExternLibName(
|
||||
break :blk;
|
||||
}
|
||||
if (target.is_libcpp_lib_name(lib_name)) {
|
||||
if (!comp.bin_file.options.link_libcpp) {
|
||||
return sema.fail(
|
||||
block,
|
||||
src_loc,
|
||||
"dependency on libc++ must be explicitly specified in the build command",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
if (!comp.config.link_libcpp) return sema.fail(
|
||||
block,
|
||||
src_loc,
|
||||
"dependency on libc++ must be explicitly specified in the build command",
|
||||
.{},
|
||||
);
|
||||
break :blk;
|
||||
}
|
||||
if (mem.eql(u8, lib_name, "unwind")) {
|
||||
comp.bin_file.options.link_libunwind = true;
|
||||
if (!comp.config.link_libunwind) return sema.fail(
|
||||
block,
|
||||
src_loc,
|
||||
"dependency on libunwind must be explicitly specified in the build command",
|
||||
.{},
|
||||
);
|
||||
break :blk;
|
||||
}
|
||||
if (!target.isWasm() and !comp.bin_file.options.pic) {
|
||||
|
||||
@ -3083,9 +3083,7 @@ pub const Object = struct {
|
||||
if (comp.unwind_tables) {
|
||||
try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
|
||||
}
|
||||
if (comp.bin_file.options.skip_linker_dependencies or
|
||||
comp.bin_file.options.no_builtin)
|
||||
{
|
||||
if (comp.skip_linker_dependencies or comp.bin_file.options.no_builtin) {
|
||||
// The intent here is for compiler-rt and libc functions to not generate
|
||||
// infinite recursion. For example, if we are compiling the memcpy function,
|
||||
// and llvm detects that the body is equivalent to memcpy, it may replace the
|
||||
|
||||
@ -119,7 +119,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: *std.Progress.Node) !void {
|
||||
});
|
||||
}
|
||||
|
||||
const to_c_or_not_to_c_sources = if (comp.bin_file.options.link_libc)
|
||||
const to_c_or_not_to_c_sources = if (comp.config.link_libc)
|
||||
&sanitizer_libcdep_sources
|
||||
else
|
||||
&sanitizer_nolibc_sources;
|
||||
|
||||
@ -133,7 +133,6 @@ pub const File = struct {
|
||||
export_symbol_names: []const []const u8,
|
||||
global_base: ?u64,
|
||||
dll_export_fns: bool,
|
||||
skip_linker_dependencies: bool,
|
||||
parent_compilation_link_libc: bool,
|
||||
each_lib_rpath: bool,
|
||||
build_id: std.zig.BuildId,
|
||||
@ -1099,7 +1098,7 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
pub fn isStatic(self: File) bool {
|
||||
return self.base.comp.config.link_mode == .Static;
|
||||
return self.comp.config.link_mode == .Static;
|
||||
}
|
||||
|
||||
pub fn isObject(self: File) bool {
|
||||
|
||||
@ -48,7 +48,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
const is_lib = self.base.comp.config.output_mode == .Lib;
|
||||
const is_dyn_lib = self.base.comp.config.link_mode == .Dynamic and is_lib;
|
||||
const is_exe_or_dyn_lib = is_dyn_lib or self.base.comp.config.output_mode == .Exe;
|
||||
const link_in_crt = self.base.options.link_libc and is_exe_or_dyn_lib;
|
||||
const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib;
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const optimize_mode = self.base.comp.root_mod.optimize_mode;
|
||||
|
||||
@ -56,17 +56,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
const id_symlink_basename = "lld.id";
|
||||
|
||||
var man: Cache.Manifest = undefined;
|
||||
defer if (!self.base.options.disable_lld_caching) man.deinit();
|
||||
defer if (!self.base.disable_lld_caching) man.deinit();
|
||||
|
||||
var digest: [Cache.hex_digest_len]u8 = undefined;
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
if (!self.base.disable_lld_caching) {
|
||||
man = comp.cache_parent.obtain();
|
||||
self.base.releaseLock();
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
man.hash.add(obj.must_link);
|
||||
}
|
||||
@ -79,12 +79,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
}
|
||||
try man.addOptionalFile(module_obj_path);
|
||||
man.hash.addOptionalBytes(self.base.options.entry);
|
||||
man.hash.addOptionalBytes(comp.config.entry);
|
||||
man.hash.add(self.base.stack_size);
|
||||
man.hash.addOptional(self.image_base);
|
||||
man.hash.addListOfBytes(self.base.options.lib_dirs);
|
||||
man.hash.add(self.base.options.skip_linker_dependencies);
|
||||
if (self.base.options.link_libc) {
|
||||
man.hash.addListOfBytes(self.lib_dirs);
|
||||
man.hash.add(comp.skip_linker_dependencies);
|
||||
if (comp.config.link_libc) {
|
||||
man.hash.add(self.base.comp.libc_installation != null);
|
||||
if (self.base.comp.libc_installation) |libc_installation| {
|
||||
man.hash.addBytes(libc_installation.crt_dir.?);
|
||||
@ -95,18 +95,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
}
|
||||
try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
|
||||
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||
man.hash.addOptional(self.base.options.subsystem);
|
||||
man.hash.add(self.base.options.is_test);
|
||||
man.hash.add(self.base.options.tsaware);
|
||||
man.hash.add(self.base.options.nxcompat);
|
||||
man.hash.add(self.base.options.dynamicbase);
|
||||
man.hash.addListOfBytes(self.base.force_undefined_symbols.keys());
|
||||
man.hash.addOptional(self.subsystem);
|
||||
man.hash.add(comp.config.is_test);
|
||||
man.hash.add(self.tsaware);
|
||||
man.hash.add(self.nxcompat);
|
||||
man.hash.add(self.dynamicbase);
|
||||
man.hash.addOptional(self.base.allow_shlib_undefined);
|
||||
// strip does not need to go into the linker hash because it is part of the hash namespace
|
||||
man.hash.addOptional(self.base.options.major_subsystem_version);
|
||||
man.hash.addOptional(self.base.options.minor_subsystem_version);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
try man.addOptionalFile(self.base.options.module_definition_file);
|
||||
man.hash.addOptional(self.major_subsystem_version);
|
||||
man.hash.addOptional(self.minor_subsystem_version);
|
||||
man.hash.addOptional(comp.version);
|
||||
try man.addOptionalFile(self.module_definition_file);
|
||||
|
||||
// We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
|
||||
_ = try man.hit();
|
||||
@ -141,8 +141,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
// here. TODO: think carefully about how we can avoid this redundant operation when doing
|
||||
// build-obj. See also the corresponding TODO in linkAsArchive.
|
||||
const the_object_path = blk: {
|
||||
if (self.base.options.objects.len != 0)
|
||||
break :blk self.base.options.objects[0].path;
|
||||
if (comp.objects.len != 0)
|
||||
break :blk comp.objects[0].path;
|
||||
|
||||
if (comp.c_object_table.count() != 0)
|
||||
break :blk comp.c_object_table.keys()[0].status.success.object_path;
|
||||
@ -171,21 +171,21 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
|
||||
try argv.append("-ERRORLIMIT:0");
|
||||
try argv.append("-NOLOGO");
|
||||
if (!self.base.options.strip) {
|
||||
if (self.base.debug_format != .strip) {
|
||||
try argv.append("-DEBUG");
|
||||
|
||||
const out_ext = std.fs.path.extension(full_out_path);
|
||||
const out_pdb = self.base.options.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
|
||||
const out_pdb = self.pdb_out_path orelse try allocPrint(arena, "{s}.pdb", .{
|
||||
full_out_path[0 .. full_out_path.len - out_ext.len],
|
||||
});
|
||||
|
||||
try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
|
||||
try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));
|
||||
}
|
||||
if (self.base.options.version) |version| {
|
||||
if (comp.version) |version| {
|
||||
try argv.append(try allocPrint(arena, "-VERSION:{}.{}", .{ version.major, version.minor }));
|
||||
}
|
||||
if (self.base.options.lto) {
|
||||
if (comp.config.lto) {
|
||||
switch (optimize_mode) {
|
||||
.Debug => {},
|
||||
.ReleaseSmall => try argv.append("-OPT:lldlto=2"),
|
||||
@ -209,7 +209,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
}
|
||||
|
||||
for (self.base.options.force_undefined_symbols.keys()) |symbol| {
|
||||
for (self.base.force_undefined_symbols.keys()) |symbol| {
|
||||
try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol}));
|
||||
}
|
||||
|
||||
@ -217,17 +217,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try argv.append("-DLL");
|
||||
}
|
||||
|
||||
if (self.base.options.entry) |entry| {
|
||||
if (comp.config.entry) |entry| {
|
||||
try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry}));
|
||||
}
|
||||
|
||||
if (self.base.options.tsaware) {
|
||||
if (self.tsaware) {
|
||||
try argv.append("-tsaware");
|
||||
}
|
||||
if (self.base.options.nxcompat) {
|
||||
if (self.nxcompat) {
|
||||
try argv.append("-nxcompat");
|
||||
}
|
||||
if (!self.base.options.dynamicbase) {
|
||||
if (!self.dynamicbase) {
|
||||
try argv.append("-dynamicbase:NO");
|
||||
}
|
||||
if (self.base.allow_shlib_undefined) {
|
||||
@ -236,12 +236,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
|
||||
try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
|
||||
|
||||
if (self.base.options.implib_emit) |emit| {
|
||||
if (self.implib_emit) |emit| {
|
||||
const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
|
||||
try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
|
||||
}
|
||||
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation) |libc_installation| {
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
|
||||
|
||||
@ -252,12 +252,12 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
}
|
||||
|
||||
for (self.base.options.lib_dirs) |lib_dir| {
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
|
||||
}
|
||||
|
||||
try argv.ensureUnusedCapacity(self.base.options.objects.len);
|
||||
for (self.base.options.objects) |obj| {
|
||||
try argv.ensureUnusedCapacity(comp.objects.len);
|
||||
for (comp.objects) |obj| {
|
||||
if (obj.must_link) {
|
||||
argv.appendAssumeCapacity(try allocPrint(arena, "-WHOLEARCHIVE:{s}", .{obj.path}));
|
||||
} else {
|
||||
@ -279,18 +279,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
try argv.append(p);
|
||||
}
|
||||
|
||||
if (self.base.options.module_definition_file) |def| {
|
||||
if (self.module_definition_file) |def| {
|
||||
try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
|
||||
}
|
||||
|
||||
const resolved_subsystem: ?std.Target.SubSystem = blk: {
|
||||
if (self.base.options.subsystem) |explicit| break :blk explicit;
|
||||
if (self.subsystem) |explicit| break :blk explicit;
|
||||
switch (target.os.tag) {
|
||||
.windows => {
|
||||
if (self.base.comp.module) |module| {
|
||||
if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)
|
||||
break :blk null;
|
||||
if (module.stage1_flags.have_c_main or self.base.options.is_test or
|
||||
if (module.stage1_flags.have_c_main or comp.config.is_test or
|
||||
module.stage1_flags.have_winmain_crt_startup or
|
||||
module.stage1_flags.have_wwinmain_crt_startup)
|
||||
{
|
||||
@ -310,8 +310,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
const mode: Mode = mode: {
|
||||
if (resolved_subsystem) |subsystem| {
|
||||
const subsystem_suffix = ss: {
|
||||
if (self.base.options.major_subsystem_version) |major| {
|
||||
if (self.base.options.minor_subsystem_version) |minor| {
|
||||
if (self.major_subsystem_version) |major| {
|
||||
if (self.minor_subsystem_version) |minor| {
|
||||
break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor });
|
||||
} else {
|
||||
break :ss try allocPrint(arena, ",{d}", .{major});
|
||||
@ -447,7 +447,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
} else {
|
||||
try argv.append("-NODEFAULTLIB");
|
||||
if (!is_lib and self.base.options.entry == null) {
|
||||
if (!is_lib and comp.config.entry == null) {
|
||||
if (self.base.comp.module) |module| {
|
||||
if (module.stage1_flags.have_winmain_crt_startup) {
|
||||
try argv.append("-ENTRY:WinMainCRTStartup");
|
||||
@ -463,18 +463,18 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (self.base.options.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libunwind dep
|
||||
if (self.base.options.link_libunwind) {
|
||||
if (comp.config.link_libunwind) {
|
||||
try argv.append(comp.libunwind_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
if (is_exe_or_dyn_lib and !self.base.options.skip_linker_dependencies) {
|
||||
if (!self.base.options.link_libc) {
|
||||
if (is_exe_or_dyn_lib and !comp.skip_linker_dependencies) {
|
||||
if (!comp.config.link_libc) {
|
||||
if (comp.libc_static_lib) |lib| {
|
||||
try argv.append(lib.full_object_path);
|
||||
}
|
||||
@ -492,13 +492,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
argv.appendAssumeCapacity(crt_file.full_object_path);
|
||||
continue;
|
||||
}
|
||||
if (try findLib(arena, lib_basename, self.base.options.lib_dirs)) |full_path| {
|
||||
if (try findLib(arena, lib_basename, self.lib_dirs)) |full_path| {
|
||||
argv.appendAssumeCapacity(full_path);
|
||||
continue;
|
||||
}
|
||||
if (target.abi.isGnu()) {
|
||||
const fallback_name = try allocPrint(arena, "lib{s}.dll.a", .{key});
|
||||
if (try findLib(arena, fallback_name, self.base.options.lib_dirs)) |full_path| {
|
||||
if (try findLib(arena, fallback_name, self.lib_dirs)) |full_path| {
|
||||
argv.appendAssumeCapacity(full_path);
|
||||
continue;
|
||||
}
|
||||
@ -582,7 +582,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
if (!self.base.disable_lld_caching) {
|
||||
// Update the file with the digest. If it fails we can continue; it only
|
||||
// means that the next invocation will have an unnecessary cache miss.
|
||||
Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
|
||||
|
||||
@ -1022,16 +1022,18 @@ const min_nop_size = 2;
|
||||
/// actual_capacity + (actual_capacity / ideal_factor)
|
||||
const ideal_factor = 3;
|
||||
|
||||
pub fn init(allocator: Allocator, bin_file: *File, format: Format) Dwarf {
|
||||
const target = &bin_file.options.target;
|
||||
pub fn init(lf: *File, format: Format) Dwarf {
|
||||
const comp = lf.comp;
|
||||
const gpa = comp.gpa;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
|
||||
0...32 => .p32,
|
||||
33...64 => .p64,
|
||||
else => unreachable,
|
||||
};
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.bin_file = bin_file,
|
||||
.allocator = gpa,
|
||||
.bin_file = lf,
|
||||
.format = format,
|
||||
.ptr_width = ptr_width,
|
||||
.dbg_line_header = switch (target.cpu.arch) {
|
||||
|
||||
295
src/link/Elf.zig
295
src/link/Elf.zig
@ -1,5 +1,6 @@
|
||||
base: link.File,
|
||||
image_base: u64,
|
||||
rdynamic: bool,
|
||||
|
||||
ptr_width: PtrWidth,
|
||||
|
||||
@ -358,19 +359,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
|
||||
.debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
|
||||
.function_sections = options.function_sections,
|
||||
.data_sections = options.data_sections,
|
||||
|
||||
.image_base = b: {
|
||||
if (is_dyn_lib) break :b 0;
|
||||
if (output_mode == .Exe and comp.config.pie) return 0;
|
||||
return options.image_base orelse switch (ptr_width) {
|
||||
.p32 => 0x1000,
|
||||
.p64 => 0x1000000,
|
||||
};
|
||||
},
|
||||
},
|
||||
.ptr_width = ptr_width,
|
||||
.page_size = page_size,
|
||||
.default_sym_version = default_sym_version,
|
||||
|
||||
.image_base = b: {
|
||||
if (is_dyn_lib) break :b 0;
|
||||
if (output_mode == .Exe and comp.config.pie) break :b 0;
|
||||
break :b options.image_base orelse switch (ptr_width) {
|
||||
.p32 => 0x1000,
|
||||
.p64 => 0x1000000,
|
||||
};
|
||||
},
|
||||
|
||||
.rdynamic = options.rdynamic,
|
||||
};
|
||||
if (use_llvm and comp.config.have_zcu) {
|
||||
self.llvm_object = try LlvmObject.create(arena, options);
|
||||
@ -1006,7 +1009,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
break :blk path;
|
||||
}
|
||||
} else null;
|
||||
const gc_sections = self.base.gc_sections;
|
||||
|
||||
// --verbose-link
|
||||
if (self.base.comp.verbose_link) try self.dumpArgv(comp);
|
||||
@ -1047,14 +1049,14 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
var rpath_table = std.StringArrayHashMap(void).init(gpa);
|
||||
defer rpath_table.deinit();
|
||||
|
||||
for (self.base.options.rpath_list) |rpath| {
|
||||
for (self.base.rpath_list) |rpath| {
|
||||
_ = try rpath_table.put(rpath, {});
|
||||
}
|
||||
|
||||
if (self.base.options.each_lib_rpath) {
|
||||
if (self.each_lib_rpath) {
|
||||
var test_path = std.ArrayList(u8).init(gpa);
|
||||
defer test_path.deinit();
|
||||
for (self.base.options.lib_dirs) |lib_dir_path| {
|
||||
for (self.lib_dirs) |lib_dir_path| {
|
||||
for (self.base.comp.system_libs.keys()) |link_lib| {
|
||||
if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
|
||||
continue;
|
||||
@ -1076,9 +1078,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
}
|
||||
|
||||
// libc
|
||||
if (!self.base.options.skip_linker_dependencies and
|
||||
!self.base.options.link_libc)
|
||||
{
|
||||
if (!comp.skip_linker_dependencies and !comp.config.link_libc) {
|
||||
if (comp.libc_static_lib) |lib| {
|
||||
try positionals.append(.{ .path = lib.full_object_path });
|
||||
}
|
||||
@ -1263,10 +1263,10 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
self.entry_index = if (entry) |name| self.globalByName(name) else null;
|
||||
}
|
||||
|
||||
if (gc_sections) {
|
||||
if (self.base.gc_sections) {
|
||||
try gc.gcAtoms(self);
|
||||
|
||||
if (self.base.options.print_gc_sections) {
|
||||
if (self.base.print_gc_sections) {
|
||||
try gc.dumpPrunedAtoms(self);
|
||||
}
|
||||
}
|
||||
@ -1347,13 +1347,13 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
}
|
||||
|
||||
pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void {
|
||||
const gpa = self.base.comp.gpa;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
|
||||
defer positionals.deinit();
|
||||
|
||||
try positionals.ensureUnusedCapacity(self.base.options.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(self.base.options.objects);
|
||||
try positionals.ensureUnusedCapacity(comp.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(comp.objects);
|
||||
|
||||
// This is a set of object files emitted by clang in a single `build-exe` invocation.
|
||||
// For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
|
||||
@ -1495,8 +1495,8 @@ pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8)
|
||||
|
||||
var positionals = std.ArrayList(Compilation.LinkObject).init(gpa);
|
||||
defer positionals.deinit();
|
||||
try positionals.ensureUnusedCapacity(self.base.options.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(self.base.options.objects);
|
||||
try positionals.ensureUnusedCapacity(comp.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(comp.objects);
|
||||
|
||||
// This is a set of object files emitted by clang in a single `build-exe` invocation.
|
||||
// For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up
|
||||
@ -1606,7 +1606,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
try argv.append(full_out_path);
|
||||
|
||||
if (self.base.isRelocatable()) {
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
try argv.append(obj.path);
|
||||
}
|
||||
|
||||
@ -1626,28 +1626,28 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
if (self.base.isDynLib()) {
|
||||
if (self.base.options.soname) |name| {
|
||||
if (self.soname) |name| {
|
||||
try argv.append("-soname");
|
||||
try argv.append(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.base.options.entry) |entry| {
|
||||
if (comp.config.entry) |entry| {
|
||||
try argv.append("--entry");
|
||||
try argv.append(entry);
|
||||
}
|
||||
|
||||
for (self.base.options.rpath_list) |rpath| {
|
||||
for (self.base.rpath_list) |rpath| {
|
||||
try argv.append("-rpath");
|
||||
try argv.append(rpath);
|
||||
}
|
||||
|
||||
if (self.base.options.each_lib_rpath) {
|
||||
for (self.base.options.lib_dirs) |lib_dir_path| {
|
||||
if (self.each_lib_rpath) {
|
||||
for (self.lib_dirs) |lib_dir_path| {
|
||||
try argv.append("-rpath");
|
||||
try argv.append(lib_dir_path);
|
||||
}
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (Compilation.classifyFileExt(obj.path) == .shared_library) {
|
||||
const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
|
||||
if (obj.loption) continue;
|
||||
@ -1669,29 +1669,29 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
try argv.append("--gc-sections");
|
||||
}
|
||||
|
||||
if (self.base.options.print_gc_sections) {
|
||||
if (self.base.print_gc_sections) {
|
||||
try argv.append("--print-gc-sections");
|
||||
}
|
||||
|
||||
if (self.base.options.eh_frame_hdr) {
|
||||
if (self.eh_frame_hdr) {
|
||||
try argv.append("--eh-frame-hdr");
|
||||
}
|
||||
|
||||
if (self.base.options.rdynamic) {
|
||||
if (self.rdynamic) {
|
||||
try argv.append("--export-dynamic");
|
||||
}
|
||||
|
||||
if (self.base.options.z_notext) {
|
||||
if (self.z_notext) {
|
||||
try argv.append("-z");
|
||||
try argv.append("notext");
|
||||
}
|
||||
|
||||
if (self.base.options.z_nocopyreloc) {
|
||||
if (self.z_nocopyreloc) {
|
||||
try argv.append("-z");
|
||||
try argv.append("nocopyreloc");
|
||||
}
|
||||
|
||||
if (self.base.options.z_now) {
|
||||
if (self.z_now) {
|
||||
try argv.append("-z");
|
||||
try argv.append("now");
|
||||
}
|
||||
@ -1702,11 +1702,11 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
try argv.append("-shared");
|
||||
}
|
||||
|
||||
if (self.base.options.pie and self.base.isExe()) {
|
||||
if (comp.config.pie and self.base.isExe()) {
|
||||
try argv.append("-pie");
|
||||
}
|
||||
|
||||
if (self.base.options.strip) {
|
||||
if (self.base.debug_format == .strip) {
|
||||
try argv.append("-s");
|
||||
}
|
||||
|
||||
@ -1715,12 +1715,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
if (csu.crti) |v| try argv.append(v);
|
||||
if (csu.crtbegin) |v| try argv.append(v);
|
||||
|
||||
for (self.base.options.lib_dirs) |lib_dir| {
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
try argv.append("-L");
|
||||
try argv.append(lib_dir);
|
||||
}
|
||||
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation) |libc_installation| {
|
||||
try argv.append("-L");
|
||||
try argv.append(libc_installation.crt_dir.?);
|
||||
@ -1728,7 +1728,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
var whole_archive = false;
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (obj.must_link and !whole_archive) {
|
||||
try argv.append("-whole-archive");
|
||||
whole_archive = true;
|
||||
@ -1756,15 +1756,12 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
try argv.append(p);
|
||||
}
|
||||
|
||||
// TSAN
|
||||
if (self.base.options.tsan) {
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try argv.append(comp.tsan_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc
|
||||
if (!self.base.options.skip_linker_dependencies and
|
||||
!self.base.options.link_libc)
|
||||
{
|
||||
if (!comp.skip_linker_dependencies and !comp.config.link_libc) {
|
||||
if (comp.libc_static_lib) |lib| {
|
||||
try argv.append(lib.full_object_path);
|
||||
}
|
||||
@ -1799,18 +1796,18 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (self.base.options.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libunwind dep
|
||||
if (self.base.options.link_libunwind) {
|
||||
if (comp.config.link_libunwind) {
|
||||
try argv.append(comp.libunwind_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc dep
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation != null) {
|
||||
const needs_grouping = link_mode == .Static;
|
||||
if (needs_grouping) try argv.append("--start-group");
|
||||
@ -1963,8 +1960,6 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
|
||||
defer script.deinit(gpa);
|
||||
try script.parse(data, self);
|
||||
|
||||
const lib_dirs = self.base.options.lib_dirs;
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
@ -1981,7 +1976,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
|
||||
|
||||
// TODO I think technically we should re-use the mechanism used by the frontend here.
|
||||
// Maybe we should hoist search-strategy all the way here?
|
||||
for (lib_dirs) |lib_dir| {
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
if (!self.isStatic()) {
|
||||
if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, lib_name, .Dynamic))
|
||||
break :success;
|
||||
@ -1998,7 +1993,7 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void {
|
||||
} else |_| {}
|
||||
|
||||
try checked_paths.append(try gpa.dupe(u8, scr_obj.path));
|
||||
for (lib_dirs) |lib_dir| {
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
if (try self.accessLibPath(&test_path, &checked_paths, lib_dir, scr_obj.path, null))
|
||||
break :success;
|
||||
}
|
||||
@ -2338,7 +2333,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
const link_mode = self.base.comp.config.link_mode;
|
||||
const is_dyn_lib = link_mode == .Dynamic and is_lib;
|
||||
const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe;
|
||||
const have_dynamic_linker = self.base.options.link_libc and
|
||||
const have_dynamic_linker = comp.config.link_libc and
|
||||
link_mode == .Dynamic and is_exe_or_dyn_lib;
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const compiler_rt_path: ?[]const u8 = blk: {
|
||||
@ -2358,11 +2353,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
const id_symlink_basename = "lld.id";
|
||||
|
||||
var man: Cache.Manifest = undefined;
|
||||
defer if (!self.base.options.disable_lld_caching) man.deinit();
|
||||
defer if (!self.base.disable_lld_caching) man.deinit();
|
||||
|
||||
var digest: [Cache.hex_digest_len]u8 = undefined;
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
if (!self.base.disable_lld_caching) {
|
||||
man = comp.cache_parent.obtain();
|
||||
|
||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||
@ -2370,9 +2365,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
|
||||
try man.addOptionalFile(self.base.options.linker_script);
|
||||
try man.addOptionalFile(self.base.options.version_script);
|
||||
for (self.base.options.objects) |obj| {
|
||||
try man.addOptionalFile(self.linker_script);
|
||||
try man.addOptionalFile(self.version_script);
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
man.hash.add(obj.must_link);
|
||||
man.hash.add(obj.loption);
|
||||
@ -2385,34 +2380,34 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
|
||||
// We can skip hashing libc and libc++ components that we are in charge of building from Zig
|
||||
// installation sources because they are always a product of the compiler version + target information.
|
||||
man.hash.addOptionalBytes(self.base.options.entry);
|
||||
man.hash.addOptionalBytes(comp.config.entry);
|
||||
man.hash.addOptional(self.image_base);
|
||||
man.hash.add(self.base.gc_sections);
|
||||
man.hash.addOptional(self.base.options.sort_section);
|
||||
man.hash.add(self.base.options.eh_frame_hdr);
|
||||
man.hash.add(self.base.options.emit_relocs);
|
||||
man.hash.add(self.base.options.rdynamic);
|
||||
man.hash.addListOfBytes(self.base.options.lib_dirs);
|
||||
man.hash.addListOfBytes(self.base.options.rpath_list);
|
||||
man.hash.add(self.base.options.each_lib_rpath);
|
||||
man.hash.addOptional(self.sort_section);
|
||||
man.hash.add(self.eh_frame_hdr);
|
||||
man.hash.add(self.emit_relocs);
|
||||
man.hash.add(self.rdynamic);
|
||||
man.hash.addListOfBytes(self.lib_dirs);
|
||||
man.hash.addListOfBytes(self.base.rpath_list);
|
||||
man.hash.add(self.each_lib_rpath);
|
||||
if (output_mode == .Exe) {
|
||||
man.hash.add(self.base.stack_size);
|
||||
man.hash.add(self.base.build_id);
|
||||
}
|
||||
man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys());
|
||||
man.hash.add(self.base.options.skip_linker_dependencies);
|
||||
man.hash.add(self.base.options.z_nodelete);
|
||||
man.hash.add(self.base.options.z_notext);
|
||||
man.hash.add(self.base.options.z_defs);
|
||||
man.hash.add(self.base.options.z_origin);
|
||||
man.hash.add(self.base.options.z_nocopyreloc);
|
||||
man.hash.add(self.base.options.z_now);
|
||||
man.hash.add(self.base.options.z_relro);
|
||||
man.hash.add(self.base.options.z_common_page_size orelse 0);
|
||||
man.hash.add(self.base.options.z_max_page_size orelse 0);
|
||||
man.hash.add(self.base.options.hash_style);
|
||||
man.hash.addListOfBytes(self.symbol_wrap_set.keys());
|
||||
man.hash.add(comp.skip_linker_dependencies);
|
||||
man.hash.add(self.z_nodelete);
|
||||
man.hash.add(self.z_notext);
|
||||
man.hash.add(self.z_defs);
|
||||
man.hash.add(self.z_origin);
|
||||
man.hash.add(self.z_nocopyreloc);
|
||||
man.hash.add(self.z_now);
|
||||
man.hash.add(self.z_relro);
|
||||
man.hash.add(self.z_common_page_size orelse 0);
|
||||
man.hash.add(self.z_max_page_size orelse 0);
|
||||
man.hash.add(self.hash_style);
|
||||
// strip does not need to go into the linker hash because it is part of the hash namespace
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
man.hash.add(self.base.comp.libc_installation != null);
|
||||
if (self.base.comp.libc_installation) |libc_installation| {
|
||||
man.hash.addBytes(libc_installation.crt_dir.?);
|
||||
@ -2421,16 +2416,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
man.hash.addOptionalBytes(target.dynamic_linker.get());
|
||||
}
|
||||
}
|
||||
man.hash.addOptionalBytes(self.base.options.soname);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
man.hash.addOptionalBytes(self.soname);
|
||||
man.hash.addOptional(comp.version);
|
||||
try link.hashAddSystemLibs(&man, self.base.comp.system_libs);
|
||||
man.hash.addListOfBytes(self.base.options.force_undefined_symbols.keys());
|
||||
man.hash.addListOfBytes(self.base.force_undefined_symbols.keys());
|
||||
man.hash.add(self.base.allow_shlib_undefined);
|
||||
man.hash.add(self.base.options.bind_global_refs_locally);
|
||||
man.hash.add(self.base.options.compress_debug_sections);
|
||||
man.hash.add(self.base.options.tsan);
|
||||
man.hash.addOptionalBytes(self.base.options.sysroot);
|
||||
man.hash.add(self.base.options.linker_optimization);
|
||||
man.hash.add(self.bind_global_refs_locally);
|
||||
man.hash.add(self.compress_debug_sections);
|
||||
man.hash.add(comp.config.any_sanitize_thread);
|
||||
man.hash.addOptionalBytes(self.sysroot);
|
||||
man.hash.add(self.optimization);
|
||||
|
||||
// We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
|
||||
_ = try man.hit();
|
||||
@ -2466,14 +2461,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
// However, because LLD wants to resolve BPF relocations which it shouldn't, it fails
|
||||
// before even generating the relocatable.
|
||||
if (output_mode == .Obj and
|
||||
(self.base.options.lto or target.isBpfFreestanding()))
|
||||
(comp.config.lto or target.isBpfFreestanding()))
|
||||
{
|
||||
// In this case we must do a simple file copy
|
||||
// here. TODO: think carefully about how we can avoid this redundant operation when doing
|
||||
// build-obj. See also the corresponding TODO in linkAsArchive.
|
||||
const the_object_path = blk: {
|
||||
if (self.base.options.objects.len != 0)
|
||||
break :blk self.base.options.objects[0].path;
|
||||
if (comp.objects.len != 0)
|
||||
break :blk comp.objects[0].path;
|
||||
|
||||
if (comp.c_object_table.count() != 0)
|
||||
break :blk comp.c_object_table.keys()[0].status.success.object_path;
|
||||
@ -2505,32 +2500,32 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
|
||||
try argv.append("--error-limit=0");
|
||||
|
||||
if (self.base.options.sysroot) |sysroot| {
|
||||
if (self.sysroot) |sysroot| {
|
||||
try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot}));
|
||||
}
|
||||
|
||||
if (self.base.options.lto) {
|
||||
switch (self.base.options.optimize_mode) {
|
||||
if (comp.config.lto) {
|
||||
switch (comp.root_mod.optimize_mode) {
|
||||
.Debug => {},
|
||||
.ReleaseSmall => try argv.append("--lto-O2"),
|
||||
.ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"),
|
||||
}
|
||||
}
|
||||
try argv.append(try std.fmt.allocPrint(arena, "-O{d}", .{
|
||||
self.base.options.linker_optimization,
|
||||
self.optimization,
|
||||
}));
|
||||
|
||||
if (self.base.options.entry) |entry| {
|
||||
if (comp.config.entry) |entry| {
|
||||
try argv.append("--entry");
|
||||
try argv.append(entry);
|
||||
}
|
||||
|
||||
for (self.base.options.force_undefined_symbols.keys()) |sym| {
|
||||
for (self.base.force_undefined_symbols.keys()) |sym| {
|
||||
try argv.append("-u");
|
||||
try argv.append(sym);
|
||||
}
|
||||
|
||||
switch (self.base.options.hash_style) {
|
||||
switch (self.hash_style) {
|
||||
.gnu => try argv.append("--hash-style=gnu"),
|
||||
.sysv => try argv.append("--hash-style=sysv"),
|
||||
.both => {}, // this is the default
|
||||
@ -2559,12 +2554,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
|
||||
try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
|
||||
|
||||
if (self.base.options.linker_script) |linker_script| {
|
||||
if (self.linker_script) |linker_script| {
|
||||
try argv.append("-T");
|
||||
try argv.append(linker_script);
|
||||
}
|
||||
|
||||
if (self.base.options.sort_section) |how| {
|
||||
if (self.sort_section) |how| {
|
||||
const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
|
||||
try argv.append(arg);
|
||||
}
|
||||
@ -2573,67 +2568,67 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
try argv.append("--gc-sections");
|
||||
}
|
||||
|
||||
if (self.base.options.print_gc_sections) {
|
||||
if (self.base.print_gc_sections) {
|
||||
try argv.append("--print-gc-sections");
|
||||
}
|
||||
|
||||
if (self.base.options.print_icf_sections) {
|
||||
if (self.print_icf_sections) {
|
||||
try argv.append("--print-icf-sections");
|
||||
}
|
||||
|
||||
if (self.base.options.print_map) {
|
||||
if (self.print_map) {
|
||||
try argv.append("--print-map");
|
||||
}
|
||||
|
||||
if (self.base.options.eh_frame_hdr) {
|
||||
if (self.eh_frame_hdr) {
|
||||
try argv.append("--eh-frame-hdr");
|
||||
}
|
||||
|
||||
if (self.base.options.emit_relocs) {
|
||||
if (self.emit_relocs) {
|
||||
try argv.append("--emit-relocs");
|
||||
}
|
||||
|
||||
if (self.base.options.rdynamic) {
|
||||
if (self.rdynamic) {
|
||||
try argv.append("--export-dynamic");
|
||||
}
|
||||
|
||||
if (self.base.options.strip) {
|
||||
if (self.base.debug_format == .strip) {
|
||||
try argv.append("-s");
|
||||
}
|
||||
|
||||
if (self.base.options.z_nodelete) {
|
||||
if (self.z_nodelete) {
|
||||
try argv.append("-z");
|
||||
try argv.append("nodelete");
|
||||
}
|
||||
if (self.base.options.z_notext) {
|
||||
if (self.z_notext) {
|
||||
try argv.append("-z");
|
||||
try argv.append("notext");
|
||||
}
|
||||
if (self.base.options.z_defs) {
|
||||
if (self.z_defs) {
|
||||
try argv.append("-z");
|
||||
try argv.append("defs");
|
||||
}
|
||||
if (self.base.options.z_origin) {
|
||||
if (self.z_origin) {
|
||||
try argv.append("-z");
|
||||
try argv.append("origin");
|
||||
}
|
||||
if (self.base.options.z_nocopyreloc) {
|
||||
if (self.z_nocopyreloc) {
|
||||
try argv.append("-z");
|
||||
try argv.append("nocopyreloc");
|
||||
}
|
||||
if (self.base.options.z_now) {
|
||||
if (self.z_now) {
|
||||
// LLD defaults to -zlazy
|
||||
try argv.append("-znow");
|
||||
}
|
||||
if (!self.base.options.z_relro) {
|
||||
if (!self.z_relro) {
|
||||
// LLD defaults to -zrelro
|
||||
try argv.append("-znorelro");
|
||||
}
|
||||
if (self.base.options.z_common_page_size) |size| {
|
||||
if (self.z_common_page_size) |size| {
|
||||
try argv.append("-z");
|
||||
try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
|
||||
}
|
||||
if (self.base.options.z_max_page_size) |size| {
|
||||
if (self.z_max_page_size) |size| {
|
||||
try argv.append("-z");
|
||||
try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
|
||||
}
|
||||
@ -2658,7 +2653,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
try argv.append("-shared");
|
||||
}
|
||||
|
||||
if (self.base.options.pie and output_mode == .Exe) {
|
||||
if (comp.config.pie and output_mode == .Exe) {
|
||||
try argv.append("-pie");
|
||||
}
|
||||
|
||||
@ -2683,20 +2678,20 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
// rpaths
|
||||
var rpath_table = std.StringHashMap(void).init(gpa);
|
||||
defer rpath_table.deinit();
|
||||
for (self.base.options.rpath_list) |rpath| {
|
||||
for (self.base.rpath_list) |rpath| {
|
||||
if ((try rpath_table.fetchPut(rpath, {})) == null) {
|
||||
try argv.append("-rpath");
|
||||
try argv.append(rpath);
|
||||
}
|
||||
}
|
||||
|
||||
for (self.base.options.symbol_wrap_set.keys()) |symbol_name| {
|
||||
for (self.symbol_wrap_set.keys()) |symbol_name| {
|
||||
try argv.appendSlice(&.{ "-wrap", symbol_name });
|
||||
}
|
||||
|
||||
if (self.base.options.each_lib_rpath) {
|
||||
if (self.each_lib_rpath) {
|
||||
var test_path = std.ArrayList(u8).init(arena);
|
||||
for (self.base.options.lib_dirs) |lib_dir_path| {
|
||||
for (self.lib_dirs) |lib_dir_path| {
|
||||
for (self.base.comp.system_libs.keys()) |link_lib| {
|
||||
if (!(try self.accessLibPath(&test_path, null, lib_dir_path, link_lib, .Dynamic)))
|
||||
continue;
|
||||
@ -2706,7 +2701,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
}
|
||||
}
|
||||
}
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (Compilation.classifyFileExt(obj.path) == .shared_library) {
|
||||
const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue;
|
||||
if (obj.loption) continue;
|
||||
@ -2719,12 +2714,12 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
}
|
||||
}
|
||||
|
||||
for (self.base.options.lib_dirs) |lib_dir| {
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
try argv.append("-L");
|
||||
try argv.append(lib_dir);
|
||||
}
|
||||
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation) |libc_installation| {
|
||||
try argv.append("-L");
|
||||
try argv.append(libc_installation.crt_dir.?);
|
||||
@ -2739,11 +2734,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
}
|
||||
|
||||
if (is_dyn_lib) {
|
||||
if (self.base.options.soname) |soname| {
|
||||
if (self.soname) |soname| {
|
||||
try argv.append("-soname");
|
||||
try argv.append(soname);
|
||||
}
|
||||
if (self.base.options.version_script) |version_script| {
|
||||
if (self.version_script) |version_script| {
|
||||
try argv.append("-version-script");
|
||||
try argv.append(version_script);
|
||||
}
|
||||
@ -2751,7 +2746,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
|
||||
// Positional arguments to the linker such as object files.
|
||||
var whole_archive = false;
|
||||
for (self.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (obj.must_link and !whole_archive) {
|
||||
try argv.append("-whole-archive");
|
||||
whole_archive = true;
|
||||
@ -2779,15 +2774,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
try argv.append(p);
|
||||
}
|
||||
|
||||
// TSAN
|
||||
if (self.base.options.tsan) {
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try argv.append(comp.tsan_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc
|
||||
if (is_exe_or_dyn_lib and
|
||||
!self.base.options.skip_linker_dependencies and
|
||||
!self.base.options.link_libc)
|
||||
!comp.skip_linker_dependencies and
|
||||
!comp.config.link_libc)
|
||||
{
|
||||
if (comp.libc_static_lib) |lib| {
|
||||
try argv.append(lib.full_object_path);
|
||||
@ -2832,19 +2826,19 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
}
|
||||
|
||||
// libc++ dep
|
||||
if (self.base.options.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libunwind dep
|
||||
if (self.base.options.link_libunwind) {
|
||||
if (comp.config.link_libunwind) {
|
||||
try argv.append(comp.libunwind_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc dep
|
||||
self.error_flags.missing_libc = false;
|
||||
if (self.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
if (self.base.comp.libc_installation != null) {
|
||||
const needs_grouping = link_mode == .Static;
|
||||
if (needs_grouping) try argv.append("--start-group");
|
||||
@ -2884,13 +2878,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
try argv.append("--allow-shlib-undefined");
|
||||
}
|
||||
|
||||
switch (self.base.options.compress_debug_sections) {
|
||||
switch (self.compress_debug_sections) {
|
||||
.none => {},
|
||||
.zlib => try argv.append("--compress-debug-sections=zlib"),
|
||||
.zstd => try argv.append("--compress-debug-sections=zstd"),
|
||||
}
|
||||
|
||||
if (self.base.options.bind_global_refs_locally) {
|
||||
if (self.bind_global_refs_locally) {
|
||||
try argv.append("-Bsymbolic");
|
||||
}
|
||||
|
||||
@ -2964,7 +2958,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
if (!self.base.disable_lld_caching) {
|
||||
// Update the file with the digest. If it fails we can continue; it only
|
||||
// means that the next invocation will have an unnecessary cache miss.
|
||||
Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
|
||||
@ -3101,7 +3095,8 @@ fn writeElfHeader(self: *Elf) !void {
|
||||
};
|
||||
index += 1;
|
||||
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const comp = self.base.comp;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const endian = target.cpu.arch.endian();
|
||||
hdr_buf[index] = switch (endian) {
|
||||
.little => elf.ELFDATA2LSB,
|
||||
@ -3120,10 +3115,10 @@ fn writeElfHeader(self: *Elf) !void {
|
||||
|
||||
assert(index == 16);
|
||||
|
||||
const output_mode = self.base.comp.config.output_mode;
|
||||
const link_mode = self.base.comp.config.link_mode;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const link_mode = comp.config.link_mode;
|
||||
const elf_type: elf.ET = switch (output_mode) {
|
||||
.Exe => if (self.base.options.pie) .DYN else .EXEC,
|
||||
.Exe => if (comp.config.pie) .DYN else .EXEC,
|
||||
.Obj => .REL,
|
||||
.Lib => switch (link_mode) {
|
||||
.Static => @as(elf.ET, .REL),
|
||||
@ -3283,7 +3278,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
|
||||
self.plt_index = try linker_defined.addGlobal("_PROCEDURE_LINKAGE_TABLE_", self);
|
||||
self.end_index = try linker_defined.addGlobal("_end", self);
|
||||
|
||||
if (self.base.options.eh_frame_hdr) {
|
||||
if (self.eh_frame_hdr) {
|
||||
self.gnu_eh_frame_hdr_index = try linker_defined.addGlobal("__GNU_EH_FRAME_HDR", self);
|
||||
}
|
||||
|
||||
@ -3314,7 +3309,8 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
|
||||
}
|
||||
|
||||
fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
const link_mode = self.base.comp.config.link_mode;
|
||||
const comp = self.base.comp;
|
||||
const link_mode = comp.config.link_mode;
|
||||
|
||||
// _DYNAMIC
|
||||
if (self.dynamic_section_index) |shndx| {
|
||||
@ -3398,7 +3394,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
|
||||
|
||||
// __rela_iplt_start, __rela_iplt_end
|
||||
if (self.rela_dyn_section_index) |shndx| blk: {
|
||||
if (link_mode != .Static or self.base.options.pie) break :blk;
|
||||
if (link_mode != .Static or comp.config.pie) break :blk;
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
const end_addr = shdr.sh_addr + shdr.sh_size;
|
||||
const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
|
||||
@ -3445,7 +3441,8 @@ fn initOutputSections(self: *Elf) !void {
|
||||
}
|
||||
|
||||
fn initSyntheticSections(self: *Elf) !void {
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const comp = self.base.comp;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const ptr_size = self.ptrWidthBytes();
|
||||
|
||||
const needs_eh_frame = for (self.objects.items) |index| {
|
||||
@ -3460,7 +3457,7 @@ fn initSyntheticSections(self: *Elf) !void {
|
||||
.offset = std.math.maxInt(u64),
|
||||
});
|
||||
|
||||
if (self.base.options.eh_frame_hdr) {
|
||||
if (self.eh_frame_hdr) {
|
||||
self.eh_frame_hdr_section_index = try self.addSection(.{
|
||||
.name = ".eh_frame_hdr",
|
||||
.type = elf.SHT_PROGBITS,
|
||||
@ -3554,7 +3551,7 @@ fn initSyntheticSections(self: *Elf) !void {
|
||||
// In this case, if we do generate .interp section and segment, we will get
|
||||
// a segfault in the dynamic linker trying to load a binary that is static
|
||||
// and doesn't contain .dynamic section.
|
||||
if (self.isStatic() and !self.base.options.pie) break :blk false;
|
||||
if (self.isStatic() and !comp.config.pie) break :blk false;
|
||||
break :blk target.dynamic_linker.get() != null;
|
||||
};
|
||||
if (needs_interp) {
|
||||
@ -3567,7 +3564,7 @@ fn initSyntheticSections(self: *Elf) !void {
|
||||
});
|
||||
}
|
||||
|
||||
if (self.base.isDynLib() or self.shared_objects.items.len > 0 or self.base.options.pie) {
|
||||
if (self.base.isDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
|
||||
self.dynstrtab_section_index = try self.addSection(.{
|
||||
.name = ".dynstr",
|
||||
.flags = elf.SHF_ALLOC,
|
||||
@ -3859,7 +3856,7 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
|
||||
}
|
||||
|
||||
if (self.base.isDynLib()) {
|
||||
if (self.base.options.soname) |soname| {
|
||||
if (self.soname) |soname| {
|
||||
try self.dynamic.setSoname(soname, self);
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,7 +543,7 @@ fn scanReloc(
|
||||
try self.reportPicError(symbol, rel, elf_file),
|
||||
|
||||
.copyrel => {
|
||||
if (elf_file.base.options.z_nocopyreloc) {
|
||||
if (elf_file.z_nocopyreloc) {
|
||||
if (symbol.isAbs(elf_file))
|
||||
try self.reportNoPicError(symbol, rel, elf_file)
|
||||
else
|
||||
@ -553,9 +553,9 @@ fn scanReloc(
|
||||
},
|
||||
|
||||
.dyn_copyrel => {
|
||||
if (is_writeable or elf_file.base.options.z_nocopyreloc) {
|
||||
if (is_writeable or elf_file.z_nocopyreloc) {
|
||||
if (!is_writeable) {
|
||||
if (elf_file.base.options.z_notext) {
|
||||
if (elf_file.z_notext) {
|
||||
elf_file.has_text_reloc = true;
|
||||
} else {
|
||||
try self.reportTextRelocError(symbol, rel, elf_file);
|
||||
@ -587,7 +587,7 @@ fn scanReloc(
|
||||
|
||||
.dynrel, .baserel, .ifunc => {
|
||||
if (!is_writeable) {
|
||||
if (elf_file.base.options.z_notext) {
|
||||
if (elf_file.z_notext) {
|
||||
elf_file.has_text_reloc = true;
|
||||
} else {
|
||||
try self.reportTextRelocError(symbol, rel, elf_file);
|
||||
@ -657,11 +657,12 @@ fn dynAbsRelocAction(symbol: *const Symbol, elf_file: *Elf) RelocAction {
|
||||
}
|
||||
|
||||
fn outputType(elf_file: *Elf) u2 {
|
||||
const comp = elf_file.base.comp;
|
||||
assert(!elf_file.isRelocatable());
|
||||
return switch (elf_file.base.comp.config.output_mode) {
|
||||
.Obj => unreachable,
|
||||
.Lib => 0,
|
||||
.Exe => if (elf_file.base.options.pie) 1 else 2,
|
||||
.Exe => if (comp.config.pie) 1 else 2,
|
||||
};
|
||||
}
|
||||
|
||||
@ -979,7 +980,7 @@ fn resolveDynAbsReloc(
|
||||
=> try writer.writeInt(i32, @as(i32, @truncate(S + A)), .little),
|
||||
|
||||
.dyn_copyrel => {
|
||||
if (is_writeable or elf_file.base.options.z_nocopyreloc) {
|
||||
if (is_writeable or elf_file.z_nocopyreloc) {
|
||||
elf_file.addRelaDynAssumeCapacity(.{
|
||||
.offset = P,
|
||||
.sym = target.extra(elf_file).?.dynamic,
|
||||
|
||||
@ -299,7 +299,7 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
|
||||
if (mem.startsWith(u8, name, ".note")) break :blk true;
|
||||
if (mem.startsWith(u8, name, ".comment")) break :blk true;
|
||||
if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
|
||||
if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
|
||||
if (elf_file.base.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
|
||||
mem.startsWith(u8, name, ".debug")) break :blk true;
|
||||
break :blk false;
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
|
||||
if (elf_file.base.debug_format != .strip) {
|
||||
self.dwarf = Dwarf.init(gpa, &elf_file.base, .dwarf32);
|
||||
self.dwarf = Dwarf.init(&elf_file.base, .dwarf32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ pub const DynamicSection = struct {
|
||||
fn getFlags(dt: DynamicSection, elf_file: *Elf) ?u64 {
|
||||
_ = dt;
|
||||
var flags: u64 = 0;
|
||||
if (elf_file.base.options.z_now) {
|
||||
if (elf_file.z_now) {
|
||||
flags |= elf.DF_BIND_NOW;
|
||||
}
|
||||
for (elf_file.got.entries.items) |entry| switch (entry.tag) {
|
||||
@ -49,15 +49,16 @@ pub const DynamicSection = struct {
|
||||
}
|
||||
|
||||
fn getFlags1(dt: DynamicSection, elf_file: *Elf) ?u64 {
|
||||
const comp = elf_file.base.comp;
|
||||
_ = dt;
|
||||
var flags_1: u64 = 0;
|
||||
if (elf_file.base.options.z_now) {
|
||||
if (elf_file.z_now) {
|
||||
flags_1 |= elf.DF_1_NOW;
|
||||
}
|
||||
if (elf_file.isExe() and elf_file.base.options.pie) {
|
||||
if (elf_file.isExe() and comp.config.pie) {
|
||||
flags_1 |= elf.DF_1_PIE;
|
||||
}
|
||||
// if (elf_file.base.options.z_nodlopen) {
|
||||
// if (elf_file.z_nodlopen) {
|
||||
// flags_1 |= elf.DF_1_NOOPEN;
|
||||
// }
|
||||
return if (flags_1 > 0) flags_1 else null;
|
||||
@ -246,12 +247,13 @@ pub const ZigGotSection = struct {
|
||||
}
|
||||
|
||||
pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
|
||||
const comp = elf_file.base.comp;
|
||||
const index = try zig_got.allocateEntry(elf_file.base.allocator);
|
||||
const entry = &zig_got.entries.items[index];
|
||||
entry.* = sym_index;
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_zig_got = true;
|
||||
if (elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) {
|
||||
if (elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) {
|
||||
zig_got.flags.needs_rela = true;
|
||||
}
|
||||
if (symbol.extra(elf_file)) |extra| {
|
||||
@ -478,6 +480,7 @@ pub const GotSection = struct {
|
||||
}
|
||||
|
||||
pub fn addGotSymbol(got: *GotSection, sym_index: Symbol.Index, elf_file: *Elf) !Index {
|
||||
const comp = elf_file.base.comp;
|
||||
const index = try got.allocateEntry(elf_file.base.allocator);
|
||||
const entry = &got.entries.items[index];
|
||||
entry.tag = .got;
|
||||
@ -485,7 +488,7 @@ pub const GotSection = struct {
|
||||
const symbol = elf_file.symbol(sym_index);
|
||||
symbol.flags.has_got = true;
|
||||
if (symbol.flags.import or symbol.isIFunc(elf_file) or
|
||||
((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and !symbol.isAbs(elf_file)))
|
||||
((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and !symbol.isAbs(elf_file)))
|
||||
{
|
||||
got.flags.needs_rela = true;
|
||||
}
|
||||
@ -561,6 +564,7 @@ pub const GotSection = struct {
|
||||
}
|
||||
|
||||
pub fn write(got: GotSection, elf_file: *Elf, writer: anytype) !void {
|
||||
const comp = elf_file.base.comp;
|
||||
const is_dyn_lib = elf_file.isDynLib();
|
||||
const apply_relocs = true; // TODO add user option for this
|
||||
|
||||
@ -576,7 +580,7 @@ pub const GotSection = struct {
|
||||
if (symbol.?.flags.import) break :blk 0;
|
||||
if (symbol.?.isIFunc(elf_file))
|
||||
break :blk if (apply_relocs) value else 0;
|
||||
if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
|
||||
if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
|
||||
!symbol.?.isAbs(elf_file))
|
||||
{
|
||||
break :blk if (apply_relocs) value else 0;
|
||||
@ -623,6 +627,7 @@ pub const GotSection = struct {
|
||||
}
|
||||
|
||||
pub fn addRela(got: GotSection, elf_file: *Elf) !void {
|
||||
const comp = elf_file.base.comp;
|
||||
const is_dyn_lib = elf_file.isDynLib();
|
||||
try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, got.numRela(elf_file));
|
||||
|
||||
@ -652,7 +657,7 @@ pub const GotSection = struct {
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if ((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
|
||||
if ((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
|
||||
!symbol.?.isAbs(elf_file))
|
||||
{
|
||||
elf_file.addRelaDynAssumeCapacity(.{
|
||||
@ -725,6 +730,7 @@ pub const GotSection = struct {
|
||||
}
|
||||
|
||||
pub fn numRela(got: GotSection, elf_file: *Elf) usize {
|
||||
const comp = elf_file.base.comp;
|
||||
const is_dyn_lib = elf_file.isDynLib();
|
||||
var num: usize = 0;
|
||||
for (got.entries.items) |entry| {
|
||||
@ -734,7 +740,7 @@ pub const GotSection = struct {
|
||||
};
|
||||
switch (entry.tag) {
|
||||
.got => if (symbol.?.flags.import or symbol.?.isIFunc(elf_file) or
|
||||
((elf_file.isDynLib() or (elf_file.isExe() and elf_file.base.options.pie)) and
|
||||
((elf_file.isDynLib() or (elf_file.isExe() and comp.config.pie)) and
|
||||
!symbol.?.isAbs(elf_file)))
|
||||
{
|
||||
num += 1;
|
||||
|
||||
@ -252,7 +252,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*MachO {
|
||||
|
||||
self.d_sym = .{
|
||||
.allocator = gpa,
|
||||
.dwarf = link.File.Dwarf.init(gpa, &self.base, .dwarf32),
|
||||
.dwarf = link.File.Dwarf.init(&self.base, .dwarf32),
|
||||
.file = d_sym_file,
|
||||
};
|
||||
}
|
||||
@ -573,7 +573,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
||||
|
||||
try self.writeLinkeditSegmentData();
|
||||
|
||||
var codesig: ?CodeSignature = if (requiresCodeSignature(&self.base.options)) blk: {
|
||||
var codesig: ?CodeSignature = if (self.requiresCodeSignature()) blk: {
|
||||
// Preallocate space for the code signature.
|
||||
// We need to do this at this stage so that we have the load commands with proper values
|
||||
// written out to the file.
|
||||
@ -619,12 +619,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
||||
});
|
||||
},
|
||||
.Lib => if (self.base.comp.config.link_mode == .Dynamic) {
|
||||
try load_commands.writeDylibIdLC(gpa, &self.base.options, lc_writer);
|
||||
try load_commands.writeDylibIdLC(self, lc_writer);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
try load_commands.writeRpathLCs(gpa, &self.base.options, lc_writer);
|
||||
try load_commands.writeRpathLCs(self, lc_writer);
|
||||
try lc_writer.writeStruct(macho.source_version_command{
|
||||
.version = 0,
|
||||
});
|
||||
@ -713,7 +713,7 @@ pub fn resolveLibSystem(
|
||||
success: {
|
||||
if (self.sdk_layout) |sdk_layout| switch (sdk_layout) {
|
||||
.sdk => {
|
||||
const dir = try fs.path.join(arena, &[_][]const u8{ self.base.options.sysroot.?, "usr", "lib" });
|
||||
const dir = try fs.path.join(arena, &[_][]const u8{ comp.sysroot.?, "usr", "lib" });
|
||||
if (try accessLibPath(arena, &test_path, &checked_paths, dir, "libSystem")) break :success;
|
||||
},
|
||||
.vendored => {
|
||||
@ -1156,7 +1156,8 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {
|
||||
// 2) afterwards, we parse dependents of the included dylibs
|
||||
// TODO this should not be performed if the user specifies `-flat_namespace` flag.
|
||||
// See ld64 manpages.
|
||||
const gpa = self.base.comp.gpa;
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
while (dependent_libs.readItem()) |dep_id| {
|
||||
defer dep_id.id.deinit(gpa);
|
||||
@ -1176,7 +1177,7 @@ pub fn parseDependentLibs(self: *MachO, dependent_libs: anytype) !void {
|
||||
var checked_paths = std.ArrayList([]const u8).init(arena);
|
||||
|
||||
success: {
|
||||
if (self.base.options.sysroot) |root| {
|
||||
if (comp.sysroot) |root| {
|
||||
const dir = try fs.path.join(arena, &[_][]const u8{ root, dirname });
|
||||
if (try accessLibPath(gpa, &test_path, &checked_paths, dir, stem)) break :success;
|
||||
}
|
||||
@ -1713,12 +1714,12 @@ pub fn resolveSymbols(self: *MachO) !void {
|
||||
// we search for it in libraries should there be no object files specified
|
||||
// on the linker line.
|
||||
if (output_mode == .Exe) {
|
||||
const entry_name = self.base.options.entry orelse load_commands.default_entry_point;
|
||||
const entry_name = comp.config.entry.?;
|
||||
_ = try self.addUndefined(entry_name, .{});
|
||||
}
|
||||
|
||||
// Force resolution of any symbols requested by the user.
|
||||
for (self.base.options.force_undefined_symbols.keys()) |sym_name| {
|
||||
for (self.base.force_undefined_symbols.keys()) |sym_name| {
|
||||
_ = try self.addUndefined(sym_name, .{});
|
||||
}
|
||||
|
||||
@ -4367,7 +4368,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
|
||||
|
||||
// We generate stabs last in order to ensure that the strtab always has debug info
|
||||
// strings trailing
|
||||
if (!self.base.options.strip) {
|
||||
if (self.base.debug_format != .strip) {
|
||||
for (self.objects.items) |object| {
|
||||
assert(self.d_sym == null); // TODO
|
||||
try self.generateSymbolStabs(object, &locals);
|
||||
@ -5171,7 +5172,8 @@ pub fn getStubsEntryAddress(self: *MachO, sym_with_loc: SymbolWithLoc) ?u64 {
|
||||
/// Returns symbol location corresponding to the set entrypoint if any.
|
||||
/// Asserts output mode is executable.
|
||||
pub fn getEntryPoint(self: MachO) ?SymbolWithLoc {
|
||||
const entry_name = self.base.options.entry orelse load_commands.default_entry_point;
|
||||
const comp = self.base.comp;
|
||||
const entry_name = comp.config.entry orelse return null;
|
||||
const global = self.getGlobal(entry_name) orelse return null;
|
||||
return global;
|
||||
}
|
||||
@ -5189,11 +5191,13 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn requiresCodeSignature(options: *const link.Options) bool {
|
||||
if (options.entitlements) |_| return true;
|
||||
const cpu_arch = options.target.cpu.arch;
|
||||
const os_tag = options.target.os.tag;
|
||||
const abi = options.target.abi;
|
||||
pub fn requiresCodeSignature(m: *MachO) bool {
|
||||
if (m.entitlements) |_| return true;
|
||||
const comp = m.base.comp;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const cpu_arch = target.cpu.arch;
|
||||
const os_tag = target.os.tag;
|
||||
const abi = target.abi;
|
||||
if (cpu_arch == .aarch64 and (os_tag == .macos or abi == .simulator)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -198,10 +198,10 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64
|
||||
}
|
||||
|
||||
pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
const comp = macho_file.base.comp;
|
||||
// TODO This linker code currently assumes there is only 1 compilation unit
|
||||
// and it corresponds to the Zig source code.
|
||||
const options = macho_file.base.options;
|
||||
const module = options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
const zcu = comp.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
for (self.relocs.items) |*reloc| {
|
||||
const sym = switch (reloc.type) {
|
||||
@ -245,7 +245,7 @@ pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {
|
||||
const text_section = macho_file.sections.items(.header)[macho_file.text_section_index.?];
|
||||
const low_pc = text_section.addr;
|
||||
const high_pc = text_section.addr + text_section.size;
|
||||
try self.dwarf.writeDbgInfoHeader(module, low_pc, high_pc);
|
||||
try self.dwarf.writeDbgInfoHeader(zcu, low_pc, high_pc);
|
||||
self.debug_info_header_dirty = false;
|
||||
}
|
||||
|
||||
@ -572,6 +572,5 @@ const trace = @import("../../tracy.zig").trace;
|
||||
const Allocator = mem.Allocator;
|
||||
const Dwarf = @import("../Dwarf.zig");
|
||||
const MachO = @import("../MachO.zig");
|
||||
const Module = @import("../../Module.zig");
|
||||
const StringTable = @import("../StringTable.zig");
|
||||
const Type = @import("../../type.zig").Type;
|
||||
|
||||
@ -60,7 +60,7 @@ fn collectRoots(macho_file: *MachO, roots: *AtomTable) !void {
|
||||
}
|
||||
|
||||
// Add all symbols force-defined by the user.
|
||||
for (macho_file.base.options.force_undefined_symbols.keys()) |sym_name| {
|
||||
for (macho_file.base.force_undefined_symbols.keys()) |sym_name| {
|
||||
const global_index = macho_file.resolver.get(sym_name).?;
|
||||
const global = macho_file.globals.items[global_index];
|
||||
const sym = macho_file.getSymbol(global);
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
/// Default implicit entrypoint symbol name.
|
||||
pub const default_entry_point: []const u8 = "_main";
|
||||
|
||||
/// Default path to dyld.
|
||||
pub const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
|
||||
|
||||
@ -17,7 +14,9 @@ const CalcLCsSizeCtx = struct {
|
||||
wants_function_starts: bool = true,
|
||||
};
|
||||
|
||||
fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 {
|
||||
fn calcLCsSize(m: *MachO, ctx: CalcLCsSizeCtx, assume_max_path_len: bool) !u32 {
|
||||
const comp = m.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
var has_text_segment: bool = false;
|
||||
var sizeofcmds: u64 = 0;
|
||||
for (ctx.segments) |seg| {
|
||||
@ -46,15 +45,15 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
|
||||
false,
|
||||
);
|
||||
// LC_MAIN
|
||||
if (options.output_mode == .Exe) {
|
||||
if (comp.config.output_mode == .Exe) {
|
||||
sizeofcmds += @sizeOf(macho.entry_point_command);
|
||||
}
|
||||
// LC_ID_DYLIB
|
||||
if (options.output_mode == .Lib and options.link_mode == .Dynamic) {
|
||||
if (comp.config.output_mode == .Lib and comp.config.link_mode == .Dynamic) {
|
||||
sizeofcmds += blk: {
|
||||
const emit = options.emit.?;
|
||||
const install_name = options.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
defer if (options.install_name == null) gpa.free(install_name);
|
||||
const emit = m.base.emit;
|
||||
const install_name = m.install_name orelse try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
defer if (m.install_name == null) gpa.free(install_name);
|
||||
break :blk calcInstallNameLen(
|
||||
@sizeOf(macho.dylib_command),
|
||||
install_name,
|
||||
@ -64,7 +63,7 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
|
||||
}
|
||||
// LC_RPATH
|
||||
{
|
||||
var it = RpathIterator.init(gpa, options.rpath_list);
|
||||
var it = RpathIterator.init(gpa, m.rpath_list);
|
||||
defer it.deinit();
|
||||
while (try it.next()) |rpath| {
|
||||
sizeofcmds += calcInstallNameLen(
|
||||
@ -78,7 +77,8 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
|
||||
sizeofcmds += @sizeOf(macho.source_version_command);
|
||||
// LC_BUILD_VERSION or LC_VERSION_MIN_ or nothing
|
||||
{
|
||||
const platform = Platform.fromTarget(options.target);
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const platform = Platform.fromTarget(target);
|
||||
if (platform.isBuildVersionCompatible()) {
|
||||
// LC_BUILD_VERSION
|
||||
sizeofcmds += @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version);
|
||||
@ -100,19 +100,19 @@ fn calcLCsSize(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx
|
||||
);
|
||||
}
|
||||
// LC_CODE_SIGNATURE
|
||||
if (MachO.requiresCodeSignature(options)) {
|
||||
if (m.requiresCodeSignature()) {
|
||||
sizeofcmds += @sizeOf(macho.linkedit_data_command);
|
||||
}
|
||||
|
||||
return @as(u32, @intCast(sizeofcmds));
|
||||
return @intCast(sizeofcmds);
|
||||
}
|
||||
|
||||
pub fn calcMinHeaderPad(gpa: Allocator, options: *const link.Options, ctx: CalcLCsSizeCtx) !u64 {
|
||||
var padding: u32 = (try calcLCsSize(gpa, options, ctx, false)) + (options.headerpad_size orelse 0);
|
||||
pub fn calcMinHeaderPad(m: *MachO, ctx: CalcLCsSizeCtx) !u64 {
|
||||
var padding: u32 = (try calcLCsSize(m, ctx, false)) + m.headerpad_size;
|
||||
log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
|
||||
|
||||
if (options.headerpad_max_install_names) {
|
||||
const min_headerpad_size: u32 = try calcLCsSize(gpa, options, ctx, true);
|
||||
if (m.headerpad_max_install_names) {
|
||||
const min_headerpad_size: u32 = try calcLCsSize(m, ctx, true);
|
||||
log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{
|
||||
min_headerpad_size + @sizeOf(macho.mach_header_64),
|
||||
});
|
||||
|
||||
@ -499,7 +499,7 @@ pub fn linkWithZld(
|
||||
}
|
||||
|
||||
// Write code signature padding if required
|
||||
var codesig: ?CodeSignature = if (MachO.requiresCodeSignature(&macho_file.base.options)) blk: {
|
||||
var codesig: ?CodeSignature = if (macho_file.requiresCodeSignature()) blk: {
|
||||
// Preallocate space for the code signature.
|
||||
// We need to do this at this stage so that we have the load commands with proper values
|
||||
// written out to the file.
|
||||
@ -547,12 +547,12 @@ pub fn linkWithZld(
|
||||
});
|
||||
},
|
||||
.Lib => if (link_mode == .Dynamic) {
|
||||
try load_commands.writeDylibIdLC(gpa, &macho_file.base.options, lc_writer);
|
||||
try load_commands.writeDylibIdLC(macho_file, lc_writer);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
try load_commands.writeRpathLCs(gpa, &macho_file.base.options, lc_writer);
|
||||
try load_commands.writeRpathLCs(macho_file, lc_writer);
|
||||
try lc_writer.writeStruct(macho.source_version_command{
|
||||
.version = 0,
|
||||
});
|
||||
@ -1072,11 +1072,10 @@ fn calcSectionSizes(macho_file: *MachO) !void {
|
||||
}
|
||||
|
||||
fn allocateSegments(macho_file: *MachO) !void {
|
||||
const gpa = macho_file.base.allocator;
|
||||
for (macho_file.segments.items, 0..) |*segment, segment_index| {
|
||||
const is_text_segment = mem.eql(u8, segment.segName(), "__TEXT");
|
||||
const base_size = if (is_text_segment)
|
||||
try load_commands.calcMinHeaderPad(gpa, &macho_file.base.options, .{
|
||||
try load_commands.calcMinHeaderPad(macho_file, .{
|
||||
.segments = macho_file.segments.items,
|
||||
.dylibs = macho_file.dylibs.items,
|
||||
.referenced_dylibs = macho_file.referenced_dylibs.keys(),
|
||||
|
||||
@ -57,6 +57,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
|
||||
.build_id = options.build_id,
|
||||
.rpath_list = options.rpath_list,
|
||||
.force_undefined_symbols = options.force_undefined_symbols,
|
||||
.debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
|
||||
.function_sections = options.function_sections,
|
||||
.data_sections = options.data_sections,
|
||||
},
|
||||
@ -66,7 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
|
||||
return nvptx;
|
||||
}
|
||||
|
||||
pub fn open(arena: Allocator, options: link.FileOpenOptions) !*NvPtx {
|
||||
pub fn open(arena: Allocator, options: link.File.OpenOptions) !*NvPtx {
|
||||
const target = options.comp.root_mod.resolved_target.result;
|
||||
assert(target.ofmt == .nvptx);
|
||||
return createEmpty(arena, options);
|
||||
|
||||
@ -295,26 +295,36 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
|
||||
}
|
||||
|
||||
pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Plan9 {
|
||||
_ = arena;
|
||||
const target = options.comp.root_mod.resolved_target.result;
|
||||
const gpa = options.comp.gpa;
|
||||
const comp = options.comp;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const gpa = comp.gpa;
|
||||
const optimize_mode = comp.root_mod.optimize_mode;
|
||||
const output_mode = comp.config.output_mode;
|
||||
|
||||
const sixtyfour_bit: bool = switch (options.target.ptrBitWidth()) {
|
||||
const sixtyfour_bit: bool = switch (target.ptrBitWidth()) {
|
||||
0...32 => false,
|
||||
33...64 => true,
|
||||
else => return error.UnsupportedP9Architecture,
|
||||
};
|
||||
|
||||
const arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
|
||||
const self = try gpa.create(Plan9);
|
||||
const self = try arena.create(Plan9);
|
||||
self.* = .{
|
||||
.path_arena = arena_allocator,
|
||||
.path_arena = std.heap.ArenaAllocator.init(gpa),
|
||||
.base = .{
|
||||
.tag = .plan9,
|
||||
.options = options,
|
||||
.allocator = gpa,
|
||||
.comp = comp,
|
||||
.emit = options.emit,
|
||||
.gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
|
||||
.stack_size = options.stack_size orelse 16777216,
|
||||
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
|
||||
.file = null,
|
||||
.disable_lld_caching = options.disable_lld_caching,
|
||||
.build_id = options.build_id,
|
||||
.rpath_list = options.rpath_list,
|
||||
.force_undefined_symbols = options.force_undefined_symbols,
|
||||
.debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
|
||||
.function_sections = options.function_sections,
|
||||
.data_sections = options.data_sections,
|
||||
},
|
||||
.sixtyfour_bit = sixtyfour_bit,
|
||||
.bases = undefined,
|
||||
@ -602,7 +612,7 @@ pub fn flush(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) li
|
||||
const use_lld = build_options.have_llvm and self.base.comp.config.use_lld;
|
||||
assert(!use_lld);
|
||||
|
||||
switch (self.base.options.effectiveOutputMode()) {
|
||||
switch (link.File.effectiveOutputMode(use_lld, comp.config.output_mode)) {
|
||||
.Exe => {},
|
||||
// plan9 object files are totally different
|
||||
.Obj => return error.TODOImplementPlan9Objs,
|
||||
|
||||
@ -67,6 +67,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
|
||||
.force_undefined_symbols = options.force_undefined_symbols,
|
||||
.function_sections = options.function_sections,
|
||||
.data_sections = options.data_sections,
|
||||
.debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
|
||||
},
|
||||
.object = codegen.Object.init(gpa),
|
||||
};
|
||||
@ -102,7 +103,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*SpirV {
|
||||
errdefer spirv.base.destroy();
|
||||
|
||||
// TODO: read the file and keep valid parts instead of truncating
|
||||
const file = try options.emit.?.directory.handle.createFile(options.emit.sub_path, .{
|
||||
const file = try options.emit.directory.handle.createFile(options.emit.sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
});
|
||||
|
||||
@ -37,6 +37,13 @@ pub const Relocation = types.Relocation;
|
||||
pub const base_tag: link.File.Tag = .wasm;
|
||||
|
||||
base: link.File,
|
||||
import_symbols: bool,
|
||||
export_symbol_names: []const []const u8,
|
||||
rdynamic: bool,
|
||||
global_base: ?u64,
|
||||
initial_memory: ?u64,
|
||||
max_memory: ?u64,
|
||||
wasi_emulated_libs: []const wasi_libc.CRTFile,
|
||||
/// Output name of the file
|
||||
name: []const u8,
|
||||
/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
|
||||
@ -368,13 +375,15 @@ pub const StringTable = struct {
|
||||
|
||||
pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
if (build_options.only_c) unreachable;
|
||||
const gpa = options.comp.gpa;
|
||||
const target = options.comp.root_mod.resolved_target.result;
|
||||
const comp = options.comp;
|
||||
const gpa = comp.gpa;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
assert(target.ofmt == .wasm);
|
||||
|
||||
const use_lld = build_options.have_llvm and options.comp.config.use_lld;
|
||||
const use_llvm = options.comp.config.use_llvm;
|
||||
const output_mode = options.comp.config.output_mode;
|
||||
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
|
||||
const wasm = try createEmpty(arena, options);
|
||||
errdefer wasm.base.destroy();
|
||||
@ -395,7 +404,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
};
|
||||
|
||||
// TODO: read the file and keep valid parts instead of truncating
|
||||
const file = try options.emit.?.directory.handle.createFile(sub_path, .{
|
||||
const file = try options.emit.directory.handle.createFile(sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = if (fs.has_executable_bit)
|
||||
@ -480,7 +489,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
}
|
||||
|
||||
// shared-memory symbols for TLS support
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
{
|
||||
const loc = try wasm.createSyntheticSymbol("__tls_base", .global);
|
||||
const symbol = loc.getSymbol(wasm);
|
||||
@ -522,14 +531,15 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
}
|
||||
|
||||
pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
const use_llvm = options.comp.config.use_llvm;
|
||||
const output_mode = options.comp.config.output_mode;
|
||||
const comp = options.comp;
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
const output_mode = comp.config.output_mode;
|
||||
|
||||
const wasm = try arena.create(Wasm);
|
||||
wasm.* = .{
|
||||
.base = .{
|
||||
.tag = .wasm,
|
||||
.comp = options.comp,
|
||||
.comp = comp,
|
||||
.emit = options.emit,
|
||||
.gc_sections = options.gc_sections orelse (output_mode != .Obj),
|
||||
.stack_size = options.stack_size orelse std.wasm.page_size * 16, // 1MB
|
||||
@ -546,6 +556,13 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Wasm {
|
||||
.name = undefined,
|
||||
.import_table = options.import_table,
|
||||
.export_table = options.export_table,
|
||||
.import_symbols = options.import_symbols,
|
||||
.export_symbol_names = options.export_symbol_names,
|
||||
.rdynamic = options.rdynamic,
|
||||
.global_base = options.global_base,
|
||||
.initial_memory = options.initial_memory,
|
||||
.max_memory = options.max_memory,
|
||||
.wasi_emulated_libs = options.wasi_emulated_libs,
|
||||
};
|
||||
|
||||
if (use_llvm) {
|
||||
@ -909,7 +926,10 @@ fn writeI32Const(writer: anytype, val: u32) !void {
|
||||
}
|
||||
|
||||
fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const import_memory = comp.config.import_memory;
|
||||
|
||||
// Passive segments are used to avoid memory being reinitialized on each
|
||||
// thread's instantiation. These passive segments are initialized and
|
||||
@ -920,7 +940,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
return;
|
||||
}
|
||||
|
||||
const flag_address: u32 = if (wasm.base.options.shared_memory) address: {
|
||||
const flag_address: u32 = if (shared_memory) address: {
|
||||
// when we have passive initialization segments and shared memory
|
||||
// `setupMemory` will create this symbol and set its virtual address.
|
||||
const loc = wasm.findGlobalSymbol("__wasm_init_memory_flag").?;
|
||||
@ -934,7 +954,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
// we have 0 locals
|
||||
try leb.writeULEB128(writer, @as(u32, 0));
|
||||
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
// destination blocks
|
||||
// based on values we jump to corresponding label
|
||||
try writer.writeByte(std.wasm.opcode(.block)); // $drop
|
||||
@ -968,14 +988,14 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
var segment_index: u32 = 0;
|
||||
while (it.next()) |entry| : (segment_index += 1) {
|
||||
const segment: Segment = wasm.segments.items[entry.value_ptr.*];
|
||||
if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) {
|
||||
if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) {
|
||||
// For passive BSS segments we can simple issue a memory.fill(0).
|
||||
// For non-BSS segments we do a memory.init. Both these
|
||||
// instructions take as their first argument the destination
|
||||
// address.
|
||||
try writeI32Const(writer, segment.offset);
|
||||
|
||||
if (wasm.base.options.shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) {
|
||||
if (shared_memory and std.mem.eql(u8, entry.key_ptr.*, ".tdata")) {
|
||||
// When we initialize the TLS segment we also set the `__tls_base`
|
||||
// global. This allows the runtime to use this static copy of the
|
||||
// TLS data for the first/main thread.
|
||||
@ -1000,7 +1020,7 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
}
|
||||
}
|
||||
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
// we set the init memory flag to value '2'
|
||||
try writeI32Const(writer, flag_address);
|
||||
try writeI32Const(writer, 2);
|
||||
@ -1043,12 +1063,12 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
while (it.next()) |entry| : (segment_index += 1) {
|
||||
const name = entry.key_ptr.*;
|
||||
const segment: Segment = wasm.segments.items[entry.value_ptr.*];
|
||||
if (segment.needsPassiveInitialization(wasm.base.options.import_memory, name) and
|
||||
if (segment.needsPassiveInitialization(import_memory, name) and
|
||||
!std.mem.eql(u8, name, ".bss"))
|
||||
{
|
||||
// The TLS region should not be dropped since its is needed
|
||||
// during the initialization of each thread (__wasm_init_tls).
|
||||
if (wasm.base.options.shared_memory and std.mem.eql(u8, name, ".tdata")) {
|
||||
if (shared_memory and std.mem.eql(u8, name, ".tdata")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1071,11 +1091,13 @@ fn setupInitMemoryFunction(wasm: *Wasm) !void {
|
||||
/// Constructs a synthetic function that performs runtime relocations for
|
||||
/// TLS symbols. This function is called by `__wasm_init_tls`.
|
||||
fn setupTLSRelocationsFunction(wasm: *Wasm) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
|
||||
// When we have TLS GOT entries and shared memory is enabled,
|
||||
// we must perform runtime relocations or else we don't create the function.
|
||||
if (!wasm.base.options.shared_memory or !wasm.requiresTLSReloc()) {
|
||||
if (!shared_memory or !wasm.requiresTLSReloc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1119,7 +1141,9 @@ fn validateFeatures(
|
||||
to_emit: *[@typeInfo(types.Feature.Tag).Enum.fields.len]bool,
|
||||
emit_features_count: *u32,
|
||||
) !void {
|
||||
const target = wasm.base.comp.root_mod.resolved_target.result;
|
||||
const comp = wasm.base.comp;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const cpu_features = target.cpu.features;
|
||||
const infer = cpu_features.isEmpty(); // when the user did not define any features, we infer them from linked objects.
|
||||
const known_features_count = @typeInfo(types.Feature.Tag).Enum.fields.len;
|
||||
@ -1190,7 +1214,7 @@ fn validateFeatures(
|
||||
return error.InvalidFeatureSet;
|
||||
}
|
||||
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
const disallowed_feature = disallowed[@intFromEnum(types.Feature.Tag.shared_mem)];
|
||||
if (@as(u1, @truncate(disallowed_feature)) != 0) {
|
||||
log.err(
|
||||
@ -1255,7 +1279,9 @@ fn validateFeatures(
|
||||
/// if one or multiple undefined references exist. When none exist, the symbol will
|
||||
/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
|
||||
fn resolveLazySymbols(wasm: *Wasm) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
|
||||
if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
|
||||
if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
|
||||
@ -1273,7 +1299,7 @@ fn resolveLazySymbols(wasm: *Wasm) !void {
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasm.base.options.shared_memory) {
|
||||
if (!shared_memory) {
|
||||
if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
|
||||
if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
|
||||
const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
|
||||
@ -1306,8 +1332,9 @@ pub fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc {
|
||||
}
|
||||
|
||||
fn checkUndefinedSymbols(wasm: *const Wasm) !void {
|
||||
if (wasm.base.comp.config.output_mode == .Obj) return;
|
||||
if (wasm.base.options.import_symbols) return;
|
||||
const comp = wasm.base.comp;
|
||||
if (comp.config.output_mode == .Obj) return;
|
||||
if (wasm.import_symbols) return;
|
||||
|
||||
var found_undefined_symbols = false;
|
||||
for (wasm.undefs.values()) |undef| {
|
||||
@ -2182,7 +2209,10 @@ const Kind = union(enum) {
|
||||
|
||||
/// Parses an Atom and inserts its metadata into the corresponding sections.
|
||||
fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const import_memory = comp.config.import_memory;
|
||||
const atom = wasm.getAtomPtr(atom_index);
|
||||
const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);
|
||||
const do_garbage_collect = wasm.base.gc_sections;
|
||||
@ -2233,7 +2263,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
|
||||
// we set the entire region of it to zeroes.
|
||||
// We do not have to do this when exporting the memory (the default) because the runtime
|
||||
// will do it for us, and we do not emit the bss segment at all.
|
||||
if ((wasm.base.comp.config.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) {
|
||||
if ((wasm.base.comp.config.output_mode == .Obj or import_memory) and kind.data == .uninitialized) {
|
||||
@memset(atom.code.items, 0);
|
||||
}
|
||||
|
||||
@ -2250,7 +2280,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void {
|
||||
} else {
|
||||
const index: u32 = @intCast(wasm.segments.items.len);
|
||||
var flags: u32 = 0;
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);
|
||||
}
|
||||
try wasm.segments.append(gpa, .{
|
||||
@ -2679,9 +2709,11 @@ fn setupStartSection(wasm: *Wasm) !void {
|
||||
}
|
||||
|
||||
fn initializeTLSFunction(wasm: *Wasm) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
|
||||
if (!wasm.base.options.shared_memory) return;
|
||||
if (!shared_memory) return;
|
||||
|
||||
var function_body = std.ArrayList(u8).init(gpa);
|
||||
defer function_body.deinit();
|
||||
@ -2940,7 +2972,7 @@ fn setupExports(wasm: *Wasm) !void {
|
||||
if (wasm.base.comp.config.output_mode == .Obj) return;
|
||||
log.debug("Building exports from symbols", .{});
|
||||
|
||||
const force_exp_names = wasm.base.options.export_symbol_names;
|
||||
const force_exp_names = wasm.export_symbol_names;
|
||||
if (force_exp_names.len > 0) {
|
||||
var failed_exports = false;
|
||||
|
||||
@ -2962,7 +2994,7 @@ fn setupExports(wasm: *Wasm) !void {
|
||||
|
||||
for (wasm.resolved_symbols.keys()) |sym_loc| {
|
||||
const symbol = sym_loc.getSymbol(wasm);
|
||||
if (!symbol.isExported(wasm.base.options.rdynamic)) continue;
|
||||
if (!symbol.isExported(wasm.rdynamic)) continue;
|
||||
|
||||
const sym_name = sym_loc.getName(wasm);
|
||||
const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {
|
||||
@ -2997,8 +3029,9 @@ fn setupExports(wasm: *Wasm) !void {
|
||||
}
|
||||
|
||||
fn setupStart(wasm: *Wasm) !void {
|
||||
const comp = wasm.base.comp;
|
||||
// do not export entry point if user set none or no default was set.
|
||||
const entry_name = wasm.base.options.entry orelse return;
|
||||
const entry_name = comp.config.entry orelse return;
|
||||
|
||||
const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse {
|
||||
log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name});
|
||||
@ -3012,13 +3045,15 @@ fn setupStart(wasm: *Wasm) !void {
|
||||
}
|
||||
|
||||
// Ensure the symbol is exported so host environment can access it
|
||||
if (wasm.base.comp.config.output_mode != .Obj) {
|
||||
if (comp.config.output_mode != .Obj) {
|
||||
symbol.setFlag(.WASM_SYM_EXPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets up the memory section of the wasm module, as well as the stack.
|
||||
fn setupMemory(wasm: *Wasm) !void {
|
||||
const comp = wasm.base.comp;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
log.debug("Setting up memory layout", .{});
|
||||
const page_size = std.wasm.page_size; // 64kb
|
||||
const stack_alignment: Alignment = .@"16"; // wasm's stack alignment as specified by tool-convention
|
||||
@ -3027,12 +3062,12 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
// Always place the stack at the start by default
|
||||
// unless the user specified the global-base flag
|
||||
var place_stack_first = true;
|
||||
var memory_ptr: u64 = if (wasm.base.options.global_base) |base| blk: {
|
||||
var memory_ptr: u64 = if (wasm.global_base) |base| blk: {
|
||||
place_stack_first = false;
|
||||
break :blk base;
|
||||
} else 0;
|
||||
|
||||
const is_obj = wasm.base.comp.config.output_mode == .Obj;
|
||||
const is_obj = comp.config.output_mode == .Obj;
|
||||
|
||||
if (place_stack_first and !is_obj) {
|
||||
memory_ptr = stack_alignment.forward(memory_ptr);
|
||||
@ -3059,7 +3094,7 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
}
|
||||
if (wasm.findGlobalSymbol("__tls_base")) |loc| {
|
||||
const sym = loc.getSymbol(wasm);
|
||||
wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (wasm.base.options.shared_memory)
|
||||
wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = if (shared_memory)
|
||||
@as(i32, 0)
|
||||
else
|
||||
@as(i32, @intCast(memory_ptr));
|
||||
@ -3072,7 +3107,7 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
}
|
||||
|
||||
// create the memory init flag which is used by the init memory function
|
||||
if (wasm.base.options.shared_memory and wasm.hasPassiveInitializationSegments()) {
|
||||
if (shared_memory and wasm.hasPassiveInitializationSegments()) {
|
||||
// align to pointer size
|
||||
memory_ptr = mem.alignForward(u64, memory_ptr, 4);
|
||||
const loc = try wasm.createSyntheticSymbol("__wasm_init_memory_flag", .data);
|
||||
@ -3098,7 +3133,7 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
// For now we only support wasm32 by setting the maximum allowed memory size 2^32-1
|
||||
const max_memory_allowed: u64 = (1 << 32) - 1;
|
||||
|
||||
if (wasm.base.options.initial_memory) |initial_memory| {
|
||||
if (wasm.initial_memory) |initial_memory| {
|
||||
if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {
|
||||
log.err("Initial memory must be {d}-byte aligned", .{page_size});
|
||||
return error.MissAlignment;
|
||||
@ -3124,7 +3159,7 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
symbol.virtual_address = @as(u32, @intCast(memory_ptr));
|
||||
}
|
||||
|
||||
if (wasm.base.options.max_memory) |max_memory| {
|
||||
if (wasm.max_memory) |max_memory| {
|
||||
if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {
|
||||
log.err("Maximum memory must be {d}-byte aligned", .{page_size});
|
||||
return error.MissAlignment;
|
||||
@ -3139,7 +3174,7 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
}
|
||||
wasm.memories.limits.max = @as(u32, @intCast(max_memory / page_size));
|
||||
wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_HAS_MAX);
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
wasm.memories.limits.setFlag(.WASM_LIMITS_FLAG_IS_SHARED);
|
||||
}
|
||||
log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max});
|
||||
@ -3150,20 +3185,22 @@ fn setupMemory(wasm: *Wasm) !void {
|
||||
/// index of the segment within the final data section. When the segment does not yet
|
||||
/// exist, a new one will be initialized and appended. The new index will be returned in that case.
|
||||
pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u32 {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const object: Object = wasm.objects.items[object_index];
|
||||
const symbol = object.symtable[symbol_index];
|
||||
const index: u32 = @intCast(wasm.segments.items.len);
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
|
||||
switch (symbol.tag) {
|
||||
.data => {
|
||||
const segment_info = object.segment_info[symbol.index];
|
||||
const merge_segment = wasm.base.comp.config.output_mode != .Obj;
|
||||
const merge_segment = comp.config.output_mode != .Obj;
|
||||
const result = try wasm.data_segments.getOrPut(gpa, segment_info.outputName(merge_segment));
|
||||
if (!result.found_existing) {
|
||||
result.value_ptr.* = index;
|
||||
var flags: u32 = 0;
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE);
|
||||
}
|
||||
try wasm.segments.append(gpa, .{
|
||||
@ -3445,6 +3482,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
|
||||
defer tracy.end();
|
||||
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const import_memory = comp.config.import_memory;
|
||||
|
||||
// Used for all temporary memory allocated during flushin
|
||||
var arena_instance = std.heap.ArenaAllocator.init(gpa);
|
||||
@ -3509,8 +3548,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l
|
||||
man.hash.addOptionalBytes(wasm.base.comp.config.entry);
|
||||
man.hash.add(wasm.base.stack_size);
|
||||
man.hash.add(wasm.base.build_id);
|
||||
man.hash.add(wasm.base.comp.config.import_memory);
|
||||
man.hash.add(wasm.base.comp.config.shared_memory);
|
||||
man.hash.add(import_memory);
|
||||
man.hash.add(shared_memory);
|
||||
man.hash.add(wasm.import_table);
|
||||
man.hash.add(wasm.export_table);
|
||||
man.hash.addOptional(wasm.initial_memory);
|
||||
@ -3726,8 +3765,12 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
|
||||
} else if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
|
||||
// for safe build modes, we store the atom in the data segment,
|
||||
// whereas for unsafe build modes we store it in bss.
|
||||
const is_initialized = wasm.base.options.optimize_mode == .Debug or
|
||||
wasm.base.options.optimize_mode == .ReleaseSafe;
|
||||
const decl_namespace = mod.namespacePtr(decl.src_namespace);
|
||||
const optimize_mode = decl_namespace.file_scope.mod.optimize_mode;
|
||||
const is_initialized = switch (optimize_mode) {
|
||||
.Debug, .ReleaseSafe => true,
|
||||
.ReleaseFast, .ReleaseSmall => false,
|
||||
};
|
||||
try wasm.parseAtom(atom_index, .{ .data = if (is_initialized) .initialized else .uninitialized });
|
||||
} else {
|
||||
// when the decl is all zeroes, we store the atom in the bss segment,
|
||||
@ -3788,9 +3831,13 @@ fn writeToFile(
|
||||
feature_count: u32,
|
||||
arena: Allocator,
|
||||
) !void {
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
const use_llvm = wasm.base.comp.config.use_llvm;
|
||||
const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld;
|
||||
const comp = wasm.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const use_llvm = comp.config.use_llvm;
|
||||
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const import_memory = comp.config.import_memory;
|
||||
const export_memory = comp.config.export_memory;
|
||||
|
||||
// Size of each section header
|
||||
const header_size = 5 + 1;
|
||||
@ -3800,7 +3847,7 @@ fn writeToFile(
|
||||
var code_section_index: ?u32 = null;
|
||||
// Index of the data section. Used to tell relocation table where the section lives.
|
||||
var data_section_index: ?u32 = null;
|
||||
const is_obj = wasm.base.comp.config.output_mode == .Obj or (!use_llvm and use_lld);
|
||||
const is_obj = comp.config.output_mode == .Obj or (!use_llvm and use_lld);
|
||||
|
||||
var binary_bytes = std.ArrayList(u8).init(gpa);
|
||||
defer binary_bytes.deinit();
|
||||
@ -3840,8 +3887,6 @@ fn writeToFile(
|
||||
}
|
||||
|
||||
// Import section
|
||||
const import_memory = wasm.base.options.import_memory or is_obj;
|
||||
const export_memory = wasm.base.options.export_memory;
|
||||
if (wasm.imports.count() != 0 or import_memory) {
|
||||
const header_offset = try reserveVecSectionHeader(&binary_bytes);
|
||||
|
||||
@ -4018,7 +4063,7 @@ fn writeToFile(
|
||||
|
||||
// When the shared-memory option is enabled, we *must* emit the 'data count' section.
|
||||
const data_segments_count = wasm.data_segments.count() - @intFromBool(wasm.data_segments.contains(".bss") and !import_memory);
|
||||
if (data_segments_count != 0 and wasm.base.options.shared_memory) {
|
||||
if (data_segments_count != 0 and shared_memory) {
|
||||
const header_offset = try reserveVecSectionHeader(&binary_bytes);
|
||||
try writeVecSectionHeader(
|
||||
binary_bytes.items,
|
||||
@ -4160,11 +4205,11 @@ fn writeToFile(
|
||||
if (data_section_index) |data_index| {
|
||||
try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
|
||||
}
|
||||
} else if (!wasm.base.options.strip) {
|
||||
} else if (wasm.base.debug_format != .strip) {
|
||||
try wasm.emitNameSection(&binary_bytes, arena);
|
||||
}
|
||||
|
||||
if (!wasm.base.options.strip) {
|
||||
if (wasm.base.debug_format != .strip) {
|
||||
// The build id must be computed on the main sections only,
|
||||
// so we have to do it now, before the debug sections.
|
||||
switch (wasm.base.build_id) {
|
||||
@ -4193,7 +4238,7 @@ fn writeToFile(
|
||||
}
|
||||
|
||||
// if (wasm.dwarf) |*dwarf| {
|
||||
// const mod = wasm.base.comp.module.?;
|
||||
// const mod = comp.module.?;
|
||||
// try dwarf.writeDbgAbbrev();
|
||||
// // for debug info and ranges, the address is always 0,
|
||||
// // as locations are always offsets relative to 'code' section.
|
||||
@ -4380,6 +4425,8 @@ fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []con
|
||||
}
|
||||
|
||||
fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
|
||||
const comp = wasm.base.comp;
|
||||
const import_memory = comp.config.import_memory;
|
||||
const Name = struct {
|
||||
index: u32,
|
||||
name: []const u8,
|
||||
@ -4418,7 +4465,7 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
|
||||
for (wasm.data_segments.keys()) |key| {
|
||||
// bss section is not emitted when this condition holds true, so we also
|
||||
// do not output a name for it.
|
||||
if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue;
|
||||
if (!import_memory and std.mem.eql(u8, key, ".bss")) continue;
|
||||
segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });
|
||||
data_segment_index += 1;
|
||||
}
|
||||
@ -4528,6 +4575,11 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const shared_memory = comp.config.shared_memory;
|
||||
const export_memory = comp.config.export_memory;
|
||||
const import_memory = comp.config.import_memory;
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
|
||||
const gpa = wasm.base.comp.gpa;
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||
defer arena_allocator.deinit();
|
||||
@ -4560,8 +4612,6 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
break :blk null;
|
||||
};
|
||||
|
||||
const target = wasm.base.comp.root_mod.resolved_target.result;
|
||||
|
||||
const id_symlink_basename = "lld.id";
|
||||
|
||||
var man: Cache.Manifest = undefined;
|
||||
@ -4577,7 +4627,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
|
||||
comptime assert(Compilation.link_hash_implementation_version == 10);
|
||||
|
||||
for (wasm.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
man.hash.add(obj.must_link);
|
||||
}
|
||||
@ -4589,17 +4639,17 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
man.hash.addOptionalBytes(wasm.base.comp.config.entry);
|
||||
man.hash.add(wasm.base.stack_size);
|
||||
man.hash.add(wasm.base.build_id);
|
||||
man.hash.add(wasm.base.options.import_memory);
|
||||
man.hash.add(wasm.base.options.export_memory);
|
||||
man.hash.add(import_memory);
|
||||
man.hash.add(export_memory);
|
||||
man.hash.add(wasm.import_table);
|
||||
man.hash.add(wasm.export_table);
|
||||
man.hash.addOptional(wasm.base.options.initial_memory);
|
||||
man.hash.addOptional(wasm.base.options.max_memory);
|
||||
man.hash.add(wasm.base.options.shared_memory);
|
||||
man.hash.addOptional(wasm.base.options.global_base);
|
||||
man.hash.add(wasm.base.options.export_symbol_names.len);
|
||||
man.hash.addOptional(wasm.initial_memory);
|
||||
man.hash.addOptional(wasm.max_memory);
|
||||
man.hash.add(shared_memory);
|
||||
man.hash.addOptional(wasm.global_base);
|
||||
man.hash.add(wasm.export_symbol_names.len);
|
||||
// strip does not need to go into the linker hash because it is part of the hash namespace
|
||||
for (wasm.base.options.export_symbol_names) |symbol_name| {
|
||||
for (wasm.export_symbol_names) |symbol_name| {
|
||||
man.hash.addBytes(symbol_name);
|
||||
}
|
||||
|
||||
@ -4637,8 +4687,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
// here. TODO: think carefully about how we can avoid this redundant operation when doing
|
||||
// build-obj. See also the corresponding TODO in linkAsArchive.
|
||||
const the_object_path = blk: {
|
||||
if (wasm.base.options.objects.len != 0)
|
||||
break :blk wasm.base.options.objects[0].path;
|
||||
if (comp.objects.len != 0)
|
||||
break :blk comp.objects[0].path;
|
||||
|
||||
if (comp.c_object_table.count() != 0)
|
||||
break :blk comp.c_object_table.keys()[0].status.success.object_path;
|
||||
@ -4666,19 +4716,19 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, linker_command });
|
||||
try argv.append("--error-limit=0");
|
||||
|
||||
if (wasm.base.options.lto) {
|
||||
switch (wasm.base.options.optimize_mode) {
|
||||
if (comp.config.lto) {
|
||||
switch (comp.root_mod.optimize_mode) {
|
||||
.Debug => {},
|
||||
.ReleaseSmall => try argv.append("-O2"),
|
||||
.ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
|
||||
}
|
||||
}
|
||||
|
||||
if (wasm.base.options.import_memory) {
|
||||
if (import_memory) {
|
||||
try argv.append("--import-memory");
|
||||
}
|
||||
|
||||
if (wasm.base.options.export_memory) {
|
||||
if (export_memory) {
|
||||
try argv.append("--export-memory");
|
||||
}
|
||||
|
||||
@ -4698,25 +4748,25 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
try argv.append("--no-gc-sections");
|
||||
}
|
||||
|
||||
if (wasm.base.options.strip) {
|
||||
if (wasm.base.debug_format == .strip) {
|
||||
try argv.append("-s");
|
||||
}
|
||||
|
||||
if (wasm.base.options.initial_memory) |initial_memory| {
|
||||
if (wasm.initial_memory) |initial_memory| {
|
||||
const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
|
||||
try argv.append(arg);
|
||||
}
|
||||
|
||||
if (wasm.base.options.max_memory) |max_memory| {
|
||||
if (wasm.max_memory) |max_memory| {
|
||||
const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
|
||||
try argv.append(arg);
|
||||
}
|
||||
|
||||
if (wasm.base.options.shared_memory) {
|
||||
if (shared_memory) {
|
||||
try argv.append("--shared-memory");
|
||||
}
|
||||
|
||||
if (wasm.base.options.global_base) |global_base| {
|
||||
if (wasm.global_base) |global_base| {
|
||||
const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
|
||||
try argv.append(arg);
|
||||
} else {
|
||||
@ -4728,16 +4778,16 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
}
|
||||
|
||||
// Users are allowed to specify which symbols they want to export to the wasm host.
|
||||
for (wasm.base.options.export_symbol_names) |symbol_name| {
|
||||
for (wasm.export_symbol_names) |symbol_name| {
|
||||
const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
|
||||
try argv.append(arg);
|
||||
}
|
||||
|
||||
if (wasm.base.options.rdynamic) {
|
||||
if (wasm.rdynamic) {
|
||||
try argv.append("--export-dynamic");
|
||||
}
|
||||
|
||||
if (wasm.base.options.entry) |entry| {
|
||||
if (comp.config.entry) |entry| {
|
||||
try argv.append("--entry");
|
||||
try argv.append(entry);
|
||||
} else {
|
||||
@ -4749,14 +4799,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
try std.fmt.allocPrint(arena, "stack-size={d}", .{wasm.base.stack_size}),
|
||||
});
|
||||
|
||||
if (wasm.base.options.import_symbols) {
|
||||
if (wasm.import_symbols) {
|
||||
try argv.append("--allow-undefined");
|
||||
}
|
||||
|
||||
if (wasm.base.comp.config.output_mode == .Lib and wasm.base.comp.config.link_mode == .Dynamic) {
|
||||
try argv.append("--shared");
|
||||
}
|
||||
if (wasm.base.options.pie) {
|
||||
if (comp.config.pie) {
|
||||
try argv.append("--pie");
|
||||
}
|
||||
|
||||
@ -4782,15 +4832,15 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
));
|
||||
}
|
||||
|
||||
if (wasm.base.options.link_libc) {
|
||||
if (comp.config.link_libc) {
|
||||
try argv.append(try comp.get_libc_crt_file(
|
||||
arena,
|
||||
wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model),
|
||||
wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
|
||||
));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));
|
||||
}
|
||||
|
||||
if (wasm.base.options.link_libcpp) {
|
||||
if (comp.config.link_libcpp) {
|
||||
try argv.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
|
||||
}
|
||||
@ -4799,7 +4849,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
|
||||
// Positional arguments to the linker such as object files.
|
||||
var whole_archive = false;
|
||||
for (wasm.base.options.objects) |obj| {
|
||||
for (comp.objects) |obj| {
|
||||
if (obj.must_link and !whole_archive) {
|
||||
try argv.append("-whole-archive");
|
||||
whole_archive = true;
|
||||
@ -4822,8 +4872,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
||||
}
|
||||
|
||||
if (wasm.base.comp.config.output_mode != .Obj and
|
||||
!wasm.base.options.skip_linker_dependencies and
|
||||
!wasm.base.options.link_libc)
|
||||
!comp.skip_linker_dependencies and
|
||||
!comp.config.link_libc)
|
||||
{
|
||||
try argv.append(comp.libc_static_lib.?.full_object_path);
|
||||
}
|
||||
@ -5168,10 +5218,13 @@ fn emitDataRelocations(
|
||||
}
|
||||
|
||||
fn hasPassiveInitializationSegments(wasm: *const Wasm) bool {
|
||||
const comp = wasm.base.comp;
|
||||
const import_memory = comp.config.import_memory;
|
||||
|
||||
var it = wasm.data_segments.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const segment: Segment = wasm.segments.items[entry.value_ptr.*];
|
||||
if (segment.needsPassiveInitialization(wasm.base.options.import_memory, entry.key_ptr.*)) {
|
||||
if (segment.needsPassiveInitialization(import_memory, entry.key_ptr.*)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -5227,14 +5280,14 @@ fn markReferences(wasm: *Wasm) !void {
|
||||
|
||||
for (wasm.resolved_symbols.keys()) |sym_loc| {
|
||||
const sym = sym_loc.getSymbol(wasm);
|
||||
if (sym.isExported(wasm.base.options.rdynamic) or sym.isNoStrip() or !do_garbage_collect) {
|
||||
if (sym.isExported(wasm.rdynamic) or sym.isNoStrip() or !do_garbage_collect) {
|
||||
try wasm.mark(sym_loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Debug sections may require to be parsed and marked when it contains
|
||||
// relocations to alive symbols.
|
||||
if (sym.tag == .section and !wasm.base.options.strip) {
|
||||
if (sym.tag == .section and wasm.base.debug_format != .strip) {
|
||||
const file = sym_loc.file orelse continue; // Incremental debug info is done independently
|
||||
const object = &wasm.objects.items[file];
|
||||
const atom_index = try Object.parseSymbolIntoAtom(object, file, sym_loc.index, wasm);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user