diff options
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Coff.zig | 21 | ||||
| -rw-r--r-- | src/link/Coff/lld.zig | 15 | ||||
| -rw-r--r-- | src/link/Elf.zig | 29 | ||||
| -rw-r--r-- | src/link/MachO.zig | 17 | ||||
| -rw-r--r-- | src/link/MachO/zld.zig | 5 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 51 |
6 files changed, 100 insertions, 38 deletions
diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 861ec030b3..53f999b965 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -17,6 +17,7 @@ dynamicbase: bool, major_subsystem_version: u16, minor_subsystem_version: u16, lib_dirs: []const []const u8, +entry: link.File.OpenOptions.Entry, entry_addr: ?u32, module_definition_file: ?[]const u8, pdb_out_path: ?[]const u8, @@ -303,7 +304,12 @@ pub fn createEmpty( .Obj => 0, }, + // Subsystem depends on the set of public symbol names from linked objects. + // See LinkerDriver::inferSubsystem from the LLD project for the flow chart. .subsystem = options.subsystem, + + .entry = options.entry, + .tsaware = options.tsaware, .nxcompat = options.nxcompat, .dynamicbase = options.dynamicbase, @@ -2498,7 +2504,20 @@ inline fn getSizeOfImage(self: Coff) u32 { /// Returns symbol location corresponding to the set entrypoint (if any). pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { const comp = self.base.comp; - const entry_name = comp.config.entry orelse return null; + + // TODO This is incomplete. + // The entry symbol name depends on the subsystem as well as the set of + // public symbol names from linked objects. + // See LinkerDriver::findDefaultEntry from the LLD project for the flow chart. + const entry_name = switch (self.entry) { + .disabled => return null, + .default => switch (comp.config.output_mode) { + .Exe => "wWinMainCRTStartup", + .Obj, .Lib => return null, + }, + .enabled => "wWinMainCRTStartup", + .named => |name| name, + }; const global_index = self.resolver.get(entry_name) orelse return null; return self.globals.items[global_index]; } diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 5b01f63645..6afe741f66 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -52,6 +52,13 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod const link_in_crt = comp.config.link_libc and is_exe_or_dyn_lib; const target = comp.root_mod.resolved_target.result; const optimize_mode = comp.root_mod.optimize_mode; + const entry_name: ?[]const u8 = switch (self.entry) { + // This logic isn't quite right for disabled or enabled. No point in fixing it + // when the goal is to eliminate dependency on LLD anyway. + // https://github.com/ziglang/zig/issues/17751 + .disabled, .default, .enabled => null, + .named => |name| name, + }; // See link/Elf.zig for comments on how this mechanism works. const id_symlink_basename = "lld.id"; @@ -80,7 +87,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } try man.addOptionalFile(module_obj_path); - man.hash.addOptionalBytes(comp.config.entry); + man.hash.addOptionalBytes(entry_name); man.hash.add(self.base.stack_size); man.hash.add(self.image_base); man.hash.addListOfBytes(self.lib_dirs); @@ -218,8 +225,8 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod try argv.append("-DLL"); } - if (comp.config.entry) |entry| { - try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{entry})); + if (entry_name) |name| { + try argv.append(try allocPrint(arena, "-ENTRY:{s}", .{name})); } if (self.tsaware) { @@ -441,7 +448,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod } } else { try argv.append("-NODEFAULTLIB"); - if (!is_lib and comp.config.entry == null) { + if (!is_lib and entry_name == null) { if (comp.module) |module| { if (module.stage1_flags.have_winmain_crt_startup) { try argv.append("-ENTRY:WinMainCRTStartup"); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ea8454490c..65fc0ff5a3 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -25,6 +25,7 @@ linker_script: ?[]const u8, version_script: ?[]const u8, print_icf_sections: bool, print_map: bool, +entry_name: ?[]const u8, ptr_width: PtrWidth, @@ -290,6 +291,13 @@ pub fn createEmpty( .page_size = page_size, .default_sym_version = default_sym_version, + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else defaultEntrySymbolName(target.cpu.arch), + .enabled => defaultEntrySymbolName(target.cpu.arch), + .named => |name| name, + }, + .image_base = b: { if (is_dyn_lib) break :b 0; if (output_mode == .Exe and comp.config.pie) break :b 0; @@ -1305,7 +1313,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node // Look for entry address in objects if not set by the incremental compiler. if (self.entry_index == null) { - if (comp.config.entry) |name| { + if (self.entry_name) |name| { self.entry_index = self.globalByName(name); } } @@ -1679,9 +1687,8 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { } } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } for (self.base.rpath_list) |rpath| { @@ -2427,7 +2434,7 @@ 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(comp.config.entry); + man.hash.addOptionalBytes(self.entry_name); man.hash.add(self.image_base); man.hash.add(self.base.gc_sections); man.hash.addOptional(self.sort_section); @@ -2563,9 +2570,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (self.entry_name) |name| { + try argv.appendSlice(&.{ "--entry", name }); } for (self.base.force_undefined_symbols.keys()) |sym| { @@ -6512,6 +6518,13 @@ const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; +fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { + return switch (cpu_arch) { + .mips, .mipsel, .mips64, .mips64el => "__start", + else => "_start", + }; +} + const std = @import("std"); const build_options = @import("build_options"); const builtin = @import("builtin"); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d8fc71c0f0..8c0874e3cb 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1,4 +1,5 @@ base: File, +entry_name: ?[]const u8, /// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path. llvm_object: ?*LlvmObject = null, @@ -231,6 +232,12 @@ pub fn createEmpty( .install_name = options.install_name, .entitlements = options.entitlements, .compatibility_version = options.compatibility_version, + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else default_entry_symbol_name, + .enabled => default_entry_symbol_name, + .named => |name| name, + }, }; if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, comp); @@ -1629,8 +1636,9 @@ 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 = comp.config.entry.?; - _ = try self.addUndefined(entry_name, .{}); + if (self.entry_name) |entry_name| { + _ = try self.addUndefined(entry_name, .{}); + } } // Force resolution of any symbols requested by the user. @@ -5085,8 +5093,7 @@ 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 comp = self.base.comp; - const entry_name = comp.config.entry orelse return null; + const entry_name = self.entry_name orelse return null; const global = self.getGlobal(entry_name) orelse return null; return global; } @@ -5645,6 +5652,8 @@ pub fn logAtom(self: *MachO, atom_index: Atom.Index, logger: anytype) void { } } +const default_entry_symbol_name = "_main"; + pub const base_tag: File.Tag = File.Tag.macho; pub const N_DEAD: u16 = @as(u16, @bitCast(@as(i16, -1))); pub const N_BOUNDARY: u16 = @as(u16, @bitCast(@as(i16, -2))); diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig index fa6aa152e4..05fa8e671a 100644 --- a/src/link/MachO/zld.zig +++ b/src/link/MachO/zld.zig @@ -276,9 +276,8 @@ pub fn linkWithZld( try argv.append("-dead_strip_dylibs"); } - if (comp.config.entry) |entry| { - try argv.append("-e"); - try argv.append(entry); + if (macho_file.entry_name) |entry_name| { + try argv.appendSlice(&.{ "-e", entry_name }); } for (objects) |obj| { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index b4b0f16d4a..91653ce641 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -37,6 +37,7 @@ pub const Relocation = types.Relocation; pub const base_tag: link.File.Tag = .wasm; base: link.File, +entry_name: ?[]const u8, import_symbols: bool, export_symbol_names: []const []const u8, global_base: ?u64, @@ -397,6 +398,7 @@ pub fn createEmpty( const use_llvm = comp.config.use_llvm; const output_mode = comp.config.output_mode; const shared_memory = comp.config.shared_memory; + const wasi_exec_model = comp.config.wasi_exec_model; // If using LLD to link, this code should produce an object file so that it // can be passed to LLD. @@ -434,6 +436,13 @@ pub fn createEmpty( .initial_memory = options.initial_memory, .max_memory = options.max_memory, .wasi_emulated_libs = options.wasi_emulated_libs, + + .entry_name = switch (options.entry) { + .disabled => null, + .default => if (output_mode != .Exe) null else defaultEntrySymbolName(wasi_exec_model), + .enabled => defaultEntrySymbolName(wasi_exec_model), + .named => |name| name, + }, }; if (use_llvm and comp.config.have_zcu) { wasm.llvm_object = try LlvmObject.create(arena, comp); @@ -3042,7 +3051,7 @@ 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 = comp.config.entry orelse return; + const entry_name = wasm.entry_name orelse return; const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); @@ -3475,8 +3484,8 @@ fn resetState(wasm: *Wasm) void { } pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { - const use_lld = build_options.have_llvm and wasm.base.comp.config.use_lld; - const use_llvm = wasm.base.comp.config.use_llvm; + const use_lld = build_options.have_llvm and comp.config.use_lld; + const use_llvm = comp.config.use_llvm; if (use_lld) { return wasm.linkWithLLD(comp, prog_node); @@ -3492,7 +3501,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const tracy = trace(@src()); defer tracy.end(); - const gpa = wasm.base.comp.gpa; + const gpa = comp.gpa; const shared_memory = comp.config.shared_memory; const import_memory = comp.config.import_memory; @@ -3503,8 +3512,8 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type. const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path}); - const opt_zcu = wasm.base.comp.module; - const use_llvm = wasm.base.comp.config.use_llvm; + const opt_zcu = comp.module; + const use_llvm = comp.config.use_llvm; // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. @@ -3535,7 +3544,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l defer if (!wasm.base.disable_lld_caching) man.deinit(); var digest: [Cache.hex_digest_len]u8 = undefined; - const objects = wasm.base.comp.objects; + const objects = comp.objects; // NOTE: The following section must be maintained to be equal // as the section defined in `linkWithLLD` @@ -3556,7 +3565,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.addOptionalBytes(wasm.entry_name); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); man.hash.add(import_memory); @@ -3605,12 +3614,12 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l var positionals = std.ArrayList([]const u8).init(arena); try positionals.ensureUnusedCapacity(objects.len); - const target = wasm.base.comp.root_mod.resolved_target.result; - const output_mode = wasm.base.comp.config.output_mode; - const link_mode = wasm.base.comp.config.link_mode; - const link_libc = wasm.base.comp.config.link_libc; - const link_libcpp = wasm.base.comp.config.link_libcpp; - const wasi_exec_model = wasm.base.comp.config.wasi_exec_model; + const target = comp.root_mod.resolved_target.result; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const link_libc = comp.config.link_libc; + const link_libcpp = comp.config.link_libcpp; + const wasi_exec_model = comp.config.wasi_exec_model; // When the target os is WASI, we allow linking with WASI-LIBC if (target.os.tag == .wasi) { @@ -4648,7 +4657,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! } try man.addOptionalFile(module_obj_path); try man.addOptionalFile(compiler_rt_path); - man.hash.addOptionalBytes(wasm.base.comp.config.entry); + man.hash.addOptionalBytes(wasm.entry_name); man.hash.add(wasm.base.stack_size); man.hash.add(wasm.base.build_id); man.hash.add(import_memory); @@ -4799,9 +4808,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--export-dynamic"); } - if (comp.config.entry) |entry| { - try argv.append("--entry"); - try argv.append(entry); + if (wasm.entry_name) |entry_name| { + try argv.appendSlice(&.{ "--entry", entry_name }); } else { try argv.append("--no-entry"); } @@ -5347,3 +5355,10 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { try wasm.mark(target_loc.finalLoc(wasm)); } } + +fn defaultEntrySymbolName(wasi_exec_model: std.builtin.WasiExecModel) []const u8 { + return switch (wasi_exec_model) { + .reactor => "_initialize", + .command => "_start", + }; +} |
