Home | History | Annotate | Download | only in debug
      1 /*
      2  * Copyright (C) 2016 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_debug_writer.h"
     18 
     19 #include <vector>
     20 
     21 #include "base/array_ref.h"
     22 #include "debug/dwarf/dwarf_constants.h"
     23 #include "debug/elf_compilation_unit.h"
     24 #include "debug/elf_debug_frame_writer.h"
     25 #include "debug/elf_debug_info_writer.h"
     26 #include "debug/elf_debug_line_writer.h"
     27 #include "debug/elf_debug_loc_writer.h"
     28 #include "debug/elf_gnu_debugdata_writer.h"
     29 #include "debug/elf_symtab_writer.h"
     30 #include "debug/method_debug_info.h"
     31 #include "elf_builder.h"
     32 #include "linker/vector_output_stream.h"
     33 #include "oat.h"
     34 
     35 namespace art {
     36 namespace debug {
     37 
     38 template <typename ElfTypes>
     39 void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
     40                     const ArrayRef<const MethodDebugInfo>& method_infos,
     41                     dwarf::CFIFormat cfi_format,
     42                     bool write_oat_patches) {
     43   // Write .strtab and .symtab.
     44   WriteDebugSymbols(builder, method_infos, true /* with_signature */);
     45 
     46   // Write .debug_frame.
     47   WriteCFISection(builder, method_infos, cfi_format, write_oat_patches);
     48 
     49   // Group the methods into compilation units based on source file.
     50   std::vector<ElfCompilationUnit> compilation_units;
     51   const char* last_source_file = nullptr;
     52   for (const MethodDebugInfo& mi : method_infos) {
     53     if (mi.dex_file != nullptr) {
     54       auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
     55       const char* source_file = mi.dex_file->GetSourceFile(dex_class_def);
     56       if (compilation_units.empty() || source_file != last_source_file) {
     57         compilation_units.push_back(ElfCompilationUnit());
     58       }
     59       ElfCompilationUnit& cu = compilation_units.back();
     60       cu.methods.push_back(&mi);
     61       // All methods must have the same addressing mode otherwise the min/max below does not work.
     62       DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
     63       cu.is_code_address_text_relative = mi.is_code_address_text_relative;
     64       cu.code_address = std::min(cu.code_address, mi.code_address);
     65       cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
     66       last_source_file = source_file;
     67     }
     68   }
     69 
     70   // Write .debug_line section.
     71   if (!compilation_units.empty()) {
     72     ElfDebugLineWriter<ElfTypes> line_writer(builder);
     73     line_writer.Start();
     74     for (auto& compilation_unit : compilation_units) {
     75       line_writer.WriteCompilationUnit(compilation_unit);
     76     }
     77     line_writer.End(write_oat_patches);
     78   }
     79 
     80   // Write .debug_info section.
     81   if (!compilation_units.empty()) {
     82     ElfDebugInfoWriter<ElfTypes> info_writer(builder);
     83     info_writer.Start();
     84     for (const auto& compilation_unit : compilation_units) {
     85       ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
     86       cu_writer.Write(compilation_unit);
     87     }
     88     info_writer.End(write_oat_patches);
     89   }
     90 }
     91 
     92 std::vector<uint8_t> MakeMiniDebugInfo(
     93     InstructionSet isa,
     94     const InstructionSetFeatures* features,
     95     size_t rodata_size,
     96     size_t text_size,
     97     const ArrayRef<const MethodDebugInfo>& method_infos) {
     98   if (Is64BitInstructionSet(isa)) {
     99     return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
    100                                                  features,
    101                                                  rodata_size,
    102                                                  text_size,
    103                                                  method_infos);
    104   } else {
    105     return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
    106                                                  features,
    107                                                  rodata_size,
    108                                                  text_size,
    109                                                  method_infos);
    110   }
    111 }
    112 
    113 template <typename ElfTypes>
    114 static std::vector<uint8_t> WriteDebugElfFileForMethodsInternal(
    115     InstructionSet isa,
    116     const InstructionSetFeatures* features,
    117     const ArrayRef<const MethodDebugInfo>& method_infos) {
    118   std::vector<uint8_t> buffer;
    119   buffer.reserve(KB);
    120   VectorOutputStream out("Debug ELF file", &buffer);
    121   std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
    122   // No program headers since the ELF file is not linked and has no allocated sections.
    123   builder->Start(false /* write_program_headers */);
    124   WriteDebugInfo(builder.get(),
    125                  method_infos,
    126                  dwarf::DW_DEBUG_FRAME_FORMAT,
    127                  false /* write_oat_patches */);
    128   builder->End();
    129   CHECK(builder->Good());
    130   return buffer;
    131 }
    132 
    133 std::vector<uint8_t> WriteDebugElfFileForMethods(
    134     InstructionSet isa,
    135     const InstructionSetFeatures* features,
    136     const ArrayRef<const MethodDebugInfo>& method_infos) {
    137   if (Is64BitInstructionSet(isa)) {
    138     return WriteDebugElfFileForMethodsInternal<ElfTypes64>(isa, features, method_infos);
    139   } else {
    140     return WriteDebugElfFileForMethodsInternal<ElfTypes32>(isa, features, method_infos);
    141   }
    142 }
    143 
    144 template <typename ElfTypes>
    145 static std::vector<uint8_t> WriteDebugElfFileForClassesInternal(
    146     InstructionSet isa,
    147     const InstructionSetFeatures* features,
    148     const ArrayRef<mirror::Class*>& types)
    149     REQUIRES_SHARED(Locks::mutator_lock_) {
    150   std::vector<uint8_t> buffer;
    151   buffer.reserve(KB);
    152   VectorOutputStream out("Debug ELF file", &buffer);
    153   std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out));
    154   // No program headers since the ELF file is not linked and has no allocated sections.
    155   builder->Start(false /* write_program_headers */);
    156   ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
    157   info_writer.Start();
    158   ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
    159   cu_writer.Write(types);
    160   info_writer.End(false /* write_oat_patches */);
    161 
    162   builder->End();
    163   CHECK(builder->Good());
    164   return buffer;
    165 }
    166 
    167 std::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa,
    168                                                  const InstructionSetFeatures* features,
    169                                                  const ArrayRef<mirror::Class*>& types) {
    170   if (Is64BitInstructionSet(isa)) {
    171     return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, features, types);
    172   } else {
    173     return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, features, types);
    174   }
    175 }
    176 
    177 std::vector<MethodDebugInfo> MakeTrampolineInfos(const OatHeader& header) {
    178   std::map<const char*, uint32_t> trampolines = {
    179     { "interpreterToInterpreterBridge", header.GetInterpreterToInterpreterBridgeOffset() },
    180     { "interpreterToCompiledCodeBridge", header.GetInterpreterToCompiledCodeBridgeOffset() },
    181     { "jniDlsymLookup", header.GetJniDlsymLookupOffset() },
    182     { "quickGenericJniTrampoline", header.GetQuickGenericJniTrampolineOffset() },
    183     { "quickImtConflictTrampoline", header.GetQuickImtConflictTrampolineOffset() },
    184     { "quickResolutionTrampoline", header.GetQuickResolutionTrampolineOffset() },
    185     { "quickToInterpreterBridge", header.GetQuickToInterpreterBridgeOffset() },
    186   };
    187   std::vector<MethodDebugInfo> result;
    188   for (const auto& it : trampolines) {
    189     if (it.second != 0) {
    190       MethodDebugInfo info = MethodDebugInfo();
    191       info.trampoline_name = it.first;
    192       info.isa = header.GetInstructionSet();
    193       info.is_code_address_text_relative = true;
    194       info.code_address = it.second - header.GetExecutableOffset();
    195       info.code_size = 0;  // The symbol lasts until the next symbol.
    196       result.push_back(std::move(info));
    197     }
    198   }
    199   return result;
    200 }
    201 
    202 // Explicit instantiations
    203 template void WriteDebugInfo<ElfTypes32>(
    204     ElfBuilder<ElfTypes32>* builder,
    205     const ArrayRef<const MethodDebugInfo>& method_infos,
    206     dwarf::CFIFormat cfi_format,
    207     bool write_oat_patches);
    208 template void WriteDebugInfo<ElfTypes64>(
    209     ElfBuilder<ElfTypes64>* builder,
    210     const ArrayRef<const MethodDebugInfo>& method_infos,
    211     dwarf::CFIFormat cfi_format,
    212     bool write_oat_patches);
    213 
    214 }  // namespace debug
    215 }  // namespace art
    216