1 /* 2 * Copyright (C) 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 "elf_writer_mclinker.h" 18 19 #include <llvm/Support/ELF.h> 20 #include <llvm/Support/TargetSelect.h> 21 22 #include <mcld/Environment.h> 23 #include <mcld/IRBuilder.h> 24 #include <mcld/Linker.h> 25 #include <mcld/LinkerConfig.h> 26 #include <mcld/LinkerScript.h> 27 #include <mcld/MC/ZOption.h> 28 #include <mcld/Module.h> 29 #include <mcld/Support/Path.h> 30 #include <mcld/Support/TargetSelect.h> 31 32 #include "base/unix_file/fd_file.h" 33 #include "class_linker.h" 34 #include "dex_method_iterator.h" 35 #include "driver/compiler_driver.h" 36 #include "elf_file.h" 37 #include "globals.h" 38 #include "mirror/art_method.h" 39 #include "mirror/art_method-inl.h" 40 #include "mirror/object-inl.h" 41 #include "oat_writer.h" 42 #include "scoped_thread_state_change.h" 43 #include "vector_output_stream.h" 44 45 namespace art { 46 47 ElfWriterMclinker::ElfWriterMclinker(const CompilerDriver& driver, File* elf_file) 48 : ElfWriter(driver, elf_file), oat_input_(nullptr) { 49 } 50 51 ElfWriterMclinker::~ElfWriterMclinker() { 52 } 53 54 bool ElfWriterMclinker::Create(File* elf_file, 55 OatWriter* oat_writer, 56 const std::vector<const DexFile*>& dex_files, 57 const std::string& android_root, 58 bool is_host, 59 const CompilerDriver& driver) { 60 ElfWriterMclinker elf_writer(driver, elf_file); 61 return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 62 } 63 64 bool ElfWriterMclinker::Write(OatWriter* oat_writer, 65 const std::vector<const DexFile*>& dex_files, 66 const std::string& android_root, 67 bool is_host) { 68 std::vector<uint8_t> oat_contents; 69 oat_contents.reserve(oat_writer->GetSize()); 70 VectorOutputStream output_stream("oat contents", oat_contents); 71 CHECK(oat_writer->Write(&output_stream)); 72 CHECK_EQ(oat_writer->GetSize(), oat_contents.size()); 73 74 Init(); 75 AddOatInput(oat_contents); 76 if (kUsePortableCompiler) { 77 AddMethodInputs(dex_files); 78 AddRuntimeInputs(android_root, is_host); 79 } 80 if (!Link()) { 81 return false; 82 } 83 oat_contents.clear(); 84 if (kUsePortableCompiler) { 85 FixupOatMethodOffsets(dex_files); 86 } 87 return true; 88 } 89 90 static void InitializeLLVM() { 91 // TODO: this is lifted from art's compiler_llvm.cc, should be factored out 92 if (kIsTargetBuild) { 93 llvm::InitializeNativeTarget(); 94 // TODO: odd that there is no InitializeNativeTargetMC? 95 } else { 96 llvm::InitializeAllTargets(); 97 llvm::InitializeAllTargetMCs(); 98 } 99 } 100 101 void ElfWriterMclinker::Init() { 102 std::string target_triple; 103 std::string target_cpu; 104 std::string target_attr; 105 CompilerDriver::InstructionSetToLLVMTarget(compiler_driver_->GetInstructionSet(), 106 &target_triple, 107 &target_cpu, 108 &target_attr); 109 110 // Based on mclinker's llvm-mcld.cpp main() and LinkerTest 111 // 112 // TODO: LinkerTest uses mcld::Initialize(), but it does an 113 // llvm::InitializeAllTargets, which we don't want. Basically we 114 // want mcld::InitializeNative, but it doesn't exist yet, so we 115 // inline the minimal we need here. 116 InitializeLLVM(); 117 mcld::InitializeAllTargets(); 118 mcld::InitializeAllLinkers(); 119 mcld::InitializeAllEmulations(); 120 mcld::InitializeAllDiagnostics(); 121 122 linker_config_.reset(new mcld::LinkerConfig(target_triple)); 123 CHECK(linker_config_.get() != NULL); 124 linker_config_->setCodeGenType(mcld::LinkerConfig::DynObj); 125 linker_config_->options().setSOName(elf_file_->GetPath()); 126 127 // error on undefined symbols. 128 // TODO: should this just be set if kIsDebugBuild? 129 linker_config_->options().setNoUndefined(true); 130 131 if (compiler_driver_->GetInstructionSet() == kMips) { 132 // MCLinker defaults MIPS section alignment to 0x10000, not 133 // 0x1000. The ABI says this is because the max page size is 134 // general is 64k but that isn't true on Android. 135 mcld::ZOption z_option; 136 z_option.setKind(mcld::ZOption::MaxPageSize); 137 z_option.setPageSize(kPageSize); 138 linker_config_->options().addZOption(z_option); 139 } 140 141 // TODO: Wire up mcld DiagnosticEngine to LOG? 142 linker_config_->options().setColor(false); 143 if (false) { 144 // enables some tracing of input file processing 145 linker_config_->options().setTrace(true); 146 } 147 148 // Based on alone::Linker::config 149 linker_script_.reset(new mcld::LinkerScript()); 150 module_.reset(new mcld::Module(linker_config_->options().soname(), *linker_script_.get())); 151 CHECK(module_.get() != NULL); 152 ir_builder_.reset(new mcld::IRBuilder(*module_.get(), *linker_config_.get())); 153 CHECK(ir_builder_.get() != NULL); 154 linker_.reset(new mcld::Linker()); 155 CHECK(linker_.get() != NULL); 156 linker_->emulate(*linker_script_.get(), *linker_config_.get()); 157 } 158 159 void ElfWriterMclinker::AddOatInput(std::vector<uint8_t>& oat_contents) { 160 // Add an artificial memory input. Based on LinkerTest. 161 std::string error_msg; 162 std::unique_ptr<OatFile> oat_file(OatFile::OpenMemory(oat_contents, elf_file_->GetPath(), &error_msg)); 163 CHECK(oat_file.get() != NULL) << elf_file_->GetPath() << ": " << error_msg; 164 165 const char* oat_data_start = reinterpret_cast<const char*>(&oat_file->GetOatHeader()); 166 const size_t oat_data_length = oat_file->GetOatHeader().GetExecutableOffset(); 167 const char* oat_code_start = oat_data_start + oat_data_length; 168 const size_t oat_code_length = oat_file->Size() - oat_data_length; 169 170 // TODO: ownership of oat_input? 171 oat_input_ = ir_builder_->CreateInput("oat contents", 172 mcld::sys::fs::Path("oat contents path"), 173 mcld::Input::Object); 174 CHECK(oat_input_ != NULL); 175 176 // TODO: ownership of null_section? 177 mcld::LDSection* null_section = ir_builder_->CreateELFHeader(*oat_input_, 178 "", 179 mcld::LDFileFormat::Null, 180 SHT_NULL, 181 0); 182 CHECK(null_section != NULL); 183 184 // TODO: we should split readonly data from readonly executable 185 // code like .oat does. We need to control section layout with 186 // linker script like functionality to guarantee references 187 // between sections maintain relative position which isn't 188 // possible right now with the mclinker APIs. 189 CHECK(oat_code_start != NULL); 190 191 // we need to ensure that oatdata is page aligned so when we 192 // fixup the segment load addresses, they remain page aligned. 193 uint32_t alignment = kPageSize; 194 195 // TODO: ownership of text_section? 196 mcld::LDSection* text_section = ir_builder_->CreateELFHeader(*oat_input_, 197 ".text", 198 SHT_PROGBITS, 199 SHF_EXECINSTR | SHF_ALLOC, 200 alignment); 201 CHECK(text_section != NULL); 202 203 mcld::SectionData* text_sectiondata = ir_builder_->CreateSectionData(*text_section); 204 CHECK(text_sectiondata != NULL); 205 206 // TODO: why does IRBuilder::CreateRegion take a non-const pointer? 207 mcld::Fragment* text_fragment = ir_builder_->CreateRegion(const_cast<char*>(oat_data_start), 208 oat_file->Size()); 209 CHECK(text_fragment != NULL); 210 ir_builder_->AppendFragment(*text_fragment, *text_sectiondata); 211 212 ir_builder_->AddSymbol(*oat_input_, 213 "oatdata", 214 mcld::ResolveInfo::Object, 215 mcld::ResolveInfo::Define, 216 mcld::ResolveInfo::Global, 217 oat_data_length, // size 218 0, // offset 219 text_section); 220 221 ir_builder_->AddSymbol(*oat_input_, 222 "oatexec", 223 mcld::ResolveInfo::Function, 224 mcld::ResolveInfo::Define, 225 mcld::ResolveInfo::Global, 226 oat_code_length, // size 227 oat_data_length, // offset 228 text_section); 229 230 ir_builder_->AddSymbol(*oat_input_, 231 "oatlastword", 232 mcld::ResolveInfo::Object, 233 mcld::ResolveInfo::Define, 234 mcld::ResolveInfo::Global, 235 0, // size 236 // subtract a word so symbol is within section 237 (oat_data_length + oat_code_length) - sizeof(uint32_t), // offset 238 text_section); 239 } 240 241 void ElfWriterMclinker::AddMethodInputs(const std::vector<const DexFile*>& dex_files) { 242 DCHECK(oat_input_ != NULL); 243 244 DexMethodIterator it(dex_files); 245 while (it.HasNext()) { 246 const DexFile& dex_file = it.GetDexFile(); 247 uint32_t method_idx = it.GetMemberIndex(); 248 const CompiledMethod* compiled_method = 249 compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, method_idx)); 250 if (compiled_method != NULL) { 251 AddCompiledCodeInput(*compiled_method); 252 } 253 it.Next(); 254 } 255 added_symbols_.clear(); 256 } 257 258 void ElfWriterMclinker::AddCompiledCodeInput(const CompiledCode& compiled_code) { 259 // Check if we've seen this compiled code before. If so skip 260 // it. This can happen for reused code such as invoke stubs. 261 const std::string& symbol = compiled_code.GetSymbol(); 262 SafeMap<const std::string*, const std::string*>::iterator it = added_symbols_.find(&symbol); 263 if (it != added_symbols_.end()) { 264 return; 265 } 266 added_symbols_.Put(&symbol, &symbol); 267 268 // Add input to supply code for symbol 269 const std::vector<uint8_t>* code = compiled_code.GetPortableCode(); 270 // TODO: ownership of code_input? 271 // TODO: why does IRBuilder::ReadInput take a non-const pointer? 272 mcld::Input* code_input = ir_builder_->ReadInput(symbol, 273 const_cast<uint8_t*>(&(*code)[0]), 274 code->size()); 275 CHECK(code_input != NULL); 276 } 277 278 void ElfWriterMclinker::AddRuntimeInputs(const std::string& android_root, bool is_host) { 279 std::string libart_so(android_root); 280 libart_so += kIsDebugBuild ? "/lib/libartd.so" : "/lib/libart.so"; 281 // TODO: ownership of libart_so_input? 282 mcld::Input* libart_so_input = ir_builder_->ReadInput(libart_so, libart_so); 283 CHECK(libart_so_input != NULL); 284 285 std::string host_prebuilt_dir("prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6"); 286 287 std::string compiler_runtime_lib; 288 if (is_host) { 289 compiler_runtime_lib += host_prebuilt_dir; 290 compiler_runtime_lib += "/lib/gcc/i686-linux/4.6.x-google/libgcc.a"; 291 } else { 292 compiler_runtime_lib += android_root; 293 compiler_runtime_lib += "/lib/libcompiler_rt.a"; 294 } 295 // TODO: ownership of compiler_runtime_lib_input? 296 mcld::Input* compiler_runtime_lib_input = ir_builder_->ReadInput(compiler_runtime_lib, 297 compiler_runtime_lib); 298 CHECK(compiler_runtime_lib_input != NULL); 299 300 std::string libc_lib; 301 if (is_host) { 302 libc_lib += host_prebuilt_dir; 303 libc_lib += "/sysroot/usr/lib/libc.so.6"; 304 } else { 305 libc_lib += android_root; 306 libc_lib += "/lib/libc.so"; 307 } 308 // TODO: ownership of libc_lib_input? 309 mcld::Input* libc_lib_input_input = ir_builder_->ReadInput(libc_lib, libc_lib); 310 CHECK(libc_lib_input_input != NULL); 311 312 std::string libm_lib; 313 if (is_host) { 314 libm_lib += host_prebuilt_dir; 315 libm_lib += "/sysroot/usr/lib/libm.so"; 316 } else { 317 libm_lib += android_root; 318 libm_lib += "/lib/libm.so"; 319 } 320 // TODO: ownership of libm_lib_input? 321 mcld::Input* libm_lib_input_input = ir_builder_->ReadInput(libm_lib, libm_lib); 322 CHECK(libm_lib_input_input != NULL); 323 } 324 325 bool ElfWriterMclinker::Link() { 326 // link inputs 327 if (!linker_->link(*module_.get(), *ir_builder_.get())) { 328 LOG(ERROR) << "Failed to link " << elf_file_->GetPath(); 329 return false; 330 } 331 332 // emit linked output 333 // TODO: avoid dup of fd by fixing Linker::emit to not close the argument fd. 334 int fd = dup(elf_file_->Fd()); 335 if (fd == -1) { 336 PLOG(ERROR) << "Failed to dup file descriptor for " << elf_file_->GetPath(); 337 return false; 338 } 339 if (!linker_->emit(*module_.get(), fd)) { 340 LOG(ERROR) << "Failed to emit " << elf_file_->GetPath(); 341 return false; 342 } 343 mcld::Finalize(); 344 LOG(INFO) << "ELF file written successfully: " << elf_file_->GetPath(); 345 return true; 346 } 347 348 void ElfWriterMclinker::FixupOatMethodOffsets(const std::vector<const DexFile*>& dex_files) { 349 std::string error_msg; 350 std::unique_ptr<ElfFile> elf_file(ElfFile::Open(elf_file_, true, false, &error_msg)); 351 CHECK(elf_file.get() != NULL) << elf_file_->GetPath() << ": " << error_msg; 352 353 uint32_t oatdata_address = GetOatDataAddress(elf_file.get()); 354 DexMethodIterator it(dex_files); 355 while (it.HasNext()) { 356 const DexFile& dex_file = it.GetDexFile(); 357 uint32_t method_idx = it.GetMemberIndex(); 358 InvokeType invoke_type = it.GetInvokeType(); 359 mirror::ArtMethod* method = NULL; 360 if (compiler_driver_->IsImage()) { 361 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 362 // Unchecked as we hold mutator_lock_ on entry. 363 ScopedObjectAccessUnchecked soa(Thread::Current()); 364 StackHandleScope<1> hs(soa.Self()); 365 Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(dex_file))); 366 method = linker->ResolveMethod(dex_file, method_idx, dex_cache, 367 NullHandle<mirror::ClassLoader>(), 368 NullHandle<mirror::ArtMethod>(), invoke_type); 369 CHECK(method != NULL); 370 } 371 const CompiledMethod* compiled_method = 372 compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, method_idx)); 373 if (compiled_method != NULL) { 374 uint32_t offset = FixupCompiledCodeOffset(*elf_file.get(), oatdata_address, *compiled_method); 375 // Don't overwrite static method trampoline 376 if (method != NULL && 377 (!method->IsStatic() || 378 method->IsConstructor() || 379 method->GetDeclaringClass()->IsInitialized())) { 380 method->SetPortableOatCodeOffset(offset); 381 } 382 } 383 it.Next(); 384 } 385 symbol_to_compiled_code_offset_.clear(); 386 } 387 388 uint32_t ElfWriterMclinker::FixupCompiledCodeOffset(ElfFile& elf_file, 389 Elf32_Addr oatdata_address, 390 const CompiledCode& compiled_code) { 391 const std::string& symbol = compiled_code.GetSymbol(); 392 SafeMap<const std::string*, uint32_t>::iterator it = symbol_to_compiled_code_offset_.find(&symbol); 393 if (it != symbol_to_compiled_code_offset_.end()) { 394 return it->second; 395 } 396 397 Elf32_Addr compiled_code_address = elf_file.FindSymbolAddress(SHT_SYMTAB, 398 symbol, 399 true); 400 CHECK_NE(0U, compiled_code_address) << symbol; 401 CHECK_LT(oatdata_address, compiled_code_address) << symbol; 402 uint32_t compiled_code_offset = compiled_code_address - oatdata_address; 403 symbol_to_compiled_code_offset_.Put(&symbol, compiled_code_offset); 404 405 const std::vector<uint32_t>& offsets = compiled_code.GetOatdataOffsetsToCompliledCodeOffset(); 406 for (uint32_t i = 0; i < offsets.size(); i++) { 407 uint32_t oatdata_offset = oatdata_address + offsets[i]; 408 uint32_t* addr = reinterpret_cast<uint32_t*>(elf_file.Begin() + oatdata_offset); 409 *addr = compiled_code_offset; 410 } 411 return compiled_code_offset; 412 } 413 414 } // namespace art 415