authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-22 17:28:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-22 17:28:11-07:00
logabc717f203060f7ab16d36f2afe681d838b46801
treebc15d848e784a0a19e24ec3d6645585550bd0432
parent55ab50efbd5e475442ac9c3b841e461ee331ee2c

modernize the PIE patch for the latest master branch

This is the part of #3960 that has to be rewritten to apply to latest master branch code.

18 files changed, 272 insertions(+), 15 deletions(-)

lib/libc/musl/ldso/dlstart.c created+148
...@@ -0,0 +1,148 @@
1#include <stddef.h>
2#include "dynlink.h"
3#include "libc.h"
4
5#ifndef START
6#define START "_dlstart"
7#endif
8
9#define SHARED
10
11#include "crt_arch.h"
12
13#ifndef GETFUNCSYM
14#define GETFUNCSYM(fp, sym, got) do { \
15 hidden void sym(); \
16 static void (*static_func_ptr)() = sym; \
17 __asm__ __volatile__ ( "" : "+m"(static_func_ptr) : : "memory"); \
18 *(fp) = static_func_ptr; } while(0)
19#endif
20
21hidden void _dlstart_c(size_t *sp, size_t *dynv)
22{
23 size_t i, aux[AUX_CNT], dyn[DYN_CNT];
24 size_t *rel, rel_size, base;
25
26 int argc = *sp;
27 char **argv = (void *)(sp+1);
28
29 for (i=argc+1; argv[i]; i++);
30 size_t *auxv = (void *)(argv+i+1);
31
32 for (i=0; i<AUX_CNT; i++) aux[i] = 0;
33 for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT)
34 aux[auxv[i]] = auxv[i+1];
35
36#if DL_FDPIC
37 struct fdpic_loadseg *segs, fakeseg;
38 size_t j;
39 if (dynv) {
40 /* crt_arch.h entry point asm is responsible for reserving
41 * space and moving the extra fdpic arguments to the stack
42 * vector where they are easily accessible from C. */
43 segs = ((struct fdpic_loadmap *)(sp[-1] ? sp[-1] : sp[-2]))->segs;
44 } else {
45 /* If dynv is null, the entry point was started from loader
46 * that is not fdpic-aware. We can assume normal fixed-
47 * displacement ELF loading was performed, but when ldso was
48 * run as a command, finding the Ehdr is a heursitic: we
49 * have to assume Phdrs start in the first 4k of the file. */
50 base = aux[AT_BASE];
51 if (!base) base = aux[AT_PHDR] & -4096;
52 segs = &fakeseg;
53 segs[0].addr = base;
54 segs[0].p_vaddr = 0;
55 segs[0].p_memsz = -1;
56 Ehdr *eh = (void *)base;
57 Phdr *ph = (void *)(base + eh->e_phoff);
58 size_t phnum = eh->e_phnum;
59 size_t phent = eh->e_phentsize;
60 while (phnum-- && ph->p_type != PT_DYNAMIC)
61 ph = (void *)((size_t)ph + phent);
62 dynv = (void *)(base + ph->p_vaddr);
63 }
64#endif
65
66 for (i=0; i<DYN_CNT; i++) dyn[i] = 0;
67 for (i=0; dynv[i]; i+=2) if (dynv[i]<DYN_CNT)
68 dyn[dynv[i]] = dynv[i+1];
69
70#if DL_FDPIC
71 for (i=0; i<DYN_CNT; i++) {
72 if (i==DT_RELASZ || i==DT_RELSZ) continue;
73 if (!dyn[i]) continue;
74 for (j=0; dyn[i]-segs[j].p_vaddr >= segs[j].p_memsz; j++);
75 dyn[i] += segs[j].addr - segs[j].p_vaddr;
76 }
77 base = 0;
78
79 const Sym *syms = (void *)dyn[DT_SYMTAB];
80
81 rel = (void *)dyn[DT_RELA];
82 rel_size = dyn[DT_RELASZ];
83 for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) {
84 if (!IS_RELATIVE(rel[1], syms)) continue;
85 for (j=0; rel[0]-segs[j].p_vaddr >= segs[j].p_memsz; j++);
86 size_t *rel_addr = (void *)
87 (rel[0] + segs[j].addr - segs[j].p_vaddr);
88 if (R_TYPE(rel[1]) == REL_FUNCDESC_VAL) {
89 *rel_addr += segs[rel_addr[1]].addr
90 - segs[rel_addr[1]].p_vaddr
91 + syms[R_SYM(rel[1])].st_value;
92 rel_addr[1] = dyn[DT_PLTGOT];
93 } else {
94 size_t val = syms[R_SYM(rel[1])].st_value;
95 for (j=0; val-segs[j].p_vaddr >= segs[j].p_memsz; j++);
96 *rel_addr = rel[2] + segs[j].addr - segs[j].p_vaddr + val;
97 }
98 }
99#else
100 /* If the dynamic linker is invoked as a command, its load
101 * address is not available in the aux vector. Instead, compute
102 * the load address as the difference between &_DYNAMIC and the
103 * virtual address in the PT_DYNAMIC program header. */
104 base = aux[AT_BASE];
105 if (!base) {
106 size_t phnum = aux[AT_PHNUM];
107 size_t phentsize = aux[AT_PHENT];
108 Phdr *ph = (void *)aux[AT_PHDR];
109 for (i=phnum; i--; ph = (void *)((char *)ph + phentsize)) {
110 if (ph->p_type == PT_DYNAMIC) {
111 base = (size_t)dynv - ph->p_vaddr;
112 break;
113 }
114 }
115 }
116
117 /* MIPS uses an ugly packed form for GOT relocations. Since we
118 * can't make function calls yet and the code is tiny anyway,
119 * it's simply inlined here. */
120 if (NEED_MIPS_GOT_RELOCS) {
121 size_t local_cnt = 0;
122 size_t *got = (void *)(base + dyn[DT_PLTGOT]);
123 for (i=0; dynv[i]; i+=2) if (dynv[i]==DT_MIPS_LOCAL_GOTNO)
124 local_cnt = dynv[i+1];
125 for (i=0; i<local_cnt; i++) got[i] += base;
126 }
127
128 rel = (void *)(base+dyn[DT_REL]);
129 rel_size = dyn[DT_RELSZ];
130 for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) {
131 if (!IS_RELATIVE(rel[1], 0)) continue;
132 size_t *rel_addr = (void *)(base + rel[0]);
133 *rel_addr += base;
134 }
135
136 rel = (void *)(base+dyn[DT_RELA]);
137 rel_size = dyn[DT_RELASZ];
138 for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) {
139 if (!IS_RELATIVE(rel[1], 0)) continue;
140 size_t *rel_addr = (void *)(base + rel[0]);
141 *rel_addr = base + rel[2];
142 }
143#endif
144
145 stage2_func dls2;
146 GETFUNCSYM(&dls2, __dls2, base+dyn[DT_PLTGOT]);
147 dls2((void *)base, sp);
148}
lib/std/build.zig+11
...@@ -1286,6 +1286,9 @@ pub const LibExeObjStep = struct {...@@ -1286,6 +1286,9 @@ pub const LibExeObjStep = struct {
1286 /// Position Independent Code1286 /// Position Independent Code
1287 force_pic: ?bool = null,1287 force_pic: ?bool = null,
12881288
1289 /// Position Independent Executable
1290 pie: ?bool = null,
1291
1289 subsystem: ?builtin.SubSystem = null,1292 subsystem: ?builtin.SubSystem = null,
12901293
1291 const LinkObject = union(enum) {1294 const LinkObject = union(enum) {
...@@ -2307,6 +2310,14 @@ pub const LibExeObjStep = struct {...@@ -2307,6 +2310,14 @@ pub const LibExeObjStep = struct {
2307 }2310 }
2308 }2311 }
23092312
2313 if (self.pie) |pie| {
2314 if (pie) {
2315 try zig_args.append("-fPIE");
2316 } else {
2317 try zig_args.append("-fno-PIE");
2318 }
2319 }
2320
2310 if (self.subsystem) |subsystem| {2321 if (self.subsystem) |subsystem| {
2311 try zig_args.append("--subsystem");2322 try zig_args.append("--subsystem");
2312 try zig_args.append(switch (subsystem) {2323 try zig_args.append(switch (subsystem) {
lib/std/dynamic_library.zig+1-1
...@@ -63,7 +63,7 @@ const RDebug = extern struct {...@@ -63,7 +63,7 @@ const RDebug = extern struct {
63extern var _DYNAMIC: [128]elf.Dyn;63extern var _DYNAMIC: [128]elf.Dyn;
6464
65comptime {65comptime {
66 if (builtin.os == .linux) {66 if (std.Target.current.os.tag == .linux) {
67 asm (67 asm (
68 \\ .weak _DYNAMIC68 \\ .weak _DYNAMIC
69 \\ .hidden _DYNAMIC69 \\ .hidden _DYNAMIC
lib/std/os/linux/start_pie.zig+6-6
...@@ -111,10 +111,10 @@ pub fn apply_relocations() void {...@@ -111,10 +111,10 @@ pub fn apply_relocations() void {
111 var i: usize = 0;111 var i: usize = 0;
112 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {112 while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) {
113 switch (dynv[i].d_tag) {113 switch (dynv[i].d_tag) {
114 elf.DT_REL => rel_addr = base_addr + dynv[i].d_un.d_ptr,114 elf.DT_REL => rel_addr = base_addr + dynv[i].d_val,
115 elf.DT_RELA => rela_addr = base_addr + dynv[i].d_un.d_ptr,115 elf.DT_RELA => rela_addr = base_addr + dynv[i].d_val,
116 elf.DT_RELSZ => rel_size = dynv[i].d_un.d_val,116 elf.DT_RELSZ => rel_size = dynv[i].d_val,
117 elf.DT_RELASZ => rela_size = dynv[i].d_un.d_val,117 elf.DT_RELASZ => rela_size = dynv[i].d_val,
118 else => {},118 else => {},
119 }119 }
120 }120 }
...@@ -122,14 +122,14 @@ pub fn apply_relocations() void {...@@ -122,14 +122,14 @@ pub fn apply_relocations() void {
122122
123 // Perform the relocations123 // Perform the relocations
124 if (rel_addr != 0) {124 if (rel_addr != 0) {
125 const rel = @bytesToSlice(elf.Rel, @intToPtr([*]u8, rel_addr)[0..rel_size]);125 const rel = std.mem.bytesAsSlice(elf.Rel, @intToPtr([*]u8, rel_addr)[0..rel_size]);
126 for (rel) |r| {126 for (rel) |r| {
127 if (r.r_type() != ARCH_RELATIVE_RELOC) continue;127 if (r.r_type() != ARCH_RELATIVE_RELOC) continue;
128 @intToPtr(*usize, base_addr + r.r_offset).* += base_addr;128 @intToPtr(*usize, base_addr + r.r_offset).* += base_addr;
129 }129 }
130 }130 }
131 if (rela_addr != 0) {131 if (rela_addr != 0) {
132 const rela = @bytesToSlice(elf.Rela, @intToPtr([*]u8, rela_addr)[0..rela_size]);132 const rela = std.mem.bytesAsSlice(elf.Rela, @intToPtr([*]u8, rela_addr)[0..rela_size]);
133 for (rela) |r| {133 for (rela) |r| {
134 if (r.r_type() != ARCH_RELATIVE_RELOC) continue;134 if (r.r_type() != ARCH_RELATIVE_RELOC) continue;
135 @intToPtr(*usize, base_addr + r.r_offset).* += base_addr + @bitCast(usize, r.r_addend);135 @intToPtr(*usize, base_addr + r.r_offset).* += base_addr + @bitCast(usize, r.r_addend);
src/Compilation.zig+29-4
...@@ -343,6 +343,10 @@ pub const InitOptions = struct {...@@ -343,6 +343,10 @@ pub const InitOptions = struct {
343 link_libc: bool = false,343 link_libc: bool = false,
344 link_libcpp: bool = false,344 link_libcpp: bool = false,
345 want_pic: ?bool = null,345 want_pic: ?bool = null,
346 /// This means that if the output mode is an executable it will be a
347 /// Position Independent Executable. If the output mode is not an
348 /// executable this field is ignored.
349 want_pie: ?bool = null,
346 want_sanitize_c: ?bool = null,350 want_sanitize_c: ?bool = null,
347 want_stack_check: ?bool = null,351 want_stack_check: ?bool = null,
348 want_valgrind: ?bool = null,352 want_valgrind: ?bool = null,
...@@ -527,17 +531,30 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -527,17 +531,30 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
527 options.libc_installation,531 options.libc_installation,
528 );532 );
529533
534 const must_pie = target_util.requiresPIE(options.target);
535 const pie = if (options.want_pie) |explicit| pie: {
536 if (!explicit and must_pie) {
537 return error.TargetRequiresPIE;
538 }
539 break :pie explicit;
540 } else must_pie;
541
530 const must_pic: bool = b: {542 const must_pic: bool = b: {
531 if (target_util.requiresPIC(options.target, link_libc))543 if (target_util.requiresPIC(options.target, link_libc))
532 break :b true;544 break :b true;
533 break :b link_mode == .Dynamic;545 break :b link_mode == .Dynamic;
534 };546 };
535 const pic = if (options.want_pic) |explicit| pic: {547 const pic = if (options.want_pic) |explicit| pic: {
536 if (!explicit and must_pic) {548 if (!explicit) {
537 return error.TargetRequiresPIC;549 if (must_pic) {
550 return error.TargetRequiresPIC;
551 }
552 if (pie) {
553 return error.PIERequiresPIC;
554 }
538 }555 }
539 break :pic explicit;556 break :pic explicit;
540 } else must_pic;557 } else pie or must_pic;
541558
542 // Make a decision on whether to use Clang for translate-c and compiling C files.559 // Make a decision on whether to use Clang for translate-c and compiling C files.
543 const use_clang = if (options.use_clang) |explicit| explicit else blk: {560 const use_clang = if (options.use_clang) |explicit| explicit else blk: {
...@@ -618,6 +635,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -618,6 +635,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
618 cache.hash.add(options.target.abi);635 cache.hash.add(options.target.abi);
619 cache.hash.add(ofmt);636 cache.hash.add(ofmt);
620 cache.hash.add(pic);637 cache.hash.add(pic);
638 cache.hash.add(pie);
621 cache.hash.add(stack_check);639 cache.hash.add(stack_check);
622 cache.hash.add(link_mode);640 cache.hash.add(link_mode);
623 cache.hash.add(options.function_sections);641 cache.hash.add(options.function_sections);
...@@ -814,6 +832,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -814,6 +832,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
814 .version = options.version,832 .version = options.version,
815 .libc_installation = libc_dirs.libc_installation,833 .libc_installation = libc_dirs.libc_installation,
816 .pic = pic,834 .pic = pic,
835 .pie = pie,
817 .valgrind = valgrind,836 .valgrind = valgrind,
818 .stack_check = stack_check,837 .stack_check = stack_check,
819 .single_threaded = single_threaded,838 .single_threaded = single_threaded,
...@@ -898,7 +917,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -898,7 +917,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
898 try comp.addBuildingGLibCJobs();917 try comp.addBuildingGLibCJobs();
899 }918 }
900 if (comp.wantBuildMuslFromSource()) {919 if (comp.wantBuildMuslFromSource()) {
901 try comp.work_queue.ensureUnusedCapacity(5);920 try comp.work_queue.ensureUnusedCapacity(6);
902 if (target_util.libc_needs_crti_crtn(comp.getTarget())) {921 if (target_util.libc_needs_crti_crtn(comp.getTarget())) {
903 comp.work_queue.writeAssumeCapacity(&[_]Job{922 comp.work_queue.writeAssumeCapacity(&[_]Job{
904 .{ .musl_crt_file = .crti_o },923 .{ .musl_crt_file = .crti_o },
...@@ -908,6 +927,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -908,6 +927,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
908 comp.work_queue.writeAssumeCapacity(&[_]Job{927 comp.work_queue.writeAssumeCapacity(&[_]Job{
909 .{ .musl_crt_file = .crt1_o },928 .{ .musl_crt_file = .crt1_o },
910 .{ .musl_crt_file = .scrt1_o },929 .{ .musl_crt_file = .scrt1_o },
930 .{ .musl_crt_file = .rcrt1_o },
911 .{ .musl_crt_file = .libc_a },931 .{ .musl_crt_file = .libc_a },
912 });932 });
913 }933 }
...@@ -2473,6 +2493,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2473,6 +2493,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2473 \\pub const have_error_return_tracing = {};2493 \\pub const have_error_return_tracing = {};
2474 \\pub const valgrind_support = {};2494 \\pub const valgrind_support = {};
2475 \\pub const position_independent_code = {};2495 \\pub const position_independent_code = {};
2496 \\pub const position_independent_executable = {};
2476 \\pub const strip_debug_info = {};2497 \\pub const strip_debug_info = {};
2477 \\pub const code_model = CodeModel.{};2498 \\pub const code_model = CodeModel.{};
2478 \\2499 \\
...@@ -2484,6 +2505,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8...@@ -2484,6 +2505,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
2484 comp.bin_file.options.error_return_tracing,2505 comp.bin_file.options.error_return_tracing,
2485 comp.bin_file.options.valgrind,2506 comp.bin_file.options.valgrind,
2486 comp.bin_file.options.pic,2507 comp.bin_file.options.pic,
2508 comp.bin_file.options.pie,
2487 comp.bin_file.options.strip,2509 comp.bin_file.options.strip,
2488 @tagName(comp.bin_file.options.machine_code_model),2510 @tagName(comp.bin_file.options.machine_code_model),
2489 });2511 });
...@@ -2587,6 +2609,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR...@@ -2587,6 +2609,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
2587 .want_stack_check = false,2609 .want_stack_check = false,
2588 .want_valgrind = false,2610 .want_valgrind = false,
2589 .want_pic = comp.bin_file.options.pic,2611 .want_pic = comp.bin_file.options.pic,
2612 .want_pie = comp.bin_file.options.pie,
2590 .emit_h = null,2613 .emit_h = null,
2591 .strip = comp.bin_file.options.strip,2614 .strip = comp.bin_file.options.strip,
2592 .is_native_os = comp.bin_file.options.is_native_os,2615 .is_native_os = comp.bin_file.options.is_native_os,
...@@ -2795,6 +2818,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node...@@ -2795,6 +2818,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
2795 .subsystem = subsystem,2818 .subsystem = subsystem,
2796 .err_color = @enumToInt(comp.color),2819 .err_color = @enumToInt(comp.color),
2797 .pic = comp.bin_file.options.pic,2820 .pic = comp.bin_file.options.pic,
2821 .pie = comp.bin_file.options.pie,
2798 .link_libc = comp.bin_file.options.link_libc,2822 .link_libc = comp.bin_file.options.link_libc,
2799 .link_libcpp = comp.bin_file.options.link_libcpp,2823 .link_libcpp = comp.bin_file.options.link_libcpp,
2800 .strip = comp.bin_file.options.strip,2824 .strip = comp.bin_file.options.strip,
...@@ -2950,6 +2974,7 @@ pub fn build_crt_file(...@@ -2950,6 +2974,7 @@ pub fn build_crt_file(
2950 .want_stack_check = false,2974 .want_stack_check = false,
2951 .want_valgrind = false,2975 .want_valgrind = false,
2952 .want_pic = comp.bin_file.options.pic,2976 .want_pic = comp.bin_file.options.pic,
2977 .want_pie = comp.bin_file.options.pie,
2953 .emit_h = null,2978 .emit_h = null,
2954 .strip = comp.bin_file.options.strip,2979 .strip = comp.bin_file.options.strip,
2955 .is_native_os = comp.bin_file.options.is_native_os,2980 .is_native_os = comp.bin_file.options.is_native_os,
src/clang_options_data.zig+16-2
...@@ -2460,7 +2460,14 @@ sepd1("exported_symbols_list"),...@@ -2460,7 +2460,14 @@ sepd1("exported_symbols_list"),
2460 .pd2 = false,2460 .pd2 = false,
2461 .psl = false,2461 .psl = false,
2462},2462},
2463flagpd1("fPIE"),2463.{
2464 .name = "fPIE",
2465 .syntax = .flag,
2466 .zig_equivalent = .pie,
2467 .pd1 = true,
2468 .pd2 = false,
2469 .psl = false,
2470},
2464flagpd1("fno-access-control"),2471flagpd1("fno-access-control"),
2465flagpd1("faddrsig"),2472flagpd1("faddrsig"),
2466flagpd1("faggressive-function-elimination"),2473flagpd1("faggressive-function-elimination"),
...@@ -2775,7 +2782,14 @@ flagpd1("fnext-runtime"),...@@ -2775,7 +2782,14 @@ flagpd1("fnext-runtime"),
2775 .pd2 = false,2782 .pd2 = false,
2776 .psl = false,2783 .psl = false,
2777},2784},
2778flagpd1("fno-PIE"),2785.{
2786 .name = "fno-PIE",
2787 .syntax = .flag,
2788 .zig_equivalent = .no_pie,
2789 .pd1 = true,
2790 .pd2 = false,
2791 .psl = false,
2792},
2779flagpd1("fno-no-access-control"),2793flagpd1("fno-no-access-control"),
2780flagpd1("fno-addrsig"),2794flagpd1("fno-addrsig"),
2781flagpd1("fno-aggressive-function-elimination"),2795flagpd1("fno-aggressive-function-elimination"),
src/libcxx.zig+2
...@@ -171,6 +171,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -171,6 +171,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
171 .want_stack_check = false,171 .want_stack_check = false,
172 .want_valgrind = false,172 .want_valgrind = false,
173 .want_pic = comp.bin_file.options.pic,173 .want_pic = comp.bin_file.options.pic,
174 .want_pie = comp.bin_file.options.pie,
174 .emit_h = null,175 .emit_h = null,
175 .strip = comp.bin_file.options.strip,176 .strip = comp.bin_file.options.strip,
176 .is_native_os = comp.bin_file.options.is_native_os,177 .is_native_os = comp.bin_file.options.is_native_os,
...@@ -288,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -288,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
288 .want_stack_check = false,289 .want_stack_check = false,
289 .want_valgrind = false,290 .want_valgrind = false,
290 .want_pic = comp.bin_file.options.pic,291 .want_pic = comp.bin_file.options.pic,
292 .want_pie = comp.bin_file.options.pie,
291 .emit_h = null,293 .emit_h = null,
292 .strip = comp.bin_file.options.strip,294 .strip = comp.bin_file.options.strip,
293 .is_native_os = comp.bin_file.options.is_native_os,295 .is_native_os = comp.bin_file.options.is_native_os,
src/libunwind.zig+1
...@@ -104,6 +104,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -104,6 +104,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
104 .want_stack_check = false,104 .want_stack_check = false,
105 .want_valgrind = false,105 .want_valgrind = false,
106 .want_pic = comp.bin_file.options.pic,106 .want_pic = comp.bin_file.options.pic,
107 .want_pie = comp.bin_file.options.pie,
107 .emit_h = null,108 .emit_h = null,
108 .strip = comp.bin_file.options.strip,109 .strip = comp.bin_file.options.strip,
109 .is_native_os = comp.bin_file.options.is_native_os,110 .is_native_os = comp.bin_file.options.is_native_os,
src/link.zig+1
...@@ -71,6 +71,7 @@ pub const Options = struct {...@@ -71,6 +71,7 @@ pub const Options = struct {
71 bind_global_refs_locally: bool,71 bind_global_refs_locally: bool,
72 is_native_os: bool,72 is_native_os: bool,
73 pic: bool,73 pic: bool,
74 pie: bool,
74 valgrind: bool,75 valgrind: bool,
75 stack_check: bool,76 stack_check: bool,
76 single_threaded: bool,77 single_threaded: bool,
src/link/Elf.zig+6-2
...@@ -1425,7 +1425,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1425,7 +1425,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1425 try argv.append("-shared");1425 try argv.append("-shared");
1426 }1426 }
14271427
1428 if (target_util.requiresPIE(target) and self.base.options.output_mode == .Exe) {1428 if (self.base.options.pie and self.base.options.output_mode == .Exe) {
1429 try argv.append("-pie");1429 try argv.append("-pie");
1430 }1430 }
14311431
...@@ -1444,7 +1444,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1444,7 +1444,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1444 break :o "crtbegin_static.o";1444 break :o "crtbegin_static.o";
1445 }1445 }
1446 } else if (self.base.options.link_mode == .Static) {1446 } else if (self.base.options.link_mode == .Static) {
1447 break :o "crt1.o";1447 if (self.base.options.pie) {
1448 break :o "rcrt1.o";
1449 } else {
1450 break :o "crt1.o";
1451 }
1448 } else {1452 } else {
1449 break :o "Scrt1.o";1453 break :o "Scrt1.o";
1450 }1454 }
src/main.zig+12
...@@ -270,6 +270,8 @@ const usage_build_generic =...@@ -270,6 +270,8 @@ const usage_build_generic =
270 \\ --main-pkg-path Set the directory of the root package270 \\ --main-pkg-path Set the directory of the root package
271 \\ -fPIC Force-enable Position Independent Code271 \\ -fPIC Force-enable Position Independent Code
272 \\ -fno-PIC Force-disable Position Independent Code272 \\ -fno-PIC Force-disable Position Independent Code
273 \\ -fPIE Force-enable Position Independent Executable
274 \\ -fno-PIE Force-disable Position Independent Executable
273 \\ -fstack-check Enable stack probing in unsafe builds275 \\ -fstack-check Enable stack probing in unsafe builds
274 \\ -fno-stack-check Disable stack probing in safe builds276 \\ -fno-stack-check Disable stack probing in safe builds
275 \\ -fsanitize-c Enable C undefined behavior detection in unsafe builds277 \\ -fsanitize-c Enable C undefined behavior detection in unsafe builds
...@@ -457,6 +459,7 @@ fn buildOutputType(...@@ -457,6 +459,7 @@ fn buildOutputType(
457 var want_native_include_dirs = false;459 var want_native_include_dirs = false;
458 var enable_cache: ?bool = null;460 var enable_cache: ?bool = null;
459 var want_pic: ?bool = null;461 var want_pic: ?bool = null;
462 var want_pie: ?bool = null;
460 var want_sanitize_c: ?bool = null;463 var want_sanitize_c: ?bool = null;
461 var want_stack_check: ?bool = null;464 var want_stack_check: ?bool = null;
462 var want_valgrind: ?bool = null;465 var want_valgrind: ?bool = null;
...@@ -795,6 +798,10 @@ fn buildOutputType(...@@ -795,6 +798,10 @@ fn buildOutputType(
795 want_pic = true;798 want_pic = true;
796 } else if (mem.eql(u8, arg, "-fno-PIC")) {799 } else if (mem.eql(u8, arg, "-fno-PIC")) {
797 want_pic = false;800 want_pic = false;
801 } else if (mem.eql(u8, arg, "-fPIE")) {
802 want_pie = true;
803 } else if (mem.eql(u8, arg, "-fno-PIE")) {
804 want_pie = false;
798 } else if (mem.eql(u8, arg, "-fstack-check")) {805 } else if (mem.eql(u8, arg, "-fstack-check")) {
799 want_stack_check = true;806 want_stack_check = true;
800 } else if (mem.eql(u8, arg, "-fno-stack-check")) {807 } else if (mem.eql(u8, arg, "-fno-stack-check")) {
...@@ -1006,6 +1013,8 @@ fn buildOutputType(...@@ -1006,6 +1013,8 @@ fn buildOutputType(
1006 },1013 },
1007 .pic => want_pic = true,1014 .pic => want_pic = true,
1008 .no_pic => want_pic = false,1015 .no_pic => want_pic = false,
1016 .pie => want_pie = true,
1017 .no_pie => want_pie = false,
1009 .nostdlib => ensure_libc_on_non_freestanding = false,1018 .nostdlib => ensure_libc_on_non_freestanding = false,
1010 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,1019 .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
1011 .shared => {1020 .shared => {
...@@ -1640,6 +1649,7 @@ fn buildOutputType(...@@ -1640,6 +1649,7 @@ fn buildOutputType(
1640 .link_libc = link_libc,1649 .link_libc = link_libc,
1641 .link_libcpp = link_libcpp,1650 .link_libcpp = link_libcpp,
1642 .want_pic = want_pic,1651 .want_pic = want_pic,
1652 .want_pie = want_pie,
1643 .want_sanitize_c = want_sanitize_c,1653 .want_sanitize_c = want_sanitize_c,
1644 .want_stack_check = want_stack_check,1654 .want_stack_check = want_stack_check,
1645 .want_valgrind = want_valgrind,1655 .want_valgrind = want_valgrind,
...@@ -2773,6 +2783,8 @@ pub const ClangArgIterator = struct {...@@ -2773,6 +2783,8 @@ pub const ClangArgIterator = struct {
2773 driver_punt,2783 driver_punt,
2774 pic,2784 pic,
2775 no_pic,2785 no_pic,
2786 pie,
2787 no_pie,
2776 nostdlib,2788 nostdlib,
2777 nostdlib_cpp,2789 nostdlib_cpp,
2778 shared,2790 shared,
src/musl.zig+18
...@@ -12,6 +12,7 @@ pub const CRTFile = enum {...@@ -12,6 +12,7 @@ pub const CRTFile = enum {
12 crti_o,12 crti_o,
13 crtn_o,13 crtn_o,
14 crt1_o,14 crt1_o,
15 rcrt1_o,
15 scrt1_o,16 scrt1_o,
16 libc_a,17 libc_a,
17};18};
...@@ -68,6 +69,23 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {...@@ -68,6 +69,23 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
68 },69 },
69 });70 });
70 },71 },
72 .rcrt1_o => {
73 var args = std.ArrayList([]const u8).init(arena);
74 try add_cc_args(comp, arena, &args, false);
75 try args.appendSlice(&[_][]const u8{
76 "-fPIC",
77 "-fno-stack-protector",
78 "-DCRT",
79 });
80 return comp.build_crt_file("rcrt1", .Obj, &[1]Compilation.CSourceFile{
81 .{
82 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
83 "libc", "musl", "crt", "rcrt1.c",
84 }),
85 .extra_flags = args.items,
86 },
87 });
88 },
71 .scrt1_o => {89 .scrt1_o => {
72 var args = std.ArrayList([]const u8).init(arena);90 var args = std.ArrayList([]const u8).init(arena);
73 try add_cc_args(comp, arena, &args, false);91 try add_cc_args(comp, arena, &args, false);
src/stage1.zig+1
...@@ -108,6 +108,7 @@ pub const Module = extern struct {...@@ -108,6 +108,7 @@ pub const Module = extern struct {
108 subsystem: TargetSubsystem,108 subsystem: TargetSubsystem,
109 err_color: ErrColor,109 err_color: ErrColor,
110 pic: bool,110 pic: bool,
111 pie: bool,
111 link_libc: bool,112 link_libc: bool,
112 link_libcpp: bool,113 link_libcpp: bool,
113 strip: bool,114 strip: bool,
src/stage1/all_types.hpp+1
...@@ -2177,6 +2177,7 @@ struct CodeGen {...@@ -2177,6 +2177,7 @@ struct CodeGen {
2177 bool is_test_build;2177 bool is_test_build;
2178 bool is_single_threaded;2178 bool is_single_threaded;
2179 bool have_pic;2179 bool have_pic;
2180 bool have_pie;
2180 bool link_mode_dynamic;2181 bool link_mode_dynamic;
2181 bool dll_export_fns;2182 bool dll_export_fns;
2182 bool have_stack_probing;2183 bool have_stack_probing;
src/stage1/codegen.cpp+9
...@@ -9043,6 +9043,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -9043,6 +9043,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
9043 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));9043 buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
9044 buf_appendf(contents, "pub const valgrind_support = false;\n");9044 buf_appendf(contents, "pub const valgrind_support = false;\n");
9045 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));9045 buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
9046 buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
9046 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));9047 buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
9047 buf_appendf(contents, "pub const code_model = CodeModel.default;\n");9048 buf_appendf(contents, "pub const code_model = CodeModel.default;\n");
90489049
...@@ -9170,6 +9171,14 @@ static void init(CodeGen *g) {...@@ -9170,6 +9171,14 @@ static void init(CodeGen *g) {
9170 reloc_mode = LLVMRelocStatic;9171 reloc_mode = LLVMRelocStatic;
9171 }9172 }
91729173
9174 if (g->have_pic) {
9175 ZigLLVMSetModulePICLevel(g->module);
9176 }
9177
9178 if (g->have_pie) {
9179 ZigLLVMSetModulePIELevel(g->module);
9180 }
9181
9173 const char *target_specific_cpu_args = "";9182 const char *target_specific_cpu_args = "";
9174 const char *target_specific_features = "";9183 const char *target_specific_features = "";
91759184
src/stage1/stage1.cpp+1
...@@ -89,6 +89,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {...@@ -89,6 +89,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
89 g->link_mode_dynamic = stage1->link_mode_dynamic;89 g->link_mode_dynamic = stage1->link_mode_dynamic;
90 g->dll_export_fns = stage1->dll_export_fns;90 g->dll_export_fns = stage1->dll_export_fns;
91 g->have_pic = stage1->pic;91 g->have_pic = stage1->pic;
92 g->have_pie = stage1->pie;
92 g->have_stack_probing = stage1->enable_stack_probing;93 g->have_stack_probing = stage1->enable_stack_probing;
93 g->is_single_threaded = stage1->is_single_threaded;94 g->is_single_threaded = stage1->is_single_threaded;
94 g->valgrind_enabled = stage1->valgrind_enabled;95 g->valgrind_enabled = stage1->valgrind_enabled;
src/stage1/stage1.h+1
...@@ -177,6 +177,7 @@ struct ZigStage1 {...@@ -177,6 +177,7 @@ struct ZigStage1 {
177 enum ErrColor err_color;177 enum ErrColor err_color;
178178
179 bool pic;179 bool pic;
180 bool pie;
180 bool link_libc;181 bool link_libc;
181 bool link_libcpp;182 bool link_libcpp;
182 bool strip;183 bool strip;
tools/update_clang_options.zig+8
...@@ -54,6 +54,14 @@ const known_options = [_]KnownOpt{...@@ -54,6 +54,14 @@ const known_options = [_]KnownOpt{
54 .name = "fno-PIC",54 .name = "fno-PIC",
55 .ident = "no_pic",55 .ident = "no_pic",
56 },56 },
57 .{
58 .name = "fPIE",
59 .ident = "pie",
60 },
61 .{
62 .name = "fno-PIE",
63 .ident = "no_pie",
64 },
57 .{65 .{
58 .name = "nolibc",66 .name = "nolibc",
59 .ident = "nostdlib",67 .ident = "nostdlib",