| author | |
| committer | |
| log | 333eec557f8ab89d74e9d66e55eea037ba0433cb |
| tree | 2a9b0b1506c63be44836144322f55a7cad32c663 |
| parent | 4d54e9a4fbb899a18f1d7b9e83bbb65f0973a0cb |
12 files changed, 296 insertions(+), 43 deletions(-)
lib/std/dynamic_library.zig+27-27| ... | @@ -24,7 +24,7 @@ pub const DynLib = switch (builtin.os) { | ... | @@ -24,7 +24,7 @@ pub const DynLib = switch (builtin.os) { |
| 24 | // fashion. | 24 | // fashion. |
| 25 | const LinkMap = extern struct { | 25 | const LinkMap = extern struct { |
| 26 | l_addr: usize, | 26 | l_addr: usize, |
| 27 | l_name: [*]const u8, | 27 | l_name: [*:0]const u8, |
| 28 | l_ld: ?*elf.Dyn, | 28 | l_ld: ?*elf.Dyn, |
| 29 | l_next: ?*LinkMap, | 29 | l_next: ?*LinkMap, |
| 30 | l_prev: ?*LinkMap, | 30 | l_prev: ?*LinkMap, |
| ... | @@ -53,48 +53,48 @@ const RDebug = extern struct { | ... | @@ -53,48 +53,48 @@ const RDebug = extern struct { |
| 53 | r_ldbase: usize, | 53 | r_ldbase: usize, |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | fn elf_get_va_offset(phdrs: []elf.Phdr) !usize { | 56 | // XXX: This should be weak (#1917) |
| 57 | for (phdrs) |*phdr| { | 57 | extern var _DYNAMIC: [128]elf.Dyn; |
| 58 | if (phdr.p_type == elf.PT_LOAD) { | 58 | |
| 59 | return @ptrToInt(phdr) - phdr.p_vaddr; | 59 | comptime { |
| 60 | } | 60 | if (builtin.os == .linux) { |
| 61 | asm ( | ||
| 62 | \\ .weak _DYNAMIC | ||
| 63 | \\ .hidden _DYNAMIC | ||
| 64 | ); | ||
| 61 | } | 65 | } |
| 62 | return error.InvalidExe; | ||
| 63 | } | 66 | } |
| 64 | 67 | ||
| 65 | pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator { | 68 | pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator { |
| 66 | const va_offset = try elf_get_va_offset(phdrs); | 69 | if (@ptrToInt(&_DYNAMIC[0]) == 0) { |
| 67 | |||
| 68 | const dyn_table = init: { | ||
| 69 | for (phdrs) |*phdr| { | ||
| 70 | if (phdr.p_type == elf.PT_DYNAMIC) { | ||
| 71 | const ptr = @intToPtr([*]elf.Dyn, va_offset + phdr.p_vaddr); | ||
| 72 | break :init ptr[0 .. phdr.p_memsz / @sizeOf(elf.Dyn)]; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | // No PT_DYNAMIC means this is either a statically-linked program or a | 70 | // No PT_DYNAMIC means this is either a statically-linked program or a |
| 76 | // badly corrupted one | 71 | // badly corrupted one |
| 77 | return LinkMap.Iterator{ .current = null }; | 72 | return LinkMap.Iterator{ .current = null }; |
| 78 | }; | 73 | } |
| 79 | 74 | ||
| 80 | const link_map_ptr = init: { | 75 | const link_map_ptr = init: { |
| 81 | for (dyn_table) |*dyn| { | 76 | var i: usize = 0; |
| 82 | switch (dyn.d_tag) { | 77 | while (_DYNAMIC[i].d_tag != elf.DT_NULL) : (i += 1) { |
| 78 | switch (_DYNAMIC[i].d_tag) { | ||
| 83 | elf.DT_DEBUG => { | 79 | elf.DT_DEBUG => { |
| 84 | const r_debug = @intToPtr(*RDebug, dyn.d_un.d_ptr); | 80 | const ptr = @intToPtr(?*RDebug, _DYNAMIC[i].d_un.d_ptr); |
| 85 | if (r_debug.r_version != 1) return error.InvalidExe; | 81 | if (ptr) |r_debug| { |
| 86 | break :init r_debug.r_map; | 82 | if (r_debug.r_version != 1) return error.InvalidExe; |
| 83 | break :init r_debug.r_map; | ||
| 84 | } | ||
| 87 | }, | 85 | }, |
| 88 | elf.DT_PLTGOT => { | 86 | elf.DT_PLTGOT => { |
| 89 | const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr); | 87 | const ptr = @intToPtr(?[*]usize, _DYNAMIC[i].d_un.d_ptr); |
| 90 | // The address to the link_map structure is stored in the | 88 | if (ptr) |got_table| { |
| 91 | // second slot | 89 | // The address to the link_map structure is stored in |
| 92 | break :init @intToPtr(?*LinkMap, got_table[1]); | 90 | // the second slot |
| 91 | break :init @intToPtr(?*LinkMap, got_table[1]); | ||
| 92 | } | ||
| 93 | }, | 93 | }, |
| 94 | else => {}, | 94 | else => {}, |
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | return error.InvalidExe; | 97 | return LinkMap.Iterator{ .current = null }; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | return LinkMap.Iterator{ .current = link_map_ptr }; | 100 | return LinkMap.Iterator{ .current = link_map_ptr }; |
lib/std/elf.zig+38| ... | @@ -640,20 +640,48 @@ pub const Elf64_Syminfo = extern struct { | ... | @@ -640,20 +640,48 @@ pub const Elf64_Syminfo = extern struct { |
| 640 | pub const Elf32_Rel = extern struct { | 640 | pub const Elf32_Rel = extern struct { |
| 641 | r_offset: Elf32_Addr, | 641 | r_offset: Elf32_Addr, |
| 642 | r_info: Elf32_Word, | 642 | r_info: Elf32_Word, |
| 643 | |||
| 644 | pub inline fn r_sym(self: @This()) u24 { | ||
| 645 | return @truncate(u24, self.r_info >> 8); | ||
| 646 | } | ||
| 647 | pub inline fn r_type(self: @This()) u8 { | ||
| 648 | return @truncate(u8, self.r_info & 0xff); | ||
| 649 | } | ||
| 643 | }; | 650 | }; |
| 644 | pub const Elf64_Rel = extern struct { | 651 | pub const Elf64_Rel = extern struct { |
| 645 | r_offset: Elf64_Addr, | 652 | r_offset: Elf64_Addr, |
| 646 | r_info: Elf64_Xword, | 653 | r_info: Elf64_Xword, |
| 654 | |||
| 655 | pub inline fn r_sym(self: @This()) u32 { | ||
| 656 | return @truncate(u32, self.r_info >> 32); | ||
| 657 | } | ||
| 658 | pub inline fn r_type(self: @This()) u32 { | ||
| 659 | return @truncate(u32, self.r_info & 0xffffffff); | ||
| 660 | } | ||
| 647 | }; | 661 | }; |
| 648 | pub const Elf32_Rela = extern struct { | 662 | pub const Elf32_Rela = extern struct { |
| 649 | r_offset: Elf32_Addr, | 663 | r_offset: Elf32_Addr, |
| 650 | r_info: Elf32_Word, | 664 | r_info: Elf32_Word, |
| 651 | r_addend: Elf32_Sword, | 665 | r_addend: Elf32_Sword, |
| 666 | |||
| 667 | pub inline fn r_sym(self: @This()) u24 { | ||
| 668 | return @truncate(u24, self.r_info >> 8); | ||
| 669 | } | ||
| 670 | pub inline fn r_type(self: @This()) u8 { | ||
| 671 | return @truncate(u8, self.r_info & 0xff); | ||
| 672 | } | ||
| 652 | }; | 673 | }; |
| 653 | pub const Elf64_Rela = extern struct { | 674 | pub const Elf64_Rela = extern struct { |
| 654 | r_offset: Elf64_Addr, | 675 | r_offset: Elf64_Addr, |
| 655 | r_info: Elf64_Xword, | 676 | r_info: Elf64_Xword, |
| 656 | r_addend: Elf64_Sxword, | 677 | r_addend: Elf64_Sxword, |
| 678 | |||
| 679 | pub inline fn r_sym(self: @This()) u32 { | ||
| 680 | return @truncate(u32, self.r_info >> 32); | ||
| 681 | } | ||
| 682 | pub inline fn r_type(self: @This()) u32 { | ||
| 683 | return @truncate(u32, self.r_info & 0xffffffff); | ||
| 684 | } | ||
| 657 | }; | 685 | }; |
| 658 | pub const Elf32_Phdr = extern struct { | 686 | pub const Elf32_Phdr = extern struct { |
| 659 | p_type: Elf32_Word, | 687 | p_type: Elf32_Word, |
| ... | @@ -853,6 +881,16 @@ pub const Dyn = switch (@sizeOf(usize)) { | ... | @@ -853,6 +881,16 @@ pub const Dyn = switch (@sizeOf(usize)) { |
| 853 | 8 => Elf64_Dyn, | 881 | 8 => Elf64_Dyn, |
| 854 | else => @compileError("expected pointer size of 32 or 64"), | 882 | else => @compileError("expected pointer size of 32 or 64"), |
| 855 | }; | 883 | }; |
| 884 | pub const Rel = switch (@sizeOf(usize)) { | ||
| 885 | 4 => Elf32_Rel, | ||
| 886 | 8 => Elf64_Rel, | ||
| 887 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 888 | }; | ||
| 889 | pub const Rela = switch (@sizeOf(usize)) { | ||
| 890 | 4 => Elf32_Rela, | ||
| 891 | 8 => Elf64_Rela, | ||
| 892 | else => @compileError("expected pointer size of 32 or 64"), | ||
| 893 | }; | ||
| 856 | pub const Shdr = switch (@sizeOf(usize)) { | 894 | pub const Shdr = switch (@sizeOf(usize)) { |
| 857 | 4 => Elf32_Shdr, | 895 | 4 => Elf32_Shdr, |
| 858 | 8 => Elf64_Shdr, | 896 | 8 => Elf64_Shdr, |
lib/std/os/bits/linux.zig+1-1| ... | @@ -996,7 +996,7 @@ pub const dirent64 = extern struct { | ... | @@ -996,7 +996,7 @@ pub const dirent64 = extern struct { |
| 996 | 996 | ||
| 997 | pub const dl_phdr_info = extern struct { | 997 | pub const dl_phdr_info = extern struct { |
| 998 | dlpi_addr: usize, | 998 | dlpi_addr: usize, |
| 999 | dlpi_name: ?[*]const u8, | 999 | dlpi_name: ?[*:0]const u8, |
| 1000 | dlpi_phdr: [*]std.elf.Phdr, | 1000 | dlpi_phdr: [*]std.elf.Phdr, |
| 1001 | dlpi_phnum: u16, | 1001 | dlpi_phnum: u16, |
| 1002 | }; | 1002 | }; |
lib/std/os/linux/start_pie.zig created+138| ... | @@ -0,0 +1,138 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const elf = std.elf; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | |||
| 6 | const R_AMD64_RELATIVE = 8; | ||
| 7 | const R_386_RELATIVE = 8; | ||
| 8 | const R_ARM_RELATIVE = 23; | ||
| 9 | const R_AARCH64_RELATIVE = 1027; | ||
| 10 | const R_RISCV_RELATIVE = 3; | ||
| 11 | |||
| 12 | const ARCH_RELATIVE_RELOC = switch (builtin.arch) { | ||
| 13 | .i386 => R_386_RELATIVE, | ||
| 14 | .x86_64 => R_AMD64_RELATIVE, | ||
| 15 | .arm => R_ARM_RELATIVE, | ||
| 16 | .aarch64 => R_AARCH64_RELATIVE, | ||
| 17 | .riscv64 => R_RISCV_RELATIVE, | ||
| 18 | else => @compileError("unsupported architecture"), | ||
| 19 | }; | ||
| 20 | |||
| 21 | // Just a convoluted (but necessary) way to obtain the address of the _DYNAMIC[] | ||
| 22 | // vector as PC-relative so that we can use it before any relocation is applied | ||
| 23 | fn getDynamicSymbol() [*]elf.Dyn { | ||
| 24 | const addr = switch (builtin.arch) { | ||
| 25 | .i386 => asm volatile ( | ||
| 26 | \\ .weak _DYNAMIC | ||
| 27 | \\ .hidden _DYNAMIC | ||
| 28 | \\ call 1f | ||
| 29 | \\ 1: pop %[ret] | ||
| 30 | \\ lea _DYNAMIC-1b(%[ret]), %[ret] | ||
| 31 | : [ret] "=r" (-> usize) | ||
| 32 | ), | ||
| 33 | .x86_64 => asm volatile ( | ||
| 34 | \\ .weak _DYNAMIC | ||
| 35 | \\ .hidden _DYNAMIC | ||
| 36 | \\ lea _DYNAMIC(%%rip), %[ret] | ||
| 37 | : [ret] "=r" (-> usize) | ||
| 38 | ), | ||
| 39 | // Work around the limited offset range of `ldr` | ||
| 40 | .arm => asm volatile ( | ||
| 41 | \\ .weak _DYNAMIC | ||
| 42 | \\ .hidden _DYNAMIC | ||
| 43 | \\ ldr %[ret], 1f | ||
| 44 | \\ add %[ret], pc | ||
| 45 | \\ b 2f | ||
| 46 | \\ 1: .word _DYNAMIC-1b | ||
| 47 | \\ 2: | ||
| 48 | : [ret] "=r" (-> usize) | ||
| 49 | ), | ||
| 50 | // A simple `adr` is not enough as it has a limited offset range | ||
| 51 | .aarch64 => asm volatile ( | ||
| 52 | \\ .weak _DYNAMIC | ||
| 53 | \\ .hidden _DYNAMIC | ||
| 54 | \\ adrp %[ret], _DYNAMIC | ||
| 55 | \\ add %[ret], %[ret], #:lo12:_DYNAMIC | ||
| 56 | : [ret] "=r" (-> usize) | ||
| 57 | ), | ||
| 58 | .riscv64 => asm volatile ( | ||
| 59 | \\ lla %[ret], _DYNAMIC | ||
| 60 | : [ret] "=r" (-> usize) | ||
| 61 | ), | ||
| 62 | else => @compileError("???"), | ||
| 63 | }; | ||
| 64 | if (addr == 0) unreachable; | ||
| 65 | return @intToPtr([*]elf.Dyn, addr); | ||
| 66 | } | ||
| 67 | |||
| 68 | pub fn apply_relocations() void { | ||
| 69 | @setRuntimeSafety(false); | ||
| 70 | |||
| 71 | const dynv = getDynamicSymbol(); | ||
| 72 | const auxv = std.os.linux.elf_aux_maybe.?; | ||
| 73 | var at_phent: usize = undefined; | ||
| 74 | var at_phnum: usize = undefined; | ||
| 75 | var at_phdr: usize = undefined; | ||
| 76 | var at_hwcap: usize = undefined; | ||
| 77 | |||
| 78 | { | ||
| 79 | var i: usize = 0; | ||
| 80 | while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { | ||
| 81 | switch (auxv[i].a_type) { | ||
| 82 | elf.AT_PHENT => at_phent = auxv[i].a_un.a_val, | ||
| 83 | elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, | ||
| 84 | elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, | ||
| 85 | else => continue, | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | // Sanity check | ||
| 91 | assert(at_phent == @sizeOf(elf.Phdr)); | ||
| 92 | |||
| 93 | // Search the TLS section | ||
| 94 | const phdrs = (@intToPtr([*]elf.Phdr, at_phdr))[0..at_phnum]; | ||
| 95 | |||
| 96 | const base_addr = blk: { | ||
| 97 | for (phdrs) |*phdr| { | ||
| 98 | if (phdr.p_type == elf.PT_DYNAMIC) { | ||
| 99 | break :blk @ptrToInt(&dynv[0]) - phdr.p_vaddr; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | unreachable; | ||
| 103 | }; | ||
| 104 | |||
| 105 | var rel_addr: usize = 0; | ||
| 106 | var rela_addr: usize = 0; | ||
| 107 | var rel_size: usize = 0; | ||
| 108 | var rela_size: usize = 0; | ||
| 109 | |||
| 110 | { | ||
| 111 | var i: usize = 0; | ||
| 112 | while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) { | ||
| 113 | switch (dynv[i].d_tag) { | ||
| 114 | elf.DT_REL => rel_addr = base_addr + dynv[i].d_un.d_ptr, | ||
| 115 | elf.DT_RELA => rela_addr = base_addr + dynv[i].d_un.d_ptr, | ||
| 116 | elf.DT_RELSZ => rel_size = dynv[i].d_un.d_val, | ||
| 117 | elf.DT_RELASZ => rela_size = dynv[i].d_un.d_val, | ||
| 118 | else => {}, | ||
| 119 | } | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | // Perform the relocations | ||
| 124 | if (rel_addr != 0) { | ||
| 125 | const rel = @bytesToSlice(elf.Rel, @intToPtr([*]u8, rel_addr)[0..rel_size]); | ||
| 126 | for (rel) |r| { | ||
| 127 | if (r.r_type() != ARCH_RELATIVE_RELOC) continue; | ||
| 128 | @intToPtr(*usize, base_addr + r.r_offset).* += base_addr; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | if (rela_addr != 0) { | ||
| 132 | const rela = @bytesToSlice(elf.Rela, @intToPtr([*]u8, rela_addr)[0..rela_size]); | ||
| 133 | for (rela) |r| { | ||
| 134 | if (r.r_type() != ARCH_RELATIVE_RELOC) continue; | ||
| 135 | @intToPtr(*usize, base_addr + r.r_offset).* += base_addr + @bitCast(usize, r.r_addend); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
lib/std/os/test.zig+2| ... | @@ -205,6 +205,8 @@ export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 { | ... | @@ -205,6 +205,8 @@ export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 { |
| 205 | test "dl_iterate_phdr" { | 205 | test "dl_iterate_phdr" { |
| 206 | if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx) | 206 | if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx) |
| 207 | return error.SkipZigTest; | 207 | return error.SkipZigTest; |
| 208 | if (builtin.position_independent_executable) | ||
| 209 | return error.SkipZigTest; | ||
| 208 | 210 | ||
| 209 | var counter: usize = 0; | 211 | var counter: usize = 0; |
| 210 | expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0); | 212 | expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0); |
lib/std/start.zig+6| ... | @@ -155,6 +155,12 @@ fn posixCallMainAndExit() noreturn { | ... | @@ -155,6 +155,12 @@ fn posixCallMainAndExit() noreturn { |
| 155 | // Find the beginning of the auxiliary vector | 155 | // Find the beginning of the auxiliary vector |
| 156 | const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); | 156 | const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); |
| 157 | std.os.linux.elf_aux_maybe = auxv; | 157 | std.os.linux.elf_aux_maybe = auxv; |
| 158 | |||
| 159 | // Do this as early as possible, the aux vector is needed | ||
| 160 | if (builtin.position_independent_executable) { | ||
| 161 | @import("os/linux/start_pie.zig").apply_relocations(); | ||
| 162 | } | ||
| 163 | |||
| 158 | // Initialize the TLS area | 164 | // Initialize the TLS area |
| 159 | const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size"); | 165 | const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size"); |
| 160 | 166 |
src/all_types.hpp+8| ... | @@ -1922,6 +1922,12 @@ enum WantPIC { | ... | @@ -1922,6 +1922,12 @@ enum WantPIC { |
| 1922 | WantPICEnabled, | 1922 | WantPICEnabled, |
| 1923 | }; | 1923 | }; |
| 1924 | 1924 | ||
| 1925 | enum WantPIE { | ||
| 1926 | WantPIEAuto, | ||
| 1927 | WantPIEDisabled, | ||
| 1928 | WantPIEEnabled, | ||
| 1929 | }; | ||
| 1930 | |||
| 1925 | enum WantStackCheck { | 1931 | enum WantStackCheck { |
| 1926 | WantStackCheckAuto, | 1932 | WantStackCheckAuto, |
| 1927 | WantStackCheckDisabled, | 1933 | WantStackCheckDisabled, |
| ... | @@ -2101,6 +2107,7 @@ struct CodeGen { | ... | @@ -2101,6 +2107,7 @@ struct CodeGen { |
| 2101 | Stage2ProgressNode *sub_progress_node; | 2107 | Stage2ProgressNode *sub_progress_node; |
| 2102 | 2108 | ||
| 2103 | WantPIC want_pic; | 2109 | WantPIC want_pic; |
| 2110 | WantPIE want_pie; | ||
| 2104 | WantStackCheck want_stack_check; | 2111 | WantStackCheck want_stack_check; |
| 2105 | WantCSanitize want_sanitize_c; | 2112 | WantCSanitize want_sanitize_c; |
| 2106 | CacheHash cache_hash; | 2113 | CacheHash cache_hash; |
| ... | @@ -2175,6 +2182,7 @@ struct CodeGen { | ... | @@ -2175,6 +2182,7 @@ struct CodeGen { |
| 2175 | bool disable_gen_h; | 2182 | bool disable_gen_h; |
| 2176 | bool bundle_compiler_rt; | 2183 | bool bundle_compiler_rt; |
| 2177 | bool have_pic; | 2184 | bool have_pic; |
| 2185 | bool have_pie; | ||
| 2178 | bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic | 2186 | bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic |
| 2179 | bool have_stack_probing; | 2187 | bool have_stack_probing; |
| 2180 | bool have_sanitize_c; | 2188 | bool have_sanitize_c; |
src/codegen.cpp+45-10| ... | @@ -8233,18 +8233,39 @@ static bool detect_dynamic_link(CodeGen *g) { | ... | @@ -8233,18 +8233,39 @@ static bool detect_dynamic_link(CodeGen *g) { |
| 8233 | return false; | 8233 | return false; |
| 8234 | } | 8234 | } |
| 8235 | 8235 | ||
| 8236 | static bool detect_pic(CodeGen *g) { | 8236 | static void detect_pic_pie(CodeGen *g) { |
| 8237 | if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr)) | 8237 | const bool requires_pic = target_requires_pic(g->zig_target, g->libc_link_lib != nullptr); |
| 8238 | return true; | 8238 | const bool requires_pie = target_requires_pie(g->zig_target); |
| 8239 | |||
| 8240 | bool have_pic = false; | ||
| 8241 | bool have_pie = false; | ||
| 8242 | |||
| 8243 | switch (g->want_pie) { | ||
| 8244 | case WantPIEDisabled: | ||
| 8245 | have_pie = false; | ||
| 8246 | break; | ||
| 8247 | case WantPIEEnabled: | ||
| 8248 | have_pie = true; | ||
| 8249 | break; | ||
| 8250 | case WantPIEAuto: | ||
| 8251 | have_pie = requires_pie; | ||
| 8252 | break; | ||
| 8253 | } | ||
| 8254 | |||
| 8239 | switch (g->want_pic) { | 8255 | switch (g->want_pic) { |
| 8240 | case WantPICDisabled: | 8256 | case WantPICDisabled: |
| 8241 | return false; | 8257 | have_pic = false; |
| 8258 | break; | ||
| 8242 | case WantPICEnabled: | 8259 | case WantPICEnabled: |
| 8243 | return true; | 8260 | have_pic = true; |
| 8261 | break; | ||
| 8244 | case WantPICAuto: | 8262 | case WantPICAuto: |
| 8245 | return g->have_dynamic_link; | 8263 | have_pic = have_pie || g->have_dynamic_link || requires_pic; |
| 8264 | break; | ||
| 8246 | } | 8265 | } |
| 8247 | zig_unreachable(); | 8266 | |
| 8267 | g->have_pic = have_pic; | ||
| 8268 | g->have_pie = have_pie; | ||
| 8248 | } | 8269 | } |
| 8249 | 8270 | ||
| 8250 | static bool detect_stack_probing(CodeGen *g) { | 8271 | static bool detect_stack_probing(CodeGen *g) { |
| ... | @@ -8309,7 +8330,7 @@ static bool detect_err_ret_tracing(CodeGen *g) { | ... | @@ -8309,7 +8330,7 @@ static bool detect_err_ret_tracing(CodeGen *g) { |
| 8309 | 8330 | ||
| 8310 | Buf *codegen_generate_builtin_source(CodeGen *g) { | 8331 | Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8311 | g->have_dynamic_link = detect_dynamic_link(g); | 8332 | g->have_dynamic_link = detect_dynamic_link(g); |
| 8312 | g->have_pic = detect_pic(g); | 8333 | detect_pic_pie(g); |
| 8313 | g->have_stack_probing = detect_stack_probing(g); | 8334 | g->have_stack_probing = detect_stack_probing(g); |
| 8314 | g->have_sanitize_c = detect_sanitize_c(g); | 8335 | g->have_sanitize_c = detect_sanitize_c(g); |
| 8315 | g->is_single_threaded = detect_single_threaded(g); | 8336 | g->is_single_threaded = detect_single_threaded(g); |
| ... | @@ -8465,6 +8486,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -8465,6 +8486,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8465 | buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); | 8486 | buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); |
| 8466 | buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g))); | 8487 | buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g))); |
| 8467 | buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); | 8488 | buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); |
| 8489 | buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie)); | ||
| 8468 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); | 8490 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); |
| 8469 | 8491 | ||
| 8470 | { | 8492 | { |
| ... | @@ -8526,6 +8548,8 @@ static Error define_builtin_compile_vars(CodeGen *g) { | ... | @@ -8526,6 +8548,8 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8526 | cache_bool(&cache_hash, g->libc_link_lib != nullptr); | 8548 | cache_bool(&cache_hash, g->libc_link_lib != nullptr); |
| 8527 | cache_bool(&cache_hash, g->valgrind_support); | 8549 | cache_bool(&cache_hash, g->valgrind_support); |
| 8528 | cache_int(&cache_hash, detect_subsystem(g)); | 8550 | cache_int(&cache_hash, detect_subsystem(g)); |
| 8551 | cache_bool(&cache_hash, g->have_pic); | ||
| 8552 | cache_bool(&cache_hash, g->have_pie); | ||
| 8529 | 8553 | ||
| 8530 | Buf digest = BUF_INIT; | 8554 | Buf digest = BUF_INIT; |
| 8531 | buf_resize(&digest, 0); | 8555 | buf_resize(&digest, 0); |
| ... | @@ -8595,7 +8619,7 @@ static void init(CodeGen *g) { | ... | @@ -8595,7 +8619,7 @@ static void init(CodeGen *g) { |
| 8595 | return; | 8619 | return; |
| 8596 | 8620 | ||
| 8597 | g->have_dynamic_link = detect_dynamic_link(g); | 8621 | g->have_dynamic_link = detect_dynamic_link(g); |
| 8598 | g->have_pic = detect_pic(g); | 8622 | detect_pic_pie(g); |
| 8599 | g->have_stack_probing = detect_stack_probing(g); | 8623 | g->have_stack_probing = detect_stack_probing(g); |
| 8600 | g->have_sanitize_c = detect_sanitize_c(g); | 8624 | g->have_sanitize_c = detect_sanitize_c(g); |
| 8601 | g->is_single_threaded = detect_single_threaded(g); | 8625 | g->is_single_threaded = detect_single_threaded(g); |
| ... | @@ -8640,6 +8664,14 @@ static void init(CodeGen *g) { | ... | @@ -8640,6 +8664,14 @@ static void init(CodeGen *g) { |
| 8640 | reloc_mode = LLVMRelocStatic; | 8664 | reloc_mode = LLVMRelocStatic; |
| 8641 | } | 8665 | } |
| 8642 | 8666 | ||
| 8667 | if (g->have_pic) { | ||
| 8668 | ZigLLVMSetModulePICLevel(g->module); | ||
| 8669 | } | ||
| 8670 | |||
| 8671 | if (g->have_pie) { | ||
| 8672 | ZigLLVMSetModulePIELevel(g->module); | ||
| 8673 | } | ||
| 8674 | |||
| 8643 | const char *target_specific_cpu_args; | 8675 | const char *target_specific_cpu_args; |
| 8644 | const char *target_specific_features; | 8676 | const char *target_specific_features; |
| 8645 | if (g->zig_target->is_native) { | 8677 | if (g->zig_target->is_native) { |
| ... | @@ -9327,6 +9359,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose | ... | @@ -9327,6 +9359,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose |
| 9327 | cache_bool(cache_hash, g->strip_debug_symbols); | 9359 | cache_bool(cache_hash, g->strip_debug_symbols); |
| 9328 | cache_int(cache_hash, g->build_mode); | 9360 | cache_int(cache_hash, g->build_mode); |
| 9329 | cache_bool(cache_hash, g->have_pic); | 9361 | cache_bool(cache_hash, g->have_pic); |
| 9362 | cache_bool(cache_hash, g->have_pie); | ||
| 9330 | cache_bool(cache_hash, g->have_sanitize_c); | 9363 | cache_bool(cache_hash, g->have_sanitize_c); |
| 9331 | cache_bool(cache_hash, want_valgrind_support(g)); | 9364 | cache_bool(cache_hash, want_valgrind_support(g)); |
| 9332 | cache_bool(cache_hash, g->function_sections); | 9365 | cache_bool(cache_hash, g->function_sections); |
| ... | @@ -10104,6 +10137,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { | ... | @@ -10104,6 +10137,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 10104 | cache_bool(ch, g->bundle_compiler_rt); | 10137 | cache_bool(ch, g->bundle_compiler_rt); |
| 10105 | cache_bool(ch, want_valgrind_support(g)); | 10138 | cache_bool(ch, want_valgrind_support(g)); |
| 10106 | cache_bool(ch, g->have_pic); | 10139 | cache_bool(ch, g->have_pic); |
| 10140 | cache_bool(ch, g->have_pie); | ||
| 10107 | cache_bool(ch, g->have_dynamic_link); | 10141 | cache_bool(ch, g->have_dynamic_link); |
| 10108 | cache_bool(ch, g->have_stack_probing); | 10142 | cache_bool(ch, g->have_stack_probing); |
| 10109 | cache_bool(ch, g->have_sanitize_c); | 10143 | cache_bool(ch, g->have_sanitize_c); |
| ... | @@ -10224,7 +10258,7 @@ void codegen_build_and_link(CodeGen *g) { | ... | @@ -10224,7 +10258,7 @@ void codegen_build_and_link(CodeGen *g) { |
| 10224 | } | 10258 | } |
| 10225 | 10259 | ||
| 10226 | g->have_dynamic_link = detect_dynamic_link(g); | 10260 | g->have_dynamic_link = detect_dynamic_link(g); |
| 10227 | g->have_pic = detect_pic(g); | 10261 | detect_pic_pie(g); |
| 10228 | g->is_single_threaded = detect_single_threaded(g); | 10262 | g->is_single_threaded = detect_single_threaded(g); |
| 10229 | g->have_err_ret_tracing = detect_err_ret_tracing(g); | 10263 | g->have_err_ret_tracing = detect_err_ret_tracing(g); |
| 10230 | g->have_sanitize_c = detect_sanitize_c(g); | 10264 | g->have_sanitize_c = detect_sanitize_c(g); |
| ... | @@ -10429,6 +10463,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o | ... | @@ -10429,6 +10463,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o |
| 10429 | 10463 | ||
| 10430 | codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); | 10464 | codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); |
| 10431 | child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled; | 10465 | child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled; |
| 10466 | child_gen->want_pie = parent_gen->have_pie ? WantPIEEnabled : WantPIEDisabled; | ||
| 10432 | child_gen->valgrind_support = ValgrindSupportDisabled; | 10467 | child_gen->valgrind_support = ValgrindSupportDisabled; |
| 10433 | 10468 | ||
| 10434 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); | 10469 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); |
src/link.cpp+14-5| ... | @@ -1469,6 +1469,14 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr | ... | @@ -1469,6 +1469,14 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1469 | c_file->args.append("-fno-stack-protector"); | 1469 | c_file->args.append("-fno-stack-protector"); |
| 1470 | c_file->args.append("-DCRT"); | 1470 | c_file->args.append("-DCRT"); |
| 1471 | return build_libc_object(parent, "crt1", c_file, progress_node); | 1471 | return build_libc_object(parent, "crt1", c_file, progress_node); |
| 1472 | } else if (strcmp(file, "rcrt1.o") == 0) { | ||
| 1473 | CFile *c_file = allocate<CFile>(1); | ||
| 1474 | c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "rcrt1.c"); | ||
| 1475 | musl_add_cc_args(parent, c_file, false); | ||
| 1476 | c_file->args.append("-fno-stack-protector"); | ||
| 1477 | c_file->args.append("-DCRT"); | ||
| 1478 | c_file->args.append("-fPIC"); | ||
| 1479 | return build_libc_object(parent, "rcrt1", c_file, progress_node); | ||
| 1472 | } else if (strcmp(file, "Scrt1.o") == 0) { | 1480 | } else if (strcmp(file, "Scrt1.o") == 0) { |
| 1473 | CFile *c_file = allocate<CFile>(1); | 1481 | CFile *c_file = allocate<CFile>(1); |
| 1474 | c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c"); | 1482 | c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c"); |
| ... | @@ -1661,6 +1669,11 @@ static void construct_linker_job_elf(LinkJob *lj) { | ... | @@ -1661,6 +1669,11 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1661 | } else { | 1669 | } else { |
| 1662 | lj->args.append("-static"); | 1670 | lj->args.append("-static"); |
| 1663 | } | 1671 | } |
| 1672 | |||
| 1673 | if (g->out_type == OutTypeExe && g->have_pie) { | ||
| 1674 | lj->args.append("-pie"); | ||
| 1675 | lj->args.append("--no-dynamic-linker"); | ||
| 1676 | } | ||
| 1664 | } else if (is_dyn_lib) { | 1677 | } else if (is_dyn_lib) { |
| 1665 | lj->args.append("-shared"); | 1678 | lj->args.append("-shared"); |
| 1666 | 1679 | ||
| ... | @@ -1668,10 +1681,6 @@ static void construct_linker_job_elf(LinkJob *lj) { | ... | @@ -1668,10 +1681,6 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1668 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); | 1681 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); |
| 1669 | } | 1682 | } |
| 1670 | 1683 | ||
| 1671 | if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) { | ||
| 1672 | lj->args.append("-pie"); | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | lj->args.append("-o"); | 1684 | lj->args.append("-o"); |
| 1676 | lj->args.append(buf_ptr(&g->output_file_path)); | 1685 | lj->args.append(buf_ptr(&g->output_file_path)); |
| 1677 | 1686 | ||
| ... | @@ -1686,7 +1695,7 @@ static void construct_linker_job_elf(LinkJob *lj) { | ... | @@ -1686,7 +1695,7 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1686 | crt1o = "crtbegin_static.o"; | 1695 | crt1o = "crtbegin_static.o"; |
| 1687 | } | 1696 | } |
| 1688 | } else if (!g->have_dynamic_link) { | 1697 | } else if (!g->have_dynamic_link) { |
| 1689 | crt1o = "crt1.o"; | 1698 | crt1o = g->have_pie ? "rcrt1.o" : "crt1.o"; |
| 1690 | } else { | 1699 | } else { |
| 1691 | crt1o = "Scrt1.o"; | 1700 | crt1o = "Scrt1.o"; |
| 1692 | } | 1701 | } |
src/main.cpp+7| ... | @@ -525,6 +525,7 @@ int main(int argc, char **argv) { | ... | @@ -525,6 +525,7 @@ int main(int argc, char **argv) { |
| 525 | Buf *main_pkg_path = nullptr; | 525 | Buf *main_pkg_path = nullptr; |
| 526 | ValgrindSupport valgrind_support = ValgrindSupportAuto; | 526 | ValgrindSupport valgrind_support = ValgrindSupportAuto; |
| 527 | WantPIC want_pic = WantPICAuto; | 527 | WantPIC want_pic = WantPICAuto; |
| 528 | WantPIE want_pie = WantPIEAuto; | ||
| 528 | WantStackCheck want_stack_check = WantStackCheckAuto; | 529 | WantStackCheck want_stack_check = WantStackCheckAuto; |
| 529 | WantCSanitize want_sanitize_c = WantCSanitizeAuto; | 530 | WantCSanitize want_sanitize_c = WantCSanitizeAuto; |
| 530 | bool function_sections = false; | 531 | bool function_sections = false; |
| ... | @@ -721,6 +722,10 @@ int main(int argc, char **argv) { | ... | @@ -721,6 +722,10 @@ int main(int argc, char **argv) { |
| 721 | want_pic = WantPICEnabled; | 722 | want_pic = WantPICEnabled; |
| 722 | } else if (strcmp(arg, "-fno-PIC") == 0) { | 723 | } else if (strcmp(arg, "-fno-PIC") == 0) { |
| 723 | want_pic = WantPICDisabled; | 724 | want_pic = WantPICDisabled; |
| 725 | } else if (strcmp(arg, "-fPIE") == 0) { | ||
| 726 | want_pie = WantPIEEnabled; | ||
| 727 | } else if (strcmp(arg, "-fno-PIE") == 0) { | ||
| 728 | want_pie = WantPIEDisabled; | ||
| 724 | } else if (strcmp(arg, "-fstack-check") == 0) { | 729 | } else if (strcmp(arg, "-fstack-check") == 0) { |
| 725 | want_stack_check = WantStackCheckEnabled; | 730 | want_stack_check = WantStackCheckEnabled; |
| 726 | } else if (strcmp(arg, "-fno-stack-check") == 0) { | 731 | } else if (strcmp(arg, "-fno-stack-check") == 0) { |
| ... | @@ -1099,6 +1104,7 @@ int main(int argc, char **argv) { | ... | @@ -1099,6 +1104,7 @@ int main(int argc, char **argv) { |
| 1099 | g->subsystem = subsystem; | 1104 | g->subsystem = subsystem; |
| 1100 | g->valgrind_support = valgrind_support; | 1105 | g->valgrind_support = valgrind_support; |
| 1101 | g->want_pic = want_pic; | 1106 | g->want_pic = want_pic; |
| 1107 | g->want_pie = want_pie; | ||
| 1102 | g->want_stack_check = want_stack_check; | 1108 | g->want_stack_check = want_stack_check; |
| 1103 | g->want_sanitize_c = want_sanitize_c; | 1109 | g->want_sanitize_c = want_sanitize_c; |
| 1104 | g->want_single_threaded = want_single_threaded; | 1110 | g->want_single_threaded = want_single_threaded; |
| ... | @@ -1199,6 +1205,7 @@ int main(int argc, char **argv) { | ... | @@ -1199,6 +1205,7 @@ int main(int argc, char **argv) { |
| 1199 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); | 1205 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); |
| 1200 | g->valgrind_support = valgrind_support; | 1206 | g->valgrind_support = valgrind_support; |
| 1201 | g->want_pic = want_pic; | 1207 | g->want_pic = want_pic; |
| 1208 | g->want_pie = want_pie; | ||
| 1202 | g->want_stack_check = want_stack_check; | 1209 | g->want_stack_check = want_stack_check; |
| 1203 | g->want_sanitize_c = want_sanitize_c; | 1210 | g->want_sanitize_c = want_sanitize_c; |
| 1204 | g->subsystem = subsystem; | 1211 | g->subsystem = subsystem; |
src/zig_llvm.cpp+8| ... | @@ -877,6 +877,14 @@ void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { | ... | @@ -877,6 +877,14 @@ void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { |
| 877 | unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1); | 877 | unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1); |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | void ZigLLVMSetModulePICLevel(LLVMModuleRef module) { | ||
| 881 | unwrap(module)->setPICLevel(PICLevel::Level::BigPIC); | ||
| 882 | } | ||
| 883 | |||
| 884 | void ZigLLVMSetModulePIELevel(LLVMModuleRef module) { | ||
| 885 | unwrap(module)->setPIELevel(PIELevel::Level::Large); | ||
| 886 | } | ||
| 887 | |||
| 880 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { | 888 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { |
| 881 | switch (Ordering) { | 889 | switch (Ordering) { |
| 882 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; | 890 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; |
src/zig_llvm.h+2| ... | @@ -158,6 +158,8 @@ ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef modul | ... | @@ -158,6 +158,8 @@ ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef modul |
| 158 | ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder); | 158 | ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder); |
| 159 | ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); | 159 | ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); |
| 160 | ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); | 160 | ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); |
| 161 | ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module); | ||
| 162 | ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module); | ||
| 161 | 163 | ||
| 162 | ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, | 164 | ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, |
| 163 | struct ZigLLVMDIScope *scope); | 165 | struct ZigLLVMDIScope *scope); |