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 #include <unordered_map>
     21 
     22 #include "base/array_ref.h"
     23 #include "debug/dwarf/dwarf_constants.h"
     24 #include "debug/elf_compilation_unit.h"
     25 #include "debug/elf_debug_frame_writer.h"
     26 #include "debug/elf_debug_info_writer.h"
     27 #include "debug/elf_debug_line_writer.h"
     28 #include "debug/elf_debug_loc_writer.h"
     29 #include "debug/elf_gnu_debugdata_writer.h"
     30 #include "debug/elf_symtab_writer.h"
     31 #include "debug/method_debug_info.h"
     32 #include "linker/elf_builder.h"
     33 #include "linker/vector_output_stream.h"
     34 #include "oat.h"
     35 
     36 namespace art {
     37 namespace debug {
     38 
     39 template <typename ElfTypes>
     40 void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder,
     41                     const DebugInfo& debug_info,
     42                     dwarf::CFIFormat cfi_format,
     43                     bool write_oat_patches) {
     44   // Write .strtab and .symtab.
     45   WriteDebugSymbols(builder, false /* mini-debug-info */, debug_info);
     46 
     47   // Write .debug_frame.
     48   WriteCFISection(builder, debug_info.compiled_methods, cfi_format, write_oat_patches);
     49 
     50   // Group the methods into compilation units based on class.
     51   std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit;
     52   for (const MethodDebugInfo& mi : debug_info.compiled_methods) {
     53     if (mi.dex_file != nullptr) {
     54       auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
     55       ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def];
     56       cu.methods.push_back(&mi);
     57       // All methods must have the same addressing mode otherwise the min/max below does not work.
     58       DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
     59       cu.is_code_address_text_relative = mi.is_code_address_text_relative;
     60       cu.code_address = std::min(cu.code_address, mi.code_address);
     61       cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
     62     }
     63   }
     64 
     65   // Sort compilation units to make the compiler output deterministic.
     66   std::vector<ElfCompilationUnit> compilation_units;
     67   compilation_units.reserve(class_to_compilation_unit.size());
     68   for (auto& it : class_to_compilation_unit) {
     69     // The .debug_line section requires the methods to be sorted by code address.
     70     std::stable_sort(it.second.methods.begin(),
     71                      it.second.methods.end(),
     72                      [](const MethodDebugInfo* a, const MethodDebugInfo* b) {
     73                          return a->code_address < b->code_address;
     74                      });
     75     compilation_units.push_back(std::move(it.second));
     76   }
     77   std::sort(compilation_units.begin(),
     78             compilation_units.end(),
     79             [](ElfCompilationUnit& a, ElfCompilationUnit& b) {
     80                 // Sort by index of the first method within the method_infos array.
     81                 // This assumes that the order of method_infos is deterministic.
     82                 // Code address is not good for sorting due to possible duplicates.
     83                 return a.methods.front() < b.methods.front();
     84             });
     85 
     86   // Write .debug_line section.
     87   if (!compilation_units.empty()) {
     88     ElfDebugLineWriter<ElfTypes> line_writer(builder);
     89     line_writer.Start();
     90     for (auto& compilation_unit : compilation_units) {
     91       line_writer.WriteCompilationUnit(compilation_unit);
     92     }
     93     line_writer.End(write_oat_patches);
     94   }
     95 
     96   // Write .debug_info section.
     97   if (!compilation_units.empty()) {
     98     ElfDebugInfoWriter<ElfTypes> info_writer(builder);
     99     info_writer.Start();
    100     for (const auto& compilation_unit : compilation_units) {
    101       ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
    102       cu_writer.Write(compilation_unit);
    103     }
    104     info_writer.End(write_oat_patches);
    105   }
    106 }
    107 
    108 std::vector<uint8_t> MakeMiniDebugInfo(
    109     InstructionSet isa,
    110     const InstructionSetFeatures* features,
    111     uint64_t text_section_address,
    112     size_t text_section_size,
    113     uint64_t dex_section_address,
    114     size_t dex_section_size,
    115     const DebugInfo& debug_info) {
    116   if (Is64BitInstructionSet(isa)) {
    117     return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
    118                                                  features,
    119                                                  text_section_address,
    120                                                  text_section_size,
    121                                                  dex_section_address,
    122                                                  dex_section_size,
    123                                                  debug_info);
    124   } else {
    125     return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
    126                                                  features,
    127                                                  text_section_address,
    128                                                  text_section_size,
    129                                                  dex_section_address,
    130                                                  dex_section_size,
    131                                                  debug_info);
    132   }
    133 }
    134 
    135 template <typename ElfTypes>
    136 static std::vector<uint8_t> MakeElfFileForJITInternal(
    137     InstructionSet isa,
    138     const InstructionSetFeatures* features,
    139     bool mini_debug_info,
    140     ArrayRef<const MethodDebugInfo> method_infos) {
    141   CHECK_GT(method_infos.size(), 0u);
    142   uint64_t min_address = std::numeric_limits<uint64_t>::max();
    143   uint64_t max_address = 0;
    144   for (const MethodDebugInfo& mi : method_infos) {
    145     CHECK_EQ(mi.is_code_address_text_relative, false);
    146     min_address = std::min(min_address, mi.code_address);
    147     max_address = std::max(max_address, mi.code_address + mi.code_size);
    148   }
    149   DebugInfo debug_info{};
    150   debug_info.compiled_methods = method_infos;
    151   std::vector<uint8_t> buffer;
    152   buffer.reserve(KB);
    153   linker::VectorOutputStream out("Debug ELF file", &buffer);
    154   std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
    155       new linker::ElfBuilder<ElfTypes>(isa, features, &out));
    156   // No program headers since the ELF file is not linked and has no allocated sections.
    157   builder->Start(false /* write_program_headers */);
    158   if (mini_debug_info) {
    159     if (method_infos.size() > 1) {
    160       std::vector<uint8_t> mdi = MakeMiniDebugInfo(isa,
    161                                                    features,
    162                                                    min_address,
    163                                                    max_address - min_address,
    164                                                    /* dex_section_address */ 0,
    165                                                    /* dex_section_size */ 0,
    166                                                    debug_info);
    167       builder->WriteSection(".gnu_debugdata", &mdi);
    168     } else {
    169       // The compression is great help for multiple methods but it is not worth it for a
    170       // single method due to the overheads so skip the compression here for performance.
    171       builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
    172       WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info);
    173       WriteCFISection(builder.get(),
    174                       debug_info.compiled_methods,
    175                       dwarf::DW_DEBUG_FRAME_FORMAT,
    176                       false /* write_oat_paches */);
    177     }
    178   } else {
    179     builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
    180     WriteDebugInfo(builder.get(),
    181                    debug_info,
    182                    dwarf::DW_DEBUG_FRAME_FORMAT,
    183                    false /* write_oat_patches */);
    184   }
    185   builder->End();
    186   CHECK(builder->Good());
    187   return buffer;
    188 }
    189 
    190 std::vector<uint8_t> MakeElfFileForJIT(
    191     InstructionSet isa,
    192     const InstructionSetFeatures* features,
    193     bool mini_debug_info,
    194     ArrayRef<const MethodDebugInfo> method_infos) {
    195   if (Is64BitInstructionSet(isa)) {
    196     return MakeElfFileForJITInternal<ElfTypes64>(isa, features, mini_debug_info, method_infos);
    197   } else {
    198     return MakeElfFileForJITInternal<ElfTypes32>(isa, features, mini_debug_info, method_infos);
    199   }
    200 }
    201 
    202 template <typename ElfTypes>
    203 static std::vector<uint8_t> WriteDebugElfFileForClassesInternal(
    204     InstructionSet isa,
    205     const InstructionSetFeatures* features,
    206     const ArrayRef<mirror::Class*>& types)
    207     REQUIRES_SHARED(Locks::mutator_lock_) {
    208   std::vector<uint8_t> buffer;
    209   buffer.reserve(KB);
    210   linker::VectorOutputStream out("Debug ELF file", &buffer);
    211   std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder(
    212       new linker::ElfBuilder<ElfTypes>(isa, features, &out));
    213   // No program headers since the ELF file is not linked and has no allocated sections.
    214   builder->Start(false /* write_program_headers */);
    215   ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
    216   info_writer.Start();
    217   ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
    218   cu_writer.Write(types);
    219   info_writer.End(false /* write_oat_patches */);
    220 
    221   builder->End();
    222   CHECK(builder->Good());
    223   return buffer;
    224 }
    225 
    226 std::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa,
    227                                                  const InstructionSetFeatures* features,
    228                                                  const ArrayRef<mirror::Class*>& types) {
    229   if (Is64BitInstructionSet(isa)) {
    230     return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, features, types);
    231   } else {
    232     return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, features, types);
    233   }
    234 }
    235 
    236 // Explicit instantiations
    237 template void WriteDebugInfo<ElfTypes32>(
    238     linker::ElfBuilder<ElfTypes32>* builder,
    239     const DebugInfo& debug_info,
    240     dwarf::CFIFormat cfi_format,
    241     bool write_oat_patches);
    242 template void WriteDebugInfo<ElfTypes64>(
    243     linker::ElfBuilder<ElfTypes64>* builder,
    244     const DebugInfo& debug_info,
    245     dwarf::CFIFormat cfi_format,
    246     bool write_oat_patches);
    247 
    248 }  // namespace debug
    249 }  // namespace art
    250