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 <openssl/sha.h> 20 #include <unordered_map> 21 #include <unordered_set> 22 23 #include <android-base/logging.h> 24 25 #include "base/casts.h" 26 #include "base/leb128.h" 27 #include "base/utils.h" 28 #include "compiled_method.h" 29 #include "debug/elf_debug_writer.h" 30 #include "debug/method_debug_info.h" 31 #include "driver/compiler_options.h" 32 #include "elf.h" 33 #include "elf_utils.h" 34 #include "globals.h" 35 #include "linker/buffered_output_stream.h" 36 #include "linker/elf_builder.h" 37 #include "linker/file_output_stream.h" 38 #include "thread-current-inl.h" 39 #include "thread_pool.h" 40 41 namespace art { 42 namespace linker { 43 44 // .eh_frame and .debug_frame are almost identical. 45 // Except for some minor formatting differences, the main difference 46 // is that .eh_frame is allocated within the running program because 47 // it is used by C++ exception handling (which we do not use so we 48 // can choose either). C++ compilers generally tend to use .eh_frame 49 // because if they need it sometimes, they might as well always use it. 50 // Let's use .debug_frame because it is easier to strip or compress. 51 constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; 52 53 class DebugInfoTask : public Task { 54 public: 55 DebugInfoTask(InstructionSet isa, 56 const InstructionSetFeatures* features, 57 uint64_t text_section_address, 58 size_t text_section_size, 59 uint64_t dex_section_address, 60 size_t dex_section_size, 61 const debug::DebugInfo& debug_info) 62 : isa_(isa), 63 instruction_set_features_(features), 64 text_section_address_(text_section_address), 65 text_section_size_(text_section_size), 66 dex_section_address_(dex_section_address), 67 dex_section_size_(dex_section_size), 68 debug_info_(debug_info) { 69 } 70 71 void Run(Thread*) { 72 result_ = debug::MakeMiniDebugInfo(isa_, 73 instruction_set_features_, 74 text_section_address_, 75 text_section_size_, 76 dex_section_address_, 77 dex_section_size_, 78 debug_info_); 79 } 80 81 std::vector<uint8_t>* GetResult() { 82 return &result_; 83 } 84 85 private: 86 InstructionSet isa_; 87 const InstructionSetFeatures* instruction_set_features_; 88 uint64_t text_section_address_; 89 size_t text_section_size_; 90 uint64_t dex_section_address_; 91 size_t dex_section_size_; 92 const debug::DebugInfo& debug_info_; 93 std::vector<uint8_t> result_; 94 }; 95 96 template <typename ElfTypes> 97 class ElfWriterQuick FINAL : public ElfWriter { 98 public: 99 ElfWriterQuick(InstructionSet instruction_set, 100 const InstructionSetFeatures* features, 101 const CompilerOptions* compiler_options, 102 File* elf_file); 103 ~ElfWriterQuick(); 104 105 void Start() OVERRIDE; 106 void PrepareDynamicSection(size_t rodata_size, 107 size_t text_size, 108 size_t bss_size, 109 size_t bss_methods_offset, 110 size_t bss_roots_offset, 111 size_t dex_section_size) OVERRIDE; 112 void PrepareDebugInfo(const debug::DebugInfo& debug_info) OVERRIDE; 113 OutputStream* StartRoData() OVERRIDE; 114 void EndRoData(OutputStream* rodata) OVERRIDE; 115 OutputStream* StartText() OVERRIDE; 116 void EndText(OutputStream* text) OVERRIDE; 117 void WriteDynamicSection() OVERRIDE; 118 void WriteDebugInfo(const debug::DebugInfo& debug_info) OVERRIDE; 119 bool End() OVERRIDE; 120 121 virtual OutputStream* GetStream() OVERRIDE; 122 123 size_t GetLoadedSize() OVERRIDE; 124 125 static void EncodeOatPatches(const std::vector<uintptr_t>& locations, 126 std::vector<uint8_t>* buffer); 127 128 private: 129 const InstructionSetFeatures* instruction_set_features_; 130 const CompilerOptions* const compiler_options_; 131 File* const elf_file_; 132 size_t rodata_size_; 133 size_t text_size_; 134 size_t bss_size_; 135 size_t dex_section_size_; 136 std::unique_ptr<BufferedOutputStream> output_stream_; 137 std::unique_ptr<ElfBuilder<ElfTypes>> builder_; 138 std::unique_ptr<DebugInfoTask> debug_info_task_; 139 std::unique_ptr<ThreadPool> debug_info_thread_pool_; 140 141 void ComputeFileBuildId(uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]); 142 143 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 144 }; 145 146 std::unique_ptr<ElfWriter> CreateElfWriterQuick(InstructionSet instruction_set, 147 const InstructionSetFeatures* features, 148 const CompilerOptions* compiler_options, 149 File* elf_file) { 150 if (Is64BitInstructionSet(instruction_set)) { 151 return std::make_unique<ElfWriterQuick<ElfTypes64>>(instruction_set, 152 features, 153 compiler_options, 154 elf_file); 155 } else { 156 return std::make_unique<ElfWriterQuick<ElfTypes32>>(instruction_set, 157 features, 158 compiler_options, 159 elf_file); 160 } 161 } 162 163 template <typename ElfTypes> 164 ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, 165 const InstructionSetFeatures* features, 166 const CompilerOptions* compiler_options, 167 File* elf_file) 168 : ElfWriter(), 169 instruction_set_features_(features), 170 compiler_options_(compiler_options), 171 elf_file_(elf_file), 172 rodata_size_(0u), 173 text_size_(0u), 174 bss_size_(0u), 175 dex_section_size_(0u), 176 output_stream_( 177 std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(elf_file))), 178 builder_(new ElfBuilder<ElfTypes>(instruction_set, features, output_stream_.get())) {} 179 180 template <typename ElfTypes> 181 ElfWriterQuick<ElfTypes>::~ElfWriterQuick() {} 182 183 template <typename ElfTypes> 184 void ElfWriterQuick<ElfTypes>::Start() { 185 builder_->Start(); 186 if (compiler_options_->GetGenerateBuildId()) { 187 builder_->GetBuildId()->AllocateVirtualMemory(builder_->GetBuildId()->GetSize()); 188 builder_->WriteBuildIdSection(); 189 } 190 } 191 192 template <typename ElfTypes> 193 void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size, 194 size_t text_size, 195 size_t bss_size, 196 size_t bss_methods_offset, 197 size_t bss_roots_offset, 198 size_t dex_section_size) { 199 DCHECK_EQ(rodata_size_, 0u); 200 rodata_size_ = rodata_size; 201 DCHECK_EQ(text_size_, 0u); 202 text_size_ = text_size; 203 DCHECK_EQ(bss_size_, 0u); 204 bss_size_ = bss_size; 205 DCHECK_EQ(dex_section_size_, 0u); 206 dex_section_size_ = dex_section_size; 207 builder_->PrepareDynamicSection(elf_file_->GetPath(), 208 rodata_size_, 209 text_size_, 210 bss_size_, 211 bss_methods_offset, 212 bss_roots_offset, 213 dex_section_size); 214 } 215 216 template <typename ElfTypes> 217 OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() { 218 auto* rodata = builder_->GetRoData(); 219 rodata->Start(); 220 return rodata; 221 } 222 223 template <typename ElfTypes> 224 void ElfWriterQuick<ElfTypes>::EndRoData(OutputStream* rodata) { 225 CHECK_EQ(builder_->GetRoData(), rodata); 226 builder_->GetRoData()->End(); 227 } 228 229 template <typename ElfTypes> 230 OutputStream* ElfWriterQuick<ElfTypes>::StartText() { 231 auto* text = builder_->GetText(); 232 text->Start(); 233 return text; 234 } 235 236 template <typename ElfTypes> 237 void ElfWriterQuick<ElfTypes>::EndText(OutputStream* text) { 238 CHECK_EQ(builder_->GetText(), text); 239 builder_->GetText()->End(); 240 } 241 242 template <typename ElfTypes> 243 void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { 244 if (builder_->GetIsa() == InstructionSet::kMips || 245 builder_->GetIsa() == InstructionSet::kMips64) { 246 builder_->WriteMIPSabiflagsSection(); 247 } 248 builder_->WriteDynamicSection(); 249 } 250 251 template <typename ElfTypes> 252 void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(const debug::DebugInfo& debug_info) { 253 if (!debug_info.Empty() && compiler_options_->GetGenerateMiniDebugInfo()) { 254 // Prepare the mini-debug-info in background while we do other I/O. 255 Thread* self = Thread::Current(); 256 debug_info_task_ = std::unique_ptr<DebugInfoTask>( 257 new DebugInfoTask(builder_->GetIsa(), 258 instruction_set_features_, 259 builder_->GetText()->GetAddress(), 260 text_size_, 261 builder_->GetDex()->Exists() ? builder_->GetDex()->GetAddress() : 0, 262 dex_section_size_, 263 debug_info)); 264 debug_info_thread_pool_ = std::unique_ptr<ThreadPool>( 265 new ThreadPool("Mini-debug-info writer", 1)); 266 debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); 267 debug_info_thread_pool_->StartWorkers(self); 268 } 269 } 270 271 template <typename ElfTypes> 272 void ElfWriterQuick<ElfTypes>::WriteDebugInfo(const debug::DebugInfo& debug_info) { 273 if (!debug_info.Empty()) { 274 if (compiler_options_->GetGenerateDebugInfo()) { 275 // Generate all the debug information we can. 276 debug::WriteDebugInfo(builder_.get(), debug_info, kCFIFormat, true /* write_oat_patches */); 277 } 278 if (compiler_options_->GetGenerateMiniDebugInfo()) { 279 // Wait for the mini-debug-info generation to finish and write it to disk. 280 Thread* self = Thread::Current(); 281 DCHECK(debug_info_thread_pool_ != nullptr); 282 debug_info_thread_pool_->Wait(self, true, false); 283 builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult()); 284 } 285 } 286 } 287 288 template <typename ElfTypes> 289 bool ElfWriterQuick<ElfTypes>::End() { 290 builder_->End(); 291 if (compiler_options_->GetGenerateBuildId()) { 292 uint8_t build_id[ElfBuilder<ElfTypes>::kBuildIdLen]; 293 ComputeFileBuildId(&build_id); 294 builder_->WriteBuildId(build_id); 295 } 296 return builder_->Good(); 297 } 298 299 template <typename ElfTypes> 300 void ElfWriterQuick<ElfTypes>::ComputeFileBuildId( 301 uint8_t (*build_id)[ElfBuilder<ElfTypes>::kBuildIdLen]) { 302 constexpr int kBufSize = 8192; 303 std::vector<char> buffer(kBufSize); 304 int64_t offset = 0; 305 SHA_CTX ctx; 306 SHA1_Init(&ctx); 307 while (true) { 308 int64_t bytes_read = elf_file_->Read(buffer.data(), kBufSize, offset); 309 CHECK_GE(bytes_read, 0); 310 if (bytes_read == 0) { 311 // End of file. 312 break; 313 } 314 SHA1_Update(&ctx, buffer.data(), bytes_read); 315 offset += bytes_read; 316 } 317 SHA1_Final(*build_id, &ctx); 318 } 319 320 template <typename ElfTypes> 321 OutputStream* ElfWriterQuick<ElfTypes>::GetStream() { 322 return builder_->GetStream(); 323 } 324 325 template <typename ElfTypes> 326 size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() { 327 return builder_->GetLoadedSize(); 328 } 329 330 // Explicit instantiations 331 template class ElfWriterQuick<ElfTypes32>; 332 template class ElfWriterQuick<ElfTypes64>; 333 334 } // namespace linker 335 } // namespace art 336