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
45namespace art {
46
47ElfWriterMclinker::ElfWriterMclinker(const CompilerDriver& driver, File* elf_file)
48  : ElfWriter(driver, elf_file), oat_input_(nullptr) {
49}
50
51ElfWriterMclinker::~ElfWriterMclinker() {
52}
53
54bool 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
64bool 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
90static 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
101void 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
159void 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
241void 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
258void 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
278void 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
325bool 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
348void 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
388uint32_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