Home | History | Annotate | Download | only in llvm
      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