-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] Implement address sanitizer on AIX #129925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The PR includes clang changes needed for the address sanitizer on AIX. Will also post llvm and compiler-rt PRs following this.
@llvm/pr-subscribers-backend-powerpc @llvm/pr-subscribers-clang Author: Jake Egan (jakeegan) ChangesThe PR includes clang changes needed for the address sanitizer on AIX. llvm PR: TBD Full diff: https://github.com/llvm/llvm-project/pull/129925.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 8d599c96eb4fb..c44d364d244bc 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -257,6 +257,8 @@ def err_drv_malformed_sanitizer_metadata_ignorelist : Error<
"malformed sanitizer metadata ignorelist: '%0'">;
def err_drv_unsupported_static_sanitizer_darwin : Error<
"static %0 runtime is not supported on darwin">;
+def err_drv_unsupported_shared_sanitizer_aix : Error<
+ "shared %0 runtime is not supported on AIX">;
def err_drv_duplicate_config : Error<
"no more than one option '--config' is allowed">;
def err_drv_cannot_open_config_file : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0ab923fcdd583..66959279d3fcf 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1542,7 +1542,7 @@ defm xl_pragma_pack : BoolFOption<"xl-pragma-pack",
"Enable IBM XL #pragma pack handling">,
NegFlag<SetFalse>>;
def shared_libsan : Flag<["-"], "shared-libsan">,
- HelpText<"Dynamically link the sanitizer runtime">;
+ HelpText<"Dynamically link the sanitizer runtime (Not supported for ASan on AIX)">;
def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 97e9bbccd61ef..b47aff95f2430 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -275,13 +275,14 @@ static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
return !CGOpts.DisableIntegratedAS;
case Triple::GOFF:
llvm::report_fatal_error("ASan not implemented for GOFF");
- case Triple::XCOFF:
- llvm::report_fatal_error("ASan not implemented for XCOFF.");
case Triple::Wasm:
case Triple::DXContainer:
case Triple::SPIRV:
case Triple::UnknownObjectFormat:
break;
+ case Triple::XCOFF:
+ // FIXME: try to enable GC-friendly instrumentation for globals on AIX.
+ return false;
}
return false;
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index ebc982096595e..d4aa71d031ba9 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -749,7 +749,7 @@ std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
case ToolChain::FT_Shared:
Suffix = TT.isOSWindows()
? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
- : ".so";
+ : (TT.isOSAIX() ? ".a" : ".so");
break;
}
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index 09a8dc2f4fa5d..30db6f45c7e81 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -20,6 +20,7 @@
#include <set>
using AIX = clang::driver::toolchains::AIX;
+using namespace clang;
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
@@ -233,6 +234,44 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Specify linker input file(s).
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ // Add sanitizer libraries.
+ const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(Args);
+ const char *sanitizer = nullptr;
+ bool NeedsSanitizerDeps = false;
+ // For now, only support address sanitizer.
+ if (Sanitize.needsAsanRt())
+ sanitizer = "AddressSanitizer";
+
+ if (sanitizer) {
+ if (Sanitize.needsSharedRt()) {
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_shared_sanitizer_aix) << sanitizer;
+ return;
+ }
+ NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ }
+
+ // Add sanitizer runtime dependencies.
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_shared, options::OPT_r)) {
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
+ }
+
+ // We won't add the static sanitizer libraries to the DSO, but we will
+ // introduce the undefined sanitizer symbols like __asan_init to the DSO. On
+ // AIX, this undefined sanitizer symbol cannot pass final link. Add the
+ // import file to make these undefined symbols be resolved at runtime.
+ if (Args.hasArg(options::OPT_shared) &&
+ ToolChain.getSanitizerArgs(Args).needsAsanRt()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
+ "/asan.link_with_main_exec.txt"));
+ if (ToolChain.getSanitizerArgs(Args).linkCXXRuntimes())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
+ "/asan_cxx.link_with_main_exec.txt"));
+ }
+
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
// Find the first filename InputInfo object.
@@ -590,6 +629,12 @@ ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
return ToolChain::RLT_CompilerRT;
}
+SanitizerMask AIX::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
+
auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }
diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h
index 8f130f6b54547..297f3f2bc2a9f 100644
--- a/clang/lib/Driver/ToolChains/AIX.h
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -98,6 +98,8 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
return llvm::DebuggerKind::DBX;
}
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index c3c22a419f352..8cedb3ef2bc43 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1395,6 +1395,19 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
// the option, so don't try to pass it.
if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd)
return true;
+
+ if (TC.getTriple().isOSAIX()) {
+ SmallString<128> SanRTSymbolList;
+ (Twine(TC.getCompilerRTPath()) + "/" + Sanitizer +
+ ".link_with_main_exec.txt")
+ .toVector(SanRTSymbolList);
+ if (llvm::sys::fs::exists(SanRTSymbolList)) {
+ CmdArgs.push_back(Args.MakeArgString(Twine("-bE:") + SanRTSymbolList));
+ return true;
+ }
+ return false;
+ }
+
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
@@ -1429,7 +1442,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
- addAsNeededOption(TC, Args, CmdArgs, false);
+ // AIX does not support any --as-needed options.
+ if (!TC.getTriple().isOSAIX())
+ addAsNeededOption(TC, Args, CmdArgs, false);
// There's no libpthread or librt on RTEMS & Android.
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
!TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
@@ -1453,6 +1468,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
!TC.getTriple().isMusl())
CmdArgs.push_back("-lresolv");
+
+ if (TC.getTriple().isOSAIX())
+ CmdArgs.push_back("-latomic");
}
static void
@@ -1508,7 +1526,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("stats_client");
// Always link the static runtime regardless of DSO or executable.
- if (SanArgs.needsAsanRt())
+ // Don't see a reason that AIX needs asan_static library though.
+ if (SanArgs.needsAsanRt() && !TC.getTriple().isOSAIX())
HelperStaticRuntimes.push_back("asan_static");
// Collect static runtimes.
@@ -1642,7 +1661,9 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
bool AddExportDynamic = false;
for (auto RT : StaticRuntimes) {
- addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
+ // AIX does not support --whole-archive.
+ addSanitizerRuntime(TC, Args, CmdArgs, RT, false,
+ !TC.getTriple().isOSAIX());
AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
}
for (auto RT : NonWholeStaticRuntimes) {
@@ -1651,8 +1672,13 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
// If there is a static runtime with no dynamic list, force all the symbols
// to be dynamic to be sure we export sanitizer interface functions.
- if (AddExportDynamic)
- CmdArgs.push_back("--export-dynamic");
+ if (AddExportDynamic) {
+ if (!TC.getTriple().isOSAIX())
+ CmdArgs.push_back("--export-dynamic");
+ else
+ llvm::report_fatal_error("Sanitizer interface functions must be exported "
+ "by export files on AIX.");
+ }
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
diff --git a/clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt b/clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt b/clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c
index 71078342b3617..3a19626ad6224 100644
--- a/clang/test/Driver/sanitizer-ld.c
+++ b/clang/test/Driver/sanitizer-ld.c
@@ -1216,3 +1216,107 @@
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lresolv"
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
+//
+// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32,CHECK-ASAN-LINK-RUNTIME-AIXCXX32,CHECK-ASAN-LINK-RUNTIME-AIXCXX %s
+//
+// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64,CHECK-ASAN-LINK-RUNTIME-AIXCXX64,CHECK-ASAN-LINK-RUNTIME-AIXCXX %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -static-libsan --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -static-libsan --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
+//
+// CHECK-ASAN-LINK-RUNTIME-AIX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ASAN-LINK-RUNTIME-AIX32: "-b32"
+// CHECK-ASAN-LINK-RUNTIME-AIX64: "-b64"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-bcdtors:all:0:s"
+// CHECK-ASAN-LINK-RUNTIME-AIX32: "{{.*}}libclang_rt.asan-powerpc.a"
+// CHECK-ASAN-LINK-RUNTIME-AIX64: "{{.*}}libclang_rt.asan-powerpc64.a"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-bE:{{.*}}asan.link_with_main_exec.txt"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX32: "{{.*}}libclang_rt.asan_cxx-powerpc.a"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX64: "{{.*}}libclang_rt.asan_cxx-powerpc64.a"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX: "-bE:{{.*}}asan_cxx.link_with_main_exec.txt"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lpthread"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-latomic"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lunwind"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lc"
+
+// RUN: not %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -shared-libsan --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
+//
+// RUN: not %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -shared-libsan --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
+//
+// CHECK-SHARED-ASAN-AIX: {{.*}}error: shared AddressSanitizer runtime is not supported on AIX
+
+// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64 %s
+//
+// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
+//
+// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
+//
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ASAN-SHARED-LIBRARY-AIX32: "-b32"
+// CHECK-ASAN-SHARED-LIBRARY-AIX64: "-b64"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bcdtors:all:0:s"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bI:{{.*}}asan.link_with_main_exec.txt"
+// CHECK-ASAN-SHARED-LIBRARY-AIXCXX: "-bI:{{.*}}asan_cxx.link_with_main_exec.txt"
+// CHECK-ASAN-SHARED-LIBRARY-AIX32-NOT: "{{.*}}libclang_rt.asan-powerpc.a"
+// CHECK-ASAN-SHARED-LIBRARY-AIX64-NOT: "{{.*}}libclang_rt.asan-powerpc64.a"
+// CHECK-ASAN-SHARED-LIBRARY-AIXCXX-NOT: "{{.*}}libclang_rt.asan_cxx-powerpc{{.*}}"
+// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-lpthread"
+// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-latomic"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lunwind"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lc"
+
|
@llvm/pr-subscribers-clang-codegen Author: Jake Egan (jakeegan) ChangesThe PR includes clang changes needed for the address sanitizer on AIX. llvm PR: TBD Full diff: https://github.com/llvm/llvm-project/pull/129925.diff 10 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 8d599c96eb4fb..c44d364d244bc 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -257,6 +257,8 @@ def err_drv_malformed_sanitizer_metadata_ignorelist : Error<
"malformed sanitizer metadata ignorelist: '%0'">;
def err_drv_unsupported_static_sanitizer_darwin : Error<
"static %0 runtime is not supported on darwin">;
+def err_drv_unsupported_shared_sanitizer_aix : Error<
+ "shared %0 runtime is not supported on AIX">;
def err_drv_duplicate_config : Error<
"no more than one option '--config' is allowed">;
def err_drv_cannot_open_config_file : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0ab923fcdd583..66959279d3fcf 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1542,7 +1542,7 @@ defm xl_pragma_pack : BoolFOption<"xl-pragma-pack",
"Enable IBM XL #pragma pack handling">,
NegFlag<SetFalse>>;
def shared_libsan : Flag<["-"], "shared-libsan">,
- HelpText<"Dynamically link the sanitizer runtime">;
+ HelpText<"Dynamically link the sanitizer runtime (Not supported for ASan on AIX)">;
def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 97e9bbccd61ef..b47aff95f2430 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -275,13 +275,14 @@ static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
return !CGOpts.DisableIntegratedAS;
case Triple::GOFF:
llvm::report_fatal_error("ASan not implemented for GOFF");
- case Triple::XCOFF:
- llvm::report_fatal_error("ASan not implemented for XCOFF.");
case Triple::Wasm:
case Triple::DXContainer:
case Triple::SPIRV:
case Triple::UnknownObjectFormat:
break;
+ case Triple::XCOFF:
+ // FIXME: try to enable GC-friendly instrumentation for globals on AIX.
+ return false;
}
return false;
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index ebc982096595e..d4aa71d031ba9 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -749,7 +749,7 @@ std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
case ToolChain::FT_Shared:
Suffix = TT.isOSWindows()
? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
- : ".so";
+ : (TT.isOSAIX() ? ".a" : ".so");
break;
}
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index 09a8dc2f4fa5d..30db6f45c7e81 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -20,6 +20,7 @@
#include <set>
using AIX = clang::driver::toolchains::AIX;
+using namespace clang;
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
@@ -233,6 +234,44 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Specify linker input file(s).
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ // Add sanitizer libraries.
+ const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(Args);
+ const char *sanitizer = nullptr;
+ bool NeedsSanitizerDeps = false;
+ // For now, only support address sanitizer.
+ if (Sanitize.needsAsanRt())
+ sanitizer = "AddressSanitizer";
+
+ if (sanitizer) {
+ if (Sanitize.needsSharedRt()) {
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_shared_sanitizer_aix) << sanitizer;
+ return;
+ }
+ NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ }
+
+ // Add sanitizer runtime dependencies.
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_shared, options::OPT_r)) {
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
+ }
+
+ // We won't add the static sanitizer libraries to the DSO, but we will
+ // introduce the undefined sanitizer symbols like __asan_init to the DSO. On
+ // AIX, this undefined sanitizer symbol cannot pass final link. Add the
+ // import file to make these undefined symbols be resolved at runtime.
+ if (Args.hasArg(options::OPT_shared) &&
+ ToolChain.getSanitizerArgs(Args).needsAsanRt()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
+ "/asan.link_with_main_exec.txt"));
+ if (ToolChain.getSanitizerArgs(Args).linkCXXRuntimes())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
+ "/asan_cxx.link_with_main_exec.txt"));
+ }
+
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
// Find the first filename InputInfo object.
@@ -590,6 +629,12 @@ ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
return ToolChain::RLT_CompilerRT;
}
+SanitizerMask AIX::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
+
auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }
diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h
index 8f130f6b54547..297f3f2bc2a9f 100644
--- a/clang/lib/Driver/ToolChains/AIX.h
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -98,6 +98,8 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
return llvm::DebuggerKind::DBX;
}
+ SanitizerMask getSupportedSanitizers() const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index c3c22a419f352..8cedb3ef2bc43 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1395,6 +1395,19 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
// the option, so don't try to pass it.
if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd)
return true;
+
+ if (TC.getTriple().isOSAIX()) {
+ SmallString<128> SanRTSymbolList;
+ (Twine(TC.getCompilerRTPath()) + "/" + Sanitizer +
+ ".link_with_main_exec.txt")
+ .toVector(SanRTSymbolList);
+ if (llvm::sys::fs::exists(SanRTSymbolList)) {
+ CmdArgs.push_back(Args.MakeArgString(Twine("-bE:") + SanRTSymbolList));
+ return true;
+ }
+ return false;
+ }
+
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
@@ -1429,7 +1442,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
- addAsNeededOption(TC, Args, CmdArgs, false);
+ // AIX does not support any --as-needed options.
+ if (!TC.getTriple().isOSAIX())
+ addAsNeededOption(TC, Args, CmdArgs, false);
// There's no libpthread or librt on RTEMS & Android.
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
!TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
@@ -1453,6 +1468,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
!TC.getTriple().isMusl())
CmdArgs.push_back("-lresolv");
+
+ if (TC.getTriple().isOSAIX())
+ CmdArgs.push_back("-latomic");
}
static void
@@ -1508,7 +1526,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("stats_client");
// Always link the static runtime regardless of DSO or executable.
- if (SanArgs.needsAsanRt())
+ // Don't see a reason that AIX needs asan_static library though.
+ if (SanArgs.needsAsanRt() && !TC.getTriple().isOSAIX())
HelperStaticRuntimes.push_back("asan_static");
// Collect static runtimes.
@@ -1642,7 +1661,9 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
bool AddExportDynamic = false;
for (auto RT : StaticRuntimes) {
- addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
+ // AIX does not support --whole-archive.
+ addSanitizerRuntime(TC, Args, CmdArgs, RT, false,
+ !TC.getTriple().isOSAIX());
AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
}
for (auto RT : NonWholeStaticRuntimes) {
@@ -1651,8 +1672,13 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
// If there is a static runtime with no dynamic list, force all the symbols
// to be dynamic to be sure we export sanitizer interface functions.
- if (AddExportDynamic)
- CmdArgs.push_back("--export-dynamic");
+ if (AddExportDynamic) {
+ if (!TC.getTriple().isOSAIX())
+ CmdArgs.push_back("--export-dynamic");
+ else
+ llvm::report_fatal_error("Sanitizer interface functions must be exported "
+ "by export files on AIX.");
+ }
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
diff --git a/clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt b/clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt b/clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/sanitizer-ld.c b/clang/test/Driver/sanitizer-ld.c
index 71078342b3617..3a19626ad6224 100644
--- a/clang/test/Driver/sanitizer-ld.c
+++ b/clang/test/Driver/sanitizer-ld.c
@@ -1216,3 +1216,107 @@
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lresolv"
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
+
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
+//
+// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32,CHECK-ASAN-LINK-RUNTIME-AIXCXX32,CHECK-ASAN-LINK-RUNTIME-AIXCXX %s
+//
+// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64,CHECK-ASAN-LINK-RUNTIME-AIXCXX64,CHECK-ASAN-LINK-RUNTIME-AIXCXX %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -static-libsan --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -static-libsan --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
+//
+// CHECK-ASAN-LINK-RUNTIME-AIX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ASAN-LINK-RUNTIME-AIX32: "-b32"
+// CHECK-ASAN-LINK-RUNTIME-AIX64: "-b64"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-bcdtors:all:0:s"
+// CHECK-ASAN-LINK-RUNTIME-AIX32: "{{.*}}libclang_rt.asan-powerpc.a"
+// CHECK-ASAN-LINK-RUNTIME-AIX64: "{{.*}}libclang_rt.asan-powerpc64.a"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-bE:{{.*}}asan.link_with_main_exec.txt"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX32: "{{.*}}libclang_rt.asan_cxx-powerpc.a"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX64: "{{.*}}libclang_rt.asan_cxx-powerpc64.a"
+// CHECK-ASAN-LINK-RUNTIME-AIXCXX: "-bE:{{.*}}asan_cxx.link_with_main_exec.txt"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lpthread"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-latomic"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lunwind"
+// CHECK-ASAN-LINK-RUNTIME-AIX: "-lc"
+
+// RUN: not %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -shared-libsan --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
+//
+// RUN: not %clang -fsanitize=address -### %s 2>&1 \
+// RUN: -shared-libsan --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
+//
+// CHECK-SHARED-ASAN-AIX: {{.*}}error: shared AddressSanitizer runtime is not supported on AIX
+
+// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32 %s
+//
+// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64 %s
+//
+// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
+// RUN: --target=powerpc-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
+//
+// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
+// RUN: --target=powerpc64-unknown-aix \
+// RUN: -resource-dir=%S/Inputs/resource_dir \
+// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
+// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
+//
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ASAN-SHARED-LIBRARY-AIX32: "-b32"
+// CHECK-ASAN-SHARED-LIBRARY-AIX64: "-b64"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bcdtors:all:0:s"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bI:{{.*}}asan.link_with_main_exec.txt"
+// CHECK-ASAN-SHARED-LIBRARY-AIXCXX: "-bI:{{.*}}asan_cxx.link_with_main_exec.txt"
+// CHECK-ASAN-SHARED-LIBRARY-AIX32-NOT: "{{.*}}libclang_rt.asan-powerpc.a"
+// CHECK-ASAN-SHARED-LIBRARY-AIX64-NOT: "{{.*}}libclang_rt.asan-powerpc64.a"
+// CHECK-ASAN-SHARED-LIBRARY-AIXCXX-NOT: "{{.*}}libclang_rt.asan_cxx-powerpc{{.*}}"
+// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-lpthread"
+// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-latomic"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lunwind"
+// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lc"
+
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
clang/lib/Driver/ToolChains/AIX.cpp
Outdated
ToolChain.getSanitizerArgs(Args).needsAsanRt()) { | ||
CmdArgs.push_back(Args.MakeArgString(Twine("-bI:") + | ||
ToolChain.getCompilerRTPath() + | ||
"/asan.link_with_main_exec.txt")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file isn't included in this patch, but the behaviour here seems to depend on it existing...
(Also, what's with the .txt
file extension? Typical this would be either .imp
or .exp
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lists are added here: #139583
The file extension is to be consistent with other asan files like compiler-rt/lib/asan/weak_symbols.txt
clang/lib/Driver/ToolChains/AIX.cpp
Outdated
if (ToolChain.getSanitizerArgs(Args).linkCXXRuntimes()) | ||
CmdArgs.push_back( | ||
Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() + | ||
"/asan_cxx.link_with_main_exec.txt")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto the previous import list comment
@@ -1364,6 +1364,19 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, | |||
// the option, so don't try to pass it. | |||
if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) | |||
return true; | |||
|
|||
if (TC.getTriple().isOSAIX()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a review comment, but a question for my own understanding. Why are these exports needed? (I see we are forcing the same on ELF platforms)
".link_with_main_exec.txt") | ||
.toVector(SanRTSymbolList); | ||
if (llvm::sys::fs::exists(SanRTSymbolList)) { | ||
CmdArgs.push_back(Args.MakeArgString(Twine("-bE:") + SanRTSymbolList)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto comment about missing lists.
I guess we can't use exactly the same list as --dynamic-list=
because format is slightly different, but I'm guessing we can generate it in a similar fashion.
@@ -256,6 +256,8 @@ def err_drv_malformed_sanitizer_metadata_ignorelist : Error< | |||
"malformed sanitizer metadata ignorelist: '%0'">; | |||
def err_drv_unsupported_static_sanitizer_darwin : Error< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename this one to err_drv_unsupported_static_sanitizer
and make the platform name a parameter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But AIX doesn't support shared, rather than static.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just make static/shared a parameter as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang/test/Driver/Inputs/resource_dir/lib/aix/libclang_rt.asan-powerpc.a is the old runtime path.
Does $triple/libclang_rt.asan.a work? If yes, the new hierarchy is preferred
per target runtime dir is enabled on AIX now, so I updated the PR accordingly. |
This PR includes frontend/driver changes needed for the address sanitizer on AIX.
Issue: #138916