Skip to content

Commit 072f4ec

Browse files
committed
[clang] Implement address sanitizer on AIX (1/3)
The PR includes clang changes needed for the address sanitizer on AIX. Will also post llvm and compiler-rt PRs following this.
1 parent 8e6fa15 commit 072f4ec

File tree

10 files changed

+189
-9
lines changed

10 files changed

+189
-9
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ def err_drv_malformed_sanitizer_metadata_ignorelist : Error<
257257
"malformed sanitizer metadata ignorelist: '%0'">;
258258
def err_drv_unsupported_static_sanitizer_darwin : Error<
259259
"static %0 runtime is not supported on darwin">;
260+
def err_drv_unsupported_shared_sanitizer_aix : Error<
261+
"shared %0 runtime is not supported on AIX">;
260262
def err_drv_duplicate_config : Error<
261263
"no more than one option '--config' is allowed">;
262264
def err_drv_cannot_open_config_file : Error<

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,7 @@ defm xl_pragma_pack : BoolFOption<"xl-pragma-pack",
15421542
"Enable IBM XL #pragma pack handling">,
15431543
NegFlag<SetFalse>>;
15441544
def shared_libsan : Flag<["-"], "shared-libsan">,
1545-
HelpText<"Dynamically link the sanitizer runtime">;
1545+
HelpText<"Dynamically link the sanitizer runtime (Not supported for ASan on AIX)">;
15461546
def static_libsan : Flag<["-"], "static-libsan">,
15471547
HelpText<"Statically link the sanitizer runtime (Not supported for ASan, TSan or UBSan on darwin)">;
15481548
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,14 @@ static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
275275
return !CGOpts.DisableIntegratedAS;
276276
case Triple::GOFF:
277277
llvm::report_fatal_error("ASan not implemented for GOFF");
278-
case Triple::XCOFF:
279-
llvm::report_fatal_error("ASan not implemented for XCOFF.");
280278
case Triple::Wasm:
281279
case Triple::DXContainer:
282280
case Triple::SPIRV:
283281
case Triple::UnknownObjectFormat:
284282
break;
283+
case Triple::XCOFF:
284+
// FIXME: try to enable GC-friendly instrumentation for globals on AIX.
285+
return false;
285286
}
286287
return false;
287288
}

clang/lib/Driver/ToolChain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
749749
case ToolChain::FT_Shared:
750750
Suffix = TT.isOSWindows()
751751
? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
752-
: ".so";
752+
: (TT.isOSAIX() ? ".a" : ".so");
753753
break;
754754
}
755755

clang/lib/Driver/ToolChains/AIX.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <set>
2121

2222
using AIX = clang::driver::toolchains::AIX;
23+
using namespace clang;
2324
using namespace clang::driver;
2425
using namespace clang::driver::tools;
2526
using namespace clang::driver::toolchains;
@@ -233,6 +234,44 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
233234
// Specify linker input file(s).
234235
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
235236

237+
// Add sanitizer libraries.
238+
const SanitizerArgs &Sanitize = ToolChain.getSanitizerArgs(Args);
239+
const char *sanitizer = nullptr;
240+
bool NeedsSanitizerDeps = false;
241+
// For now, only support address sanitizer.
242+
if (Sanitize.needsAsanRt())
243+
sanitizer = "AddressSanitizer";
244+
245+
if (sanitizer) {
246+
if (Sanitize.needsSharedRt()) {
247+
ToolChain.getDriver().Diag(diag::err_drv_unsupported_shared_sanitizer_aix) << sanitizer;
248+
return;
249+
}
250+
NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
251+
}
252+
253+
// Add sanitizer runtime dependencies.
254+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
255+
options::OPT_shared, options::OPT_r)) {
256+
if (NeedsSanitizerDeps)
257+
linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
258+
}
259+
260+
// We won't add the static sanitizer libraries to the DSO, but we will
261+
// introduce the undefined sanitizer symbols like __asan_init to the DSO. On
262+
// AIX, this undefined sanitizer symbol cannot pass final link. Add the
263+
// import file to make these undefined symbols be resolved at runtime.
264+
if (Args.hasArg(options::OPT_shared) &&
265+
ToolChain.getSanitizerArgs(Args).needsAsanRt()) {
266+
CmdArgs.push_back(
267+
Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
268+
"/asan.link_with_main_exec.txt"));
269+
if (ToolChain.getSanitizerArgs(Args).linkCXXRuntimes())
270+
CmdArgs.push_back(
271+
Args.MakeArgString(Twine("-bI:") + ToolChain.getCompilerRTPath() +
272+
"/asan_cxx.link_with_main_exec.txt"));
273+
}
274+
236275
if (D.isUsingLTO()) {
237276
assert(!Inputs.empty() && "Must have at least one input.");
238277
// Find the first filename InputInfo object.
@@ -590,6 +629,12 @@ ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
590629
return ToolChain::RLT_CompilerRT;
591630
}
592631

632+
SanitizerMask AIX::getSupportedSanitizers() const {
633+
SanitizerMask Res = ToolChain::getSupportedSanitizers();
634+
Res |= SanitizerKind::Address;
635+
return Res;
636+
}
637+
593638
auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
594639

595640
auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }

clang/lib/Driver/ToolChains/AIX.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
9898
return llvm::DebuggerKind::DBX;
9999
}
100100

101+
SanitizerMask getSupportedSanitizers() const override;
102+
101103
protected:
102104
Tool *buildAssembler() const override;
103105
Tool *buildLinker() const override;

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,19 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
13951395
// the option, so don't try to pass it.
13961396
if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd)
13971397
return true;
1398+
1399+
if (TC.getTriple().isOSAIX()) {
1400+
SmallString<128> SanRTSymbolList;
1401+
(Twine(TC.getCompilerRTPath()) + "/" + Sanitizer +
1402+
".link_with_main_exec.txt")
1403+
.toVector(SanRTSymbolList);
1404+
if (llvm::sys::fs::exists(SanRTSymbolList)) {
1405+
CmdArgs.push_back(Args.MakeArgString(Twine("-bE:") + SanRTSymbolList));
1406+
return true;
1407+
}
1408+
return false;
1409+
}
1410+
13981411
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
13991412
if (llvm::sys::fs::exists(SanRT + ".syms")) {
14001413
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
@@ -1429,7 +1442,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
14291442
ArgStringList &CmdArgs) {
14301443
// Force linking against the system libraries sanitizers depends on
14311444
// (see PR15823 why this is necessary).
1432-
addAsNeededOption(TC, Args, CmdArgs, false);
1445+
// AIX does not support any --as-needed options.
1446+
if (!TC.getTriple().isOSAIX())
1447+
addAsNeededOption(TC, Args, CmdArgs, false);
14331448
// There's no libpthread or librt on RTEMS & Android.
14341449
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
14351450
!TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
@@ -1453,6 +1468,9 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
14531468
if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
14541469
!TC.getTriple().isMusl())
14551470
CmdArgs.push_back("-lresolv");
1471+
1472+
if (TC.getTriple().isOSAIX())
1473+
CmdArgs.push_back("-latomic");
14561474
}
14571475

14581476
static void
@@ -1508,7 +1526,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
15081526
StaticRuntimes.push_back("stats_client");
15091527

15101528
// Always link the static runtime regardless of DSO or executable.
1511-
if (SanArgs.needsAsanRt())
1529+
// Don't see a reason that AIX needs asan_static library though.
1530+
if (SanArgs.needsAsanRt() && !TC.getTriple().isOSAIX())
15121531
HelperStaticRuntimes.push_back("asan_static");
15131532

15141533
// Collect static runtimes.
@@ -1642,7 +1661,9 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
16421661
addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
16431662
bool AddExportDynamic = false;
16441663
for (auto RT : StaticRuntimes) {
1645-
addSanitizerRuntime(TC, Args, CmdArgs, RT, false, true);
1664+
// AIX does not support --whole-archive.
1665+
addSanitizerRuntime(TC, Args, CmdArgs, RT, false,
1666+
!TC.getTriple().isOSAIX());
16461667
AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
16471668
}
16481669
for (auto RT : NonWholeStaticRuntimes) {
@@ -1651,8 +1672,13 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
16511672
}
16521673
// If there is a static runtime with no dynamic list, force all the symbols
16531674
// to be dynamic to be sure we export sanitizer interface functions.
1654-
if (AddExportDynamic)
1655-
CmdArgs.push_back("--export-dynamic");
1675+
if (AddExportDynamic) {
1676+
if (!TC.getTriple().isOSAIX())
1677+
CmdArgs.push_back("--export-dynamic");
1678+
else
1679+
llvm::report_fatal_error("Sanitizer interface functions must be exported "
1680+
"by export files on AIX.");
1681+
}
16561682

16571683
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
16581684
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");

clang/test/Driver/Inputs/resource_dir/lib/aix/asan.link_with_main_exec.txt

Whitespace-only changes.

clang/test/Driver/Inputs/resource_dir/lib/aix/asan_cxx.link_with_main_exec.txt

Whitespace-only changes.

clang/test/Driver/sanitizer-ld.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,3 +1216,107 @@
12161216
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "-lresolv"
12171217
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--export-dynamic"
12181218
// CHECK-DSO-SHARED-HWASAN-AARCH64-LINUX-NOT: "--dynamic-list"
1219+
1220+
// RUN: %clang -fsanitize=address -### %s 2>&1 \
1221+
// RUN: --target=powerpc-unknown-aix \
1222+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1223+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1224+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
1225+
//
1226+
// RUN: %clang -fsanitize=address -### %s 2>&1 \
1227+
// RUN: --target=powerpc64-unknown-aix \
1228+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1229+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1230+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
1231+
//
1232+
// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
1233+
// RUN: --target=powerpc-unknown-aix \
1234+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1235+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1236+
// 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
1237+
//
1238+
// RUN: %clang --driver-mode=g++ -fsanitize=address -### %s 2>&1 \
1239+
// RUN: --target=powerpc64-unknown-aix \
1240+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1241+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1242+
// 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
1243+
//
1244+
// RUN: %clang -fsanitize=address -### %s 2>&1 \
1245+
// RUN: -static-libsan --target=powerpc-unknown-aix \
1246+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1247+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1248+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX32 %s
1249+
//
1250+
// RUN: %clang -fsanitize=address -### %s 2>&1 \
1251+
// RUN: -static-libsan --target=powerpc64-unknown-aix \
1252+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1253+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1254+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-LINK-RUNTIME-AIX,CHECK-ASAN-LINK-RUNTIME-AIX64 %s
1255+
//
1256+
// CHECK-ASAN-LINK-RUNTIME-AIX: "{{.*}}ld{{(.exe)?}}"
1257+
// CHECK-ASAN-LINK-RUNTIME-AIX32: "-b32"
1258+
// CHECK-ASAN-LINK-RUNTIME-AIX64: "-b64"
1259+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-bcdtors:all:0:s"
1260+
// CHECK-ASAN-LINK-RUNTIME-AIX32: "{{.*}}libclang_rt.asan-powerpc.a"
1261+
// CHECK-ASAN-LINK-RUNTIME-AIX64: "{{.*}}libclang_rt.asan-powerpc64.a"
1262+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-bE:{{.*}}asan.link_with_main_exec.txt"
1263+
// CHECK-ASAN-LINK-RUNTIME-AIXCXX32: "{{.*}}libclang_rt.asan_cxx-powerpc.a"
1264+
// CHECK-ASAN-LINK-RUNTIME-AIXCXX64: "{{.*}}libclang_rt.asan_cxx-powerpc64.a"
1265+
// CHECK-ASAN-LINK-RUNTIME-AIXCXX: "-bE:{{.*}}asan_cxx.link_with_main_exec.txt"
1266+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-lpthread"
1267+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-latomic"
1268+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-lunwind"
1269+
// CHECK-ASAN-LINK-RUNTIME-AIX: "-lc"
1270+
1271+
// RUN: not %clang -fsanitize=address -### %s 2>&1 \
1272+
// RUN: -shared-libsan --target=powerpc-unknown-aix \
1273+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1274+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1275+
// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
1276+
//
1277+
// RUN: not %clang -fsanitize=address -### %s 2>&1 \
1278+
// RUN: -shared-libsan --target=powerpc64-unknown-aix \
1279+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1280+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1281+
// RUN: | FileCheck --check-prefixes=CHECK-SHARED-ASAN-AIX %s
1282+
//
1283+
// CHECK-SHARED-ASAN-AIX: {{.*}}error: shared AddressSanitizer runtime is not supported on AIX
1284+
1285+
// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
1286+
// RUN: --target=powerpc-unknown-aix \
1287+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1288+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1289+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32 %s
1290+
//
1291+
// RUN: %clang -fsanitize=address -shared -### %s 2>&1 \
1292+
// RUN: --target=powerpc64-unknown-aix \
1293+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1294+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1295+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64 %s
1296+
//
1297+
// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
1298+
// RUN: --target=powerpc-unknown-aix \
1299+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1300+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1301+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX32,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
1302+
//
1303+
// RUN: %clang -fsanitize=address --driver-mode=g++ -shared -### %s 2>&1 \
1304+
// RUN: --target=powerpc64-unknown-aix \
1305+
// RUN: -resource-dir=%S/Inputs/resource_dir \
1306+
// RUN: --sysroot=%S/Inputs/aix_ppc_tree \
1307+
// RUN: | FileCheck --check-prefixes=CHECK-ASAN-SHARED-LIBRARY-AIX,CHECK-ASAN-SHARED-LIBRARY-AIX64,CHECK-ASAN-SHARED-LIBRARY-AIXCXX %s
1308+
//
1309+
// CHECK-ASAN-SHARED-LIBRARY-AIX: "{{.*}}ld{{(.exe)?}}"
1310+
// CHECK-ASAN-SHARED-LIBRARY-AIX32: "-b32"
1311+
// CHECK-ASAN-SHARED-LIBRARY-AIX64: "-b64"
1312+
// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bcdtors:all:0:s"
1313+
// CHECK-ASAN-SHARED-LIBRARY-AIX: "-bI:{{.*}}asan.link_with_main_exec.txt"
1314+
// CHECK-ASAN-SHARED-LIBRARY-AIXCXX: "-bI:{{.*}}asan_cxx.link_with_main_exec.txt"
1315+
// CHECK-ASAN-SHARED-LIBRARY-AIX32-NOT: "{{.*}}libclang_rt.asan-powerpc.a"
1316+
// CHECK-ASAN-SHARED-LIBRARY-AIX64-NOT: "{{.*}}libclang_rt.asan-powerpc64.a"
1317+
// CHECK-ASAN-SHARED-LIBRARY-AIXCXX-NOT: "{{.*}}libclang_rt.asan_cxx-powerpc{{.*}}"
1318+
// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-lpthread"
1319+
// CHECK-ASAN-SHARED-LIBRARY-AIX-NOT: "-latomic"
1320+
// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lunwind"
1321+
// CHECK-ASAN-SHARED-LIBRARY-AIX: "-lc"
1322+

0 commit comments

Comments
 (0)