Skip to content

[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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

jakeegan
Copy link
Member

@jakeegan jakeegan commented Mar 5, 2025

This PR includes frontend/driver changes needed for the address sanitizer on AIX.

Issue: #138916

The PR includes clang changes needed for the address sanitizer on AIX. Will also post llvm and
compiler-rt PRs following this.
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:PowerPC clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. labels Mar 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 5, 2025

@llvm/pr-subscribers-backend-powerpc
@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-clang

Author: Jake Egan (jakeegan)

Changes

The PR includes clang changes needed for the address sanitizer on AIX.

llvm PR: TBD
compiler-rt PR: TBD


Full diff: https://github.com/llvm/llvm-project/pull/129925.diff

10 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+2)
  • (modified) clang/include/clang/Driver/Options.td (+1-1)
  • (modified) clang/lib/CodeGen/BackendUtil.cpp (+3-2)
  • (modified) clang/lib/Driver/ToolChain.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/AIX.cpp (+45)
  • (modified) clang/lib/Driver/ToolChains/AIX.h (+2)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+31-5)
  • (added) clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt ()
  • (added) clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt ()
  • (modified) clang/test/Driver/sanitizer-ld.c (+104)
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"
+

@llvmbot
Copy link
Member

llvmbot commented Mar 5, 2025

@llvm/pr-subscribers-clang-codegen

Author: Jake Egan (jakeegan)

Changes

The PR includes clang changes needed for the address sanitizer on AIX.

llvm PR: TBD
compiler-rt PR: TBD


Full diff: https://github.com/llvm/llvm-project/pull/129925.diff

10 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+2)
  • (modified) clang/include/clang/Driver/Options.td (+1-1)
  • (modified) clang/lib/CodeGen/BackendUtil.cpp (+3-2)
  • (modified) clang/lib/Driver/ToolChain.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/AIX.cpp (+45)
  • (modified) clang/lib/Driver/ToolChains/AIX.h (+2)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+31-5)
  • (added) clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt ()
  • (added) clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt ()
  • (modified) clang/test/Driver/sanitizer-ld.c (+104)
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"
+

@jakeegan jakeegan changed the title [clang] Implement address sanitizer on AIX (1/3) [clang] Implement address sanitizer on AIX (1/n) Mar 24, 2025
Copy link

github-actions bot commented Apr 30, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@jakeegan jakeegan changed the title [clang] Implement address sanitizer on AIX (1/n) [clang] Implement address sanitizer on AIX (1/6) Apr 30, 2025
ToolChain.getSanitizerArgs(Args).needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString(Twine("-bI:") +
ToolChain.getCompilerRTPath() +
"/asan.link_with_main_exec.txt"));
Copy link
Member

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)

Copy link
Member Author

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

if (ToolChain.getSanitizerArgs(Args).linkCXXRuntimes())
CmdArgs.push_back(
Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
"/asan_cxx.link_with_main_exec.txt"));
Copy link
Member

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()) {
Copy link
Member

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));
Copy link
Member

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<
Copy link
Member

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

Copy link
Member Author

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.

Copy link
Member

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?

Copy link
Member

@MaskRay MaskRay left a 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

@jakeegan jakeegan changed the title [clang] Implement address sanitizer on AIX (1/6) [clang] Implement address sanitizer on AIX (1/n) May 7, 2025
@jakeegan jakeegan changed the title [clang] Implement address sanitizer on AIX (1/n) [clang] Implement address sanitizer on AIX May 12, 2025
@jakeegan
Copy link
Member Author

jakeegan commented May 26, 2025

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:PowerPC clang:codegen IR generation bugs: mangling, exceptions, etc. clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants