elf_writer_quick.cc revision 579942fc26f8a0b0ff1d909d19086fca6d2396a3
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_quick.h" 18 19#include <unordered_map> 20#include <unordered_set> 21 22#include "base/casts.h" 23#include "base/logging.h" 24#include "base/stl_util.h" 25#include "compiled_method.h" 26#include "driver/compiler_options.h" 27#include "dwarf/method_debug_info.h" 28#include "elf.h" 29#include "elf_builder.h" 30#include "elf_utils.h" 31#include "elf_writer_debug.h" 32#include "globals.h" 33#include "leb128.h" 34#include "linker/buffered_output_stream.h" 35#include "linker/file_output_stream.h" 36#include "utils.h" 37 38namespace art { 39 40// .eh_frame and .debug_frame are almost identical. 41// Except for some minor formatting differences, the main difference 42// is that .eh_frame is allocated within the running program because 43// it is used by C++ exception handling (which we do not use so we 44// can choose either). C++ compilers generally tend to use .eh_frame 45// because if they need it sometimes, they might as well always use it. 46// Let's use .debug_frame because it is easier to strip or compress. 47constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; 48 49template <typename ElfTypes> 50class ElfWriterQuick FINAL : public ElfWriter { 51 public: 52 ElfWriterQuick(InstructionSet instruction_set, 53 const CompilerOptions* compiler_options, 54 File* elf_file); 55 ~ElfWriterQuick(); 56 57 void Start() OVERRIDE; 58 OutputStream* StartRoData() OVERRIDE; 59 void EndRoData(OutputStream* rodata) OVERRIDE; 60 OutputStream* StartText() OVERRIDE; 61 void EndText(OutputStream* text) OVERRIDE; 62 void SetBssSize(size_t bss_size) OVERRIDE; 63 void WriteDynamicSection() OVERRIDE; 64 void WriteDebugInfo(const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE; 65 void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE; 66 bool End() OVERRIDE; 67 68 virtual OutputStream* GetStream() OVERRIDE; 69 70 static void EncodeOatPatches(const std::vector<uintptr_t>& locations, 71 std::vector<uint8_t>* buffer); 72 73 private: 74 const CompilerOptions* const compiler_options_; 75 File* const elf_file_; 76 std::unique_ptr<BufferedOutputStream> output_stream_; 77 std::unique_ptr<ElfBuilder<ElfTypes>> builder_; 78 79 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 80}; 81 82std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, 83 const CompilerOptions* compiler_options, 84 File* elf_file) { 85 if (Is64BitInstructionSet(instruction_set)) { 86 return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file); 87 } else { 88 return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file); 89 } 90} 91 92template <typename ElfTypes> 93ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, 94 const CompilerOptions* compiler_options, 95 File* elf_file) 96 : ElfWriter(), 97 compiler_options_(compiler_options), 98 elf_file_(elf_file), 99 output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))), 100 builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {} 101 102template <typename ElfTypes> 103ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {} 104 105template <typename ElfTypes> 106void ElfWriterQuick<ElfTypes>::Start() { 107 builder_->Start(); 108} 109 110template <typename ElfTypes> 111OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() { 112 auto* rodata = builder_->GetRoData(); 113 rodata->Start(); 114 return rodata; 115} 116 117template <typename ElfTypes> 118void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) { 119 CHECK_EQ(builder_->GetRoData(), rodata); 120 builder_->GetRoData()->End(); 121} 122 123template <typename ElfTypes> 124OutputStream* ElfWriterQuick<ElfTypes>::StartText() { 125 auto* text = builder_->GetText(); 126 text->Start(); 127 return text; 128} 129 130template <typename ElfTypes> 131void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) { 132 CHECK_EQ(builder_->GetText(), text); 133 builder_->GetText()->End(); 134} 135 136template <typename ElfTypes> 137void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) { 138 auto* bss = builder_->GetBss(); 139 if (bss_size != 0u) { 140 bss->WriteNoBitsSection(bss_size); 141 } 142} 143 144template <typename ElfTypes> 145void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { 146 builder_->WriteDynamicSection(elf_file_->GetPath()); 147} 148 149template <typename ElfTypes> 150void ElfWriterQuick<ElfTypes>::WriteDebugInfo( 151 const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { 152 if (compiler_options_->GetGenerateDebugInfo()) { 153 // Generate all the debug information we can. 154 dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */); 155 } 156 if (compiler_options_->GetGenerateMiniDebugInfo()) { 157 // Generate only some information and compress it. 158 dwarf::WriteMiniDebugInfo(builder_.get(), method_infos); 159 } 160} 161 162template <typename ElfTypes> 163void ElfWriterQuick<ElfTypes>::WritePatchLocations( 164 const ArrayRef<const uintptr_t>& patch_locations) { 165 // Add relocation section for .text. 166 if (compiler_options_->GetIncludePatchInformation()) { 167 // Note that ElfWriter::Fixup will be called regardless and therefore 168 // we need to include oat_patches for debug sections unconditionally. 169 builder_->WritePatches(".text.oat_patches", patch_locations); 170 } 171} 172 173template <typename ElfTypes> 174bool ElfWriterQuick<ElfTypes>::End() { 175 builder_->End(); 176 177 return builder_->Good(); 178} 179 180template <typename ElfTypes> 181OutputStream* ElfWriterQuick<ElfTypes>::GetStream() { 182 return builder_->GetStream(); 183} 184 185// Explicit instantiations 186template class ElfWriterQuick<ElfTypes32>; 187template class ElfWriterQuick<ElfTypes64>; 188 189} // namespace art 190