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