elf_writer_quick.cc revision 533c207f9d2da6d913c4b10f6f757fe9d6367b10
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/logging.h" 23#include "base/unix_file/fd_file.h" 24#include "buffered_output_stream.h" 25#include "compiled_method.h" 26#include "dex_file-inl.h" 27#include "driver/compiler_driver.h" 28#include "driver/compiler_options.h" 29#include "elf_builder.h" 30#include "elf_file.h" 31#include "elf_utils.h" 32#include "elf_writer_debug.h" 33#include "file_output_stream.h" 34#include "globals.h" 35#include "leb128.h" 36#include "oat.h" 37#include "oat_writer.h" 38#include "utils.h" 39 40namespace art { 41 42template <typename ElfTypes> 43bool ElfWriterQuick<ElfTypes>::Create(File* elf_file, 44 OatWriter* oat_writer, 45 const std::vector<const DexFile*>& dex_files, 46 const std::string& android_root, 47 bool is_host, 48 const CompilerDriver& driver) { 49 ElfWriterQuick elf_writer(driver, elf_file); 50 return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 51} 52 53class OatWriterWrapper FINAL : public CodeOutput { 54 public: 55 explicit OatWriterWrapper(OatWriter* oat_writer) : oat_writer_(oat_writer) {} 56 57 void SetCodeOffset(size_t offset) { 58 oat_writer_->SetOatDataOffset(offset); 59 } 60 bool Write(OutputStream* out) OVERRIDE { 61 return oat_writer_->Write(out); 62 } 63 private: 64 OatWriter* const oat_writer_; 65}; 66 67template <typename ElfTypes> 68static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer); 69 70// Encode patch locations in .oat_patches format. 71template <typename ElfTypes> 72void ElfWriterQuick<ElfTypes>::EncodeOatPatches( 73 const OatWriter::PatchLocationsMap& sections, 74 std::vector<uint8_t>* buffer) { 75 for (const auto& section : sections) { 76 const std::string& name = section.first; 77 std::vector<uintptr_t>* locations = section.second.get(); 78 DCHECK(!name.empty()); 79 std::sort(locations->begin(), locations->end()); 80 // Reserve buffer space - guess 2 bytes per ULEB128. 81 buffer->reserve(buffer->size() + name.size() + locations->size() * 2); 82 // Write null-terminated section name. 83 const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str()); 84 buffer->insert(buffer->end(), name_data, name_data + name.size() + 1); 85 // Write placeholder for data length. 86 size_t length_pos = buffer->size(); 87 EncodeUnsignedLeb128(buffer, UINT32_MAX); 88 // Write LEB128 encoded list of advances (deltas between consequtive addresses). 89 size_t data_pos = buffer->size(); 90 uintptr_t address = 0; // relative to start of section. 91 for (uintptr_t location : *locations) { 92 DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations"; 93 EncodeUnsignedLeb128(buffer, location - address); 94 address = location; 95 } 96 // Update length. 97 UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos); 98 } 99 buffer->push_back(0); // End of sections. 100} 101 102template<typename AddressType, bool SubtractPatchLocation = false> 103static void PatchAddresses(const std::vector<uintptr_t>* patch_locations, 104 AddressType delta, std::vector<uint8_t>* buffer) { 105 // Addresses in .debug_* sections are unaligned. 106 typedef __attribute__((__aligned__(1))) AddressType UnalignedAddressType; 107 if (patch_locations != nullptr) { 108 for (uintptr_t patch_location : *patch_locations) { 109 *reinterpret_cast<UnalignedAddressType*>(buffer->data() + patch_location) += 110 delta - (SubtractPatchLocation ? patch_location : 0); 111 } 112 } 113} 114 115template <typename ElfTypes> 116bool ElfWriterQuick<ElfTypes>::Write( 117 OatWriter* oat_writer, 118 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED, 119 const std::string& android_root_unused ATTRIBUTE_UNUSED, 120 bool is_host_unused ATTRIBUTE_UNUSED) { 121 constexpr bool debug = false; 122 const OatHeader& oat_header = oat_writer->GetOatHeader(); 123 typename ElfTypes::Word oat_data_size = oat_header.GetExecutableOffset(); 124 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size; 125 uint32_t oat_bss_size = oat_writer->GetBssSize(); 126 127 OatWriterWrapper wrapper(oat_writer); 128 129 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>( 130 &wrapper, 131 elf_file_, 132 compiler_driver_->GetInstructionSet(), 133 0, 134 oat_data_size, 135 oat_data_size, 136 oat_exec_size, 137 RoundUp(oat_data_size + oat_exec_size, kPageSize), 138 oat_bss_size, 139 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols(), 140 debug)); 141 142 InstructionSet isa = compiler_driver_->GetInstructionSet(); 143 int alignment = GetInstructionSetPointerSize(isa); 144 typedef ElfRawSectionBuilder<ElfTypes> RawSection; 145 RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, alignment, 0); 146 RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); 147 RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 148 RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 149 RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 150 RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 151 RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, 1, 0); 152 153 // Do not add to .oat_patches since we will make the addresses relative. 154 std::vector<uintptr_t> eh_frame_patches; 155 if (compiler_driver_->GetCompilerOptions().GetIncludeCFI() && 156 !oat_writer->GetMethodDebugInfo().empty()) { 157 dwarf::WriteEhFrame(compiler_driver_, oat_writer, 158 dwarf::DW_EH_PE_pcrel, 159 eh_frame.GetBuffer(), &eh_frame_patches, 160 eh_frame_hdr.GetBuffer()); 161 builder->RegisterRawSection(&eh_frame); 162 builder->RegisterRawSection(&eh_frame_hdr); 163 } 164 165 // Must be done after .eh_frame is created since it is used in the Elf layout. 166 if (!builder->Init()) { 167 return false; 168 } 169 170 std::vector<uintptr_t>* debug_info_patches = nullptr; 171 std::vector<uintptr_t>* debug_line_patches = nullptr; 172 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols() && 173 !oat_writer->GetMethodDebugInfo().empty()) { 174 // Add methods to .symtab. 175 WriteDebugSymbols(builder.get(), oat_writer); 176 // Generate DWARF .debug_* sections. 177 debug_info_patches = oat_writer->GetAbsolutePatchLocationsFor(".debug_info"); 178 debug_line_patches = oat_writer->GetAbsolutePatchLocationsFor(".debug_line"); 179 dwarf::WriteDebugSections(compiler_driver_, oat_writer, 180 debug_info.GetBuffer(), debug_info_patches, 181 debug_abbrev.GetBuffer(), 182 debug_str.GetBuffer(), 183 debug_line.GetBuffer(), debug_line_patches); 184 builder->RegisterRawSection(&debug_info); 185 builder->RegisterRawSection(&debug_abbrev); 186 builder->RegisterRawSection(&debug_str); 187 builder->RegisterRawSection(&debug_line); 188 } 189 190 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() || 191 // ElfWriter::Fixup will be called regardless and it needs to be able 192 // to patch debug sections so we have to include patches for them. 193 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { 194 EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer()); 195 builder->RegisterRawSection(&oat_patches); 196 } 197 198 // We know where .text and .eh_frame will be located, so patch the addresses. 199 typename ElfTypes::Addr text_addr = builder->GetTextBuilder().GetSection()->sh_addr; 200 // TODO: Simplify once we use Elf64 - we can use ElfTypes::Addr instead of branching. 201 if (Is64BitInstructionSet(compiler_driver_->GetInstructionSet())) { 202 // relative_address = (text_addr + address) - (eh_frame_addr + patch_location); 203 PatchAddresses<uint64_t, true>(&eh_frame_patches, 204 text_addr - eh_frame.GetSection()->sh_addr, eh_frame.GetBuffer()); 205 PatchAddresses<uint64_t>(debug_info_patches, text_addr, debug_info.GetBuffer()); 206 PatchAddresses<uint64_t>(debug_line_patches, text_addr, debug_line.GetBuffer()); 207 } else { 208 // relative_address = (text_addr + address) - (eh_frame_addr + patch_location); 209 PatchAddresses<uint32_t, true>(&eh_frame_patches, 210 text_addr - eh_frame.GetSection()->sh_addr, eh_frame.GetBuffer()); 211 PatchAddresses<uint32_t>(debug_info_patches, text_addr, debug_info.GetBuffer()); 212 PatchAddresses<uint32_t>(debug_line_patches, text_addr, debug_line.GetBuffer()); 213 } 214 215 return builder->Write(); 216} 217 218template <typename ElfTypes> 219// Do not inline to avoid Clang stack frame problems. b/18738594 220NO_INLINE 221static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) { 222 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo(); 223 224 // Find all addresses (low_pc) which contain deduped methods. 225 // The first instance of method is not marked deduped_, but the rest is. 226 std::unordered_set<uint32_t> deduped_addresses; 227 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 228 if (it->deduped_) { 229 deduped_addresses.insert(it->low_pc_); 230 } 231 } 232 233 ElfSymtabBuilder<ElfTypes>* symtab = builder->GetSymtabBuilder(); 234 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 235 std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true); 236 if (deduped_addresses.find(it->low_pc_) != deduped_addresses.end()) { 237 name += " [DEDUPED]"; 238 } 239 240 uint32_t low_pc = it->low_pc_; 241 // Add in code delta, e.g., thumb bit 0 for Thumb2 code. 242 low_pc += it->compiled_method_->CodeDelta(); 243 symtab->AddSymbol(name, &builder->GetTextBuilder(), low_pc, 244 true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC); 245 246 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 247 // instructions, so that disassembler tools can correctly disassemble. 248 if (it->compiled_method_->GetInstructionSet() == kThumb2) { 249 symtab->AddSymbol("$t", &builder->GetTextBuilder(), it->low_pc_ & ~1, true, 250 0, STB_LOCAL, STT_NOTYPE); 251 } 252 } 253} 254 255// Explicit instantiations 256template class ElfWriterQuick<ElfTypes32>; 257template class ElfWriterQuick<ElfTypes64>; 258 259} // namespace art 260