aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-11-22 17:30:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-11-22 17:30:34 -0700
commitc7170e4a5480581db5f30913eebd9ad4f7cd121e (patch)
treefba79b8f4241c94f886e7708d18081e8fc0e31fe /src
parent98d5bfbd4d21e99363a0a68ef5a0d0104c302ecb (diff)
parentabc717f203060f7ab16d36f2afe681d838b46801 (diff)
downloadzig-c7170e4a5480581db5f30913eebd9ad4f7cd121e.tar.gz
zig-c7170e4a5480581db5f30913eebd9ad4f7cd121e.zip
Support PIE (Position Independent Executables)
Closes #4503 Revives #3960 Merges branch 'pie' into master
Diffstat (limited to 'src')
-rw-r--r--src/Compilation.zig33
-rw-r--r--src/clang_options_data.zig18
-rw-r--r--src/libcxx.zig2
-rw-r--r--src/libunwind.zig1
-rw-r--r--src/link.zig1
-rw-r--r--src/link/Elf.zig8
-rw-r--r--src/main.zig12
-rw-r--r--src/musl.zig18
-rw-r--r--src/stage1.zig1
-rw-r--r--src/stage1/all_types.hpp1
-rw-r--r--src/stage1/codegen.cpp9
-rw-r--r--src/stage1/stage1.cpp1
-rw-r--r--src/stage1/stage1.h1
-rw-r--r--src/zig_llvm.cpp8
-rw-r--r--src/zig_llvm.h2
15 files changed, 108 insertions, 8 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index b3cb9e31f0..b813182e30 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -343,6 +343,10 @@ pub const InitOptions = struct {
link_libc: bool = false,
link_libcpp: bool = false,
want_pic: ?bool = null,
+ /// This means that if the output mode is an executable it will be a
+ /// Position Independent Executable. If the output mode is not an
+ /// executable this field is ignored.
+ want_pie: ?bool = null,
want_sanitize_c: ?bool = null,
want_stack_check: ?bool = null,
want_valgrind: ?bool = null,
@@ -527,17 +531,30 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
options.libc_installation,
);
+ const must_pie = target_util.requiresPIE(options.target);
+ const pie = if (options.want_pie) |explicit| pie: {
+ if (!explicit and must_pie) {
+ return error.TargetRequiresPIE;
+ }
+ break :pie explicit;
+ } else must_pie;
+
const must_pic: bool = b: {
if (target_util.requiresPIC(options.target, link_libc))
break :b true;
break :b link_mode == .Dynamic;
};
const pic = if (options.want_pic) |explicit| pic: {
- if (!explicit and must_pic) {
- return error.TargetRequiresPIC;
+ if (!explicit) {
+ if (must_pic) {
+ return error.TargetRequiresPIC;
+ }
+ if (pie) {
+ return error.PIERequiresPIC;
+ }
}
break :pic explicit;
- } else must_pic;
+ } else pie or must_pic;
// Make a decision on whether to use Clang for translate-c and compiling C files.
const use_clang = if (options.use_clang) |explicit| explicit else blk: {
@@ -618,6 +635,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
cache.hash.add(options.target.abi);
cache.hash.add(ofmt);
cache.hash.add(pic);
+ cache.hash.add(pie);
cache.hash.add(stack_check);
cache.hash.add(link_mode);
cache.hash.add(options.function_sections);
@@ -814,6 +832,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.version = options.version,
.libc_installation = libc_dirs.libc_installation,
.pic = pic,
+ .pie = pie,
.valgrind = valgrind,
.stack_check = stack_check,
.single_threaded = single_threaded,
@@ -898,7 +917,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
try comp.addBuildingGLibCJobs();
}
if (comp.wantBuildMuslFromSource()) {
- try comp.work_queue.ensureUnusedCapacity(5);
+ try comp.work_queue.ensureUnusedCapacity(6);
if (target_util.libc_needs_crti_crtn(comp.getTarget())) {
comp.work_queue.writeAssumeCapacity(&[_]Job{
.{ .musl_crt_file = .crti_o },
@@ -908,6 +927,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
comp.work_queue.writeAssumeCapacity(&[_]Job{
.{ .musl_crt_file = .crt1_o },
.{ .musl_crt_file = .scrt1_o },
+ .{ .musl_crt_file = .rcrt1_o },
.{ .musl_crt_file = .libc_a },
});
}
@@ -2473,6 +2493,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
\\pub const have_error_return_tracing = {};
\\pub const valgrind_support = {};
\\pub const position_independent_code = {};
+ \\pub const position_independent_executable = {};
\\pub const strip_debug_info = {};
\\pub const code_model = CodeModel.{};
\\
@@ -2484,6 +2505,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
comp.bin_file.options.error_return_tracing,
comp.bin_file.options.valgrind,
comp.bin_file.options.pic,
+ comp.bin_file.options.pie,
comp.bin_file.options.strip,
@tagName(comp.bin_file.options.machine_code_model),
});
@@ -2587,6 +2609,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
.want_stack_check = false,
.want_valgrind = false,
.want_pic = comp.bin_file.options.pic,
+ .want_pie = comp.bin_file.options.pie,
.emit_h = null,
.strip = comp.bin_file.options.strip,
.is_native_os = comp.bin_file.options.is_native_os,
@@ -2795,6 +2818,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
.subsystem = subsystem,
.err_color = @enumToInt(comp.color),
.pic = comp.bin_file.options.pic,
+ .pie = comp.bin_file.options.pie,
.link_libc = comp.bin_file.options.link_libc,
.link_libcpp = comp.bin_file.options.link_libcpp,
.strip = comp.bin_file.options.strip,
@@ -2950,6 +2974,7 @@ pub fn build_crt_file(
.want_stack_check = false,
.want_valgrind = false,
.want_pic = comp.bin_file.options.pic,
+ .want_pie = comp.bin_file.options.pie,
.emit_h = null,
.strip = comp.bin_file.options.strip,
.is_native_os = comp.bin_file.options.is_native_os,
diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig
index e9093ac845..52dc8c0280 100644
--- a/src/clang_options_data.zig
+++ b/src/clang_options_data.zig
@@ -2460,7 +2460,14 @@ sepd1("exported_symbols_list"),
.pd2 = false,
.psl = false,
},
-flagpd1("fPIE"),
+.{
+ .name = "fPIE",
+ .syntax = .flag,
+ .zig_equivalent = .pie,
+ .pd1 = true,
+ .pd2 = false,
+ .psl = false,
+},
flagpd1("fno-access-control"),
flagpd1("faddrsig"),
flagpd1("faggressive-function-elimination"),
@@ -2775,7 +2782,14 @@ flagpd1("fnext-runtime"),
.pd2 = false,
.psl = false,
},
-flagpd1("fno-PIE"),
+.{
+ .name = "fno-PIE",
+ .syntax = .flag,
+ .zig_equivalent = .no_pie,
+ .pd1 = true,
+ .pd2 = false,
+ .psl = false,
+},
flagpd1("fno-no-access-control"),
flagpd1("fno-addrsig"),
flagpd1("fno-aggressive-function-elimination"),
diff --git a/src/libcxx.zig b/src/libcxx.zig
index b76c8f1163..9c5ec93776 100644
--- a/src/libcxx.zig
+++ b/src/libcxx.zig
@@ -171,6 +171,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
.want_stack_check = false,
.want_valgrind = false,
.want_pic = comp.bin_file.options.pic,
+ .want_pie = comp.bin_file.options.pie,
.emit_h = null,
.strip = comp.bin_file.options.strip,
.is_native_os = comp.bin_file.options.is_native_os,
@@ -288,6 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
.want_stack_check = false,
.want_valgrind = false,
.want_pic = comp.bin_file.options.pic,
+ .want_pie = comp.bin_file.options.pie,
.emit_h = null,
.strip = comp.bin_file.options.strip,
.is_native_os = comp.bin_file.options.is_native_os,
diff --git a/src/libunwind.zig b/src/libunwind.zig
index d47eed40dd..3607488aba 100644
--- a/src/libunwind.zig
+++ b/src/libunwind.zig
@@ -104,6 +104,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
.want_stack_check = false,
.want_valgrind = false,
.want_pic = comp.bin_file.options.pic,
+ .want_pie = comp.bin_file.options.pie,
.emit_h = null,
.strip = comp.bin_file.options.strip,
.is_native_os = comp.bin_file.options.is_native_os,
diff --git a/src/link.zig b/src/link.zig
index 7b0271f978..064c178d66 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -71,6 +71,7 @@ pub const Options = struct {
bind_global_refs_locally: bool,
is_native_os: bool,
pic: bool,
+ pie: bool,
valgrind: bool,
stack_check: bool,
single_threaded: bool,
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index 18388f0589..9747eced41 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -1425,7 +1425,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
try argv.append("-shared");
}
- if (target_util.requiresPIE(target) and self.base.options.output_mode == .Exe) {
+ if (self.base.options.pie and self.base.options.output_mode == .Exe) {
try argv.append("-pie");
}
@@ -1444,7 +1444,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
break :o "crtbegin_static.o";
}
} else if (self.base.options.link_mode == .Static) {
- break :o "crt1.o";
+ if (self.base.options.pie) {
+ break :o "rcrt1.o";
+ } else {
+ break :o "crt1.o";
+ }
} else {
break :o "Scrt1.o";
}
diff --git a/src/main.zig b/src/main.zig
index d09599e3c6..595faed88f 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -270,6 +270,8 @@ const usage_build_generic =
\\ --main-pkg-path Set the directory of the root package
\\ -fPIC Force-enable Position Independent Code
\\ -fno-PIC Force-disable Position Independent Code
+ \\ -fPIE Force-enable Position Independent Executable
+ \\ -fno-PIE Force-disable Position Independent Executable
\\ -fstack-check Enable stack probing in unsafe builds
\\ -fno-stack-check Disable stack probing in safe builds
\\ -fsanitize-c Enable C undefined behavior detection in unsafe builds
@@ -457,6 +459,7 @@ fn buildOutputType(
var want_native_include_dirs = false;
var enable_cache: ?bool = null;
var want_pic: ?bool = null;
+ var want_pie: ?bool = null;
var want_sanitize_c: ?bool = null;
var want_stack_check: ?bool = null;
var want_valgrind: ?bool = null;
@@ -795,6 +798,10 @@ fn buildOutputType(
want_pic = true;
} else if (mem.eql(u8, arg, "-fno-PIC")) {
want_pic = false;
+ } else if (mem.eql(u8, arg, "-fPIE")) {
+ want_pie = true;
+ } else if (mem.eql(u8, arg, "-fno-PIE")) {
+ want_pie = false;
} else if (mem.eql(u8, arg, "-fstack-check")) {
want_stack_check = true;
} else if (mem.eql(u8, arg, "-fno-stack-check")) {
@@ -1006,6 +1013,8 @@ fn buildOutputType(
},
.pic => want_pic = true,
.no_pic => want_pic = false,
+ .pie => want_pie = true,
+ .no_pie => want_pie = false,
.nostdlib => ensure_libc_on_non_freestanding = false,
.nostdlib_cpp => ensure_libcpp_on_non_freestanding = false,
.shared => {
@@ -1640,6 +1649,7 @@ fn buildOutputType(
.link_libc = link_libc,
.link_libcpp = link_libcpp,
.want_pic = want_pic,
+ .want_pie = want_pie,
.want_sanitize_c = want_sanitize_c,
.want_stack_check = want_stack_check,
.want_valgrind = want_valgrind,
@@ -2773,6 +2783,8 @@ pub const ClangArgIterator = struct {
driver_punt,
pic,
no_pic,
+ pie,
+ no_pie,
nostdlib,
nostdlib_cpp,
shared,
diff --git a/src/musl.zig b/src/musl.zig
index 75b0a67584..c405013afe 100644
--- a/src/musl.zig
+++ b/src/musl.zig
@@ -12,6 +12,7 @@ pub const CRTFile = enum {
crti_o,
crtn_o,
crt1_o,
+ rcrt1_o,
scrt1_o,
libc_a,
};
@@ -68,6 +69,23 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
},
});
},
+ .rcrt1_o => {
+ var args = std.ArrayList([]const u8).init(arena);
+ try add_cc_args(comp, arena, &args, false);
+ try args.appendSlice(&[_][]const u8{
+ "-fPIC",
+ "-fno-stack-protector",
+ "-DCRT",
+ });
+ return comp.build_crt_file("rcrt1", .Obj, &[1]Compilation.CSourceFile{
+ .{
+ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
+ "libc", "musl", "crt", "rcrt1.c",
+ }),
+ .extra_flags = args.items,
+ },
+ });
+ },
.scrt1_o => {
var args = std.ArrayList([]const u8).init(arena);
try add_cc_args(comp, arena, &args, false);
diff --git a/src/stage1.zig b/src/stage1.zig
index 2dabea91ad..504b35df94 100644
--- a/src/stage1.zig
+++ b/src/stage1.zig
@@ -108,6 +108,7 @@ pub const Module = extern struct {
subsystem: TargetSubsystem,
err_color: ErrColor,
pic: bool,
+ pie: bool,
link_libc: bool,
link_libcpp: bool,
strip: bool,
diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp
index d56bcffff1..957a377b6d 100644
--- a/src/stage1/all_types.hpp
+++ b/src/stage1/all_types.hpp
@@ -2177,6 +2177,7 @@ struct CodeGen {
bool is_test_build;
bool is_single_threaded;
bool have_pic;
+ bool have_pie;
bool link_mode_dynamic;
bool dll_export_fns;
bool have_stack_probing;
diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp
index 26fe00228e..d0bb9b4411 100644
--- a/src/stage1/codegen.cpp
+++ b/src/stage1/codegen.cpp
@@ -9043,6 +9043,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
buf_appendf(contents, "pub const valgrind_support = false;\n");
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
+ buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
buf_appendf(contents, "pub const code_model = CodeModel.default;\n");
@@ -9170,6 +9171,14 @@ static void init(CodeGen *g) {
reloc_mode = LLVMRelocStatic;
}
+ if (g->have_pic) {
+ ZigLLVMSetModulePICLevel(g->module);
+ }
+
+ if (g->have_pie) {
+ ZigLLVMSetModulePIELevel(g->module);
+ }
+
const char *target_specific_cpu_args = "";
const char *target_specific_features = "";
diff --git a/src/stage1/stage1.cpp b/src/stage1/stage1.cpp
index 1034f9ff88..fec6760623 100644
--- a/src/stage1/stage1.cpp
+++ b/src/stage1/stage1.cpp
@@ -89,6 +89,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
g->link_mode_dynamic = stage1->link_mode_dynamic;
g->dll_export_fns = stage1->dll_export_fns;
g->have_pic = stage1->pic;
+ g->have_pie = stage1->pie;
g->have_stack_probing = stage1->enable_stack_probing;
g->is_single_threaded = stage1->is_single_threaded;
g->valgrind_enabled = stage1->valgrind_enabled;
diff --git a/src/stage1/stage1.h b/src/stage1/stage1.h
index 412118a6fa..0552aa09e0 100644
--- a/src/stage1/stage1.h
+++ b/src/stage1/stage1.h
@@ -177,6 +177,7 @@ struct ZigStage1 {
enum ErrColor err_color;
bool pic;
+ bool pie;
bool link_libc;
bool link_libcpp;
bool strip;
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index cc02c4c028..d8eeaf7fae 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -855,6 +855,14 @@ void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {
unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1);
}
+void ZigLLVMSetModulePICLevel(LLVMModuleRef module) {
+ unwrap(module)->setPICLevel(PICLevel::Level::BigPIC);
+}
+
+void ZigLLVMSetModulePIELevel(LLVMModuleRef module) {
+ unwrap(module)->setPIELevel(PIELevel::Level::Large);
+}
+
static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
switch (Ordering) {
case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic;
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index 2500c162eb..24ea533954 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -206,6 +206,8 @@ ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef modul
ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder);
ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
+ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module);
+ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module);
ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column,
struct ZigLLVMDIScope *scope);