elf_writer_quick.cc revision 388d2861ce185fe9bbf1989f1467031467bd1de7
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 "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 "globals.h" 33#include "leb128.h" 34#include "oat.h" 35#include "oat_writer.h" 36#include "utils.h" 37 38namespace art { 39 40// .eh_frame and .debug_frame are almost identical. 41// Except for some minor formatting differences, the main difference 42// is that .eh_frame is allocated within the running program because 43// it is used by C++ exception handling (which we do not use so we 44// can choose either). C++ compilers generally tend to use .eh_frame 45// because if they need it sometimes, they might as well always use it. 46constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_EH_FRAME_FORMAT; 47 48// The ARM specification defines three special mapping symbols 49// $a, $t and $d which mark ARM, Thumb and data ranges respectively. 50// These symbols can be used by tools, for example, to pretty 51// print instructions correctly. Objdump will use them if they 52// exist, but it will still work well without them. 53// However, these extra symbols take space, so let's just generate 54// one symbol which marks the whole .text section as code. 55constexpr bool kGenerateSingleArmMappingSymbol = true; 56 57template <typename ElfTypes> 58bool ElfWriterQuick<ElfTypes>::Create(File* elf_file, 59 OatWriter* oat_writer, 60 const std::vector<const DexFile*>& dex_files, 61 const std::string& android_root, 62 bool is_host, 63 const CompilerDriver& driver) { 64 ElfWriterQuick elf_writer(driver, elf_file); 65 return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 66} 67 68template <typename ElfTypes> 69static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer); 70 71// Encode patch locations in .oat_patches format. 72template <typename ElfTypes> 73void ElfWriterQuick<ElfTypes>::EncodeOatPatches( 74 const OatWriter::PatchLocationsMap& sections, 75 std::vector<uint8_t>* buffer) { 76 for (const auto& section : sections) { 77 const std::string& name = section.first; 78 std::vector<uintptr_t>* locations = section.second.get(); 79 DCHECK(!name.empty()); 80 std::sort(locations->begin(), locations->end()); 81 // Reserve buffer space - guess 2 bytes per ULEB128. 82 buffer->reserve(buffer->size() + name.size() + locations->size() * 2); 83 // Write null-terminated section name. 84 const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str()); 85 buffer->insert(buffer->end(), name_data, name_data + name.size() + 1); 86 // Write placeholder for data length. 87 size_t length_pos = buffer->size(); 88 EncodeUnsignedLeb128(buffer, UINT32_MAX); 89 // Write LEB128 encoded list of advances (deltas between consequtive addresses). 90 size_t data_pos = buffer->size(); 91 uintptr_t address = 0; // relative to start of section. 92 for (uintptr_t location : *locations) { 93 DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations"; 94 EncodeUnsignedLeb128(buffer, location - address); 95 address = location; 96 } 97 // Update length. 98 UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos); 99 } 100 buffer->push_back(0); // End of sections. 101} 102 103class RodataWriter FINAL : public CodeOutput { 104 public: 105 explicit RodataWriter(OatWriter* oat_writer) : oat_writer_(oat_writer) {} 106 107 bool Write(OutputStream* out) OVERRIDE { 108 return oat_writer_->WriteRodata(out); 109 } 110 111 private: 112 OatWriter* oat_writer_; 113}; 114 115class TextWriter FINAL : public CodeOutput { 116 public: 117 explicit TextWriter(OatWriter* oat_writer) : oat_writer_(oat_writer) {} 118 119 bool Write(OutputStream* out) OVERRIDE { 120 return oat_writer_->WriteCode(out); 121 } 122 123 private: 124 OatWriter* oat_writer_; 125}; 126 127enum PatchResult { 128 kAbsoluteAddress, // Absolute memory location. 129 kPointerRelativeAddress, // Offset relative to the location of the pointer. 130 kSectionRelativeAddress, // Offset relative to start of containing section. 131}; 132 133// Patch memory addresses within a buffer. 134// It assumes that the unpatched addresses are offsets relative to base_address. 135// (which generally means method's low_pc relative to the start of .text) 136template <typename Elf_Addr, typename Address, PatchResult kPatchResult> 137static void Patch(const std::vector<uintptr_t>& patch_locations, 138 Elf_Addr buffer_address, Elf_Addr base_address, 139 std::vector<uint8_t>* buffer) { 140 for (uintptr_t location : patch_locations) { 141 typedef __attribute__((__aligned__(1))) Address UnalignedAddress; 142 auto* to_patch = reinterpret_cast<UnalignedAddress*>(buffer->data() + location); 143 switch (kPatchResult) { 144 case kAbsoluteAddress: 145 *to_patch = (base_address + *to_patch); 146 break; 147 case kPointerRelativeAddress: 148 *to_patch = (base_address + *to_patch) - (buffer_address + location); 149 break; 150 case kSectionRelativeAddress: 151 *to_patch = (base_address + *to_patch) - buffer_address; 152 break; 153 } 154 } 155} 156 157template <typename ElfTypes> 158bool ElfWriterQuick<ElfTypes>::Write( 159 OatWriter* oat_writer, 160 const std::vector<const DexFile*>& dex_files_unused ATTRIBUTE_UNUSED, 161 const std::string& android_root_unused ATTRIBUTE_UNUSED, 162 bool is_host_unused ATTRIBUTE_UNUSED) { 163 using Elf_Addr = typename ElfTypes::Addr; 164 const InstructionSet isa = compiler_driver_->GetInstructionSet(); 165 166 // Setup the builder with the main OAT sections (.rodata .text .bss). 167 const size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset(); 168 const size_t text_size = oat_writer->GetSize() - rodata_size; 169 const size_t bss_size = oat_writer->GetBssSize(); 170 RodataWriter rodata_writer(oat_writer); 171 TextWriter text_writer(oat_writer); 172 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>( 173 isa, rodata_size, &rodata_writer, text_size, &text_writer, bss_size)); 174 175 // Add debug sections. 176 // They are stack allocated here (in the same scope as the builder), 177 // but they are registred with the builder only if they are used. 178 using RawSection = typename ElfBuilder<ElfTypes>::RawSection; 179 const auto* text = builder->GetText(); 180 const bool is64bit = Is64BitInstructionSet(isa); 181 const int pointer_size = GetInstructionSetPointerSize(isa); 182 RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0, 183 is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> : 184 Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>, 185 text); 186 RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0, 187 Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text); 188 RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0, 189 is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> : 190 Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, 191 text); 192 RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0, 193 Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text); 194 RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 195 RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 196 RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0, 197 Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text); 198 if (!oat_writer->GetMethodDebugInfo().empty()) { 199 if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) { 200 if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) { 201 dwarf::WriteCFISection( 202 compiler_driver_, oat_writer, 203 dwarf::DW_EH_PE_pcrel, kCFIFormat, 204 eh_frame.GetBuffer(), eh_frame.GetPatchLocations(), 205 eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations()); 206 builder->RegisterSection(&eh_frame); 207 builder->RegisterSection(&eh_frame_hdr); 208 } else { 209 DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT); 210 dwarf::WriteCFISection( 211 compiler_driver_, oat_writer, 212 dwarf::DW_EH_PE_absptr, kCFIFormat, 213 debug_frame.GetBuffer(), debug_frame.GetPatchLocations(), 214 nullptr, nullptr); 215 builder->RegisterSection(&debug_frame); 216 *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") = 217 *debug_frame.GetPatchLocations(); 218 } 219 } 220 if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { 221 // Add methods to .symtab. 222 WriteDebugSymbols(builder.get(), oat_writer); 223 // Generate DWARF .debug_* sections. 224 dwarf::WriteDebugSections( 225 compiler_driver_, oat_writer, 226 debug_info.GetBuffer(), debug_info.GetPatchLocations(), 227 debug_abbrev.GetBuffer(), 228 debug_str.GetBuffer(), 229 debug_line.GetBuffer(), debug_line.GetPatchLocations()); 230 builder->RegisterSection(&debug_info); 231 builder->RegisterSection(&debug_abbrev); 232 builder->RegisterSection(&debug_str); 233 builder->RegisterSection(&debug_line); 234 *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") = 235 *debug_info.GetPatchLocations(); 236 *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") = 237 *debug_line.GetPatchLocations(); 238 } 239 } 240 241 // Add relocation section. 242 RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0); 243 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() || 244 // ElfWriter::Fixup will be called regardless and it needs to be able 245 // to patch debug sections so we have to include patches for them. 246 compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) { 247 EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer()); 248 builder->RegisterSection(&oat_patches); 249 } 250 251 return builder->Write(elf_file_); 252} 253 254template <typename ElfTypes> 255static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) { 256 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo(); 257 bool generated_mapping_symbol = false; 258 259 // Find all addresses (low_pc) which contain deduped methods. 260 // The first instance of method is not marked deduped_, but the rest is. 261 std::unordered_set<uint32_t> deduped_addresses; 262 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 263 if (it->deduped_) { 264 deduped_addresses.insert(it->low_pc_); 265 } 266 } 267 268 auto* symtab = builder->GetSymtab(); 269 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 270 if (it->deduped_) { 271 continue; // Add symbol only for the first instance. 272 } 273 std::string name = PrettyMethod(it->dex_method_index_, *it->dex_file_, true); 274 if (deduped_addresses.find(it->low_pc_) != deduped_addresses.end()) { 275 name += " [DEDUPED]"; 276 } 277 278 uint32_t low_pc = it->low_pc_; 279 // Add in code delta, e.g., thumb bit 0 for Thumb2 code. 280 low_pc += it->compiled_method_->CodeDelta(); 281 symtab->AddSymbol(name, builder->GetText(), low_pc, 282 true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC); 283 284 // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2 285 // instructions, so that disassembler tools can correctly disassemble. 286 // Note that even if we generate just a single mapping symbol, ARM's Streamline 287 // requires it to match function symbol. Just address 0 does not work. 288 if (it->compiled_method_->GetInstructionSet() == kThumb2) { 289 if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) { 290 symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true, 291 0, STB_LOCAL, STT_NOTYPE); 292 generated_mapping_symbol = true; 293 } 294 } 295 } 296} 297 298// Explicit instantiations 299template class ElfWriterQuick<ElfTypes32>; 300template class ElfWriterQuick<ElfTypes64>; 301 302} // namespace art 303