authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-12 14:12:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:19-07:00
log3b6cb257dfbcfe7217cdb00819615d1cf1e6b89c
tree4431c016e34bbda2600a0a582064a1ba932ffe9e
parent9a48a5ab0784ae9744c72cfcc6d7ad9b2cea6a9c

update image_base references


7 files changed, 129 insertions(+), 115 deletions(-)

src/Compilation.zig+43-33
...@@ -1014,7 +1014,7 @@ pub const InitOptions = struct {...@@ -1014,7 +1014,7 @@ pub const InitOptions = struct {
1014 entry: ?[]const u8 = null,1014 entry: ?[]const u8 = null,
1015 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{},1015 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{},
1016 stack_size: ?u64 = null,1016 stack_size: ?u64 = null,
1017 image_base_override: ?u64 = null,1017 image_base: ?u64 = null,
1018 version: ?std.SemanticVersion = null,1018 version: ?std.SemanticVersion = null,
1019 compatibility_version: ?std.SemanticVersion = null,1019 compatibility_version: ?std.SemanticVersion = null,
1020 libc_installation: ?*const LibCInstallation = null,1020 libc_installation: ?*const LibCInstallation = null,
...@@ -1686,7 +1686,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1686,7 +1686,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1686 .major_subsystem_version = options.major_subsystem_version,1686 .major_subsystem_version = options.major_subsystem_version,
1687 .minor_subsystem_version = options.minor_subsystem_version,1687 .minor_subsystem_version = options.minor_subsystem_version,
1688 .stack_size = options.stack_size,1688 .stack_size = options.stack_size,
1689 .image_base_override = options.image_base_override,1689 .image_base = options.image_base,
1690 .version_script = options.version_script,1690 .version_script = options.version_script,
1691 .gc_sections = options.linker_gc_sections,1691 .gc_sections = options.linker_gc_sections,
1692 .eh_frame_hdr = link_eh_frame_hdr,1692 .eh_frame_hdr = link_eh_frame_hdr,
...@@ -2429,7 +2429,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2429,7 +2429,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2429 man.hash.add(comp.formatted_panics);2429 man.hash.add(comp.formatted_panics);
2430 man.hash.add(mod.emit_h != null);2430 man.hash.add(mod.emit_h != null);
2431 man.hash.add(mod.error_limit);2431 man.hash.add(mod.error_limit);
2432 man.hash.addOptional(comp.bin_file.options.want_structured_cfg);2432 man.hash.add(comp.bin_file.options.want_structured_cfg);
2433 }2433 }
24342434
2435 try man.addOptionalFile(comp.bin_file.options.linker_script);2435 try man.addOptionalFile(comp.bin_file.options.linker_script);
...@@ -2468,8 +2468,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2468,8 +2468,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2468 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);2468 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
24692469
2470 man.hash.add(comp.bin_file.stack_size);2470 man.hash.add(comp.bin_file.stack_size);
2471 man.hash.addOptional(comp.bin_file.options.image_base_override);2471 man.hash.add(comp.bin_file.options.gc_sections);
2472 man.hash.addOptional(comp.bin_file.options.gc_sections);
2473 man.hash.add(comp.bin_file.options.eh_frame_hdr);2472 man.hash.add(comp.bin_file.options.eh_frame_hdr);
2474 man.hash.add(comp.bin_file.options.emit_relocs);2473 man.hash.add(comp.bin_file.options.emit_relocs);
2475 man.hash.add(comp.bin_file.options.rdynamic);2474 man.hash.add(comp.bin_file.options.rdynamic);
...@@ -2491,8 +2490,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2491,8 +2490,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2491 man.hash.add(comp.bin_file.options.hash_style);2490 man.hash.add(comp.bin_file.options.hash_style);
2492 man.hash.add(comp.bin_file.options.compress_debug_sections);2491 man.hash.add(comp.bin_file.options.compress_debug_sections);
2493 man.hash.add(comp.bin_file.options.include_compiler_rt);2492 man.hash.add(comp.bin_file.options.include_compiler_rt);
2494 man.hash.addOptional(comp.bin_file.options.sort_section);2493 man.hash.add(comp.bin_file.options.sort_section);
2495 if (comp.bin_file.options.link_libc) {2494 if (comp.config.link_libc) {
2496 man.hash.add(comp.bin_file.options.libc_installation != null);2495 man.hash.add(comp.bin_file.options.libc_installation != null);
2497 if (comp.bin_file.options.libc_installation) |libc_installation| {2496 if (comp.bin_file.options.libc_installation) |libc_installation| {
2498 man.hash.addOptionalBytes(libc_installation.crt_dir);2497 man.hash.addOptionalBytes(libc_installation.crt_dir);
...@@ -2504,39 +2503,50 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2504,39 +2503,50 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2504 man.hash.addOptionalBytes(target.dynamic_linker.get());2503 man.hash.addOptionalBytes(target.dynamic_linker.get());
2505 }2504 }
2506 man.hash.addOptionalBytes(comp.bin_file.options.soname);2505 man.hash.addOptionalBytes(comp.bin_file.options.soname);
2507 man.hash.addOptional(comp.bin_file.options.version);2506 man.hash.add(comp.bin_file.options.version);
2508 try link.hashAddSystemLibs(man, comp.system_libs);2507 try link.hashAddSystemLibs(man, comp.system_libs);
2509 man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys());2508 man.hash.addListOfBytes(comp.bin_file.options.force_undefined_symbols.keys());
2510 man.hash.addOptional(comp.bin_file.allow_shlib_undefined);2509 man.hash.add(comp.bin_file.allow_shlib_undefined);
2511 man.hash.add(comp.bin_file.options.bind_global_refs_locally);2510 man.hash.add(comp.bin_file.options.bind_global_refs_locally);
2512 man.hash.add(comp.bin_file.options.tsan);2511 man.hash.add(comp.bin_file.options.tsan);
2513 man.hash.addOptionalBytes(comp.bin_file.options.sysroot);2512 man.hash.addOptionalBytes(comp.bin_file.options.sysroot);
2514 man.hash.add(comp.bin_file.options.linker_optimization);2513 man.hash.add(comp.bin_file.options.linker_optimization);
25152514
2516 // WASM specific stuff2515 switch (comp.bin_file.tag) {
2517 man.hash.add(comp.bin_file.options.import_memory);2516 .elf => {
2518 man.hash.add(comp.bin_file.options.export_memory);2517 const elf = comp.bin_file.cast(link.File.Elf).?;
2519 man.hash.addOptional(comp.bin_file.options.initial_memory);2518 man.hash.add(elf.image_base);
2520 man.hash.addOptional(comp.bin_file.options.max_memory);2519 },
2521 man.hash.add(comp.bin_file.options.shared_memory);2520 .wasm => {
2522 man.hash.addOptional(comp.bin_file.options.global_base);2521 const wasm = comp.bin_file.cast(link.File.Wasm).?;
25232522 man.hash.add(comp.config.import_memory);
2524 // Mach-O specific stuff2523 man.hash.add(comp.config.export_memory);
2525 man.hash.addListOfBytes(comp.framework_dirs);2524 man.hash.add(comp.config.shared_memory);
2526 try link.hashAddFrameworks(man, comp.bin_file.options.frameworks);2525 man.hash.add(wasm.initial_memory);
2527 try man.addOptionalFile(comp.bin_file.options.entitlements);2526 man.hash.add(wasm.max_memory);
2528 man.hash.addOptional(comp.bin_file.options.pagezero_size);2527 man.hash.add(wasm.global_base);
2529 man.hash.addOptional(comp.bin_file.options.headerpad_size);2528 },
2530 man.hash.add(comp.bin_file.options.headerpad_max_install_names);2529 .macho => {
2531 man.hash.add(comp.bin_file.options.dead_strip_dylibs);2530 const macho = comp.bin_file.cast(link.File.MachO).?;
25322531 man.hash.addListOfBytes(comp.framework_dirs);
2533 // COFF specific stuff2532 try link.hashAddFrameworks(man, macho.frameworks);
2534 man.hash.addOptional(comp.bin_file.options.subsystem);2533 try man.addOptionalFile(macho.entitlements);
2535 man.hash.add(comp.bin_file.options.tsaware);2534 man.hash.add(macho.pagezero_size);
2536 man.hash.add(comp.bin_file.options.nxcompat);2535 man.hash.add(macho.headerpad_size);
2537 man.hash.add(comp.bin_file.options.dynamicbase);2536 man.hash.add(macho.headerpad_max_install_names);
2538 man.hash.addOptional(comp.bin_file.options.major_subsystem_version);2537 man.hash.add(macho.dead_strip_dylibs);
2539 man.hash.addOptional(comp.bin_file.options.minor_subsystem_version);2538 },
2539 .coff => {
2540 const coff = comp.bin_file.cast(link.File.Coff).?;
2541 man.hash.add(coff.image_base);
2542 man.hash.add(coff.subsystem);
2543 man.hash.add(coff.tsaware);
2544 man.hash.add(coff.nxcompat);
2545 man.hash.add(coff.dynamicbase);
2546 man.hash.add(coff.major_subsystem_version);
2547 man.hash.add(coff.minor_subsystem_version);
2548 },
2549 }
2540}2550}
25412551
2542fn emitOthers(comp: *Compilation) void {2552fn emitOthers(comp: *Compilation) void {
src/link.zig+4-3
...@@ -102,7 +102,7 @@ pub const File = struct {...@@ -102,7 +102,7 @@ pub const File = struct {
102 /// Virtual address of the entry point procedure relative to image base.102 /// Virtual address of the entry point procedure relative to image base.
103 entry_addr: ?u64,103 entry_addr: ?u64,
104 stack_size: ?u64,104 stack_size: ?u64,
105 image_base_override: ?u64,105 image_base: ?u64,
106 function_sections: bool,106 function_sections: bool,
107 data_sections: bool,107 data_sections: bool,
108 no_builtin: bool,108 no_builtin: bool,
...@@ -974,8 +974,9 @@ pub const File = struct {...@@ -974,8 +974,9 @@ pub const File = struct {
974 const llvm_bindings = @import("codegen/llvm/bindings.zig");974 const llvm_bindings = @import("codegen/llvm/bindings.zig");
975 const Builder = @import("codegen/llvm/Builder.zig");975 const Builder = @import("codegen/llvm/Builder.zig");
976 const llvm = @import("codegen/llvm.zig");976 const llvm = @import("codegen/llvm.zig");
977 Builder.initializeLLVMTarget(base.options.target.cpu.arch);977 const target = comp.root_mod.resolved_target.result;
978 const os_tag = llvm.targetOs(base.options.target.os.tag);978 Builder.initializeLLVMTarget(target.cpu.arch);
979 const os_tag = llvm.targetOs(target.os.tag);
979 const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag);980 const bad = llvm_bindings.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_tag);
980 if (bad) return error.UnableToWriteArchive;981 if (bad) return error.UnableToWriteArchive;
981982
src/link/C.zig+9-3
...@@ -93,10 +93,13 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {...@@ -93,10 +93,13 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
93}93}
9494
95pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {95pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
96 assert(options.target.ofmt == .c);96 const target = options.comp.root_mod.resolved_target.result;
97 assert(target.ofmt == .c);
97 const optimize_mode = options.comp.root_mod.optimize_mode;98 const optimize_mode = options.comp.root_mod.optimize_mode;
98 const use_lld = build_options.have_llvm and options.comp.config.use_lld;99 const use_lld = build_options.have_llvm and options.comp.config.use_lld;
99 const use_llvm = options.comp.config.use_llvm;100 const use_llvm = options.comp.config.use_llvm;
101 const output_mode = options.comp.config.output_mode;
102 const link_mode = options.comp.config.link_mode;
100103
101 // These are caught by `Compilation.Config.resolve`.104 // These are caught by `Compilation.Config.resolve`.
102 assert(!use_lld);105 assert(!use_lld);
...@@ -107,7 +110,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {...@@ -107,7 +110,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
107 const file = try emit.directory.handle.createFile(emit.sub_path, .{110 const file = try emit.directory.handle.createFile(emit.sub_path, .{
108 // Truncation is done on `flush`.111 // Truncation is done on `flush`.
109 .truncate = false,112 .truncate = false,
110 .mode = link.determineMode(options),113 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
111 });114 });
112 errdefer file.close();115 errdefer file.close();
113116
...@@ -118,7 +121,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {...@@ -118,7 +121,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
118 .tag = .c,121 .tag = .c,
119 .comp = options.comp,122 .comp = options.comp,
120 .emit = emit,123 .emit = emit,
121 .gc_sections = options.gc_sections orelse optimize_mode != .Debug,124 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
122 .stack_size = options.stack_size orelse 16777216,125 .stack_size = options.stack_size orelse 16777216,
123 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,126 .allow_shlib_undefined = options.allow_shlib_undefined orelse false,
124 .file = file,127 .file = file,
...@@ -126,6 +129,9 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {...@@ -126,6 +129,9 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*C {
126 .build_id = options.build_id,129 .build_id = options.build_id,
127 .rpath_list = options.rpath_list,130 .rpath_list = options.rpath_list,
128 .force_undefined_symbols = options.force_undefined_symbols,131 .force_undefined_symbols = options.force_undefined_symbols,
132 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
133 .function_sections = options.function_sections,
134 .data_sections = options.data_sections,
129 },135 },
130 };136 };
131137
src/link/Coff.zig+37-34
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7llvm_object: ?*LlvmObject = null,7llvm_object: ?*LlvmObject = null,
88
9base: link.File,9base: link.File,
10image_base: u64,
10error_flags: link.File.ErrorFlags = .{},11error_flags: link.File.ErrorFlags = .{},
1112
12ptr_width: PtrWidth,13ptr_width: PtrWidth,
...@@ -352,8 +353,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -352,8 +353,10 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Coff {
352}353}
353354
354pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {355pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
355 const target = options.comp.root_mod.resolved_target.result;356 const comp = options.comp;
356 const optimize_mode = options.comp.root_mod.optimize_mode;357 const target = comp.root_mod.resolved_target.result;
358 const optimize_mode = comp.root_mod.optimize_mode;
359 const output_mode = comp.config.output_mode;
357 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {360 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
358 0...32 => .p32,361 0...32 => .p32,
359 33...64 => .p64,362 33...64 => .p64,
...@@ -366,7 +369,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -366,7 +369,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
366 self.* = .{369 self.* = .{
367 .base = .{370 .base = .{
368 .tag = .coff,371 .tag = .coff,
369 .comp = options.comp,372 .comp = comp,
370 .emit = options.emit,373 .emit = options.emit,
371 .stack_size = options.stack_size orelse 16777216,374 .stack_size = options.stack_size orelse 16777216,
372 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),375 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug),
...@@ -382,11 +385,25 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {...@@ -382,11 +385,25 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Coff {
382 },385 },
383 .ptr_width = ptr_width,386 .ptr_width = ptr_width,
384 .page_size = page_size,387 .page_size = page_size,
385 .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory),388
389 .data_directories = [1]coff.ImageDataDirectory{.{
390 .virtual_address = 0,
391 .size = 0,
392 }} ** coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES,
393
394 .image_base = options.image_base orelse switch (output_mode) {
395 .Exe => switch (target.cpu.arch) {
396 .aarch64 => 0x140000000,
397 .x86_64, .x86 => 0x400000,
398 else => unreachable,
399 },
400 .Lib => 0x10000000,
401 .Obj => 0,
402 },
386 };403 };
387404
388 const use_llvm = options.comp.config.use_llvm;405 const use_llvm = comp.config.use_llvm;
389 if (use_llvm and options.comp.config.have_zcu) {406 if (use_llvm and comp.config.have_zcu) {
390 self.llvm_object = try LlvmObject.create(arena, options);407 self.llvm_object = try LlvmObject.create(arena, options);
391 }408 }
392 return self;409 return self;
...@@ -833,7 +850,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {...@@ -833,7 +850,7 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {
833 }850 }
834 }851 }
835852
836 self.resolveRelocs(atom_index, relocs.items, code, self.getImageBase());853 self.resolveRelocs(atom_index, relocs.items, code, self.image_base);
837 try self.base.file.?.pwriteAll(code, file_offset);854 try self.base.file.?.pwriteAll(code, file_offset);
838855
839 // Now we can mark the relocs as resolved.856 // Now we can mark the relocs as resolved.
...@@ -879,17 +896,17 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {...@@ -879,17 +896,17 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
879 const file_offset = header.pointer_to_raw_data + entry_offset;896 const file_offset = header.pointer_to_raw_data + entry_offset;
880 const vmaddr = header.virtual_address + entry_offset;897 const vmaddr = header.virtual_address + entry_offset;
881898
882 log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.getImageBase() });899 log.debug("writing GOT entry {d}: @{x} => {x}", .{ index, vmaddr, entry_value + self.image_base });
883900
884 switch (self.ptr_width) {901 switch (self.ptr_width) {
885 .p32 => {902 .p32 => {
886 var buf: [4]u8 = undefined;903 var buf: [4]u8 = undefined;
887 mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.getImageBase())), .little);904 mem.writeInt(u32, &buf, @as(u32, @intCast(entry_value + self.image_base)), .little);
888 try self.base.file.?.pwriteAll(&buf, file_offset);905 try self.base.file.?.pwriteAll(&buf, file_offset);
889 },906 },
890 .p64 => {907 .p64 => {
891 var buf: [8]u8 = undefined;908 var buf: [8]u8 = undefined;
892 mem.writeInt(u64, &buf, entry_value + self.getImageBase(), .little);909 mem.writeInt(u64, &buf, entry_value + self.image_base, .little);
893 try self.base.file.?.pwriteAll(&buf, file_offset);910 try self.base.file.?.pwriteAll(&buf, file_offset);
894 },911 },
895 }912 }
...@@ -1467,9 +1484,10 @@ pub fn updateExports(...@@ -1467,9 +1484,10 @@ pub fn updateExports(
1467 }1484 }
14681485
1469 const ip = &mod.intern_pool;1486 const ip = &mod.intern_pool;
1470 const target = self.base.comp.root_mod.resolved_target.result;1487 const comp = self.base.comp;
1488 const target = comp.root_mod.resolved_target.result;
14711489
1472 if (self.base.options.use_llvm) {1490 if (comp.config.use_llvm) {
1473 // Even in the case of LLVM, we need to notice certain exported symbols in order to1491 // Even in the case of LLVM, we need to notice certain exported symbols in order to
1474 // detect the default subsystem.1492 // detect the default subsystem.
1475 for (exports) |exp| {1493 for (exports) |exp| {
...@@ -1485,7 +1503,7 @@ pub fn updateExports(...@@ -1485,7 +1503,7 @@ pub fn updateExports(
1485 };1503 };
1486 const decl_cc = exported_decl.ty.fnCallingConvention(mod);1504 const decl_cc = exported_decl.ty.fnCallingConvention(mod);
1487 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and1505 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and
1488 self.base.options.link_libc)1506 comp.config.link_libc)
1489 {1507 {
1490 mod.stage1_flags.have_c_main = true;1508 mod.stage1_flags.have_c_main = true;
1491 } else if (decl_cc == winapi_cc and target.os.tag == .windows) {1509 } else if (decl_cc == winapi_cc and target.os.tag == .windows) {
...@@ -1506,7 +1524,7 @@ pub fn updateExports(...@@ -1506,7 +1524,7 @@ pub fn updateExports(
15061524
1507 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);1525 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);
15081526
1509 const gpa = self.base.comp.gpa;1527 const gpa = comp.gpa;
15101528
1511 const metadata = switch (exported) {1529 const metadata = switch (exported) {
1512 .decl_index => |decl_index| blk: {1530 .decl_index => |decl_index| blk: {
...@@ -2247,8 +2265,6 @@ fn writeHeader(self: *Coff) !void {...@@ -2247,8 +2265,6 @@ fn writeHeader(self: *Coff) !void {
2247 const subsystem: coff.Subsystem = .WINDOWS_CUI;2265 const subsystem: coff.Subsystem = .WINDOWS_CUI;
2248 const size_of_image: u32 = self.getSizeOfImage();2266 const size_of_image: u32 = self.getSizeOfImage();
2249 const size_of_headers: u32 = mem.alignForward(u32, self.getSizeOfHeaders(), default_file_alignment);2267 const size_of_headers: u32 = mem.alignForward(u32, self.getSizeOfHeaders(), default_file_alignment);
2250 const image_base = self.getImageBase();
2251
2252 const base_of_code = self.sections.get(self.text_section_index.?).header.virtual_address;2268 const base_of_code = self.sections.get(self.text_section_index.?).header.virtual_address;
2253 const base_of_data = self.sections.get(self.data_section_index.?).header.virtual_address;2269 const base_of_data = self.sections.get(self.data_section_index.?).header.virtual_address;
22542270
...@@ -2279,7 +2295,7 @@ fn writeHeader(self: *Coff) !void {...@@ -2279,7 +2295,7 @@ fn writeHeader(self: *Coff) !void {
2279 .address_of_entry_point = self.entry_addr orelse 0,2295 .address_of_entry_point = self.entry_addr orelse 0,
2280 .base_of_code = base_of_code,2296 .base_of_code = base_of_code,
2281 .base_of_data = base_of_data,2297 .base_of_data = base_of_data,
2282 .image_base = @as(u32, @intCast(image_base)),2298 .image_base = @intCast(self.image_base),
2283 .section_alignment = self.page_size,2299 .section_alignment = self.page_size,
2284 .file_alignment = default_file_alignment,2300 .file_alignment = default_file_alignment,
2285 .major_operating_system_version = 6,2301 .major_operating_system_version = 6,
...@@ -2313,7 +2329,7 @@ fn writeHeader(self: *Coff) !void {...@@ -2313,7 +2329,7 @@ fn writeHeader(self: *Coff) !void {
2313 .size_of_uninitialized_data = size_of_uninitialized_data,2329 .size_of_uninitialized_data = size_of_uninitialized_data,
2314 .address_of_entry_point = self.entry_addr orelse 0,2330 .address_of_entry_point = self.entry_addr orelse 0,
2315 .base_of_code = base_of_code,2331 .base_of_code = base_of_code,
2316 .image_base = image_base,2332 .image_base = self.image_base,
2317 .section_alignment = self.page_size,2333 .section_alignment = self.page_size,
2318 .file_alignment = default_file_alignment,2334 .file_alignment = default_file_alignment,
2319 .major_operating_system_version = 6,2335 .major_operating_system_version = 6,
...@@ -2333,7 +2349,7 @@ fn writeHeader(self: *Coff) !void {...@@ -2333,7 +2349,7 @@ fn writeHeader(self: *Coff) !void {
2333 .size_of_heap_reserve = default_size_of_heap_reserve,2349 .size_of_heap_reserve = default_size_of_heap_reserve,
2334 .size_of_heap_commit = default_size_of_heap_commit,2350 .size_of_heap_commit = default_size_of_heap_commit,
2335 .loader_flags = 0,2351 .loader_flags = 0,
2336 .number_of_rva_and_sizes = @as(u32, @intCast(self.data_directories.len)),2352 .number_of_rva_and_sizes = @intCast(self.data_directories.len),
2337 };2353 };
2338 writer.writeAll(mem.asBytes(&opt_header)) catch unreachable;2354 writer.writeAll(mem.asBytes(&opt_header)) catch unreachable;
2339 },2355 },
...@@ -2447,25 +2463,12 @@ inline fn getSizeOfImage(self: Coff) u32 {...@@ -2447,25 +2463,12 @@ inline fn getSizeOfImage(self: Coff) u32 {
24472463
2448/// Returns symbol location corresponding to the set entrypoint (if any).2464/// Returns symbol location corresponding to the set entrypoint (if any).
2449pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {2465pub fn getEntryPoint(self: Coff) ?SymbolWithLoc {
2450 const entry_name = self.base.options.entry orelse "wWinMainCRTStartup"; // TODO this is incomplete2466 const comp = self.base.comp;
2467 const entry_name = comp.config.entry orelse return null;
2451 const global_index = self.resolver.get(entry_name) orelse return null;2468 const global_index = self.resolver.get(entry_name) orelse return null;
2452 return self.globals.items[global_index];2469 return self.globals.items[global_index];
2453}2470}
24542471
2455pub fn getImageBase(self: Coff) u64 {
2456 const target = self.base.comp.root_mod.resolved_target.result;
2457 const image_base: u64 = self.base.options.image_base_override orelse switch (self.base.comp.config.output_mode) {
2458 .Exe => switch (target.cpu.arch) {
2459 .aarch64 => @as(u64, 0x140000000),
2460 .x86_64, .x86 => 0x400000,
2461 else => unreachable, // unsupported target architecture
2462 },
2463 .Lib => 0x10000000,
2464 .Obj => 0,
2465 };
2466 return image_base;
2467}
2468
2469/// Returns pointer-to-symbol described by `sym_loc` descriptor.2472/// Returns pointer-to-symbol described by `sym_loc` descriptor.
2470pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol {2473pub fn getSymbolPtr(self: *Coff, sym_loc: SymbolWithLoc) *coff.Symbol {
2471 assert(sym_loc.file == null); // TODO linking object files2474 assert(sym_loc.file == null); // TODO linking object files
src/link/Coff/lld.zig+2-4
...@@ -81,7 +81,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -81,7 +81,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
81 try man.addOptionalFile(module_obj_path);81 try man.addOptionalFile(module_obj_path);
82 man.hash.addOptionalBytes(self.base.options.entry);82 man.hash.addOptionalBytes(self.base.options.entry);
83 man.hash.add(self.base.stack_size);83 man.hash.add(self.base.stack_size);
84 man.hash.addOptional(self.base.options.image_base_override);84 man.hash.addOptional(self.image_base);
85 man.hash.addListOfBytes(self.base.options.lib_dirs);85 man.hash.addListOfBytes(self.base.options.lib_dirs);
86 man.hash.add(self.base.options.skip_linker_dependencies);86 man.hash.add(self.base.options.skip_linker_dependencies);
87 if (self.base.options.link_libc) {87 if (self.base.options.link_libc) {
...@@ -195,9 +195,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -195,9 +195,7 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
195 if (self.base.comp.config.output_mode == .Exe) {195 if (self.base.comp.config.output_mode == .Exe) {
196 try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size}));196 try argv.append(try allocPrint(arena, "-STACK:{d}", .{self.base.stack_size}));
197 }197 }
198 if (self.base.options.image_base_override) |image_base| {198 try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{self.image_base}));
199 try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base}));
200 }
201199
202 if (target.cpu.arch == .x86) {200 if (target.cpu.arch == .x86) {
203 try argv.append("-MACHINE:X86");201 try argv.append("-MACHINE:X86");
src/link/Elf.zig+25-28
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1base: link.File,1base: link.File,
2image_base: u64,
23
3ptr_width: PtrWidth,4ptr_width: PtrWidth,
45
...@@ -264,7 +265,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -264,7 +265,6 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
264 .p32 => @alignOf(elf.Elf32_Phdr),265 .p32 => @alignOf(elf.Elf32_Phdr),
265 .p64 => @alignOf(elf.Elf64_Phdr),266 .p64 => @alignOf(elf.Elf64_Phdr),
266 };267 };
267 const image_base = self.calcImageBase();
268 const ehsize: u64 = switch (self.ptr_width) {268 const ehsize: u64 = switch (self.ptr_width) {
269 .p32 => @sizeOf(elf.Elf32_Ehdr),269 .p32 => @sizeOf(elf.Elf32_Ehdr),
270 .p64 => @sizeOf(elf.Elf64_Ehdr),270 .p64 => @sizeOf(elf.Elf64_Ehdr),
...@@ -279,7 +279,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -279,7 +279,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
279 .type = elf.PT_PHDR,279 .type = elf.PT_PHDR,
280 .flags = elf.PF_R,280 .flags = elf.PF_R,
281 .@"align" = p_align,281 .@"align" = p_align,
282 .addr = image_base + ehsize,282 .addr = self.image_base + ehsize,
283 .offset = ehsize,283 .offset = ehsize,
284 .filesz = reserved,284 .filesz = reserved,
285 .memsz = reserved,285 .memsz = reserved,
...@@ -288,7 +288,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -288,7 +288,7 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
288 .type = elf.PT_LOAD,288 .type = elf.PT_LOAD,
289 .flags = elf.PF_R,289 .flags = elf.PF_R,
290 .@"align" = self.page_size,290 .@"align" = self.page_size,
291 .addr = image_base,291 .addr = self.image_base,
292 .offset = 0,292 .offset = 0,
293 .filesz = reserved + ehsize,293 .filesz = reserved + ehsize,
294 .memsz = reserved + ehsize,294 .memsz = reserved + ehsize,
...@@ -317,12 +317,13 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -317,12 +317,13 @@ pub fn open(arena: Allocator, options: link.File.OpenOptions) !*Elf {
317}317}
318318
319pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {319pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
320 const use_llvm = options.comp.config.use_llvm;320 const comp = options.comp;
321 const optimize_mode = options.comp.root_mod.optimize_mode;321 const use_llvm = comp.config.use_llvm;
322 const target = options.comp.root_mod.resolved_target.result;322 const optimize_mode = comp.root_mod.optimize_mode;
323 const output_mode = options.comp.config.output_mode;323 const target = comp.root_mod.resolved_target.result;
324 const link_mode = options.comp.config.link_mode;324 const output_mode = comp.config.output_mode;
325 const is_native_os = options.comp.root_mod.resolved_target.is_native_os;325 const link_mode = comp.config.link_mode;
326 const is_native_os = comp.root_mod.resolved_target.is_native_os;
326 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {327 const ptr_width: PtrWidth = switch (target.ptrBitWidth()) {
327 0...32 => .p32,328 0...32 => .p32,
328 33...64 => .p64,329 33...64 => .p64,
...@@ -344,7 +345,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -344,7 +345,7 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
344 self.* = .{345 self.* = .{
345 .base = .{346 .base = .{
346 .tag = .elf,347 .tag = .elf,
347 .comp = options.comp,348 .comp = comp,
348 .emit = options.emit,349 .emit = options.emit,
349 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),350 .gc_sections = options.gc_sections orelse (optimize_mode != .Debug and output_mode != .Obj),
350 .stack_size = options.stack_size orelse 16777216,351 .stack_size = options.stack_size orelse 16777216,
...@@ -357,12 +358,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {...@@ -357,12 +358,21 @@ pub fn createEmpty(arena: Allocator, options: link.File.OpenOptions) !*Elf {
357 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },358 .debug_format = options.debug_format orelse .{ .dwarf = .@"32" },
358 .function_sections = options.function_sections,359 .function_sections = options.function_sections,
359 .data_sections = options.data_sections,360 .data_sections = options.data_sections,
361
362 .image_base = b: {
363 if (is_dyn_lib) break :b 0;
364 if (output_mode == .Exe and comp.config.pie) return 0;
365 return options.image_base orelse switch (ptr_width) {
366 .p32 => 0x1000,
367 .p64 => 0x1000000,
368 };
369 },
360 },370 },
361 .ptr_width = ptr_width,371 .ptr_width = ptr_width,
362 .page_size = page_size,372 .page_size = page_size,
363 .default_sym_version = default_sym_version,373 .default_sym_version = default_sym_version,
364 };374 };
365 if (use_llvm and options.comp.config.have_zcu) {375 if (use_llvm and comp.config.have_zcu) {
366 self.llvm_object = try LlvmObject.create(arena, options);376 self.llvm_object = try LlvmObject.create(arena, options);
367 }377 }
368378
...@@ -1653,9 +1663,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {...@@ -1653,9 +1663,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
1653 try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}),1663 try std.fmt.allocPrint(arena, "stack-size={d}", .{self.base.stack_size}),
1654 });1664 });
16551665
1656 if (self.base.options.image_base_override) |image_base| {1666 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
1657 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base}));
1658 }
16591667
1660 if (self.base.gc_sections) {1668 if (self.base.gc_sections) {
1661 try argv.append("--gc-sections");1669 try argv.append("--gc-sections");
...@@ -2378,7 +2386,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -2378,7 +2386,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2378 // We can skip hashing libc and libc++ components that we are in charge of building from Zig2386 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
2379 // installation sources because they are always a product of the compiler version + target information.2387 // installation sources because they are always a product of the compiler version + target information.
2380 man.hash.addOptionalBytes(self.base.options.entry);2388 man.hash.addOptionalBytes(self.base.options.entry);
2381 man.hash.addOptional(self.base.options.image_base_override);2389 man.hash.addOptional(self.image_base);
2382 man.hash.add(self.base.gc_sections);2390 man.hash.add(self.base.gc_sections);
2383 man.hash.addOptional(self.base.options.sort_section);2391 man.hash.addOptional(self.base.options.sort_section);
2384 man.hash.add(self.base.options.eh_frame_hdr);2392 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...@@ -2549,9 +2557,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
2549 }2557 }
2550 }2558 }
25512559
2552 if (self.base.options.image_base_override) |image_base| {2560 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{self.image_base}));
2553 try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base}));
2554 }
25552561
2556 if (self.base.options.linker_script) |linker_script| {2562 if (self.base.options.linker_script) |linker_script| {
2557 try argv.append("-T");2563 try argv.append("-T");
...@@ -3321,7 +3327,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -3321,7 +3327,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
3321 // __ehdr_start3327 // __ehdr_start
3322 {3328 {
3323 const symbol_ptr = self.symbol(self.ehdr_start_index.?);3329 const symbol_ptr = self.symbol(self.ehdr_start_index.?);
3324 symbol_ptr.value = self.calcImageBase();3330 symbol_ptr.value = self.image_base;
3325 symbol_ptr.output_section_index = 1;3331 symbol_ptr.output_section_index = 1;
3326 }3332 }
33273333
...@@ -5631,15 +5637,6 @@ const CsuObjects = struct {...@@ -5631,15 +5637,6 @@ const CsuObjects = struct {
5631 }5637 }
5632};5638};
56335639
5634pub fn calcImageBase(self: Elf) u64 {
5635 if (self.base.isDynLib()) return 0;
5636 if (self.base.isExe() and self.base.options.pie) return 0;
5637 return self.base.options.image_base_override orelse switch (self.ptr_width) {
5638 .p32 => 0x1000,
5639 .p64 => 0x1000000,
5640 };
5641}
5642
5643pub fn isZigSection(self: Elf, shndx: u16) bool {5640pub fn isZigSection(self: Elf, shndx: u16) bool {
5644 inline for (&[_]?u16{5641 inline for (&[_]?u16{
5645 self.zig_text_section_index,5642 self.zig_text_section_index,
src/main.zig+9-10
...@@ -860,7 +860,7 @@ fn buildOutputType(...@@ -860,7 +860,7 @@ fn buildOutputType(
860 var test_no_exec = false;860 var test_no_exec = false;
861 var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};861 var force_undefined_symbols: std.StringArrayHashMapUnmanaged(void) = .{};
862 var stack_size: ?u64 = null;862 var stack_size: ?u64 = null;
863 var image_base_override: ?u64 = null;863 var image_base: ?u64 = null;
864 var link_eh_frame_hdr = false;864 var link_eh_frame_hdr = false;
865 var link_emit_relocs = false;865 var link_emit_relocs = false;
866 var each_lib_rpath: ?bool = null;866 var each_lib_rpath: ?bool = null;
...@@ -1131,10 +1131,7 @@ fn buildOutputType(...@@ -1131,10 +1131,7 @@ fn buildOutputType(
1131 } else if (mem.eql(u8, arg, "--stack")) {1131 } else if (mem.eql(u8, arg, "--stack")) {
1132 stack_size = parseStackSize(args_iter.nextOrFatal());1132 stack_size = parseStackSize(args_iter.nextOrFatal());
1133 } else if (mem.eql(u8, arg, "--image-base")) {1133 } else if (mem.eql(u8, arg, "--image-base")) {
1134 const next_arg = args_iter.nextOrFatal();1134 image_base = parseImageBase(args_iter.nextOrFatal());
1135 image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
1136 fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) });
1137 };
1138 } else if (mem.eql(u8, arg, "--name")) {1135 } else if (mem.eql(u8, arg, "--name")) {
1139 provided_name = args_iter.nextOrFatal();1136 provided_name = args_iter.nextOrFatal();
1140 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?)))1137 if (!mem.eql(u8, provided_name.?, fs.path.basename(provided_name.?)))
...@@ -2283,10 +2280,7 @@ fn buildOutputType(...@@ -2283,10 +2280,7 @@ fn buildOutputType(
2283 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) {2280 } else if (mem.eql(u8, arg, "--stack") or mem.eql(u8, arg, "-stack_size")) {
2284 stack_size = parseStackSize(linker_args_it.nextOrFatal());2281 stack_size = parseStackSize(linker_args_it.nextOrFatal());
2285 } else if (mem.eql(u8, arg, "--image-base")) {2282 } else if (mem.eql(u8, arg, "--image-base")) {
2286 const image_base = linker_args_it.nextOrFatal();2283 image_base = parseImageBase(linker_args_it.nextOrFatal());
2287 image_base_override = std.fmt.parseUnsigned(u64, image_base, 0) catch |err| {
2288 fatal("unable to parse image base override '{s}': {s}", .{ image_base, @errorName(err) });
2289 };
2290 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {2284 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
2291 linker_script = linker_args_it.nextOrFatal();2285 linker_script = linker_args_it.nextOrFatal();
2292 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {2286 } else if (mem.eql(u8, arg, "--eh-frame-hdr")) {
...@@ -3424,7 +3418,7 @@ fn buildOutputType(...@@ -3424,7 +3418,7 @@ fn buildOutputType(
3424 .link_emit_relocs = link_emit_relocs,3418 .link_emit_relocs = link_emit_relocs,
3425 .force_undefined_symbols = force_undefined_symbols,3419 .force_undefined_symbols = force_undefined_symbols,
3426 .stack_size = stack_size,3420 .stack_size = stack_size,
3427 .image_base_override = image_base_override,3421 .image_base = image_base,
3428 .formatted_panics = formatted_panics,3422 .formatted_panics = formatted_panics,
3429 .function_sections = function_sections,3423 .function_sections = function_sections,
3430 .data_sections = data_sections,3424 .data_sections = data_sections,
...@@ -7686,3 +7680,8 @@ fn parseStackSize(s: []const u8) u64 {...@@ -7686,3 +7680,8 @@ fn parseStackSize(s: []const u8) u64 {
7686 return std.fmt.parseUnsigned(u64, s, 0) catch |err|7680 return std.fmt.parseUnsigned(u64, s, 0) catch |err|
7687 fatal("unable to parse stack size '{s}': {s}", .{ s, @errorName(err) });7681 fatal("unable to parse stack size '{s}': {s}", .{ s, @errorName(err) });
7688}7682}
7683
7684fn parseImageBase(s: []const u8) u64 {
7685 return std.fmt.parseUnsigned(u64, s, 0) catch |err|
7686 fatal("unable to parse image base '{s}': {s}", .{ s, @errorName(err) });
7687}