1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "bcc/AndroidBitcode/ABCCompilerDriver.h" 18 19 #include <llvm/IR/Module.h> 20 #include <llvm/Pass.h> 21 #include <llvm/Support/MemoryBuffer.h> 22 #include <llvm/Support/raw_ostream.h> 23 #include <mcld/Config/Config.h> 24 25 #include "bcc/Config/Config.h" 26 #include "bcc/Script.h" 27 #include "bcc/Source.h" 28 #include "bcc/Support/CompilerConfig.h" 29 #include "bcc/Support/LinkerConfig.h" 30 #include "bcc/Support/Log.h" 31 #include "bcc/Support/OutputFile.h" 32 #include "bcc/Support/TargetLinkerConfigs.h" 33 #include "bcc/Support/TargetCompilerConfigs.h" 34 35 #if defined(PROVIDE_ARM_CODEGEN) 36 # include "ARM/ARMABCCompilerDriver.h" 37 #endif 38 #if defined(PROVIDE_MIPS_CODEGEN) 39 # include "Mips/MipsABCCompilerDriver.h" 40 #endif 41 #if defined(PROVIDE_X86_CODEGEN) 42 # include "X86/X86ABCCompilerDriver.h" 43 #endif 44 45 namespace bcc { 46 47 ABCCompilerDriver::ABCCompilerDriver() 48 : mContext(), mCompiler(*this), mLinker(), 49 mCompilerConfig(NULL), mLinkerConfig(NULL), mAndroidSysroot("/") { 50 } 51 52 ABCCompilerDriver::~ABCCompilerDriver() { 53 delete mCompilerConfig; 54 delete mLinkerConfig; 55 } 56 57 bool ABCCompilerDriver::configCompiler() { 58 if (mCompilerConfig != NULL) { 59 return true; 60 } 61 62 mCompilerConfig = createCompilerConfig(); 63 if (mCompilerConfig == NULL) { 64 ALOGE("Out of memory when create the compiler configuration!"); 65 return false; 66 } 67 68 // Set PIC mode for relocatables. 69 mCompilerConfig->setRelocationModel(llvm::Reloc::PIC_); 70 71 // Set optimization level to -O1. 72 mCompilerConfig->setOptimizationLevel(llvm::CodeGenOpt::Less); 73 74 Compiler::ErrorCode result = mCompiler.config(*mCompilerConfig); 75 76 if (result != Compiler::kSuccess) { 77 ALOGE("Failed to configure the compiler! (detail: %s)", 78 Compiler::GetErrorString(result)); 79 return false; 80 } 81 82 return true; 83 } 84 85 bool ABCCompilerDriver::configLinker() { 86 if (mLinkerConfig != NULL) { 87 return true; 88 } 89 90 mLinkerConfig = createLinkerConfig(); 91 if (mLinkerConfig == NULL) { 92 ALOGE("Out of memory when create the linker configuration!"); 93 return false; 94 } 95 96 // FIXME: how can we get the soname if input/output is file descriptor? 97 mLinkerConfig->setSOName(""); 98 99 mLinkerConfig->setDyld("/system/bin/linker"); 100 mLinkerConfig->setSysRoot(mAndroidSysroot); 101 mLinkerConfig->addSearchDir("=/system/lib"); 102 103 // Add non-portable function list. For each function X, linker will rename 104 // it to X_portable. And X_portable" is implemented in libportable to solve 105 // portable issues. 106 const char **non_portable_func = getNonPortableList(); 107 if (non_portable_func != NULL) { 108 while (*non_portable_func != NULL) { 109 mLinkerConfig->addPortable(*non_portable_func); 110 non_portable_func++; 111 } 112 } 113 114 // -shared 115 mLinkerConfig->setShared(true); 116 117 // -Bsymbolic. 118 mLinkerConfig->setBsymbolic(true); 119 120 // Set kRelro for -z relro 121 // Not set kExecStack for -z noexecstack 122 // Not set kLazy for -z now 123 mLinkerConfig->setZOption(LinkerConfig::kRelro); 124 125 // Config the linker. 126 Linker::ErrorCode result = mLinker.config(*mLinkerConfig); 127 if (result != Linker::kSuccess) { 128 ALOGE("Failed to configure the linker! (%s)", 129 Linker::GetErrorString(result)); 130 return false; 131 } 132 133 return true; 134 } 135 136 //------------------------------------------------------------------------------ 137 138 Script *ABCCompilerDriver::prepareScript(int pInputFd) { 139 Source *source = Source::CreateFromFd(mContext, pInputFd); 140 if (source == NULL) { 141 ALOGE("Failed to load LLVM module from file descriptor `%d'", pInputFd); 142 return NULL; 143 } 144 145 Script *script = new (std::nothrow) Script(*source); 146 if (script == NULL) { 147 ALOGE("Out of memory when create script for file descriptor `%d'!", 148 pInputFd); 149 delete source; 150 return NULL; 151 } 152 153 return script; 154 } 155 156 bool ABCCompilerDriver::compile(Script &pScript, llvm::raw_ostream &pOutput) { 157 // Config the compiler. 158 if (!configCompiler()) { 159 return false; 160 } 161 162 // Run the compiler. 163 Compiler::ErrorCode result = mCompiler.compile(pScript, pOutput); 164 if (result != Compiler::kSuccess) { 165 ALOGE("Fatal error during compilation (%s)!", 166 Compiler::GetErrorString(result)); 167 return false; 168 } 169 170 return true; 171 } 172 173 bool ABCCompilerDriver::link(const Script &pScript, 174 const std::string &input_relocatable, 175 int pOutputFd) { 176 // Config the linker. 177 if (!configLinker()) { 178 return false; 179 } 180 181 // Prepare output file. 182 Linker::ErrorCode result = mLinker.setOutput(pOutputFd); 183 184 if (result != Linker::kSuccess) { 185 ALOGE("Failed to open the output file! (file descriptor `%d': %s)", 186 pOutputFd, Linker::GetErrorString(result)); 187 return false; 188 } 189 190 mLinker.addObject(mAndroidSysroot + "/system/lib/crtbegin_so.o"); 191 192 // Prepare the relocatables. 193 // 194 // FIXME: Ugly const_cast here. 195 mLinker.addObject(const_cast<char *>(input_relocatable.data()), 196 input_relocatable.size()); 197 198 // TODO: Refactor libbcc/runtime/ to libcompilerRT.so and use it. 199 mLinker.addNameSpec("bcc"); 200 201 mLinker.addObject(mAndroidSysroot + "/system/lib/crtend_so.o"); 202 203 // Perform linking. 204 result = mLinker.link(); 205 if (result != Linker::kSuccess) { 206 ALOGE("Failed to link the shared object (detail: %s)", 207 Linker::GetErrorString(result)); 208 return false; 209 } 210 211 return true; 212 } 213 214 //------------------------------------------------------------------------------ 215 216 ABCCompilerDriver *ABCCompilerDriver::Create(const std::string &pTriple) { 217 std::string error; 218 const llvm::Target *target = 219 llvm::TargetRegistry::lookupTarget(pTriple, error); 220 221 if (target == NULL) { 222 ALOGE("Unsupported target '%s' (detail: %s)!", pTriple.c_str(), 223 error.c_str()); 224 return NULL; 225 } 226 227 switch (llvm::Triple::getArchTypeForLLVMName(target->getName())) { 228 #if defined(PROVIDE_ARM_CODEGEN) 229 case llvm::Triple::arm: { 230 return new ARMABCCompilerDriver(/* pInThumbMode */false); 231 } 232 case llvm::Triple::thumb: { 233 return new ARMABCCompilerDriver(/* pInThumbMode */true); 234 } 235 #endif 236 #if defined(PROVIDE_MIPS_CODEGEN) 237 case llvm::Triple::mipsel: { 238 return new MipsABCCompilerDriver(); 239 } 240 #endif 241 #if defined(PROVIDE_X86_CODEGEN) 242 case llvm::Triple::x86: { 243 return new X86ABCCompilerDriver(); 244 } 245 #endif 246 default: { 247 ALOGE("Unknown architecture '%s' supplied in %s!", target->getName(), 248 pTriple.c_str()); 249 break; 250 } 251 } 252 253 return NULL; 254 } 255 256 bool ABCCompilerDriver::build(int pInputFd, int pOutputFd) { 257 //===--------------------------------------------------------------------===// 258 // Prepare the input. 259 //===--------------------------------------------------------------------===// 260 Script *script = prepareScript(pInputFd); 261 if (script == NULL) { 262 return false; 263 } 264 265 //===--------------------------------------------------------------------===// 266 // Prepare the output. 267 //===--------------------------------------------------------------------===// 268 std::string output_relocatable; 269 llvm::raw_ostream *output = 270 new (std::nothrow) llvm::raw_string_ostream(output_relocatable); 271 if (output == NULL) { 272 ALOGE("Failed to prepare the output for compile the input from %d into " 273 "relocatable object!", pInputFd); 274 delete script; 275 return false; 276 } 277 278 //===--------------------------------------------------------------------===// 279 // Compile. 280 //===--------------------------------------------------------------------===// 281 if (!compile(*script, *output)) { 282 delete output; 283 delete script; 284 return false; 285 } 286 287 //===--------------------------------------------------------------------===// 288 // Close the output. 289 //===--------------------------------------------------------------------===// 290 delete output; 291 292 //===--------------------------------------------------------------------===// 293 // Link. 294 //===--------------------------------------------------------------------===// 295 if (!link(*script, output_relocatable, pOutputFd)) { 296 delete script; 297 return false; 298 } 299 300 //===--------------------------------------------------------------------===// 301 // Clean up. 302 //===--------------------------------------------------------------------===// 303 delete script; 304 305 return true; 306 } 307 308 } // namespace bcc 309