elf_writer_quick.cc revision 131980fc9aeb2b4d03480443e0fb494c76ce03a2
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" 2410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "base/stl_util.h" 2520f85597828194c12be10d3a927999def066555eVladimir Marko#include "compiled_method.h" 2620f85597828194c12be10d3a927999def066555eVladimir Marko#include "driver/compiler_options.h" 2710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "dwarf/method_debug_info.h" 2810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko#include "elf.h" 2954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "elf_builder.h" 3050cfe74daaece80853cb3b45d4338329b7d0345bNicolas Geoffray#include "elf_utils.h" 313b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "elf_writer_debug.h" 326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h" 3379273802f2b788bcd3eb76edf4df1bcaa57f886fAndreas Gampe#include "leb128.h" 34131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/buffered_output_stream.h" 35131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko#include "linker/file_output_stream.h" 366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "utils.h" 376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art { 396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 40ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// .eh_frame and .debug_frame are almost identical. 41ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// Except for some minor formatting differences, the main difference 42ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// is that .eh_frame is allocated within the running program because 43ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// it is used by C++ exception handling (which we do not use so we 44ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// can choose either). C++ compilers generally tend to use .eh_frame 45ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky// because if they need it sometimes, they might as well always use it. 46aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbecky// Let's use .debug_frame because it is easier to strip or compress. 47aaf143d80bc6f226290eadb10361a752ed5d204eDavid Srbeckyconstexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; 48ad5fa8c5b26a325dc2a9521b87188755046c17f3David Srbecky 49388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// The ARM specification defines three special mapping symbols 50388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// $a, $t and $d which mark ARM, Thumb and data ranges respectively. 51388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// These symbols can be used by tools, for example, to pretty 52388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// print instructions correctly. Objdump will use them if they 53388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// exist, but it will still work well without them. 54388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// However, these extra symbols take space, so let's just generate 55388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky// one symbol which marks the whole .text section as code. 56388d2861ce185fe9bbf1989f1467031467bd1de7David Srbeckyconstexpr bool kGenerateSingleArmMappingSymbol = true; 57388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky 58533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes> 5910c13565474de2786aad7c2e79757ea250747a15Vladimir Markoclass ElfWriterQuick FINAL : public ElfWriter { 6010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko public: 6110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko ElfWriterQuick(InstructionSet instruction_set, 6210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const CompilerOptions* compiler_options, 6310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko File* elf_file); 6410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko ~ElfWriterQuick(); 6510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 6610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void Start() OVERRIDE; 6710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko OutputStream* StartRoData() OVERRIDE; 6810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void EndRoData(OutputStream* rodata) OVERRIDE; 6910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko OutputStream* StartText() OVERRIDE; 7010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void EndText(OutputStream* text) OVERRIDE; 7110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void SetBssSize(size_t bss_size) OVERRIDE; 7210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void WriteDynamicSection() OVERRIDE; 7310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE; 7410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE; 7510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko bool End() OVERRIDE; 7610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 77131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko virtual OutputStream* GetStream() OVERRIDE; 78131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko 7910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko static void EncodeOatPatches(const std::vector<uintptr_t>& locations, 8010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko std::vector<uint8_t>* buffer); 8110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 8210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko private: 8310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const CompilerOptions* const compiler_options_; 8410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko File* const elf_file_; 8510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko std::unique_ptr<BufferedOutputStream> output_stream_; 8610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko std::unique_ptr<ElfBuilder<ElfTypes>> builder_; 8710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 8810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 8910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko}; 9010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 9110c13565474de2786aad7c2e79757ea250747a15Vladimir Markostd::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, 9210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const CompilerOptions* compiler_options, 9310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko File* elf_file) { 9410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (Is64BitInstructionSet(instruction_set)) { 9510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file); 9610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko } else { 9710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file); 9810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko } 99b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom} 100b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom 101533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes> 10210c13565474de2786aad7c2e79757ea250747a15Vladimir Markostatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, 10310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const ArrayRef<const dwarf::MethodDebugInfo>& method_infos); 10410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 10510c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 10610c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, 10710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const CompilerOptions* compiler_options, 10810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko File* elf_file) 10910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko : ElfWriter(), 11010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko compiler_options_(compiler_options), 11110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko elf_file_(elf_file), 11210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))), 11310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {} 11454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 115533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes> 11610c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoElfWriterQuick<ElfTypes>::~ElfWriterQuick() {} 117bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky 11810c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 11910c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::Start() { 12010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->Start(); 12110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 12210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 12310c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 12410c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::StartRoData() { 12510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko auto* rodata = builder_->GetRoData(); 1266d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky rodata->Start(); 12710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return rodata; 12810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 129bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky 13010c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 13110c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) { 13210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko CHECK_EQ(builder_->GetRoData(), rodata); 13310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->GetRoData()->End(); 13410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 13510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 13610c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 13710c13565474de2786aad7c2e79757ea250747a15Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::StartText() { 13810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko auto* text = builder_->GetText(); 1396d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky text->Start(); 14010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return text; 14110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 14210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko 14310c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 14410c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) { 14510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko CHECK_EQ(builder_->GetText(), text); 14610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->GetText()->End(); 14710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 148033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky 14910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 15010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) { 15110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko auto* bss = builder_->GetBss(); 15210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (bss_size != 0u) { 1536d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky bss->Start(); 15410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko bss->SetSize(bss_size); 1556d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky bss->End(); 1566d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky } 15710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 158bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky 15910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 16010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WriteDynamicSection() { 16110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->WriteDynamicSection(elf_file_->GetPath()); 16210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 163bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky 16410c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 16510c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WriteDebugInfo( 16610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { 16710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (compiler_options_->GetGenerateDebugInfo()) { 1686d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky if (!method_infos.empty()) { 169bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky // Add methods to .symtab. 17010c13565474de2786aad7c2e79757ea250747a15Vladimir Marko WriteDebugSymbols(builder_.get(), method_infos); 1716d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky // Generate CFI (stack unwinding information). 17210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko dwarf::WriteCFISection(builder_.get(), method_infos, kCFIFormat); 1736d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky // Write DWARF .debug_* sections. 17410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko dwarf::WriteDebugSections(builder_.get(), method_infos); 175bc90fd09e09a845ae6ea0d84ad67560575a94142David Srbecky } 1766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom } 17710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 1786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom 17910c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 18010c13565474de2786aad7c2e79757ea250747a15Vladimir Markovoid ElfWriterQuick<ElfTypes>::WritePatchLocations( 18110c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const ArrayRef<const uintptr_t>& patch_locations) { 182f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky // Add relocation section for .text. 18310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (compiler_options_->GetIncludePatchInformation()) { 184f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky // Note that ElfWriter::Fixup will be called regardless and therefore 185f8980875ef8fb0ce86be4ed2c0af7070f5ae9cfdDavid Srbecky // we need to include oat_patches for debug sections unconditionally. 18610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->WritePatches(".text.oat_patches", patch_locations); 18753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light } 18810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko} 18953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light 19010c13565474de2786aad7c2e79757ea250747a15Vladimir Markotemplate <typename ElfTypes> 19110c13565474de2786aad7c2e79757ea250747a15Vladimir Markobool ElfWriterQuick<ElfTypes>::End() { 19210c13565474de2786aad7c2e79757ea250747a15Vladimir Marko builder_->End(); 1936d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky 19410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko return builder_->Good(); 195b12f34742be4adaa804cc0d388ba51603bb95955Brian Carlstrom} 196ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 197533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate <typename ElfTypes> 198131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir MarkoOutputStream* ElfWriterQuick<ElfTypes>::GetStream() { 199131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko return builder_->GetStream(); 200131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko} 201131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Marko 202131980fc9aeb2b4d03480443e0fb494c76ce03a2Vladimir Markotemplate <typename ElfTypes> 20310c13565474de2786aad7c2e79757ea250747a15Vladimir Markostatic void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, 20410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { 205388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky bool generated_mapping_symbol = false; 2066d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky auto* strtab = builder->GetStrTab(); 2076d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky auto* symtab = builder->GetSymTab(); 2086d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky 20910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (method_infos.empty()) { 2106d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky return; 2116d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky } 212626a1666015b0fa201e979870baf06afa93b65e7David Srbecky 213626a1666015b0fa201e979870baf06afa93b65e7David Srbecky // Find all addresses (low_pc) which contain deduped methods. 214626a1666015b0fa201e979870baf06afa93b65e7David Srbecky // The first instance of method is not marked deduped_, but the rest is. 215626a1666015b0fa201e979870baf06afa93b65e7David Srbecky std::unordered_set<uint32_t> deduped_addresses; 21610c13565474de2786aad7c2e79757ea250747a15Vladimir Marko for (const dwarf::MethodDebugInfo& info : method_infos) { 21710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (info.deduped_) { 21810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko deduped_addresses.insert(info.low_pc_); 219626a1666015b0fa201e979870baf06afa93b65e7David Srbecky } 220626a1666015b0fa201e979870baf06afa93b65e7David Srbecky } 221626a1666015b0fa201e979870baf06afa93b65e7David Srbecky 2226d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky strtab->Start(); 2236d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky strtab->Write(""); // strtab should start with empty string. 22410c13565474de2786aad7c2e79757ea250747a15Vladimir Marko for (const dwarf::MethodDebugInfo& info : method_infos) { 22510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (info.deduped_) { 2266d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky continue; // Add symbol only for the first instance. 2276d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky } 22810c13565474de2786aad7c2e79757ea250747a15Vladimir Marko std::string name = PrettyMethod(info.dex_method_index_, *info.dex_file_, true); 22910c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (deduped_addresses.find(info.low_pc_) != deduped_addresses.end()) { 230626a1666015b0fa201e979870baf06afa93b65e7David Srbecky name += " [DEDUPED]"; 2310df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky } 2320df9e1faed9b095b084c4eca6ee59d24fba21c9fDavid Srbecky 23310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko uint32_t low_pc = info.low_pc_; 2346f7158927fee233255f8e96719c374694b10cad3David Srbecky // Add in code delta, e.g., thumb bit 0 for Thumb2 code. 23510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko low_pc += info.compiled_method_->CodeDelta(); 2366d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky symtab->Add(strtab->Write(name), builder->GetText(), low_pc, 23710c13565474de2786aad7c2e79757ea250747a15Vladimir Marko true, info.high_pc_ - info.low_pc_, STB_GLOBAL, STT_FUNC); 23854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 239f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 240f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian // instructions, so that disassembler tools can correctly disassemble. 241388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky // Note that even if we generate just a single mapping symbol, ARM's Streamline 242388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky // requires it to match function symbol. Just address 0 does not work. 24310c13565474de2786aad7c2e79757ea250747a15Vladimir Marko if (info.compiled_method_->GetInstructionSet() == kThumb2) { 244388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) { 24510c13565474de2786aad7c2e79757ea250747a15Vladimir Marko symtab->Add(strtab->Write("$t"), builder->GetText(), info.low_pc_ & ~1, 2466d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky true, 0, STB_LOCAL, STT_NOTYPE); 247388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky generated_mapping_symbol = true; 248388d2861ce185fe9bbf1989f1467031467bd1de7David Srbecky } 249f9734550c1453f173150b12efc72b10ebf67878dNingsheng Jian } 25054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe } 2516d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky strtab->End(); 2526d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky 2536d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky // Symbols are buffered and written after names (because they are smaller). 2546d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky // We could also do two passes in this function to avoid the buffering. 2556d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky symtab->Start(); 2566d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky symtab->Write(); 2576d8c8f0344a706df651567387ede683ab3ec1b5fDavid Srbecky symtab->End(); 25854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe} 25954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe 260f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray// Explicit instantiations 261533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes32>; 262533c207f9d2da6d913c4b10f6f757fe9d6367b10David Srbeckytemplate class ElfWriterQuick<ElfTypes64>; 263f9b87b1eece0e03578c4d1b627f1d5e8691a539aNicolas Geoffray 2646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom} // namespace art 265