elf_writer_quick.cc revision 6d8c8f0344a706df651567387ede683ab3ec1b5f
16a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom/*
26a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Copyright (C) 2012 The Android Open Source Project
36a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
46a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
56a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * you may not use this file except in compliance with the License.
66a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * You may obtain a copy of the License at
76a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
86a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
96a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * See the License for the specific language governing permissions and
146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * limitations under the License.
156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom */
166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "elf_writer_quick.h"
186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
19e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include <unordered_map>
20626a1666015b0fa201e979870baf06afa93b65e7David Srbecky#include <unordered_set>
21e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban
22f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky#include "base/casts.h"
236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/logging.h"
246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/unix_file/fd_file.h"
2520f85597828194c12be10d3a927999def066555eVladimir Marko#include "compiled_method.h"
260df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky#include "dex_file-inl.h"
277940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h"
2820f85597828194c12be10d3a927999def066555eVladimir Marko#include "driver/compiler_options.h"
2954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "elf_builder.h"
30e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban#include "elf_file.h"
3150cfe74daaece80853cb3b45d4338329b7d0345bNicolas Geoffray#include "elf_utils.h"
323b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "elf_writer_debug.h"
336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h"
3479273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe#include "leb128.h"
356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "oat.h"
36c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "oat_writer.h"
376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "utils.h"
386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art {
406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
41ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// .eh_frame and .debug_frame are almost identical.
42ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// Except for some minor formatting differences, the main difference
43ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// is that .eh_frame is allocated within the running program because
44ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// it is used by C++ exception handling (which we do not use so we
45ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// can choose either).  C++ compilers generally tend to use .eh_frame
46ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// because if they need it sometimes, they might as well always use it.
47aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbecky// Let's use .debug_frame because it is easier to strip or compress.
48aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbeckyconstexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
49ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky
50388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// The ARM specification defines three special mapping symbols
51388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// $a, $t and $d which mark ARM, Thumb and data ranges respectively.
52388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// These symbols can be used by tools, for example, to pretty
53388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// print instructions correctly.  Objdump will use them if they
54388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// exist, but it will still work well without them.
55388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// However, these extra symbols take space, so let's just generate
56388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// one symbol which marks the whole .text section as code.
57388d2861ce185fe9bbf1989f1467031467bd1de7David Srbeckyconstexpr bool kGenerateSingleArmMappingSymbol = true;
58388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky
59533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
60533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckybool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
61533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky                                      OatWriter* oat_writer,
62533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky                                      const std::vector<const DexFile*>& dex_files,
63533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky                                      const std::string& android_root,
64533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky                                      bool is_host,
65533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbecky                                      const CompilerDriver& driver) {
66b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  ElfWriterQuick elf_writer(driver, elf_file);
67b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom  return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
68b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
69b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom
70533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
71533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckystatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
7254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
73533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
746d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbeckybool ElfWriterQuick<ElfTypes>::Write(
756d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    OatWriter* oat_writer,
766d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED,
776d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    const std::string& android_root_unused ATTRIBUTE_UNUSED,
786d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bool is_host_unused ATTRIBUTE_UNUSED) {
796d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  const InstructionSet isa = compiler_driver_->GetInstructionSet();
806d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  std::unique_ptr<BufferedOutputStream> output_stream(
816d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      new BufferedOutputStream(new FileOutputStream(elf_file_)));
826d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  std::unique_ptr<ElfBuilder<ElfTypes>> builder(
836d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      new ElfBuilder<ElfTypes>(isa, output_stream.get()));
84bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
856d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  builder->Start();
86bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
876d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* rodata = builder->GetRoData();
886d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* text = builder->GetText();
896d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* bss = builder->GetBss();
90bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
916d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  rodata->Start();
926d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (!oat_writer->WriteRodata(rodata)) {
936d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    return false;
94bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky  }
956d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  rodata->End();
96bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
976d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  text->Start();
986d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (!oat_writer->WriteCode(text)) {
996d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    return false;
100033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky  }
1016d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  text->End();
102033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky
1036d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (oat_writer->GetBssSize() != 0) {
1046d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bss->Start();
1056d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bss->SetSize(oat_writer->GetBssSize());
1066d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    bss->End();
1076d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  }
108bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
1096d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  builder->WriteDynamicSection(elf_file_->GetPath());
110bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky
1116d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (compiler_driver_->GetCompilerOptions().GetGenerateDebugInfo()) {
1126d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    const auto& method_infos = oat_writer->GetMethodDebugInfo();
1136d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    if (!method_infos.empty()) {
114bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky      // Add methods to .symtab.
115bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky      WriteDebugSymbols(builder.get(), oat_writer);
1166d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      // Generate CFI (stack unwinding information).
1176d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      dwarf::WriteCFISection(builder.get(), method_infos, kCFIFormat);
1186d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      // Write DWARF .debug_* sections.
1196d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky      dwarf::WriteDebugSections(builder.get(), method_infos);
120bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky    }
1216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
1226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
123f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky  // Add relocation section for .text.
124f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
125f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky    // Note that ElfWriter::Fixup will be called regardless and therefore
126f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky    // we need to include oat_patches for debug sections unconditionally.
1276d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    builder->WritePatches(".text.oat_patches", &oat_writer->GetAbsolutePatchLocations());
12853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
12953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
1306d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  builder->End();
1316d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
1326d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  return builder->Good() && output_stream->Flush();
133b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom}
134ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
135533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes>
136533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckystatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) {
1373b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky  const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
138388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky  bool generated_mapping_symbol = false;
1396d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* strtab = builder->GetStrTab();
1406d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  auto* symtab = builder->GetSymTab();
1416d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
1426d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  if (method_info.empty()) {
1436d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    return;
1446d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  }
145626a1666015b0fa201e979870baf06afa93b65e7David Srbecky
146626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  // Find all addresses (low_pc) which contain deduped methods.
147626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  // The first instance of method is not marked deduped_, but the rest is.
148626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  std::unordered_set<uint32_t> deduped_addresses;
149626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  for (auto it = method_info.begin(); it != method_info.end(); ++it) {
150626a1666015b0fa201e979870baf06afa93b65e7David Srbecky    if (it->deduped_) {
151626a1666015b0fa201e979870baf06afa93b65e7David Srbecky      deduped_addresses.insert(it->low_pc_);
152626a1666015b0fa201e979870baf06afa93b65e7David Srbecky    }
153626a1666015b0fa201e979870baf06afa93b65e7David Srbecky  }
154626a1666015b0fa201e979870baf06afa93b65e7David Srbecky
1556d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->Start();
1566d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->Write("");  // strtab should start with empty string.
15754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  for (auto it = method_info.begin(); it != method_info.end(); ++it) {
1586d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky    if (it->deduped_) {
1596d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky      continue;  // Add symbol only for the first instance.
1606d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky    }
1610df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky    std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true);
162626a1666015b0fa201e979870baf06afa93b65e7David Srbecky    if (deduped_addresses.find(it->low_pc_) != deduped_addresses.end()) {
163626a1666015b0fa201e979870baf06afa93b65e7David Srbecky      name += " [DEDUPED]";
1640df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky    }
1650df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky
1666f7158927fee233255f8e96719c374694b10cad3David Srbecky    uint32_t low_pc = it->low_pc_;
1676f7158927fee233255f8e96719c374694b10cad3David Srbecky    // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
1686f7158927fee233255f8e96719c374694b10cad3David Srbecky    low_pc += it->compiled_method_->CodeDelta();
1696d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky    symtab->Add(strtab->Write(name), builder->GetText(), low_pc,
1706d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky                true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
17154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
172f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
173f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    // instructions, so that disassembler tools can correctly disassemble.
174388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky    // Note that even if we generate just a single mapping symbol, ARM's Streamline
175388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky    // requires it to match function symbol.  Just address 0 does not work.
176f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    if (it->compiled_method_->GetInstructionSet() == kThumb2) {
177388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky      if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
1786d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky        symtab->Add(strtab->Write("$t"), builder->GetText(), it->low_pc_ & ~1,
1796d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky                    true, 0, STB_LOCAL, STT_NOTYPE);
180388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky        generated_mapping_symbol = true;
181388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky      }
182f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian    }
18354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
1846d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  strtab->End();
1856d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky
1866d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  // Symbols are buffered and written after names (because they are smaller).
1876d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  // We could also do two passes in this function to avoid the buffering.
1886d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->Start();
1896d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->Write();
1906d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky  symtab->End();
19154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe}
19254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
193f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray// Explicit instantiations
194533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes32>;
195533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes64>;
196f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray
1976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}  // namespace art
198