/// This needs to be called before we add the C run-time (malloc, etc).
static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- // Add asan linker flags when linking an executable, but not a shared object.
- if (Args.hasArg(options::OPT_shared) ||
- !Args.hasFlag(options::OPT_faddress_sanitizer,
+ if (!Args.hasFlag(options::OPT_faddress_sanitizer,
options::OPT_fno_address_sanitizer, false))
return;
+ if(TC.getTriple().getEnvironment() == llvm::Triple::ANDROIDEABI) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ // For an executable, we add a .preinit_array stub.
+ CmdArgs.push_back("-u");
+ CmdArgs.push_back("__asan_preinit");
+ CmdArgs.push_back("-lasan");
+ }
- // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library resource
- // directory.
- SmallString<128> LibAsan(TC.getDriver().ResourceDir);
- llvm::sys::path::append(LibAsan, "lib", "linux",
- (Twine("libclang_rt.asan-") +
- TC.getArchName() + ".a"));
- CmdArgs.push_back(Args.MakeArgString(LibAsan));
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-ldl");
- CmdArgs.push_back("-export-dynamic");
+ CmdArgs.push_back("-lasan_preload");
+ CmdArgs.push_back("-ldl");
+ } else {
+ if (!Args.hasArg(options::OPT_shared)) {
+ // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library
+ // resource directory.
+ SmallString<128> LibAsan(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(LibAsan, "lib", "linux",
+ (Twine("libclang_rt.asan-") +
+ TC.getArchName() + ".a"));
+ CmdArgs.push_back(Args.MakeArgString(LibAsan));
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-ldl");
+ CmdArgs.push_back("-export-dynamic");
+ }
+ }
}
static bool shouldUseFramePointer(const ArgList &Args,
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
-static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs,
- const ArgList &Args) {
- bool StaticLibgcc = Args.hasArg(options::OPT_static) ||
+static void AddLibgcc(llvm::Triple Triple, const Driver &D,
+ ArgStringList &CmdArgs, const ArgList &Args) {
+ bool isAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI;
+ bool StaticLibgcc = isAndroid || Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_static_libgcc);
if (!D.CCCIsCXX)
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("--no-as-needed");
}
- if (StaticLibgcc)
+ if (StaticLibgcc && !isAndroid)
CmdArgs.push_back("-lgcc_eh");
else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX)
CmdArgs.push_back("-lgcc");
const toolchains::Linux& ToolChain =
static_cast<const toolchains::Linux&>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const bool isAndroid = ToolChain.getTriple().getEnvironment() ==
+ llvm::Triple::ANDROIDEABI;
+
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
CmdArgs.push_back("-static");
} else if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
+ if ((ToolChain.getArch() == llvm::Triple::arm
+ || ToolChain.getArch() == llvm::Triple::thumb) && isAndroid) {
+ CmdArgs.push_back("-Bsymbolic");
+ }
}
if (ToolChain.getArch() == llvm::Triple::arm ||
(!Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_shared))) {
CmdArgs.push_back("-dynamic-linker");
- if (ToolChain.getArch() == llvm::Triple::x86)
+ if (isAndroid)
+ CmdArgs.push_back("/system/bin/linker");
+ else if (ToolChain.getArch() == llvm::Triple::x86)
CmdArgs.push_back("/lib/ld-linux.so.2");
else if (ToolChain.getArch() == llvm::Triple::arm ||
ToolChain.getArch() == llvm::Triple::thumb)
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
- const char *crt1 = NULL;
- if (!Args.hasArg(options::OPT_shared)){
- if (Args.hasArg(options::OPT_pie))
- crt1 = "Scrt1.o";
- else
- crt1 = "crt1.o";
- }
- if (crt1)
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+ if (!isAndroid) {
+ const char *crt1 = NULL;
+ if (!Args.hasArg(options::OPT_shared)){
+ if (Args.hasArg(options::OPT_pie))
+ crt1 = "Scrt1.o";
+ else
+ crt1 = "crt1.o";
+ }
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ }
const char *crtbegin;
if (Args.hasArg(options::OPT_static))
- crtbegin = "crtbeginT.o";
+ crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- crtbegin = "crtbeginS.o";
+ crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
else
- crtbegin = "crtbegin.o";
+ crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o";
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--start-group");
- AddLibgcc(D, CmdArgs, Args);
+ AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
if (Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads))
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--end-group");
else
- AddLibgcc(D, CmdArgs, Args);
+ AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args);
if (!Args.hasArg(options::OPT_nostartfiles)) {
const char *crtend;
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- crtend = "crtendS.o";
+ crtend = isAndroid ? "crtend_so.o" : "crtendS.o";
else
- crtend = "crtend.o";
+ crtend = isAndroid ? "crtend_android.o" : "crtend.o";
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ if (!isAndroid)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
}
--- /dev/null
+// Test AddressSanitizer ld flags.
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target i386-unknown-linux -faddress-sanitizer \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-LINUX-NOT: "-lc"
+// CHECK-LINUX: lib/linux/libclang_rt.asan-i386.a"
+// CHECK-LINUX: "-lpthread"
+// CHECK-LINUX: "-ldl"
+// CHECK-LINUX: "-export-dynamic"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi -faddress-sanitizer \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
+// CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ANDROID-NOT: "-lc"
+// CHECK-ANDROID: "-u" "__asan_preinit" "-lasan"
+// CHECK-ANDROID: "-lasan_preload" "-ldl"
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi -faddress-sanitizer \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: -shared \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SHARED %s
+// CHECK-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ANDROID-SHARED-NOT: "-lc"
+// CHECK-ANDROID-SHARED-NOT: "-lasan"
+// CHECK-ANDROID-SHARED: "-lasan_preload" "-ldl"
// CHECK-DEBIAN-PPC64: "-L[[SYSROOT]]/lib"
// CHECK-DEBIAN-PPC64: "-L[[SYSROOT]]/usr/lib"
//
+// Test linker invocation on Android.
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
+// CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-ANDROID: "{{.*}}/crtbegin_dynamic.o"
+// CHECK-ANDROID: "-L[[SYSROOT]]/usr/lib"
+// CHECK-ANDROID-NOT: "gcc_s"
+// CHECK-ANDROID: "-lgcc"
+// CHECK-ANDROID-NOT: "gcc_s"
+// CHECK-ANDROID: "{{.*}}/crtend_android.o"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: -shared \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
+// CHECK-ANDROID-SO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-ANDROID-SO: "{{.*}}/crtbegin_so.o"
+// CHECK-ANDROID-SO: "-L[[SYSROOT]]/usr/lib"
+// CHECK-ANDROID-SO-NOT: "gcc_s"
+// CHECK-ANDROID-SO: "-lgcc"
+// CHECK-ANDROID-SO-NOT: "gcc_s"
+// CHECK-ANDROID-SO: "{{.*}}/crtend_so.o"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: -static \
+// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
+// CHECK-ANDROID-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-ANDROID-STATIC: "{{.*}}/crtbegin_static.o"
+// CHECK-ANDROID-STATIC: "-L[[SYSROOT]]/usr/lib"
+// CHECK-ANDROID-STATIC-NOT: "gcc_s"
+// CHECK-ANDROID-STATIC: "-lgcc"
+// CHECK-ANDROID-STATIC-NOT: "gcc_s"
+// CHECK-ANDROID-STATIC: "{{.*}}/crtend_android.o"