Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
"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<
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,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>;
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,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;
}
Expand Down
46 changes: 46 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -259,6 +260,45 @@ 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.
Expand Down Expand Up @@ -616,6 +656,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); }
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/AIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
return llvm::DebuggerKind::DBX;
}

SanitizerMask getSupportedSanitizers() const override;

path_list getArchSpecificLibPaths() const override { return path_list(); };

protected:
Expand Down
36 changes: 31 additions & 5 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
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"));
Expand Down Expand Up @@ -1398,7 +1411,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()) {
Expand All @@ -1425,6 +1440,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
Expand Down Expand Up @@ -1480,7 +1498,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.
Expand Down Expand Up @@ -1614,7 +1633,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) {
Expand All @@ -1623,8 +1644,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");
Expand Down
Empty file.
104 changes: 104 additions & 0 deletions clang/test/Driver/sanitizer-ld.c
Original file line number Diff line number Diff line change
Expand Up @@ -1369,3 +1369,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"