elf_writer_quick.cc revision 8dc7324da5bd0f2afd2ab558ab04882329a61fe8
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 21#include "base/logging.h" 22#include "base/unix_file/fd_file.h" 23#include "buffered_output_stream.h" 24#include "compiled_method.h" 25#include "dex_file-inl.h" 26#include "driver/compiler_driver.h" 27#include "driver/compiler_options.h" 28#include "elf_builder.h" 29#include "elf_file.h" 30#include "elf_utils.h" 31#include "elf_writer_debug.h" 32#include "file_output_stream.h" 33#include "globals.h" 34#include "leb128.h" 35#include "oat.h" 36#include "oat_writer.h" 37#include "utils.h" 38 39namespace art { 40 41template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 42 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 43 typename Elf_Phdr, typename Elf_Shdr> 44bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 45 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Create(File* elf_file, 46 OatWriter* oat_writer, 47 const std::vector<const DexFile*>& dex_files, 48 const std::string& android_root, 49 bool is_host, 50 const CompilerDriver& driver) { 51 ElfWriterQuick elf_writer(driver, elf_file); 52 return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 53} 54 55class OatWriterWrapper FINAL : public CodeOutput { 56 public: 57 explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {} 58 59 void SetCodeOffset(size_t offset) { 60 oat_writer_->SetOatDataOffset(offset); 61 } 62 bool Write(OutputStream* out) OVERRIDE { 63 return oat_writer_->Write(out); 64 } 65 private: 66 OatWriter* const oat_writer_; 67}; 68 69template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 70 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 71 typename Elf_Phdr, typename Elf_Shdr> 72static void WriteDebugSymbols(const CompilerDriver* compiler_driver, 73 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 74 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder, 75 OatWriter* oat_writer); 76 77// Encode patch locations in .oat_patches format. 78template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 79 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 80 typename Elf_Phdr, typename Elf_Shdr> 81void ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, Elf_Sym, Elf_Ehdr, 82 Elf_Phdr, Elf_Shdr>::EncodeOatPatches(const OatWriter::PatchLocationsMap& sections, 83 std::vector<uint8_t>* buffer) { 84 for (const auto& section : sections) { 85 const std::string& name = section.first; 86 std::vector<uintptr_t>* locations = section.second.get(); 87 DCHECK(!name.empty()); 88 std::sort(locations->begin(), locations->end()); 89 // Reserve buffer space - guess 2 bytes per ULEB128. 90 buffer->reserve(buffer->size() + name.size() + locations->size() * 2); 91 // Write null-terminated section name. 92 const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str()); 93 buffer->insert(buffer->end(), name_data, name_data + name.size() + 1); 94 // Write placeholder for data length. 95 size_t length_pos = buffer->size(); 96 EncodeUnsignedLeb128(buffer, UINT32_MAX); 97 // Write LEB128 encoded list of advances (deltas between consequtive addresses). 98 size_t data_pos = buffer->size(); 99 uintptr_t address = 0; // relative to start of section. 100 for (uintptr_t location : *locations) { 101 DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations"; 102 EncodeUnsignedLeb128(buffer, location - address); 103 address = location; 104 } 105 // Update length. 106 UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos); 107 } 108 buffer->push_back(0); // End of sections. 109} 110 111template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 112 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 113 typename Elf_Phdr, typename Elf_Shdr> 114bool ElfWriterQuick<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 115 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>::Write(OatWriter* oat_writer, 116 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED, 117 const std::string& android_root_unused ATTRIBUTE_UNUSED, 118 bool is_host_unused ATTRIBUTE_UNUSED) { 119 constexpr bool debug = false; 120 const OatHeader& oat_header = oat_writer->GetOatHeader(); 121 Elf_Word oat_data_size = oat_header.GetExecutableOffset(); 122 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size; 123 uint32_t oat_bss_size = oat_writer->GetBssSize(); 124 125 OatWriterWrapper wrapper(oat_writer); 126 127 std::unique_ptr<ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 128 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr> > builder( 129 new ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 130 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>( 131 &wrapper, 132 elf_file_, 133 compiler_driver_->GetInstructionSet(), 134 0, 135 oat_data_size, 136 oat_data_size, 137 oat_exec_size, 138 RoundUp(oat_data_size + oat_exec_size, kPageSize), 139 oat_bss_size, 140 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(), 141 debug)); 142 143 if (!builder->Init()) { 144 return false; 145 } 146 147 if (compiler_driver_->GetCompilerOptions().GetIncludeCFI() && 148 !oat_writer->GetMethodDebugInfo().empty()) { 149 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> eh_frame( 150 ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); 151 dwarf::WriteEhFrame(compiler_driver_, oat_writer, 152 builder->GetTextBuilder().GetSection()->sh_addr, 153 eh_frame.GetBuffer()); 154 builder->RegisterRawSection(eh_frame); 155 } 156 157 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols() && 158 !oat_writer->GetMethodDebugInfo().empty()) { 159 WriteDebugSymbols(compiler_driver_, builder.get(), oat_writer); 160 } 161 162 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() || 163 // ElfWriter::Fixup will be called regardless and it needs to be able 164 // to patch debug sections so we have to include patches for them. 165 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { 166 ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> oat_patches( 167 ".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, 1, 0); 168 EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer()); 169 builder->RegisterRawSection(oat_patches); 170 } 171 172 return builder->Write(); 173} 174 175template <typename Elf_Word, typename Elf_Sword, typename Elf_Addr, 176 typename Elf_Dyn, typename Elf_Sym, typename Elf_Ehdr, 177 typename Elf_Phdr, typename Elf_Shdr> 178// Do not inline to avoid Clang stack frame problems. b/18738594 179NO_INLINE 180static void WriteDebugSymbols(const CompilerDriver* compiler_driver, 181 ElfBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Dyn, 182 Elf_Sym, Elf_Ehdr, Elf_Phdr, Elf_Shdr>* builder, 183 OatWriter* oat_writer) { 184 // Iterate over the compiled methods. 185 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo(); 186 ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab = 187 builder->GetSymtabBuilder(); 188 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 189 std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true); 190 if (it->deduped_) { 191 // TODO We should place the DEDUPED tag on the first instance of a deduplicated symbol 192 // so that it will show up in a debuggerd crash report. 193 name += " [ DEDUPED ]"; 194 } 195 196 uint32_t low_pc = it->low_pc_; 197 // Add in code delta, e.g., thumb bit 0 for Thumb2 code. 198 low_pc += it->compiled_method_->CodeDelta(); 199 symtab->AddSymbol(name, &builder->GetTextBuilder(), low_pc, 200 true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC); 201 202 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 203 // instructions, so that disassembler tools can correctly disassemble. 204 if (it->compiled_method_->GetInstructionSet() == kThumb2) { 205 symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true, 206 0, STB_LOCAL, STT_NOTYPE); 207 } 208 } 209 210 typedef ElfRawSectionBuilder<Elf_Word, Elf_Sword, Elf_Shdr> Section; 211 Section debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 212 Section debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 213 Section debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 214 Section debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 215 216 dwarf::WriteDebugSections(compiler_driver, 217 oat_writer, 218 builder->GetTextBuilder().GetSection()->sh_addr, 219 debug_info.GetBuffer(), 220 debug_abbrev.GetBuffer(), 221 debug_str.GetBuffer(), 222 debug_line.GetBuffer()); 223 224 builder->RegisterRawSection(debug_info); 225 builder->RegisterRawSection(debug_abbrev); 226 builder->RegisterRawSection(debug_str); 227 builder->RegisterRawSection(debug_line); 228} 229 230// Explicit instantiations 231template class ElfWriterQuick<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn, 232 Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>; 233template class ElfWriterQuick<Elf64_Word, Elf64_Sword, Elf64_Addr, Elf64_Dyn, 234 Elf64_Sym, Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>; 235 236} // namespace art 237