elf_writer_quick.cc revision 944da603cde59a4277f3bbc31d860a90842a1a2a
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 "debug/elf_debug_writer.h" 27#include "debug/method_debug_info.h" 28#include "driver/compiler_options.h" 29#include "elf.h" 30#include "elf_builder.h" 31#include "elf_utils.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 "thread-inl.h" 37#include "thread_pool.h" 38#include "utils.h" 39 40namespace art { 41 42// .eh_frame and .debug_frame are almost identical. 43// Except for some minor formatting differences, the main difference 44// is that .eh_frame is allocated within the running program because 45// it is used by C++ exception handling (which we do not use so we 46// can choose either). C++ compilers generally tend to use .eh_frame 47// because if they need it sometimes, they might as well always use it. 48// Let's use .debug_frame because it is easier to strip or compress. 49constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; 50 51class DebugInfoTask : public Task { 52 public: 53 DebugInfoTask(InstructionSet isa, 54 size_t rodata_section_size, 55 size_t text_section_size, 56 const ArrayRef<const debug::MethodDebugInfo>& method_infos) 57 : isa_(isa), 58 rodata_section_size_(rodata_section_size), 59 text_section_size_(text_section_size), 60 method_infos_(method_infos) { 61 } 62 63 void Run(Thread*) { 64 result_ = debug::MakeMiniDebugInfo(isa_, 65 rodata_section_size_, 66 text_section_size_, 67 method_infos_); 68 } 69 70 std::vector<uint8_t>* GetResult() { 71 return &result_; 72 } 73 74 private: 75 InstructionSet isa_; 76 size_t rodata_section_size_; 77 size_t text_section_size_; 78 const ArrayRef<const debug::MethodDebugInfo>& method_infos_; 79 std::vector<uint8_t> result_; 80}; 81 82template <typename ElfTypes> 83class ElfWriterQuick FINAL : public ElfWriter { 84 public: 85 ElfWriterQuick(InstructionSet instruction_set, 86 const CompilerOptions* compiler_options, 87 File* elf_file); 88 ~ElfWriterQuick(); 89 90 void Start() OVERRIDE; 91 void SetLoadedSectionSizes(size_t rodata_size, size_t text_size, size_t bss_size) OVERRIDE; 92 void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; 93 OutputStream* StartRoData() OVERRIDE; 94 void EndRoData(OutputStream* rodata) OVERRIDE; 95 OutputStream* StartText() OVERRIDE; 96 void EndText(OutputStream* text) OVERRIDE; 97 void WriteDynamicSection() OVERRIDE; 98 void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; 99 void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE; 100 bool End() OVERRIDE; 101 102 virtual OutputStream* GetStream() OVERRIDE; 103 104 size_t GetLoadedSize() OVERRIDE; 105 106 static void EncodeOatPatches(const std::vector<uintptr_t>& locations, 107 std::vector<uint8_t>* buffer); 108 109 private: 110 const CompilerOptions* const compiler_options_; 111 File* const elf_file_; 112 size_t rodata_size_; 113 size_t text_size_; 114 size_t bss_size_; 115 std::unique_ptr<BufferedOutputStream> output_stream_; 116 std::unique_ptr<ElfBuilder<ElfTypes>> builder_; 117 std::unique_ptr<DebugInfoTask> debug_info_task_; 118 std::unique_ptr<ThreadPool> debug_info_thread_pool_; 119 120 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 121}; 122 123std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, 124 const CompilerOptions* compiler_options, 125 File* elf_file) { 126 if (Is64BitInstructionSet(instruction_set)) { 127 return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file); 128 } else { 129 return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file); 130 } 131} 132 133template <typename ElfTypes> 134ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, 135 const CompilerOptions* compiler_options, 136 File* elf_file) 137 : ElfWriter(), 138 compiler_options_(compiler_options), 139 elf_file_(elf_file), 140 rodata_size_(0u), 141 text_size_(0u), 142 bss_size_(0u), 143 output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))), 144 builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {} 145 146template <typename ElfTypes> 147ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {} 148 149template <typename ElfTypes> 150void ElfWriterQuick<ElfTypes>::Start() { 151 builder_->Start(); 152} 153 154template <typename ElfTypes> 155void ElfWriterQuick<ElfTypes>::SetLoadedSectionSizes(size_t rodata_size, 156 size_t text_size, 157 size_t bss_size) { 158 DCHECK_EQ(rodata_size_, 0u); 159 rodata_size_ = rodata_size; 160 DCHECK_EQ(text_size_, 0u); 161 text_size_ = text_size; 162 DCHECK_EQ(bss_size_, 0u); 163 bss_size_ = bss_size; 164 builder_->PrepareDynamicSection(elf_file_->GetPath(), rodata_size_, text_size_, bss_size_); 165} 166 167template <typename ElfTypes> 168OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() { 169 auto* rodata = builder_->GetRoData(); 170 rodata->Start(); 171 return rodata; 172} 173 174template <typename ElfTypes> 175void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) { 176 CHECK_EQ(builder_->GetRoData(), rodata); 177 builder_->GetRoData()->End(); 178} 179 180template <typename ElfTypes> 181OutputStream* ElfWriterQuick<ElfTypes>::StartText() { 182 auto* text = builder_->GetText(); 183 text->Start(); 184 return text; 185} 186 187template <typename ElfTypes> 188void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) { 189 CHECK_EQ(builder_->GetText(), text); 190 builder_->GetText()->End(); 191} 192 193template <typename ElfTypes> 194void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { 195 if (bss_size_ != 0u) { 196 builder_->GetBss()->WriteNoBitsSection(bss_size_); 197 } 198 builder_->WriteDynamicSection(); 199} 200 201template <typename ElfTypes> 202void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( 203 const ArrayRef<const debug::MethodDebugInfo>& method_infos) { 204 if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) { 205 // Prepare the mini-debug-info in background while we do other I/O. 206 Thread* self = Thread::Current(); 207 debug_info_task_ = std::unique_ptr<DebugInfoTask>( 208 new DebugInfoTask(builder_->GetIsa(), rodata_size_, text_size_, method_infos)); 209 debug_info_thread_pool_ = std::unique_ptr<ThreadPool>( 210 new ThreadPool("Mini-debug-info writer", 1)); 211 debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); 212 debug_info_thread_pool_->StartWorkers(self); 213 } 214} 215 216template <typename ElfTypes> 217void ElfWriterQuick<ElfTypes>::WriteDebugInfo( 218 const ArrayRef<const debug::MethodDebugInfo>& method_infos) { 219 if (!method_infos.empty()) { 220 if (compiler_options_->GetGenerateDebugInfo()) { 221 // Generate all the debug information we can. 222 debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */); 223 } 224 if (compiler_options_->GetGenerateMiniDebugInfo()) { 225 // Wait for the mini-debug-info generation to finish and write it to disk. 226 Thread* self = Thread::Current(); 227 DCHECK(debug_info_thread_pool_ != nullptr); 228 debug_info_thread_pool_->Wait(self, true, false); 229 builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult()); 230 } 231 } 232} 233 234template <typename ElfTypes> 235void ElfWriterQuick<ElfTypes>::WritePatchLocations( 236 const ArrayRef<const uintptr_t>& patch_locations) { 237 // Add relocation section for .text. 238 if (compiler_options_->GetIncludePatchInformation()) { 239 // Note that ElfWriter::Fixup will be called regardless and therefore 240 // we need to include oat_patches for debug sections unconditionally. 241 builder_->WritePatches(".text.oat_patches", patch_locations); 242 } 243} 244 245template <typename ElfTypes> 246bool ElfWriterQuick<ElfTypes>::End() { 247 builder_->End(); 248 249 return builder_->Good(); 250} 251 252template <typename ElfTypes> 253OutputStream* ElfWriterQuick<ElfTypes>::GetStream() { 254 return builder_->GetStream(); 255} 256 257template <typename ElfTypes> 258size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() { 259 return builder_->GetLoadedSize(); 260} 261 262// Explicit instantiations 263template class ElfWriterQuick<ElfTypes32>; 264template class ElfWriterQuick<ElfTypes64>; 265 266} // namespace art 267