1 From 3be54de4b8317101dedde535cef72ce56c2c20e6 Mon Sep 17 00:00:00 2001 2 From: Evgeniy Stepanov <eugeni.stepanov (a] gmail.com> 3 Date: Thu, 16 Aug 2012 15:58:17 +0800 4 Subject: [PATCH 2/2] Clang driver support for linking on Android. 5 6 --- 7 llvm-3.1/tools/clang/lib/Driver/Tools.cpp | 96 +++++++++++++++++---------- 8 llvm-3.1/tools/clang/test/Driver/asan-ld.c | 31 +++++++++ 9 llvm-3.1/tools/clang/test/Driver/linux-ld.c | 36 ++++++++++ 10 3 files changed, 127 insertions(+), 36 deletions(-) 11 create mode 100644 llvm-3.1/tools/clang/test/Driver/asan-ld.c 12 13 diff --git a/llvm-3.1/tools/clang/lib/Driver/Tools.cpp b/llvm-3.1/tools/clang/lib/Driver/Tools.cpp 14 index 4931f8c..8ef16b5 100644 15 --- a/llvm-3.1/tools/clang/lib/Driver/Tools.cpp 16 +++ b/llvm-3.1/tools/clang/lib/Driver/Tools.cpp 17 @@ -1269,22 +1269,33 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { 18 /// This needs to be called before we add the C run-time (malloc, etc). 19 static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, 20 ArgStringList &CmdArgs) { 21 - // Add asan linker flags when linking an executable, but not a shared object. 22 - if (Args.hasArg(options::OPT_shared) || 23 - !Args.hasFlag(options::OPT_faddress_sanitizer, 24 + if (!Args.hasFlag(options::OPT_faddress_sanitizer, 25 options::OPT_fno_address_sanitizer, false)) 26 return; 27 + if(TC.getTriple().getEnvironment() == llvm::Triple::ANDROIDEABI) { 28 + if (!Args.hasArg(options::OPT_shared)) { 29 + // For an executable, we add a .preinit_array stub. 30 + CmdArgs.push_back("-u"); 31 + CmdArgs.push_back("__asan_preinit"); 32 + CmdArgs.push_back("-lasan"); 33 + } 34 35 - // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library resource 36 - // directory. 37 - SmallString<128> LibAsan(TC.getDriver().ResourceDir); 38 - llvm::sys::path::append(LibAsan, "lib", "linux", 39 - (Twine("libclang_rt.asan-") + 40 - TC.getArchName() + ".a")); 41 - CmdArgs.push_back(Args.MakeArgString(LibAsan)); 42 - CmdArgs.push_back("-lpthread"); 43 - CmdArgs.push_back("-ldl"); 44 - CmdArgs.push_back("-export-dynamic"); 45 + CmdArgs.push_back("-lasan_preload"); 46 + CmdArgs.push_back("-ldl"); 47 + } else { 48 + if (!Args.hasArg(options::OPT_shared)) { 49 + // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library 50 + // resource directory. 51 + SmallString<128> LibAsan(TC.getDriver().ResourceDir); 52 + llvm::sys::path::append(LibAsan, "lib", "linux", 53 + (Twine("libclang_rt.asan-") + 54 + TC.getArchName() + ".a")); 55 + CmdArgs.push_back(Args.MakeArgString(LibAsan)); 56 + CmdArgs.push_back("-lpthread"); 57 + CmdArgs.push_back("-ldl"); 58 + CmdArgs.push_back("-export-dynamic"); 59 + } 60 + } 61 } 62 63 static bool shouldUseFramePointer(const ArgList &Args, 64 @@ -5112,9 +5123,10 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 65 C.addCommand(new Command(JA, *this, Exec, CmdArgs)); 66 } 67 68 -static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs, 69 - const ArgList &Args) { 70 - bool StaticLibgcc = Args.hasArg(options::OPT_static) || 71 +static void AddLibgcc(llvm::Triple Triple, const Driver &D, 72 + ArgStringList &CmdArgs, const ArgList &Args) { 73 + bool isAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI; 74 + bool StaticLibgcc = isAndroid || Args.hasArg(options::OPT_static) || 75 Args.hasArg(options::OPT_static_libgcc); 76 if (!D.CCCIsCXX) 77 CmdArgs.push_back("-lgcc"); 78 @@ -5130,7 +5142,7 @@ static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs, 79 CmdArgs.push_back("--no-as-needed"); 80 } 81 82 - if (StaticLibgcc) 83 + if (StaticLibgcc && !isAndroid) 84 CmdArgs.push_back("-lgcc_eh"); 85 else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) 86 CmdArgs.push_back("-lgcc"); 87 @@ -5144,6 +5156,9 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 88 const toolchains::Linux& ToolChain = 89 static_cast<const toolchains::Linux&>(getToolChain()); 90 const Driver &D = ToolChain.getDriver(); 91 + const bool isAndroid = ToolChain.getTriple().getEnvironment() == 92 + llvm::Triple::ANDROIDEABI; 93 + 94 ArgStringList CmdArgs; 95 96 // Silence warning for "clang -g foo.o -o foo" 97 @@ -5204,6 +5219,10 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 98 CmdArgs.push_back("-static"); 99 } else if (Args.hasArg(options::OPT_shared)) { 100 CmdArgs.push_back("-shared"); 101 + if ((ToolChain.getArch() == llvm::Triple::arm 102 + || ToolChain.getArch() == llvm::Triple::thumb) && isAndroid) { 103 + CmdArgs.push_back("-Bsymbolic"); 104 + } 105 } 106 107 if (ToolChain.getArch() == llvm::Triple::arm || 108 @@ -5211,7 +5230,9 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 109 (!Args.hasArg(options::OPT_static) && 110 !Args.hasArg(options::OPT_shared))) { 111 CmdArgs.push_back("-dynamic-linker"); 112 - if (ToolChain.getArch() == llvm::Triple::x86) 113 + if (isAndroid) 114 + CmdArgs.push_back("/system/bin/linker"); 115 + else if (ToolChain.getArch() == llvm::Triple::x86) 116 CmdArgs.push_back("/lib/ld-linux.so.2"); 117 else if (ToolChain.getArch() == llvm::Triple::arm || 118 ToolChain.getArch() == llvm::Triple::thumb) 119 @@ -5235,25 +5256,27 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 120 121 if (!Args.hasArg(options::OPT_nostdlib) && 122 !Args.hasArg(options::OPT_nostartfiles)) { 123 - const char *crt1 = NULL; 124 - if (!Args.hasArg(options::OPT_shared)){ 125 - if (Args.hasArg(options::OPT_pie)) 126 - crt1 = "Scrt1.o"; 127 - else 128 - crt1 = "crt1.o"; 129 - } 130 - if (crt1) 131 - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); 132 + if (!isAndroid) { 133 + const char *crt1 = NULL; 134 + if (!Args.hasArg(options::OPT_shared)){ 135 + if (Args.hasArg(options::OPT_pie)) 136 + crt1 = "Scrt1.o"; 137 + else 138 + crt1 = "crt1.o"; 139 + } 140 + if (crt1) 141 + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); 142 143 - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); 144 + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); 145 + } 146 147 const char *crtbegin; 148 if (Args.hasArg(options::OPT_static)) 149 - crtbegin = "crtbeginT.o"; 150 + crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o"; 151 else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 152 - crtbegin = "crtbeginS.o"; 153 + crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o"; 154 else 155 - crtbegin = "crtbegin.o"; 156 + crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbegin.o"; 157 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); 158 } 159 160 @@ -5294,7 +5317,7 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 161 if (Args.hasArg(options::OPT_static)) 162 CmdArgs.push_back("--start-group"); 163 164 - AddLibgcc(D, CmdArgs, Args); 165 + AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); 166 167 if (Args.hasArg(options::OPT_pthread) || 168 Args.hasArg(options::OPT_pthreads)) 169 @@ -5305,18 +5328,19 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, 170 if (Args.hasArg(options::OPT_static)) 171 CmdArgs.push_back("--end-group"); 172 else 173 - AddLibgcc(D, CmdArgs, Args); 174 + AddLibgcc(ToolChain.getTriple(), D, CmdArgs, Args); 175 176 177 if (!Args.hasArg(options::OPT_nostartfiles)) { 178 const char *crtend; 179 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 180 - crtend = "crtendS.o"; 181 + crtend = isAndroid ? "crtend_so.o" : "crtendS.o"; 182 else 183 - crtend = "crtend.o"; 184 + crtend = isAndroid ? "crtend_android.o" : "crtend.o"; 185 186 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); 187 - CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 188 + if (!isAndroid) 189 + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 190 } 191 } 192 193 diff --git a/llvm-3.1/tools/clang/test/Driver/asan-ld.c b/llvm-3.1/tools/clang/test/Driver/asan-ld.c 194 new file mode 100644 195 index 0000000..feb8e21 196 --- /dev/null 197 +++ b/llvm-3.1/tools/clang/test/Driver/asan-ld.c 198 @@ -0,0 +1,31 @@ 199 +// Test AddressSanitizer ld flags. 200 + 201 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 202 +// RUN: -target i386-unknown-linux -faddress-sanitizer \ 203 +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ 204 +// RUN: | FileCheck --check-prefix=CHECK-LINUX %s 205 +// CHECK-LINUX: "{{.*}}ld{{(.exe)?}}" 206 +// CHECK-LINUX-NOT: "-lc" 207 +// CHECK-LINUX: lib/linux/libclang_rt.asan-i386.a" 208 +// CHECK-LINUX: "-lpthread" 209 +// CHECK-LINUX: "-ldl" 210 +// CHECK-LINUX: "-export-dynamic" 211 + 212 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 213 +// RUN: -target arm-linux-androideabi -faddress-sanitizer \ 214 +// RUN: --sysroot=%S/Inputs/basic_android_tree \ 215 +// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s 216 +// CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" 217 +// CHECK-ANDROID-NOT: "-lc" 218 +// CHECK-ANDROID: "-u" "__asan_preinit" "-lasan" 219 +// CHECK-ANDROID: "-lasan_preload" "-ldl" 220 + 221 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 222 +// RUN: -target arm-linux-androideabi -faddress-sanitizer \ 223 +// RUN: --sysroot=%S/Inputs/basic_android_tree \ 224 +// RUN: -shared \ 225 +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SHARED %s 226 +// CHECK-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}" 227 +// CHECK-ANDROID-SHARED-NOT: "-lc" 228 +// CHECK-ANDROID-SHARED-NOT: "-lasan" 229 +// CHECK-ANDROID-SHARED: "-lasan_preload" "-ldl" 230 diff --git a/llvm-3.1/tools/clang/test/Driver/linux-ld.c b/llvm-3.1/tools/clang/test/Driver/linux-ld.c 231 index 9a35d5d..3d6a7e6 100644 232 --- a/llvm-3.1/tools/clang/test/Driver/linux-ld.c 233 +++ b/llvm-3.1/tools/clang/test/Driver/linux-ld.c 234 @@ -268,3 +268,39 @@ 235 // CHECK-DEBIAN-PPC64: "-L[[SYSROOT]]/lib" 236 // CHECK-DEBIAN-PPC64: "-L[[SYSROOT]]/usr/lib" 237 // 238 +// Test linker invocation on Android. 239 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 240 +// RUN: -target arm-linux-androideabi \ 241 +// RUN: --sysroot=%S/Inputs/basic_android_tree \ 242 +// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s 243 +// CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" 244 +// CHECK-ANDROID: "{{.*}}/crtbegin_dynamic.o" 245 +// CHECK-ANDROID: "-L[[SYSROOT]]/usr/lib" 246 +// CHECK-ANDROID-NOT: "gcc_s" 247 +// CHECK-ANDROID: "-lgcc" 248 +// CHECK-ANDROID-NOT: "gcc_s" 249 +// CHECK-ANDROID: "{{.*}}/crtend_android.o" 250 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 251 +// RUN: -target arm-linux-androideabi \ 252 +// RUN: --sysroot=%S/Inputs/basic_android_tree \ 253 +// RUN: -shared \ 254 +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s 255 +// CHECK-ANDROID-SO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" 256 +// CHECK-ANDROID-SO: "{{.*}}/crtbegin_so.o" 257 +// CHECK-ANDROID-SO: "-L[[SYSROOT]]/usr/lib" 258 +// CHECK-ANDROID-SO-NOT: "gcc_s" 259 +// CHECK-ANDROID-SO: "-lgcc" 260 +// CHECK-ANDROID-SO-NOT: "gcc_s" 261 +// CHECK-ANDROID-SO: "{{.*}}/crtend_so.o" 262 +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ 263 +// RUN: -target arm-linux-androideabi \ 264 +// RUN: --sysroot=%S/Inputs/basic_android_tree \ 265 +// RUN: -static \ 266 +// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s 267 +// CHECK-ANDROID-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" 268 +// CHECK-ANDROID-STATIC: "{{.*}}/crtbegin_static.o" 269 +// CHECK-ANDROID-STATIC: "-L[[SYSROOT]]/usr/lib" 270 +// CHECK-ANDROID-STATIC-NOT: "gcc_s" 271 +// CHECK-ANDROID-STATIC: "-lgcc" 272 +// CHECK-ANDROID-STATIC-NOT: "gcc_s" 273 +// CHECK-ANDROID-STATIC: "{{.*}}/crtend_android.o" 274 -- 275 1.7.7.3 276 277