diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-05-01 17:35:52 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-01 17:35:52 -0400 |
| commit | 3386bb896d071eef4ff571fac399e18b2270a382 (patch) | |
| tree | c3e597506a6f5a41269acdd386fd87bd473cdaa9 /src-self-hosted/link.zig | |
| parent | 94b0d0e80242563f4ad7ad41e3c0f5193a60b70c (diff) | |
| parent | ec6ef86219578822fd32bbe2e5eb83b24ddfdca6 (diff) | |
| download | zig-3386bb896d071eef4ff571fac399e18b2270a382.tar.gz zig-3386bb896d071eef4ff571fac399e18b2270a382.zip | |
Merge pull request #5192 from ziglang/stage2-tests
add ZIR compare output test case to test suite
Diffstat (limited to 'src-self-hosted/link.zig')
| -rw-r--r-- | src-self-hosted/link.zig | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index cb6aa40afe..504c374ca7 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -7,11 +7,6 @@ const fs = std.fs; const elf = std.elf; const codegen = @import("codegen.zig"); -/// On common systems with a 0o022 umask, 0o777 will still result in a file created -/// with 0o755 permissions, but it works appropriately if the system is configured -/// more leniently. As another data point, C's fopen seems to open files with the -/// 666 mode. -const executable_mode = 0o777; const default_entry_addr = 0x8000000; pub const ErrorMsg = struct { @@ -35,29 +30,29 @@ pub const Result = struct { /// If incremental linking fails, falls back to truncating the file and rewriting it. /// A malicious file is detected as incremental link failure and does not cause Illegal Behavior. /// This operation is not atomic. -pub fn updateExecutableFilePath( +pub fn updateFilePath( allocator: *Allocator, module: ir.Module, dir: fs.Dir, sub_path: []const u8, ) !Result { - const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = executable_mode }); + const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = determineMode(module) }); defer file.close(); - return updateExecutableFile(allocator, module, file); + return updateFile(allocator, module, file); } /// Atomically overwrites the old file, if present. -pub fn writeExecutableFilePath( +pub fn writeFilePath( allocator: *Allocator, module: ir.Module, dir: fs.Dir, sub_path: []const u8, ) !Result { - const af = try dir.atomicFile(sub_path, .{ .mode = executable_mode }); + const af = try dir.atomicFile(sub_path, .{ .mode = determineMode(module) }); defer af.deinit(); - const result = try writeExecutableFile(allocator, module, af.file); + const result = try writeFile(allocator, module, af.file); try af.finish(); return result; } @@ -67,10 +62,10 @@ pub fn writeExecutableFilePath( /// Returns an error if `file` is not already open with +read +write +seek abilities. /// A malicious file is detected as incremental link failure and does not cause Illegal Behavior. /// This operation is not atomic. -pub fn updateExecutableFile(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { - return updateExecutableFileInner(allocator, module, file) catch |err| switch (err) { +pub fn updateFile(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { + return updateFileInner(allocator, module, file) catch |err| switch (err) { error.IncrFailed => { - return writeExecutableFile(allocator, module, file); + return writeFile(allocator, module, file); }, else => |e| return e, }; @@ -436,7 +431,7 @@ const Update = struct { }, } } - if (self.entry_addr == null) { + if (self.entry_addr == null and self.module.output_mode == .Exe) { const msg = try std.fmt.allocPrint(self.errors.allocator, "no entry point found", .{}); errdefer self.errors.allocator.free(msg); try self.errors.append(.{ @@ -485,7 +480,15 @@ const Update = struct { assert(index == 16); - mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(elf.ET.EXEC), endian); + const elf_type = switch (self.module.output_mode) { + .Exe => elf.ET.EXEC, + .Obj => elf.ET.REL, + .Lib => switch (self.module.link_mode) { + .Static => elf.ET.REL, + .Dynamic => elf.ET.DYN, + }, + }; + mem.writeInt(u16, hdr_buf[index..][0..2], @enumToInt(elf_type), endian); index += 2; const machine = self.module.target.cpu.arch.toElfMachine(); @@ -496,10 +499,11 @@ const Update = struct { mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); index += 4; + const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?; + switch (ptr_width) { .p32 => { - // e_entry - mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, self.entry_addr.?), endian); + mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(u32, e_entry), endian); index += 4; // e_phoff @@ -512,7 +516,7 @@ const Update = struct { }, .p64 => { // e_entry - mem.writeInt(u64, hdr_buf[index..][0..8], self.entry_addr.?, endian); + mem.writeInt(u64, hdr_buf[index..][0..8], e_entry, endian); index += 8; // e_phoff @@ -750,7 +754,20 @@ const Update = struct { /// Truncates the existing file contents and overwrites the contents. /// Returns an error if `file` is not already open with +read +write +seek abilities. -pub fn writeExecutableFile(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { +pub fn writeFile(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { + switch (module.output_mode) { + .Exe => {}, + .Obj => {}, + .Lib => return error.TODOImplementWritingLibFiles, + } + switch (module.object_format) { + .unknown => unreachable, // TODO remove this tag from the enum + .coff => return error.TODOImplementWritingCOFF, + .elf => {}, + .macho => return error.TODOImplementWritingMachO, + .wasm => return error.TODOImplementWritingWasmObjects, + } + var update = Update{ .file = file, .module = &module, @@ -778,7 +795,7 @@ pub fn writeExecutableFile(allocator: *Allocator, module: ir.Module, file: fs.Fi } /// Returns error.IncrFailed if incremental update could not be performed. -fn updateExecutableFileInner(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { +fn updateFileInner(allocator: *Allocator, module: ir.Module, file: fs.File) !Result { //var ehdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; // TODO implement incremental linking @@ -822,3 +839,19 @@ fn sectHeaderTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { .sh_entsize = @intCast(u32, shdr.sh_entsize), }; } + +fn determineMode(module: ir.Module) fs.File.Mode { + // On common systems with a 0o022 umask, 0o777 will still result in a file created + // with 0o755 permissions, but it works appropriately if the system is configured + // more leniently. As another data point, C's fopen seems to open files with the + // 666 mode. + const executable_mode = if (std.Target.current.os.tag == .windows) 0 else 0o777; + switch (module.output_mode) { + .Lib => return switch (module.link_mode) { + .Dynamic => executable_mode, + .Static => fs.File.default_mode, + }, + .Exe => return executable_mode, + .Obj => return fs.File.default_mode, + } +} |
