From 3b6cb257dfbcfe7217cdb00819615d1cf1e6b89c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Dec 2023 14:12:45 -0700 Subject: [PATCH] update image_base references --- src/Compilation.zig | 76 ++++++++++++++++++++++++------------------- src/link.zig | 7 ++-- src/link/C.zig | 12 +++++-- src/link/Coff.zig | 71 +++++++++++++++++++++------------------- src/link/Coff/lld.zig | 6 ++-- src/link/Elf.zig | 53 ++++++++++++++---------------- src/main.zig | 19 +++++------ 7 files changed, 129 insertions(+), 115 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 4d4eafba65..2859090edc 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1014,7 +1014,7 @@ pub const InitOptions = struct { entry: ?[]const u8 = null, force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}, stack_size: ?u64 = null, - image_base_override: ?u64 = null, + image_base: ?u64 = null, version: ?std.SemanticVersion = null, compatibility_version: ?std.SemanticVersion = null, libc_installation: ?*const LibCInstallation = null, @@ -1686,7 +1686,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .major_subsystem_version = options.major_subsystem_version, .minor_subsystem_version = options.minor_subsystem_version, .stack_size = options.stack_size, - .image_base_override = options.image_base_override, + .image_base = options.image_base, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, .eh_frame_hdr = link_eh_frame_hdr, @@ -2429,7 +2429,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.formatted_panics); man.hash.add(mod.emit_h != null); man.hash.add(mod.error_limit); - man.hash.addOptional(comp.bin_file.options.want_structured_cfg); + man.hash.add(comp.bin_file.options.want_structured_cfg); } try man.addOptionalFile(comp.bin_file.options.linker_script); @@ -2468,8 +2468,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc); man.hash.add(comp.bin_file.stack_size); - man.hash.addOptional(comp.bin_file.options.image_base_override); - man.hash.addOptional(comp.bin_file.options.gc_sections); + man.hash.add(comp.bin_file.options.gc_sections); man.hash.add(comp.bin_file.options.eh_frame_hdr); man.hash.add(comp.bin_file.options.emit_relocs); man.hash.add(comp.bin_file.options.rdynamic); @@ -2491,8 +2490,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes 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.addOptional(comp.bin_file.options.sort_section); - if (comp.bin_file.options.link_libc) { + man.hash.add(comp.bin_file.options.sort_section); + if (comp.config.link_libc) { man.hash.add(comp.bin_file.options.libc_installation != null); if (comp.bin_file.options.libc_installation) |libc_installation| { man.hash.addOptionalBytes(libc_installation.crt_dir); @@ -2504,39 +2503,50 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptionalBytes(target.dynamic_linker.get()); } man.hash.addOptionalBytes(comp.bin_file.options.soname); - man.hash.addOptional(comp.bin_file.options.version); + man.hash.add(comp.bin_file.options.version); try link.hashAddSystemLibs(man, comp.system_libs); man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys()); - man.hash.addOptional(comp.bin_file.allow_shlib_undefined); + man.hash.add(comp.bin_file.allow_shlib_undefined); man.hash.add(comp.bin_file.options.bind_global_refs_locally); man.hash.add(comp.bin_file.options.tsan); man.hash.addOptionalBytes(comp.bin_file.options.sysroot); man.hash.add(comp.bin_file.options.linker_optimization); - // WASM specific stuff - man.hash.add(comp.bin_file.options.import_memory); - man.hash.add(comp.bin_file.options.export_memory); - man.hash.addOptional(comp.bin_file.options.initial_memory); - man.hash.addOptional(comp.bin_file.options.max_memory); - man.hash.add(comp.bin_file.options.shared_memory); - man.hash.addOptional(comp.bin_file.options.global_base); - - // Mach-O specific stuff - man.hash.addListOfBytes(comp.framework_dirs); - try link.hashAddFrameworks(man, comp.bin_file.options.frameworks); - try man.addOptionalFile(comp.bin_file.options.entitlements); - man.hash.addOptional(comp.bin_file.options.pagezero_size); - man.hash.addOptional(comp.bin_file.options.headerpad_size); - man.hash.add(comp.bin_file.options.headerpad_max_install_names); - man.hash.add(comp.bin_file.options.dead_strip_dylibs); - - // COFF specific stuff - man.hash.addOptional(comp.bin_file.options.subsystem); - man.hash.add(comp.bin_file.options.tsaware); - man.hash.add(comp.bin_file.options.nxcompat); - man.hash.add(comp.bin_file.options.dynamicbase); - man.hash.addOptional(comp.bin_file.options.major_subsystem_version); - man.hash.addOptional(comp.bin_file.options.minor_subsystem_version); + switch (comp.bin_file.tag) { + .elf => { + const elf = comp.bin_file.cast(link.File.Elf).?; + man.hash.add(elf.image_base); + }, + .wasm => { + const wasm = comp.bin_file.cast(link.File.Wasm).?; + man.hash.add(comp.config.import_memory); + man.hash.add(comp.config.export_memory); + man.hash.add(comp.config.shared_memory); + man.hash.add(wasm.initial_memory); + man.hash.add(wasm.max_memory); + man.hash.add(wasm.global_base); + }, + .macho => { + const macho = comp.bin_file.cast(link.File.MachO).?; + man.hash.addListOfBytes(comp.framework_dirs); + try link.hashAddFrameworks(man, macho.frameworks); + try man.addOptionalFile(macho.entitlements); + man.hash.add(macho.pagezero_size); + man.hash.add(macho.headerpad_size); + man.hash.add(macho.headerpad_max_install_names); + man.hash.add(macho.dead_strip_dylibs); + }, + .coff => { + const coff = comp.bin_file.cast(link.File.Coff).?; + man.hash.add(coff.image_base); + man.hash.add(coff.subsystem); + man.hash.add(coff.tsaware); + man.hash.add(coff.nxcompat); + man.hash.add(coff.dynamicbase); + man.hash.add(coff.major_subsystem_version); + man.hash.add(coff.minor_subsystem_version); + }, + } } fn emitOthers(comp: *Compilation) void { diff --git a/src/link.zig b/src/link.zig index fd8d84f765..95a3282186 100644 --- a/src/link.zig +++ b/src/link.zig @@ -102,7 +102,7 @@ pub const File = struct { /// Virtual address of the entry point procedure relative to image base. entry_addr: ?u64, stack_size: ?u64, - image_base_override: ?u64, + image_base: ?u64, function_sections: bool, data_sections: bool, no_builtin: bool, @@ -974,8 +974,9 @@ pub const File = struct { const llvm_bindings = @import("codegen/llvm/bindings.zig"); const Builder = @import("codegen/llvm/Builder.zig"); const llvm = @import("codegen/llvm.zig"); - Builder.initializeLLVMTarget(base.options.target.cpu.arch); - const os_tag = llvm.targetOs(base.options.target.os.tag); + const target = comp.root_mod.resolved_target.result; + Builder.initializeLLVMTarget(target.cpu.arch); + const os_tag = llvm.targetOs(target.os.tag); const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag); if (bad) return error.UnableToWriteArchive; diff --git a/src/link/C.zig b/src/link/C.zig index e6827947ae..043ca0ce6f 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -93,10 +93,13 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String { } pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { - assert(options.target.ofmt == .c); + const target = options.comp.root_mod.resolved_target.result; + assert(target.ofmt == .c); const optimize_mode = options.comp.root_mod.optimize_mode; 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 link_mode = options.comp.config.link_mode; // These are caught by `Compilation.Config.resolve`. assert(!use_lld); @@ -107,7 +110,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { const file = try emit.directory.handle.createFile(emit.sub_path, .{ // Truncation is done on `flush`. .truncate = false, - .mode = link.determineMode(options), + .mode = link.File.determineMode(use_lld, output_mode, link_mode), }); errdefer file.close(); @@ -118,7 +121,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { .tag = .c, .comp = options.comp, .emit = emit, - .gc_sections = options.gc_sections orelse optimize_mode != .Debug, + .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 = file, @@ -126,6 +129,9 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C { .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, }, }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index d99460d333..6bb2e6b1f8 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -7,6 +7,7 @@ llvm_object: ?*LlvmObject = null, base: link.File, +image_base: u64, error_flags: link.File.ErrorFlags = .{}, ptr_width: PtrWidth, @@ -352,8 +353,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { - const target = options.comp.root_mod.resolved_target.result; - const optimize_mode = options.comp.root_mod.optimize_mode; + const comp = options.comp; + const target = comp.root_mod.resolved_target.result; + const optimize_mode = comp.root_mod.optimize_mode; + const output_mode = comp.config.output_mode; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -366,7 +369,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { self.* = .{ .base = .{ .tag = .coff, - .comp = options.comp, + .comp = comp, .emit = options.emit, .stack_size = options.stack_size orelse 16777216, .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), @@ -382,11 +385,25 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff { }, .ptr_width = ptr_width, .page_size = page_size, - .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory), + + .data_directories = [1]coff.ImageDataDirectory{.{ + .virtual_address = 0, + .size = 0, + }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES, + + .image_base = options.image_base orelse switch (output_mode) { + .Exe => switch (target.cpu.arch) { + .aarch64 => 0x140000000, + .x86_64, .x86 => 0x400000, + else => unreachable, + }, + .Lib => 0x10000000, + .Obj => 0, + }, }; - const use_llvm = options.comp.config.use_llvm; - if (use_llvm and options.comp.config.have_zcu) { + const use_llvm = comp.config.use_llvm; + if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } return self; @@ -833,7 +850,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void { } } - self.resolveRelocs(atom_index, relocs.items, code, self.getImageBase()); + self.resolveRelocs(atom_index, relocs.items, code, self.image_base); try self.base.file.?.pwriteAll(code, file_offset); // Now we can mark the relocs as resolved. @@ -879,17 +896,17 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void { const file_offset = header.pointer_to_raw_data + entry_offset; const vmaddr = header.virtual_address + entry_offset; - log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.getImageBase() }); + log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.image_base }); switch (self.ptr_width) { .p32 => { var buf: [4]u8 = undefined; - mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.getImageBase())), .little); + mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.image_base)), .little); try self.base.file.?.pwriteAll(&buf, file_offset); }, .p64 => { var buf: [8]u8 = undefined; - mem.writeInt(u64, &buf, entry_value + self.getImageBase(), .little); + mem.writeInt(u64, &buf, entry_value + self.image_base, .little); try self.base.file.?.pwriteAll(&buf, file_offset); }, } @@ -1467,9 +1484,10 @@ pub fn updateExports( } const ip = &mod.intern_pool; - const target = self.base.comp.root_mod.resolved_target.result; + const comp = self.base.comp; + const target = comp.root_mod.resolved_target.result; - if (self.base.options.use_llvm) { + if (comp.config.use_llvm) { // Even in the case of LLVM, we need to notice certain exported symbols in order to // detect the default subsystem. for (exports) |exp| { @@ -1485,7 +1503,7 @@ pub fn updateExports( }; const decl_cc = exported_decl.ty.fnCallingConvention(mod); if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and - self.base.options.link_libc) + comp.config.link_libc) { mod.stage1_flags.have_c_main = true; } else if (decl_cc == winapi_cc and target.os.tag == .windows) { @@ -1506,7 +1524,7 @@ pub fn updateExports( if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports); - const gpa = self.base.comp.gpa; + const gpa = comp.gpa; const metadata = switch (exported) { .decl_index => |decl_index| blk: { @@ -2247,8 +2265,6 @@ fn writeHeader(self: *Coff) !void { const subsystem: coff.Subsystem = .WINDOWS_CUI; const size_of_image: u32 = self.getSizeOfImage(); const size_of_headers: u32 = mem.alignForward(u32, self.getSizeOfHeaders(), default_file_alignment); - const image_base = self.getImageBase(); - const base_of_code = self.sections.get(self.text_section_index.?).header.virtual_address; const base_of_data = self.sections.get(self.data_section_index.?).header.virtual_address; @@ -2279,7 +2295,7 @@ fn writeHeader(self: *Coff) !void { .address_of_entry_point = self.entry_addr orelse 0, .base_of_code = base_of_code, .base_of_data = base_of_data, - .image_base = @as(u32, @intCast(image_base)), + .image_base = @intCast(self.image_base), .section_alignment = self.page_size, .file_alignment = default_file_alignment, .major_operating_system_version = 6, @@ -2313,7 +2329,7 @@ fn writeHeader(self: *Coff) !void { .size_of_uninitialized_data = size_of_uninitialized_data, .address_of_entry_point = self.entry_addr orelse 0, .base_of_code = base_of_code, - .image_base = image_base, + .image_base = self.image_base, .section_alignment = self.page_size, .file_alignment = default_file_alignment, .major_operating_system_version = 6, @@ -2333,7 +2349,7 @@ fn writeHeader(self: *Coff) !void { .size_of_heap_reserve = default_size_of_heap_reserve, .size_of_heap_commit = default_size_of_heap_commit, .loader_flags = 0, - .number_of_rva_and_sizes = @as(u32, @intCast(self.data_directories.len)), + .number_of_rva_and_sizes = @intCast(self.data_directories.len), }; writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; }, @@ -2447,25 +2463,12 @@ inline fn getSizeOfImage(self: Coff) u32 { /// Returns symbol location corresponding to the set entrypoint (if any). pub fn getEntryPoint(self: Coff) ?SymbolWithLoc { - const entry_name = self.base.options.entry orelse "wWinMainCRTStartup"; // TODO this is incomplete + const comp = self.base.comp; + const entry_name = comp.config.entry orelse return null; const global_index = self.resolver.get(entry_name) orelse return null; return self.globals.items[global_index]; } -pub fn getImageBase(self: Coff) u64 { - const target = self.base.comp.root_mod.resolved_target.result; - const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.comp.config.output_mode) { - .Exe => switch (target.cpu.arch) { - .aarch64 => @as(u64, 0x140000000), - .x86_64, .x86 => 0x400000, - else => unreachable, // unsupported target architecture - }, - .Lib => 0x10000000, - .Obj => 0, - }; - return image_base; -} - /// Returns pointer-to-symbol described by `sym_loc` descriptor. pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol { assert(sym_loc.file == null); // TODO linking object files diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig index 918a7004c1..a321d28fb3 100644 --- a/src/link/Coff/lld.zig +++ b/src/link/Coff/lld.zig @@ -81,7 +81,7 @@ 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.add(self.base.stack_size); - man.hash.addOptional(self.base.options.image_base_override); + 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) { @@ -195,9 +195,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod if (self.base.comp.config.output_mode == .Exe) { try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size})); } - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{self.image_base})); if (target.cpu.arch == .x86) { try argv.append("-MACHINE:X86"); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1ddbece4e1..df83878494 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,4 +1,5 @@ base: link.File, +image_base: u64, ptr_width: PtrWidth, @@ -264,7 +265,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .p32 => @alignOf(elf.Elf32_Phdr), .p64 => @alignOf(elf.Elf64_Phdr), }; - const image_base = self.calcImageBase(); const ehsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Ehdr), .p64 => @sizeOf(elf.Elf64_Ehdr), @@ -279,7 +279,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .type = elf.PT_PHDR, .flags = elf.PF_R, .@"align" = p_align, - .addr = image_base + ehsize, + .addr = self.image_base + ehsize, .offset = ehsize, .filesz = reserved, .memsz = reserved, @@ -288,7 +288,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { .type = elf.PT_LOAD, .flags = elf.PF_R, .@"align" = self.page_size, - .addr = image_base, + .addr = self.image_base, .offset = 0, .filesz = reserved + ehsize, .memsz = reserved + ehsize, @@ -317,12 +317,13 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf { } pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { - const use_llvm = options.comp.config.use_llvm; - const optimize_mode = options.comp.root_mod.optimize_mode; - const target = options.comp.root_mod.resolved_target.result; - const output_mode = options.comp.config.output_mode; - const link_mode = options.comp.config.link_mode; - const is_native_os = options.comp.root_mod.resolved_target.is_native_os; + const comp = options.comp; + const use_llvm = comp.config.use_llvm; + const optimize_mode = comp.root_mod.optimize_mode; + const target = comp.root_mod.resolved_target.result; + const output_mode = comp.config.output_mode; + const link_mode = comp.config.link_mode; + const is_native_os = comp.root_mod.resolved_target.is_native_os; const ptr_width: PtrWidth = switch (target.ptrBitWidth()) { 0...32 => .p32, 33...64 => .p64, @@ -344,7 +345,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf { self.* = .{ .base = .{ .tag = .elf, - .comp = options.comp, + .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, @@ -357,12 +358,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, }; - if (use_llvm and options.comp.config.have_zcu) { + if (use_llvm and comp.config.have_zcu) { self.llvm_object = try LlvmObject.create(arena, options); } @@ -1653,9 +1663,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}), }); - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); if (self.base.gc_sections) { try argv.append("--gc-sections"); @@ -2378,7 +2386,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(self.base.options.entry); - man.hash.addOptional(self.base.options.image_base_override); + 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); @@ -2549,9 +2557,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v } } - if (self.base.options.image_base_override) |image_base| { - try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); - } + try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base})); if (self.base.options.linker_script) |linker_script| { try argv.append("-T"); @@ -3321,7 +3327,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { // __ehdr_start { const symbol_ptr = self.symbol(self.ehdr_start_index.?); - symbol_ptr.value = self.calcImageBase(); + symbol_ptr.value = self.image_base; symbol_ptr.output_section_index = 1; } @@ -5631,15 +5637,6 @@ const CsuObjects = struct { } }; -pub fn calcImageBase(self: Elf) u64 { - if (self.base.isDynLib()) return 0; - if (self.base.isExe() and self.base.options.pie) return 0; - return self.base.options.image_base_override orelse switch (self.ptr_width) { - .p32 => 0x1000, - .p64 => 0x1000000, - }; -} - pub fn isZigSection(self: Elf, shndx: u16) bool { inline for (&[_]?u16{ self.zig_text_section_index, diff --git a/src/main.zig b/src/main.zig index 61b9b6ff56..499d0f57f9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -860,7 +860,7 @@ fn buildOutputType( var test_no_exec = false; var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{}; var stack_size: ?u64 = null; - var image_base_override: ?u64 = null; + var image_base: ?u64 = null; var link_eh_frame_hdr = false; var link_emit_relocs = false; var each_lib_rpath: ?bool = null; @@ -1131,10 +1131,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--stack")) { stack_size = parseStackSize(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { - const next_arg = args_iter.nextOrFatal(); - image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { - fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) }); - }; + image_base = parseImageBase(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "--name")) { provided_name = args_iter.nextOrFatal(); if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?))) @@ -2283,10 +2280,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) { stack_size = parseStackSize(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "--image-base")) { - const image_base = linker_args_it.nextOrFatal(); - image_base_override = std.fmt.parseUnsigned(u64, image_base, 0) catch |err| { - fatal("unable to parse image base override '{s}': {s}", .{ image_base, @errorName(err) }); - }; + image_base = parseImageBase(linker_args_it.nextOrFatal()); } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { linker_script = linker_args_it.nextOrFatal(); } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { @@ -3424,7 +3418,7 @@ fn buildOutputType( .link_emit_relocs = link_emit_relocs, .force_undefined_symbols = force_undefined_symbols, .stack_size = stack_size, - .image_base_override = image_base_override, + .image_base = image_base, .formatted_panics = formatted_panics, .function_sections = function_sections, .data_sections = data_sections, @@ -7686,3 +7680,8 @@ fn parseStackSize(s: []const u8) u64 { return std.fmt.parseUnsigned(u64, s, 0) catch |err| fatal("unable to parse stack size '{s}': {s}", .{ s, @errorName(err) }); } + +fn parseImageBase(s: []const u8) u64 { + return std.fmt.parseUnsigned(u64, s, 0) catch |err| + fatal("unable to parse image base '{s}': {s}", .{ s, @errorName(err) }); +}