| author | |
| committer | |
| log | c7170e4a5480581db5f30913eebd9ad4f7cd121e |
| tree | fba79b8f4241c94f886e7708d18081e8fc0e31fe |
| parent | 98d5bfbd4d21e99363a0a68ef5a0d0104c302ecb |
| parent | abc717f203060f7ab16d36f2afe681d838b46801 |
Closes #4503
Revives #3960
Merges branch 'pie' into master23 files changed, 485 insertions(+), 34 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 | ||
| 21 | hidden 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 | 1286 | /// Position Independent Code |
| 1287 | 1287 | force_pic: ?bool = null, |
| 1288 | 1288 | |
| 1289 | /// Position Independent Executable | |
| 1290 | pie: ?bool = null, | |
| 1291 | ||
| 1289 | 1292 | subsystem: ?builtin.SubSystem = null, |
| 1290 | 1293 | |
| 1291 | 1294 | const LinkObject = union(enum) { |
| ... | ... | @@ -2307,6 +2310,14 @@ pub const LibExeObjStep = struct { |
| 2307 | 2310 | } |
| 2308 | 2311 | } |
| 2309 | 2312 | |
| 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 | 2321 | if (self.subsystem) |subsystem| { |
| 2311 | 2322 | try zig_args.append("--subsystem"); |
| 2312 | 2323 | try zig_args.append(switch (subsystem) { |
lib/std/dynamic_library.zig+26-26| ... | ... | @@ -59,48 +59,48 @@ const RDebug = extern struct { |
| 59 | 59 | r_ldbase: usize, |
| 60 | 60 | }; |
| 61 | 61 | |
| 62 | fn elf_get_va_offset(phdrs: []elf.Phdr) !usize { | |
| 63 | for (phdrs) |*phdr| { | |
| 64 | if (phdr.p_type == elf.PT_LOAD) { | |
| 65 | return @ptrToInt(phdr) - phdr.p_vaddr; | |
| 66 | } | |
| 62 | // TODO: This should be weak (#1917) | |
| 63 | extern var _DYNAMIC: [128]elf.Dyn; | |
| 64 | ||
| 65 | comptime { | |
| 66 | if (std.Target.current.os.tag == .linux) { | |
| 67 | asm ( | |
| 68 | \\ .weak _DYNAMIC | |
| 69 | \\ .hidden _DYNAMIC | |
| 70 | ); | |
| 67 | 71 | } |
| 68 | return error.InvalidExe; | |
| 69 | 72 | } |
| 70 | 73 | |
| 71 | 74 | pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator { |
| 72 | const va_offset = try elf_get_va_offset(phdrs); | |
| 73 | ||
| 74 | const dyn_table = init: { | |
| 75 | for (phdrs) |*phdr| { | |
| 76 | if (phdr.p_type == elf.PT_DYNAMIC) { | |
| 77 | const ptr = @intToPtr([*]elf.Dyn, va_offset + phdr.p_vaddr); | |
| 78 | break :init ptr[0 .. phdr.p_memsz / @sizeOf(elf.Dyn)]; | |
| 79 | } | |
| 80 | } | |
| 75 | if (@ptrToInt(&_DYNAMIC[0]) == 0) { | |
| 81 | 76 | // No PT_DYNAMIC means this is either a statically-linked program or a |
| 82 | 77 | // badly corrupted one |
| 83 | 78 | return LinkMap.Iterator{ .current = null }; |
| 84 | }; | |
| 79 | } | |
| 85 | 80 | |
| 86 | 81 | const link_map_ptr = init: { |
| 87 | for (dyn_table) |*dyn| { | |
| 88 | switch (dyn.d_tag) { | |
| 82 | var i: usize = 0; | |
| 83 | while (_DYNAMIC[i].d_tag != elf.DT_NULL) : (i += 1) { | |
| 84 | switch (_DYNAMIC[i].d_tag) { | |
| 89 | 85 | elf.DT_DEBUG => { |
| 90 | const r_debug = @intToPtr(*RDebug, dyn.d_val); | |
| 91 | if (r_debug.r_version != 1) return error.InvalidExe; | |
| 92 | break :init r_debug.r_map; | |
| 86 | const ptr = @intToPtr(?*RDebug, _DYNAMIC[i].d_val); | |
| 87 | if (ptr) |r_debug| { | |
| 88 | if (r_debug.r_version != 1) return error.InvalidExe; | |
| 89 | break :init r_debug.r_map; | |
| 90 | } | |
| 93 | 91 | }, |
| 94 | 92 | elf.DT_PLTGOT => { |
| 95 | const got_table = @intToPtr([*]usize, dyn.d_val); | |
| 96 | // The address to the link_map structure is stored in the | |
| 97 | // second slot | |
| 98 | break :init @intToPtr(?*LinkMap, got_table[1]); | |
| 93 | const ptr = @intToPtr(?[*]usize, _DYNAMIC[i].d_val); | |
| 94 | if (ptr) |got_table| { | |
| 95 | // The address to the link_map structure is stored in | |
| 96 | // the second slot | |
| 97 | break :init @intToPtr(?*LinkMap, got_table[1]); | |
| 98 | } | |
| 99 | 99 | }, |
| 100 | 100 | else => {}, |
| 101 | 101 | } |
| 102 | 102 | } |
| 103 | return error.InvalidExe; | |
| 103 | return LinkMap.Iterator{ .current = null }; | |
| 104 | 104 | }; |
| 105 | 105 | |
| 106 | 106 | return LinkMap.Iterator{ .current = link_map_ptr }; |
lib/std/elf.zig+38| ... | ... | @@ -719,20 +719,48 @@ pub const Elf64_Syminfo = extern struct { |
| 719 | 719 | pub const Elf32_Rel = extern struct { |
| 720 | 720 | r_offset: Elf32_Addr, |
| 721 | 721 | r_info: Elf32_Word, |
| 722 | ||
| 723 | pub inline fn r_sym(self: @This()) u24 { | |
| 724 | return @truncate(u24, self.r_info >> 8); | |
| 725 | } | |
| 726 | pub inline fn r_type(self: @This()) u8 { | |
| 727 | return @truncate(u8, self.r_info & 0xff); | |
| 728 | } | |
| 722 | 729 | }; |
| 723 | 730 | pub const Elf64_Rel = extern struct { |
| 724 | 731 | r_offset: Elf64_Addr, |
| 725 | 732 | r_info: Elf64_Xword, |
| 733 | ||
| 734 | pub inline fn r_sym(self: @This()) u32 { | |
| 735 | return @truncate(u32, self.r_info >> 32); | |
| 736 | } | |
| 737 | pub inline fn r_type(self: @This()) u32 { | |
| 738 | return @truncate(u32, self.r_info & 0xffffffff); | |
| 739 | } | |
| 726 | 740 | }; |
| 727 | 741 | pub const Elf32_Rela = extern struct { |
| 728 | 742 | r_offset: Elf32_Addr, |
| 729 | 743 | r_info: Elf32_Word, |
| 730 | 744 | r_addend: Elf32_Sword, |
| 745 | ||
| 746 | pub inline fn r_sym(self: @This()) u24 { | |
| 747 | return @truncate(u24, self.r_info >> 8); | |
| 748 | } | |
| 749 | pub inline fn r_type(self: @This()) u8 { | |
| 750 | return @truncate(u8, self.r_info & 0xff); | |
| 751 | } | |
| 731 | 752 | }; |
| 732 | 753 | pub const Elf64_Rela = extern struct { |
| 733 | 754 | r_offset: Elf64_Addr, |
| 734 | 755 | r_info: Elf64_Xword, |
| 735 | 756 | r_addend: Elf64_Sxword, |
| 757 | ||
| 758 | pub inline fn r_sym(self: @This()) u32 { | |
| 759 | return @truncate(u32, self.r_info >> 32); | |
| 760 | } | |
| 761 | pub inline fn r_type(self: @This()) u32 { | |
| 762 | return @truncate(u32, self.r_info & 0xffffffff); | |
| 763 | } | |
| 736 | 764 | }; |
| 737 | 765 | pub const Elf32_Dyn = extern struct { |
| 738 | 766 | d_tag: Elf32_Sword, |
| ... | ... | @@ -917,6 +945,16 @@ pub const Dyn = switch (@sizeOf(usize)) { |
| 917 | 945 | 8 => Elf64_Dyn, |
| 918 | 946 | else => @compileError("expected pointer size of 32 or 64"), |
| 919 | 947 | }; |
| 948 | pub const Rel = switch (@sizeOf(usize)) { | |
| 949 | 4 => Elf32_Rel, | |
| 950 | 8 => Elf64_Rel, | |
| 951 | else => @compileError("expected pointer size of 32 or 64"), | |
| 952 | }; | |
| 953 | pub const Rela = switch (@sizeOf(usize)) { | |
| 954 | 4 => Elf32_Rela, | |
| 955 | 8 => Elf64_Rela, | |
| 956 | else => @compileError("expected pointer size of 32 or 64"), | |
| 957 | }; | |
| 920 | 958 | pub const Shdr = switch (@sizeOf(usize)) { |
| 921 | 959 | 4 => Elf32_Shdr, |
| 922 | 960 | 8 => Elf64_Shdr, |
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_val, | |
| 115 | elf.DT_RELA => rela_addr = base_addr + dynv[i].d_val, | |
| 116 | elf.DT_RELSZ => rel_size = dynv[i].d_val, | |
| 117 | elf.DT_RELASZ => rela_size = dynv[i].d_val, | |
| 118 | else => {}, | |
| 119 | } | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | // Perform the relocations | |
| 124 | if (rel_addr != 0) { | |
| 125 | const rel = std.mem.bytesAsSlice(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 = std.mem.bytesAsSlice(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| ... | ... | @@ -386,6 +386,8 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void { |
| 386 | 386 | test "dl_iterate_phdr" { |
| 387 | 387 | if (builtin.os.tag == .windows or builtin.os.tag == .wasi or builtin.os.tag == .macos) |
| 388 | 388 | return error.SkipZigTest; |
| 389 | if (builtin.position_independent_executable) | |
| 390 | return error.SkipZigTest; | |
| 389 | 391 | |
| 390 | 392 | var counter: usize = 0; |
| 391 | 393 | try os.dl_iterate_phdr(&counter, IterFnError, iter_fn); |
lib/std/start.zig+6| ... | ... | @@ -202,6 +202,12 @@ fn posixCallMainAndExit() noreturn { |
| 202 | 202 | // Find the beginning of the auxiliary vector |
| 203 | 203 | const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1)); |
| 204 | 204 | std.os.linux.elf_aux_maybe = auxv; |
| 205 | ||
| 206 | // Do this as early as possible, the aux vector is needed | |
| 207 | if (builtin.position_independent_executable) { | |
| 208 | @import("os/linux/start_pie.zig").apply_relocations(); | |
| 209 | } | |
| 210 | ||
| 205 | 211 | // Initialize the TLS area |
| 206 | 212 | std.os.linux.tls.initStaticTLS(); |
| 207 | 213 |
src/Compilation.zig+29-4| ... | ... | @@ -343,6 +343,10 @@ pub const InitOptions = struct { |
| 343 | 343 | link_libc: bool = false, |
| 344 | 344 | link_libcpp: bool = false, |
| 345 | 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 | 350 | want_sanitize_c: ?bool = null, |
| 347 | 351 | want_stack_check: ?bool = null, |
| 348 | 352 | want_valgrind: ?bool = null, |
| ... | ... | @@ -527,17 +531,30 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 527 | 531 | options.libc_installation, |
| 528 | 532 | ); |
| 529 | 533 | |
| 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 | 542 | const must_pic: bool = b: { |
| 531 | 543 | if (target_util.requiresPIC(options.target, link_libc)) |
| 532 | 544 | break :b true; |
| 533 | 545 | break :b link_mode == .Dynamic; |
| 534 | 546 | }; |
| 535 | 547 | const pic = if (options.want_pic) |explicit| pic: { |
| 536 | if (!explicit and must_pic) { | |
| 537 | return error.TargetRequiresPIC; | |
| 548 | if (!explicit) { | |
| 549 | if (must_pic) { | |
| 550 | return error.TargetRequiresPIC; | |
| 551 | } | |
| 552 | if (pie) { | |
| 553 | return error.PIERequiresPIC; | |
| 554 | } | |
| 538 | 555 | } |
| 539 | 556 | break :pic explicit; |
| 540 | } else must_pic; | |
| 557 | } else pie or must_pic; | |
| 541 | 558 | |
| 542 | 559 | // Make a decision on whether to use Clang for translate-c and compiling C files. |
| 543 | 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 | 635 | cache.hash.add(options.target.abi); |
| 619 | 636 | cache.hash.add(ofmt); |
| 620 | 637 | cache.hash.add(pic); |
| 638 | cache.hash.add(pie); | |
| 621 | 639 | cache.hash.add(stack_check); |
| 622 | 640 | cache.hash.add(link_mode); |
| 623 | 641 | cache.hash.add(options.function_sections); |
| ... | ... | @@ -814,6 +832,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 814 | 832 | .version = options.version, |
| 815 | 833 | .libc_installation = libc_dirs.libc_installation, |
| 816 | 834 | .pic = pic, |
| 835 | .pie = pie, | |
| 817 | 836 | .valgrind = valgrind, |
| 818 | 837 | .stack_check = stack_check, |
| 819 | 838 | .single_threaded = single_threaded, |
| ... | ... | @@ -898,7 +917,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 898 | 917 | try comp.addBuildingGLibCJobs(); |
| 899 | 918 | } |
| 900 | 919 | if (comp.wantBuildMuslFromSource()) { |
| 901 | try comp.work_queue.ensureUnusedCapacity(5); | |
| 920 | try comp.work_queue.ensureUnusedCapacity(6); | |
| 902 | 921 | if (target_util.libc_needs_crti_crtn(comp.getTarget())) { |
| 903 | 922 | comp.work_queue.writeAssumeCapacity(&[_]Job{ |
| 904 | 923 | .{ .musl_crt_file = .crti_o }, |
| ... | ... | @@ -908,6 +927,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 908 | 927 | comp.work_queue.writeAssumeCapacity(&[_]Job{ |
| 909 | 928 | .{ .musl_crt_file = .crt1_o }, |
| 910 | 929 | .{ .musl_crt_file = .scrt1_o }, |
| 930 | .{ .musl_crt_file = .rcrt1_o }, | |
| 911 | 931 | .{ .musl_crt_file = .libc_a }, |
| 912 | 932 | }); |
| 913 | 933 | } |
| ... | ... | @@ -2473,6 +2493,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2473 | 2493 | \\pub const have_error_return_tracing = {}; |
| 2474 | 2494 | \\pub const valgrind_support = {}; |
| 2475 | 2495 | \\pub const position_independent_code = {}; |
| 2496 | \\pub const position_independent_executable = {}; | |
| 2476 | 2497 | \\pub const strip_debug_info = {}; |
| 2477 | 2498 | \\pub const code_model = CodeModel.{}; |
| 2478 | 2499 | \\ |
| ... | ... | @@ -2484,6 +2505,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2484 | 2505 | comp.bin_file.options.error_return_tracing, |
| 2485 | 2506 | comp.bin_file.options.valgrind, |
| 2486 | 2507 | comp.bin_file.options.pic, |
| 2508 | comp.bin_file.options.pie, | |
| 2487 | 2509 | comp.bin_file.options.strip, |
| 2488 | 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 | 2609 | .want_stack_check = false, |
| 2588 | 2610 | .want_valgrind = false, |
| 2589 | 2611 | .want_pic = comp.bin_file.options.pic, |
| 2612 | .want_pie = comp.bin_file.options.pie, | |
| 2590 | 2613 | .emit_h = null, |
| 2591 | 2614 | .strip = comp.bin_file.options.strip, |
| 2592 | 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 | 2818 | .subsystem = subsystem, |
| 2796 | 2819 | .err_color = @enumToInt(comp.color), |
| 2797 | 2820 | .pic = comp.bin_file.options.pic, |
| 2821 | .pie = comp.bin_file.options.pie, | |
| 2798 | 2822 | .link_libc = comp.bin_file.options.link_libc, |
| 2799 | 2823 | .link_libcpp = comp.bin_file.options.link_libcpp, |
| 2800 | 2824 | .strip = comp.bin_file.options.strip, |
| ... | ... | @@ -2950,6 +2974,7 @@ pub fn build_crt_file( |
| 2950 | 2974 | .want_stack_check = false, |
| 2951 | 2975 | .want_valgrind = false, |
| 2952 | 2976 | .want_pic = comp.bin_file.options.pic, |
| 2977 | .want_pie = comp.bin_file.options.pie, | |
| 2953 | 2978 | .emit_h = null, |
| 2954 | 2979 | .strip = comp.bin_file.options.strip, |
| 2955 | 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 | 2460 | .pd2 = false, |
| 2461 | 2461 | .psl = false, |
| 2462 | 2462 | }, |
| 2463 | flagpd1("fPIE"), | |
| 2463 | .{ | |
| 2464 | .name = "fPIE", | |
| 2465 | .syntax = .flag, | |
| 2466 | .zig_equivalent = .pie, | |
| 2467 | .pd1 = true, | |
| 2468 | .pd2 = false, | |
| 2469 | .psl = false, | |
| 2470 | }, | |
| 2464 | 2471 | flagpd1("fno-access-control"), |
| 2465 | 2472 | flagpd1("faddrsig"), |
| 2466 | 2473 | flagpd1("faggressive-function-elimination"), |
| ... | ... | @@ -2775,7 +2782,14 @@ flagpd1("fnext-runtime"), |
| 2775 | 2782 | .pd2 = false, |
| 2776 | 2783 | .psl = false, |
| 2777 | 2784 | }, |
| 2778 | flagpd1("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 | }, | |
| 2779 | 2793 | flagpd1("fno-no-access-control"), |
| 2780 | 2794 | flagpd1("fno-addrsig"), |
| 2781 | 2795 | flagpd1("fno-aggressive-function-elimination"), |
src/libcxx.zig+2| ... | ... | @@ -171,6 +171,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 171 | 171 | .want_stack_check = false, |
| 172 | 172 | .want_valgrind = false, |
| 173 | 173 | .want_pic = comp.bin_file.options.pic, |
| 174 | .want_pie = comp.bin_file.options.pie, | |
| 174 | 175 | .emit_h = null, |
| 175 | 176 | .strip = comp.bin_file.options.strip, |
| 176 | 177 | .is_native_os = comp.bin_file.options.is_native_os, |
| ... | ... | @@ -288,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 288 | 289 | .want_stack_check = false, |
| 289 | 290 | .want_valgrind = false, |
| 290 | 291 | .want_pic = comp.bin_file.options.pic, |
| 292 | .want_pie = comp.bin_file.options.pie, | |
| 291 | 293 | .emit_h = null, |
| 292 | 294 | .strip = comp.bin_file.options.strip, |
| 293 | 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 | 104 | .want_stack_check = false, |
| 105 | 105 | .want_valgrind = false, |
| 106 | 106 | .want_pic = comp.bin_file.options.pic, |
| 107 | .want_pie = comp.bin_file.options.pie, | |
| 107 | 108 | .emit_h = null, |
| 108 | 109 | .strip = comp.bin_file.options.strip, |
| 109 | 110 | .is_native_os = comp.bin_file.options.is_native_os, |
src/link.zig+1| ... | ... | @@ -71,6 +71,7 @@ pub const Options = struct { |
| 71 | 71 | bind_global_refs_locally: bool, |
| 72 | 72 | is_native_os: bool, |
| 73 | 73 | pic: bool, |
| 74 | pie: bool, | |
| 74 | 75 | valgrind: bool, |
| 75 | 76 | stack_check: bool, |
| 76 | 77 | single_threaded: bool, |
src/link/Elf.zig+6-2| ... | ... | @@ -1425,7 +1425,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1425 | 1425 | try argv.append("-shared"); |
| 1426 | 1426 | } |
| 1427 | 1427 | |
| 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 | 1429 | try argv.append("-pie"); |
| 1430 | 1430 | } |
| 1431 | 1431 | |
| ... | ... | @@ -1444,7 +1444,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1444 | 1444 | break :o "crtbegin_static.o"; |
| 1445 | 1445 | } |
| 1446 | 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 | 1452 | } else { |
| 1449 | 1453 | break :o "Scrt1.o"; |
| 1450 | 1454 | } |
src/main.zig+12| ... | ... | @@ -270,6 +270,8 @@ const usage_build_generic = |
| 270 | 270 | \\ --main-pkg-path Set the directory of the root package |
| 271 | 271 | \\ -fPIC Force-enable Position Independent Code |
| 272 | 272 | \\ -fno-PIC Force-disable Position Independent Code |
| 273 | \\ -fPIE Force-enable Position Independent Executable | |
| 274 | \\ -fno-PIE Force-disable Position Independent Executable | |
| 273 | 275 | \\ -fstack-check Enable stack probing in unsafe builds |
| 274 | 276 | \\ -fno-stack-check Disable stack probing in safe builds |
| 275 | 277 | \\ -fsanitize-c Enable C undefined behavior detection in unsafe builds |
| ... | ... | @@ -457,6 +459,7 @@ fn buildOutputType( |
| 457 | 459 | var want_native_include_dirs = false; |
| 458 | 460 | var enable_cache: ?bool = null; |
| 459 | 461 | var want_pic: ?bool = null; |
| 462 | var want_pie: ?bool = null; | |
| 460 | 463 | var want_sanitize_c: ?bool = null; |
| 461 | 464 | var want_stack_check: ?bool = null; |
| 462 | 465 | var want_valgrind: ?bool = null; |
| ... | ... | @@ -795,6 +798,10 @@ fn buildOutputType( |
| 795 | 798 | want_pic = true; |
| 796 | 799 | } else if (mem.eql(u8, arg, "-fno-PIC")) { |
| 797 | 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 | 805 | } else if (mem.eql(u8, arg, "-fstack-check")) { |
| 799 | 806 | want_stack_check = true; |
| 800 | 807 | } else if (mem.eql(u8, arg, "-fno-stack-check")) { |
| ... | ... | @@ -1006,6 +1013,8 @@ fn buildOutputType( |
| 1006 | 1013 | }, |
| 1007 | 1014 | .pic => want_pic = true, |
| 1008 | 1015 | .no_pic => want_pic = false, |
| 1016 | .pie => want_pie = true, | |
| 1017 | .no_pie => want_pie = false, | |
| 1009 | 1018 | .nostdlib => ensure_libc_on_non_freestanding = false, |
| 1010 | 1019 | .nostdlib_cpp => ensure_libcpp_on_non_freestanding = false, |
| 1011 | 1020 | .shared => { |
| ... | ... | @@ -1640,6 +1649,7 @@ fn buildOutputType( |
| 1640 | 1649 | .link_libc = link_libc, |
| 1641 | 1650 | .link_libcpp = link_libcpp, |
| 1642 | 1651 | .want_pic = want_pic, |
| 1652 | .want_pie = want_pie, | |
| 1643 | 1653 | .want_sanitize_c = want_sanitize_c, |
| 1644 | 1654 | .want_stack_check = want_stack_check, |
| 1645 | 1655 | .want_valgrind = want_valgrind, |
| ... | ... | @@ -2773,6 +2783,8 @@ pub const ClangArgIterator = struct { |
| 2773 | 2783 | driver_punt, |
| 2774 | 2784 | pic, |
| 2775 | 2785 | no_pic, |
| 2786 | pie, | |
| 2787 | no_pie, | |
| 2776 | 2788 | nostdlib, |
| 2777 | 2789 | nostdlib_cpp, |
| 2778 | 2790 | shared, |
src/musl.zig+18| ... | ... | @@ -12,6 +12,7 @@ pub const CRTFile = enum { |
| 12 | 12 | crti_o, |
| 13 | 13 | crtn_o, |
| 14 | 14 | crt1_o, |
| 15 | rcrt1_o, | |
| 15 | 16 | scrt1_o, |
| 16 | 17 | libc_a, |
| 17 | 18 | }; |
| ... | ... | @@ -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 | 89 | .scrt1_o => { |
| 72 | 90 | var args = std.ArrayList([]const u8).init(arena); |
| 73 | 91 | try add_cc_args(comp, arena, &args, false); |
src/stage1.zig+1| ... | ... | @@ -108,6 +108,7 @@ pub const Module = extern struct { |
| 108 | 108 | subsystem: TargetSubsystem, |
| 109 | 109 | err_color: ErrColor, |
| 110 | 110 | pic: bool, |
| 111 | pie: bool, | |
| 111 | 112 | link_libc: bool, |
| 112 | 113 | link_libcpp: bool, |
| 113 | 114 | strip: bool, |
src/stage1/all_types.hpp+1| ... | ... | @@ -2177,6 +2177,7 @@ struct CodeGen { |
| 2177 | 2177 | bool is_test_build; |
| 2178 | 2178 | bool is_single_threaded; |
| 2179 | 2179 | bool have_pic; |
| 2180 | bool have_pie; | |
| 2180 | 2181 | bool link_mode_dynamic; |
| 2181 | 2182 | bool dll_export_fns; |
| 2182 | 2183 | bool have_stack_probing; |
src/stage1/codegen.cpp+9| ... | ... | @@ -9043,6 +9043,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 9043 | 9043 | buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); |
| 9044 | 9044 | buf_appendf(contents, "pub const valgrind_support = false;\n"); |
| 9045 | 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 | 9047 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); |
| 9047 | 9048 | buf_appendf(contents, "pub const code_model = CodeModel.default;\n"); |
| 9048 | 9049 | |
| ... | ... | @@ -9170,6 +9171,14 @@ static void init(CodeGen *g) { |
| 9170 | 9171 | reloc_mode = LLVMRelocStatic; |
| 9171 | 9172 | } |
| 9172 | 9173 | |
| 9174 | if (g->have_pic) { | |
| 9175 | ZigLLVMSetModulePICLevel(g->module); | |
| 9176 | } | |
| 9177 | ||
| 9178 | if (g->have_pie) { | |
| 9179 | ZigLLVMSetModulePIELevel(g->module); | |
| 9180 | } | |
| 9181 | ||
| 9173 | 9182 | const char *target_specific_cpu_args = ""; |
| 9174 | 9183 | const char *target_specific_features = ""; |
| 9175 | 9184 |
src/stage1/stage1.cpp+1| ... | ... | @@ -89,6 +89,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { |
| 89 | 89 | g->link_mode_dynamic = stage1->link_mode_dynamic; |
| 90 | 90 | g->dll_export_fns = stage1->dll_export_fns; |
| 91 | 91 | g->have_pic = stage1->pic; |
| 92 | g->have_pie = stage1->pie; | |
| 92 | 93 | g->have_stack_probing = stage1->enable_stack_probing; |
| 93 | 94 | g->is_single_threaded = stage1->is_single_threaded; |
| 94 | 95 | g->valgrind_enabled = stage1->valgrind_enabled; |
src/stage1/stage1.h+1| ... | ... | @@ -177,6 +177,7 @@ struct ZigStage1 { |
| 177 | 177 | enum ErrColor err_color; |
| 178 | 178 | |
| 179 | 179 | bool pic; |
| 180 | bool pie; | |
| 180 | 181 | bool link_libc; |
| 181 | 182 | bool link_libcpp; |
| 182 | 183 | bool strip; |
src/zig_llvm.cpp+8| ... | ... | @@ -855,6 +855,14 @@ void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { |
| 855 | 855 | unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1); |
| 856 | 856 | } |
| 857 | 857 | |
| 858 | void ZigLLVMSetModulePICLevel(LLVMModuleRef module) { | |
| 859 | unwrap(module)->setPICLevel(PICLevel::Level::BigPIC); | |
| 860 | } | |
| 861 | ||
| 862 | void ZigLLVMSetModulePIELevel(LLVMModuleRef module) { | |
| 863 | unwrap(module)->setPIELevel(PIELevel::Level::Large); | |
| 864 | } | |
| 865 | ||
| 858 | 866 | static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { |
| 859 | 867 | switch (Ordering) { |
| 860 | 868 | case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic; |
src/zig_llvm.h+2| ... | ... | @@ -206,6 +206,8 @@ ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef modul |
| 206 | 206 | ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder); |
| 207 | 207 | ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module); |
| 208 | 208 | ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module); |
| 209 | ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module); | |
| 210 | ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module); | |
| 209 | 211 | |
| 210 | 212 | ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, |
| 211 | 213 | struct ZigLLVMDIScope *scope); |
tools/update_clang_options.zig+8| ... | ... | @@ -54,6 +54,14 @@ const known_options = [_]KnownOpt{ |
| 54 | 54 | .name = "fno-PIC", |
| 55 | 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 | 66 | .name = "nolibc", |
| 59 | 67 | .ident = "nostdlib", |