| author | |
| committer | |
| log | 1d777e99588be047ec4d7650f048b043d6e52da0 |
| tree | c6155fb3f8b3d9f6218942bbce293bab355d2bf8 |
| parent | da596b7e4febc95ec5249c9f489166944fbe69b9 |
Based on #6121 by Jay Petacat.6 files changed, 64 insertions(+), 19 deletions(-)
lib/std/build.zig+8| ... | @@ -1232,6 +1232,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1232,6 +1232,9 @@ pub const LibExeObjStep = struct { |
| 1232 | installed_path: ?[]const u8, | 1232 | installed_path: ?[]const u8, |
| 1233 | install_step: ?*InstallArtifactStep, | 1233 | install_step: ?*InstallArtifactStep, |
| 1234 | 1234 | ||
| 1235 | /// Base address for an executable image. | ||
| 1236 | image_base: ?u64 = null, | ||
| 1237 | |||
| 1235 | libc_file: ?[]const u8 = null, | 1238 | libc_file: ?[]const u8 = null, |
| 1236 | 1239 | ||
| 1237 | valgrind_support: ?bool = null, | 1240 | valgrind_support: ?bool = null, |
| ... | @@ -2041,6 +2044,11 @@ pub const LibExeObjStep = struct { | ... | @@ -2041,6 +2044,11 @@ pub const LibExeObjStep = struct { |
| 2041 | try zig_args.append("--pkg-end"); | 2044 | try zig_args.append("--pkg-end"); |
| 2042 | } | 2045 | } |
| 2043 | 2046 | ||
| 2047 | if (self.image_base) |image_base| { | ||
| 2048 | try zig_args.append("--image-base"); | ||
| 2049 | try zig_args.append(image_base); | ||
| 2050 | } | ||
| 2051 | |||
| 2044 | if (self.filter) |filter| { | 2052 | if (self.filter) |filter| { |
| 2045 | try zig_args.append("--test-filter"); | 2053 | try zig_args.append("--test-filter"); |
| 2046 | try zig_args.append(filter); | 2054 | try zig_args.append(filter); |
src/Compilation.zig+3| ... | @@ -378,6 +378,7 @@ pub const InitOptions = struct { | ... | @@ -378,6 +378,7 @@ pub const InitOptions = struct { |
| 378 | is_compiler_rt_or_libc: bool = false, | 378 | is_compiler_rt_or_libc: bool = false, |
| 379 | parent_compilation_link_libc: bool = false, | 379 | parent_compilation_link_libc: bool = false, |
| 380 | stack_size_override: ?u64 = null, | 380 | stack_size_override: ?u64 = null, |
| 381 | image_base_override: ?u64 = null, | ||
| 381 | self_exe_path: ?[]const u8 = null, | 382 | self_exe_path: ?[]const u8 = null, |
| 382 | version: ?std.builtin.Version = null, | 383 | version: ?std.builtin.Version = null, |
| 383 | libc_installation: ?*const LibCInstallation = null, | 384 | libc_installation: ?*const LibCInstallation = null, |
| ... | @@ -452,6 +453,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -452,6 +453,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 452 | options.link_emit_relocs or | 453 | options.link_emit_relocs or |
| 453 | options.output_mode == .Lib or | 454 | options.output_mode == .Lib or |
| 454 | options.lld_argv.len != 0 or | 455 | options.lld_argv.len != 0 or |
| 456 | options.image_base_override != null or | ||
| 455 | options.linker_script != null or options.version_script != null) | 457 | options.linker_script != null or options.version_script != null) |
| 456 | { | 458 | { |
| 457 | break :blk true; | 459 | break :blk true; |
| ... | @@ -772,6 +774,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -772,6 +774,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 772 | .z_nodelete = options.linker_z_nodelete, | 774 | .z_nodelete = options.linker_z_nodelete, |
| 773 | .z_defs = options.linker_z_defs, | 775 | .z_defs = options.linker_z_defs, |
| 774 | .stack_size_override = options.stack_size_override, | 776 | .stack_size_override = options.stack_size_override, |
| 777 | .image_base_override = options.image_base_override, | ||
| 775 | .linker_script = options.linker_script, | 778 | .linker_script = options.linker_script, |
| 776 | .version_script = options.version_script, | 779 | .version_script = options.version_script, |
| 777 | .gc_sections = options.linker_gc_sections, | 780 | .gc_sections = options.linker_gc_sections, |
src/link.zig+1| ... | @@ -45,6 +45,7 @@ pub const Options = struct { | ... | @@ -45,6 +45,7 @@ pub const Options = struct { |
| 45 | program_code_size_hint: u64 = 256 * 1024, | 45 | program_code_size_hint: u64 = 256 * 1024, |
| 46 | entry_addr: ?u64 = null, | 46 | entry_addr: ?u64 = null, |
| 47 | stack_size_override: ?u64, | 47 | stack_size_override: ?u64, |
| 48 | image_base_override: ?u64, | ||
| 48 | /// Set to `true` to omit debug info. | 49 | /// Set to `true` to omit debug info. |
| 49 | strip: bool, | 50 | strip: bool, |
| 50 | /// If this is true then this link code is responsible for outputting an object | 51 | /// If this is true then this link code is responsible for outputting an object |
src/link/Coff.zig+17-13| ... | @@ -22,10 +22,10 @@ const minimum_text_block_size = 64 * allocation_padding; | ... | @@ -22,10 +22,10 @@ const minimum_text_block_size = 64 * allocation_padding; |
| 22 | 22 | ||
| 23 | const section_alignment = 4096; | 23 | const section_alignment = 4096; |
| 24 | const file_alignment = 512; | 24 | const file_alignment = 512; |
| 25 | const image_base = 0x400_000; | 25 | const default_image_base = 0x400_000; |
| 26 | const section_table_size = 2 * 40; | 26 | const section_table_size = 2 * 40; |
| 27 | comptime { | 27 | comptime { |
| 28 | assert(mem.isAligned(image_base, section_alignment)); | 28 | assert(mem.isAligned(default_image_base, section_alignment)); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | pub const base_tag: link.File.Tag = .coff; | 31 | pub const base_tag: link.File.Tag = .coff; |
| ... | @@ -55,7 +55,7 @@ offset_table: std.ArrayListUnmanaged(u64) = .{}, | ... | @@ -55,7 +55,7 @@ offset_table: std.ArrayListUnmanaged(u64) = .{}, |
| 55 | /// Free list of offset table indices | 55 | /// Free list of offset table indices |
| 56 | offset_table_free_list: std.ArrayListUnmanaged(u32) = .{}, | 56 | offset_table_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 57 | 57 | ||
| 58 | /// Virtual address of the entry point procedure relative to `image_base` | 58 | /// Virtual address of the entry point procedure relative to image base. |
| 59 | entry_addr: ?u32 = null, | 59 | entry_addr: ?u32 = null, |
| 60 | 60 | ||
| 61 | /// Absolute virtual address of the text section when the executable is loaded in memory. | 61 | /// Absolute virtual address of the text section when the executable is loaded in memory. |
| ... | @@ -183,14 +183,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -183,14 +183,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 183 | 183 | ||
| 184 | self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment); | 184 | self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment); |
| 185 | const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment); | 185 | const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment); |
| 186 | self.offset_table_virtual_address = image_base + section_data_relative_virtual_address; | 186 | self.offset_table_virtual_address = default_image_base + section_data_relative_virtual_address; |
| 187 | self.offset_table_size = default_offset_table_size; | 187 | self.offset_table_size = default_offset_table_size; |
| 188 | self.section_table_offset = section_table_offset; | 188 | self.section_table_offset = section_table_offset; |
| 189 | self.text_section_virtual_address = image_base + section_data_relative_virtual_address + section_alignment; | 189 | self.text_section_virtual_address = default_image_base + section_data_relative_virtual_address + section_alignment; |
| 190 | self.text_section_size = default_size_of_code; | 190 | self.text_section_size = default_size_of_code; |
| 191 | 191 | ||
| 192 | // Size of file when loaded in memory | 192 | // Size of file when loaded in memory |
| 193 | const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment); | 193 | const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + default_size_of_code, section_alignment); |
| 194 | 194 | ||
| 195 | mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size); | 195 | mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size); |
| 196 | index += 2; | 196 | index += 2; |
| ... | @@ -234,11 +234,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -234,11 +234,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 234 | index += 4; | 234 | index += 4; |
| 235 | 235 | ||
| 236 | // Image base address | 236 | // Image base address |
| 237 | mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base); | 237 | mem.writeIntLittle(u32, hdr_data[index..][0..4], default_image_base); |
| 238 | index += 4; | 238 | index += 4; |
| 239 | } else { | 239 | } else { |
| 240 | // Image base address | 240 | // Image base address |
| 241 | mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base); | 241 | mem.writeIntLittle(u64, hdr_data[index..][0..8], default_image_base); |
| 242 | index += 8; | 242 | index += 8; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| ... | @@ -328,7 +328,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -328,7 +328,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 328 | mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size); | 328 | mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size); |
| 329 | index += 4; | 329 | index += 4; |
| 330 | // Virtual address (u32) | 330 | // Virtual address (u32) |
| 331 | mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base); | 331 | mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - default_image_base); |
| 332 | index += 4; | 332 | index += 4; |
| 333 | } else { | 333 | } else { |
| 334 | mem.set(u8, hdr_data[index..][0..8], 0); | 334 | mem.set(u8, hdr_data[index..][0..8], 0); |
| ... | @@ -354,7 +354,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -354,7 +354,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 354 | mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code); | 354 | mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code); |
| 355 | index += 4; | 355 | index += 4; |
| 356 | // Virtual address (u32) | 356 | // Virtual address (u32) |
| 357 | mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base); | 357 | mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - default_image_base); |
| 358 | index += 4; | 358 | index += 4; |
| 359 | } else { | 359 | } else { |
| 360 | mem.set(u8, hdr_data[index..][0..8], 0); | 360 | mem.set(u8, hdr_data[index..][0..8], 0); |
| ... | @@ -601,7 +601,7 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void { | ... | @@ -601,7 +601,7 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void { |
| 601 | 601 | ||
| 602 | // Write .text new virtual address | 602 | // Write .text new virtual address |
| 603 | self.text_section_virtual_address = self.text_section_virtual_address + va_offset; | 603 | self.text_section_virtual_address = self.text_section_virtual_address + va_offset; |
| 604 | mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base); | 604 | mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - default_image_base); |
| 605 | try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12); | 605 | try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12); |
| 606 | 606 | ||
| 607 | // Fix the VAs in the offset table | 607 | // Fix the VAs in the offset table |
| ... | @@ -716,7 +716,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, | ... | @@ -716,7 +716,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, |
| 716 | } | 716 | } |
| 717 | } | 717 | } |
| 718 | if (mem.eql(u8, exp.options.name, "_start")) { | 718 | if (mem.eql(u8, exp.options.name, "_start")) { |
| 719 | self.entry_addr = decl.link.coff.getVAddr(self.*) - image_base; | 719 | self.entry_addr = decl.link.coff.getVAddr(self.*) - default_image_base; |
| 720 | } else { | 720 | } else { |
| 721 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | 721 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 722 | module.failed_exports.putAssumeCapacityNoClobber( | 722 | module.failed_exports.putAssumeCapacityNoClobber( |
| ... | @@ -754,7 +754,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { | ... | @@ -754,7 +754,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void { |
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) { | 756 | if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) { |
| 757 | const new_size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment); | 757 | const new_size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + self.text_section_size, section_alignment); |
| 758 | var buf: [4]u8 = undefined; | 758 | var buf: [4]u8 = undefined; |
| 759 | mem.writeIntLittle(u32, &buf, new_size_of_image); | 759 | mem.writeIntLittle(u32, &buf, new_size_of_image); |
| 760 | try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56); | 760 | try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56); |
| ... | @@ -832,6 +832,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -832,6 +832,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 832 | } | 832 | } |
| 833 | try man.addOptionalFile(module_obj_path); | 833 | try man.addOptionalFile(module_obj_path); |
| 834 | man.hash.addOptional(self.base.options.stack_size_override); | 834 | man.hash.addOptional(self.base.options.stack_size_override); |
| 835 | man.hash.addOptional(self.base.options.image_base_override); | ||
| 835 | man.hash.addListOfBytes(self.base.options.extra_lld_args); | 836 | man.hash.addListOfBytes(self.base.options.extra_lld_args); |
| 836 | man.hash.addListOfBytes(self.base.options.lib_dirs); | 837 | man.hash.addListOfBytes(self.base.options.lib_dirs); |
| 837 | man.hash.add(self.base.options.is_compiler_rt_or_libc); | 838 | man.hash.add(self.base.options.is_compiler_rt_or_libc); |
| ... | @@ -914,6 +915,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { | ... | @@ -914,6 +915,9 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { |
| 914 | const stack_size = self.base.options.stack_size_override orelse 16777216; | 915 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| 915 | try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size})); | 916 | try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size})); |
| 916 | } | 917 | } |
| 918 | if (self.base.options.image_base_override) |image_base| { | ||
| 919 | try argv.append(try std.fmt.allocPrint(arena, "-BASE:{d}", .{image_base})); | ||
| 920 | } | ||
| 917 | 921 | ||
| 918 | if (target.cpu.arch == .i386) { | 922 | if (target.cpu.arch == .i386) { |
| 919 | try argv.append("-MACHINE:X86"); | 923 | try argv.append("-MACHINE:X86"); |
src/link/Elf.zig+5| ... | @@ -1284,6 +1284,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1284,6 +1284,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1284 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig | 1284 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig |
| 1285 | // installation sources because they are always a product of the compiler version + target information. | 1285 | // installation sources because they are always a product of the compiler version + target information. |
| 1286 | man.hash.add(stack_size); | 1286 | man.hash.add(stack_size); |
| 1287 | man.hash.addOptional(self.base.options.image_base_override); | ||
| 1287 | man.hash.add(gc_sections); | 1288 | man.hash.add(gc_sections); |
| 1288 | man.hash.add(self.base.options.eh_frame_hdr); | 1289 | man.hash.add(self.base.options.eh_frame_hdr); |
| 1289 | man.hash.add(self.base.options.emit_relocs); | 1290 | man.hash.add(self.base.options.emit_relocs); |
| ... | @@ -1353,6 +1354,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1353,6 +1354,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1353 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={}", .{stack_size})); | 1354 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={}", .{stack_size})); |
| 1354 | } | 1355 | } |
| 1355 | 1356 | ||
| 1357 | if (self.base.options.image_base_override) |image_base| { | ||
| 1358 | try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); | ||
| 1359 | } | ||
| 1360 | |||
| 1356 | if (self.base.options.linker_script) |linker_script| { | 1361 | if (self.base.options.linker_script) |linker_script| { |
| 1357 | try argv.append("-T"); | 1362 | try argv.append("-T"); |
| 1358 | try argv.append(linker_script); | 1363 | try argv.append(linker_script); |
src/main.zig+30-6| ... | @@ -279,6 +279,7 @@ const usage_build_generic = | ... | @@ -279,6 +279,7 @@ const usage_build_generic = |
| 279 | \\ -Bsymbolic Bind global references locally | 279 | \\ -Bsymbolic Bind global references locally |
| 280 | \\ --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n" | 280 | \\ --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n" |
| 281 | \\ --stack [size] Override default stack size | 281 | \\ --stack [size] Override default stack size |
| 282 | \\ --image-base [addr] Set base address for executable image | ||
| 282 | \\ -framework [name] (darwin) link against framework | 283 | \\ -framework [name] (darwin) link against framework |
| 283 | \\ -F[dir] (darwin) add search path for frameworks | 284 | \\ -F[dir] (darwin) add search path for frameworks |
| 284 | \\ | 285 | \\ |
| ... | @@ -435,6 +436,7 @@ fn buildOutputType( | ... | @@ -435,6 +436,7 @@ fn buildOutputType( |
| 435 | var linker_z_defs = false; | 436 | var linker_z_defs = false; |
| 436 | var test_evented_io = false; | 437 | var test_evented_io = false; |
| 437 | var stack_size_override: ?u64 = null; | 438 | var stack_size_override: ?u64 = null; |
| 439 | var image_base_override: ?u64 = null; | ||
| 438 | var use_llvm: ?bool = null; | 440 | var use_llvm: ?bool = null; |
| 439 | var use_lld: ?bool = null; | 441 | var use_lld: ?bool = null; |
| 440 | var use_clang: ?bool = null; | 442 | var use_clang: ?bool = null; |
| ... | @@ -628,9 +630,11 @@ fn buildOutputType( | ... | @@ -628,9 +630,11 @@ fn buildOutputType( |
| 628 | } else if (mem.eql(u8, arg, "--stack")) { | 630 | } else if (mem.eql(u8, arg, "--stack")) { |
| 629 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); | 631 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 630 | i += 1; | 632 | i += 1; |
| 631 | stack_size_override = std.fmt.parseInt(u64, args[i], 10) catch |err| { | 633 | stack_size_override = parseAnyBaseInt(args[i]); |
| 632 | fatal("unable to parse '{}': {}", .{ arg, @errorName(err) }); | 634 | } else if (mem.eql(u8, arg, "--image-base")) { |
| 633 | }; | 635 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 636 | i += 1; | ||
| 637 | image_base_override = parseAnyBaseInt(args[i]); | ||
| 634 | } else if (mem.eql(u8, arg, "--name")) { | 638 | } else if (mem.eql(u8, arg, "--name")) { |
| 635 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); | 639 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 636 | i += 1; | 640 | i += 1; |
| ... | @@ -1147,9 +1151,13 @@ fn buildOutputType( | ... | @@ -1147,9 +1151,13 @@ fn buildOutputType( |
| 1147 | if (i >= linker_args.items.len) { | 1151 | if (i >= linker_args.items.len) { |
| 1148 | fatal("expected linker arg after '{}'", .{arg}); | 1152 | fatal("expected linker arg after '{}'", .{arg}); |
| 1149 | } | 1153 | } |
| 1150 | stack_size_override = std.fmt.parseInt(u64, linker_args.items[i], 10) catch |err| { | 1154 | stack_size_override = parseAnyBaseInt(linker_args.items[i]); |
| 1151 | fatal("unable to parse '{}': {}", .{ arg, @errorName(err) }); | 1155 | } else if (mem.eql(u8, arg, "--image-base")) { |
| 1152 | }; | 1156 | i += 1; |
| 1157 | if (i >= linker_args.items.len) { | ||
| 1158 | fatal("expected linker arg after '{}'", .{arg}); | ||
| 1159 | } | ||
| 1160 | image_base_override = parseAnyBaseInt(linker_args.items[i]); | ||
| 1153 | } else { | 1161 | } else { |
| 1154 | warn("unsupported linker arg: {}", .{arg}); | 1162 | warn("unsupported linker arg: {}", .{arg}); |
| 1155 | } | 1163 | } |
| ... | @@ -1595,6 +1603,7 @@ fn buildOutputType( | ... | @@ -1595,6 +1603,7 @@ fn buildOutputType( |
| 1595 | .link_eh_frame_hdr = link_eh_frame_hdr, | 1603 | .link_eh_frame_hdr = link_eh_frame_hdr, |
| 1596 | .link_emit_relocs = link_emit_relocs, | 1604 | .link_emit_relocs = link_emit_relocs, |
| 1597 | .stack_size_override = stack_size_override, | 1605 | .stack_size_override = stack_size_override, |
| 1606 | .image_base_override = image_base_override, | ||
| 1598 | .strip = strip, | 1607 | .strip = strip, |
| 1599 | .single_threaded = single_threaded, | 1608 | .single_threaded = single_threaded, |
| 1600 | .function_sections = function_sections, | 1609 | .function_sections = function_sections, |
| ... | @@ -3051,3 +3060,18 @@ pub fn cleanExit() void { | ... | @@ -3051,3 +3060,18 @@ pub fn cleanExit() void { |
| 3051 | process.exit(0); | 3060 | process.exit(0); |
| 3052 | } | 3061 | } |
| 3053 | } | 3062 | } |
| 3063 | |||
| 3064 | fn parseAnyBaseInt(prefixed_bytes: []const u8) u64 { | ||
| 3065 | const base: u8 = if (mem.startsWith(u8, prefixed_bytes, "0x")) | ||
| 3066 | 16 | ||
| 3067 | else if (mem.startsWith(u8, prefixed_bytes, "0o")) | ||
| 3068 | 8 | ||
| 3069 | else if (mem.startsWith(u8, prefixed_bytes, "0b")) | ||
| 3070 | 2 | ||
| 3071 | else | ||
| 3072 | @as(u8, 10); | ||
| 3073 | const bytes = if (base == 10) prefixed_bytes else prefixed_bytes[2..]; | ||
| 3074 | return std.fmt.parseInt(u64, bytes, base) catch |err| { | ||
| 3075 | fatal("unable to parse '{}': {}", .{ prefixed_bytes, @errorName(err) }); | ||
| 3076 | }; | ||
| 3077 | } |