diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-11-22 17:30:34 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-11-22 17:30:34 -0700 |
| commit | c7170e4a5480581db5f30913eebd9ad4f7cd121e (patch) | |
| tree | fba79b8f4241c94f886e7708d18081e8fc0e31fe /src | |
| parent | 98d5bfbd4d21e99363a0a68ef5a0d0104c302ecb (diff) | |
| parent | abc717f203060f7ab16d36f2afe681d838b46801 (diff) | |
| download | zig-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.zig | 33 | ||||
| -rw-r--r-- | src/clang_options_data.zig | 18 | ||||
| -rw-r--r-- | src/libcxx.zig | 2 | ||||
| -rw-r--r-- | src/libunwind.zig | 1 | ||||
| -rw-r--r-- | src/link.zig | 1 | ||||
| -rw-r--r-- | src/link/Elf.zig | 8 | ||||
| -rw-r--r-- | src/main.zig | 12 | ||||
| -rw-r--r-- | src/musl.zig | 18 | ||||
| -rw-r--r-- | src/stage1.zig | 1 | ||||
| -rw-r--r-- | src/stage1/all_types.hpp | 1 | ||||
| -rw-r--r-- | src/stage1/codegen.cpp | 9 | ||||
| -rw-r--r-- | src/stage1/stage1.cpp | 1 | ||||
| -rw-r--r-- | src/stage1/stage1.h | 1 | ||||
| -rw-r--r-- | src/zig_llvm.cpp | 8 | ||||
| -rw-r--r-- | src/zig_llvm.h | 2 |
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); |
