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