diff --git a/src/all_types.hpp b/src/all_types.hpp index 2cd4a5f958..a0b4fadedc 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1633,6 +1633,12 @@ enum WantPIC { WantPICEnabled, }; +enum WantStackCheck { + WantStackCheckAuto, + WantStackCheckDisabled, + WantStackCheckEnabled, +}; + struct CFile { ZigList args; const char *source_path; @@ -1790,6 +1796,8 @@ struct CodeGen { TldFn *panic_tld_fn; AstNode *root_export_decl; + WantPIC want_pic; + WantStackCheck want_stack_check; CacheHash cache_hash; ErrColor err_color; uint32_t next_unresolved_index; @@ -1807,8 +1815,6 @@ struct CodeGen { bool have_dllmain_crt_startup; bool have_pub_panic; bool have_err_ret_tracing; - bool have_pic; - bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic bool c_want_stdint; bool c_want_stdbool; bool verbose_tokenize; @@ -1824,6 +1830,7 @@ struct CodeGen { bool enable_time_report; bool system_linker_hack; bool reported_bad_link_libc_error; + bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. //////////////////////////// Participates in Input Parameter Cache Hash /////// Note: there is a separate cache hash for builtin.zig, when adding fields, @@ -1852,8 +1859,6 @@ struct CodeGen { const ZigTarget *zig_target; TargetSubsystem subsystem; ValgrindSupport valgrind_support; - WantPIC want_pic; - bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl. bool strip_debug_symbols; bool is_test_build; bool is_single_threaded; @@ -1863,7 +1868,9 @@ struct CodeGen { bool is_dummy_so; bool disable_gen_h; bool bundle_compiler_rt; - bool disable_stack_probing; + bool have_pic; + bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic + bool have_stack_probing; Buf *mmacosx_version_min; Buf *mios_version_min; diff --git a/src/codegen.cpp b/src/codegen.cpp index 00a4338810..2c3e30b3d8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -399,15 +399,6 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { } } -static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) { - // Windows already emits its own stack probes - if (!g->disable_stack_probing && g->zig_target->os != OsWindows && - (g->zig_target->arch == ZigLLVM_x86 || - g->zig_target->arch == ZigLLVM_x86_64)) { - addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack"); - } -} - static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { switch (id) { case GlobalLinkageIdInternal: @@ -596,8 +587,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4"); } - - add_probe_stack_attr(g, fn_table_entry->llvm_value); + } + if (g->have_stack_probing && !fn_table_entry->def_scope->safety_off) { + addLLVMFnAttrStr(fn_table_entry->llvm_value, "probe-stack", "__zig_probe_stack"); } } else { maybe_import_dll(g, fn_table_entry->llvm_value, linkage); @@ -7458,6 +7450,20 @@ static bool detect_pic(CodeGen *g) { zig_unreachable(); } +static bool detect_stack_probing(CodeGen *g) { + if (!target_supports_stack_probing(g->zig_target)) + return false; + switch (g->want_stack_check) { + case WantStackCheckDisabled: + return false; + case WantStackCheckEnabled: + return true; + case WantStackCheckAuto: + return g->build_mode == BuildModeSafeRelease || g->build_mode == BuildModeDebug; + } + zig_unreachable(); +} + static bool detect_single_threaded(CodeGen *g) { if (g->want_single_threaded) return true; @@ -7476,6 +7482,7 @@ static bool detect_err_ret_tracing(CodeGen *g) { Buf *codegen_generate_builtin_source(CodeGen *g) { g->have_dynamic_link = detect_dynamic_link(g); g->have_pic = detect_pic(g); + g->have_stack_probing = detect_stack_probing(g); g->is_single_threaded = detect_single_threaded(g); g->have_err_ret_tracing = detect_err_ret_tracing(g); @@ -7982,6 +7989,7 @@ static void init(CodeGen *g) { g->have_dynamic_link = detect_dynamic_link(g); g->have_pic = detect_pic(g); + g->have_stack_probing = detect_stack_probing(g); g->is_single_threaded = detect_single_threaded(g); g->have_err_ret_tracing = detect_err_ret_tracing(g); @@ -9351,10 +9359,10 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->each_lib_rpath); cache_bool(ch, g->disable_gen_h); cache_bool(ch, g->bundle_compiler_rt); - cache_bool(ch, g->disable_stack_probing); cache_bool(ch, want_valgrind_support(g)); cache_bool(ch, g->have_pic); cache_bool(ch, g->have_dynamic_link); + cache_bool(ch, g->have_stack_probing); cache_bool(ch, g->is_dummy_so); cache_buf_opt(ch, g->mmacosx_version_min); cache_buf_opt(ch, g->mios_version_min); diff --git a/src/link.cpp b/src/link.cpp index b47da87c68..4c3b3d4769 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -25,7 +25,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path()); child_gen->disable_gen_h = true; - child_gen->disable_stack_probing = true; + child_gen->want_stack_check = WantStackCheckDisabled; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; child_gen->verbose_ast = parent_gen->verbose_ast; child_gen->verbose_link = parent_gen->verbose_link; diff --git a/src/main.cpp b/src/main.cpp index 934c998435..cbfd946899 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,7 +55,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --disable-gen-h do not generate a C header file (.h)\n" " --disable-valgrind omit valgrind client requests in debug builds\n" " --enable-valgrind include valgrind client requests release builds\n" - " --disable-stack-probing workaround for macosx\n" + " -fstack-check enable stack probing in unsafe builds\n" + " -fno-stack-check disable stack probing in safe builds\n" " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" @@ -443,12 +444,12 @@ int main(int argc, char **argv) { bool want_single_threaded = false; bool disable_gen_h = false; bool bundle_compiler_rt = false; - bool disable_stack_probing = false; Buf *override_std_dir = nullptr; Buf *override_lib_dir = nullptr; Buf *main_pkg_path = nullptr; ValgrindSupport valgrind_support = ValgrindSupportAuto; WantPIC want_pic = WantPICAuto; + WantStackCheck want_stack_check = WantStackCheckAuto; ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); @@ -648,6 +649,10 @@ int main(int argc, char **argv) { want_pic = WantPICEnabled; } else if (strcmp(arg, "-fno-PIC") == 0) { want_pic = WantPICDisabled; + } else if (strcmp(arg, "-fstack-check") == 0) { + want_stack_check = WantStackCheckEnabled; + } else if (strcmp(arg, "-fno-stack-check") == 0) { + want_stack_check = WantStackCheckDisabled; } else if (strcmp(arg, "--system-linker-hack") == 0) { system_linker_hack = true; } else if (strcmp(arg, "--single-threaded") == 0) { @@ -656,8 +661,6 @@ int main(int argc, char **argv) { disable_gen_h = true; } else if (strcmp(arg, "--bundle-compiler-rt") == 0) { bundle_compiler_rt = true; - } else if (strcmp(arg, "--disable-stack-probing") == 0) { - disable_stack_probing = true; } else if (strcmp(arg, "--test-cmd-bin") == 0) { test_exec_args.append(nullptr); } else if (arg[1] == 'L' && arg[2] != 0) { @@ -953,6 +956,7 @@ int main(int argc, char **argv) { out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr); g->valgrind_support = valgrind_support; g->want_pic = want_pic; + g->want_stack_check = want_stack_check; g->want_single_threaded = want_single_threaded; Buf *builtin_source = codegen_generate_builtin_source(g); if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { @@ -1048,6 +1052,7 @@ int main(int argc, char **argv) { if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); g->valgrind_support = valgrind_support; g->want_pic = want_pic; + g->want_stack_check = want_stack_check; g->subsystem = subsystem; g->enable_time_report = timing_info; @@ -1074,7 +1079,6 @@ int main(int argc, char **argv) { g->output_dir = output_dir; g->disable_gen_h = disable_gen_h; g->bundle_compiler_rt = bundle_compiler_rt; - g->disable_stack_probing = disable_stack_probing; codegen_set_errmsg_color(g, color); g->system_linker_hack = system_linker_hack; diff --git a/src/target.cpp b/src/target.cpp index 630096204b..7862f6d449 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1356,6 +1356,10 @@ bool target_supports_fpic(const ZigTarget *target) { return target->os != OsWindows; } +bool target_supports_stack_probing(const ZigTarget *target) { + return target->os != OsWindows && (target->arch == ZigLLVM_x86 || target->arch == ZigLLVM_x86_64); +} + bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. return target->os == OsWindows || target_os_requires_libc(target->os) || diff --git a/src/target.hpp b/src/target.hpp index fd5c7471c3..f3cde902a0 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -172,6 +172,7 @@ bool target_is_glibc(const ZigTarget *target); bool target_is_musl(const ZigTarget *target); bool target_is_wasm(const ZigTarget *target); bool target_is_single_threaded(const ZigTarget *target); +bool target_supports_stack_probing(const ZigTarget *target); uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);