elf_writer_quick.cc revision c5bfa97c47d656b76f297af8abcd5f7502987399
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 PrepareDebugInfo(size_t rodata_section_size, 92 size_t text_section_size, 93 const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; 94 OutputStream* StartRoData() OVERRIDE; 95 void EndRoData(OutputStream* rodata) OVERRIDE; 96 OutputStream* StartText() OVERRIDE; 97 void EndText(OutputStream* text) OVERRIDE; 98 void SetBssSize(size_t bss_size) OVERRIDE; 99 void WriteDynamicSection() OVERRIDE; 100 void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; 101 void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE; 102 bool End() OVERRIDE; 103 104 virtual OutputStream* GetStream() 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 std::unique_ptr<BufferedOutputStream> output_stream_; 113 std::unique_ptr<ElfBuilder<ElfTypes>> builder_; 114 std::unique_ptr<DebugInfoTask> debug_info_task_; 115 std::unique_ptr<ThreadPool> debug_info_thread_pool_; 116 117 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 118}; 119 120std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, 121 const CompilerOptions* compiler_options, 122 File* elf_file) { 123 if (Is64BitInstructionSet(instruction_set)) { 124 return MakeUnique<ElfWriterQuick<ElfTypes64>>(instruction_set, compiler_options, elf_file); 125 } else { 126 return MakeUnique<ElfWriterQuick<ElfTypes32>>(instruction_set, compiler_options, elf_file); 127 } 128} 129 130template <typename ElfTypes> 131ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, 132 const CompilerOptions* compiler_options, 133 File* elf_file) 134 : ElfWriter(), 135 compiler_options_(compiler_options), 136 elf_file_(elf_file), 137 output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))), 138 builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {} 139 140template <typename ElfTypes> 141ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {} 142 143template <typename ElfTypes> 144void ElfWriterQuick<ElfTypes>::Start() { 145 builder_->Start(); 146} 147 148template <typename ElfTypes> 149OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() { 150 auto* rodata = builder_->GetRoData(); 151 rodata->Start(); 152 return rodata; 153} 154 155template <typename ElfTypes> 156void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) { 157 CHECK_EQ(builder_->GetRoData(), rodata); 158 builder_->GetRoData()->End(); 159} 160 161template <typename ElfTypes> 162OutputStream* ElfWriterQuick<ElfTypes>::StartText() { 163 auto* text = builder_->GetText(); 164 text->Start(); 165 return text; 166} 167 168template <typename ElfTypes> 169void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) { 170 CHECK_EQ(builder_->GetText(), text); 171 builder_->GetText()->End(); 172} 173 174template <typename ElfTypes> 175void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) { 176 auto* bss = builder_->GetBss(); 177 if (bss_size != 0u) { 178 bss->WriteNoBitsSection(bss_size); 179 } 180} 181 182template <typename ElfTypes> 183void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { 184 builder_->WriteDynamicSection(elf_file_->GetPath()); 185} 186 187template <typename ElfTypes> 188void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( 189 size_t rodata_section_size, 190 size_t text_section_size, 191 const ArrayRef<const debug::MethodDebugInfo>& method_infos) { 192 if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) { 193 // Prepare the mini-debug-info in background while we do other I/O. 194 Thread* self = Thread::Current(); 195 debug_info_task_ = std::unique_ptr<DebugInfoTask>( 196 new DebugInfoTask(builder_->GetIsa(), 197 rodata_section_size, 198 text_section_size, 199 method_infos)); 200 debug_info_thread_pool_ = std::unique_ptr<ThreadPool>( 201 new ThreadPool("Mini-debug-info writer", 1)); 202 debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); 203 debug_info_thread_pool_->StartWorkers(self); 204 } 205} 206 207template <typename ElfTypes> 208void ElfWriterQuick<ElfTypes>::WriteDebugInfo( 209 const ArrayRef<const debug::MethodDebugInfo>& method_infos) { 210 if (!method_infos.empty()) { 211 if (compiler_options_->GetGenerateDebugInfo()) { 212 // Generate all the debug information we can. 213 debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */); 214 } 215 if (compiler_options_->GetGenerateMiniDebugInfo()) { 216 // Wait for the mini-debug-info generation to finish and write it to disk. 217 Thread* self = Thread::Current(); 218 DCHECK(debug_info_thread_pool_ != nullptr); 219 debug_info_thread_pool_->Wait(self, true, false); 220 builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult()); 221 } 222 } 223} 224 225template <typename ElfTypes> 226void ElfWriterQuick<ElfTypes>::WritePatchLocations( 227 const ArrayRef<const uintptr_t>& patch_locations) { 228 // Add relocation section for .text. 229 if (compiler_options_->GetIncludePatchInformation()) { 230 // Note that ElfWriter::Fixup will be called regardless and therefore 231 // we need to include oat_patches for debug sections unconditionally. 232 builder_->WritePatches(".text.oat_patches", patch_locations); 233 } 234} 235 236template <typename ElfTypes> 237bool ElfWriterQuick<ElfTypes>::End() { 238 builder_->End(); 239 240 return builder_->Good(); 241} 242 243template <typename ElfTypes> 244OutputStream* ElfWriterQuick<ElfTypes>::GetStream() { 245 return builder_->GetStream(); 246} 247 248// Explicit instantiations 249template class ElfWriterQuick<ElfTypes32>; 250template class ElfWriterQuick<ElfTypes64>; 251 252} // namespace art 253