diff options
-rw-r--r-- | compiler/debug/debug_info.h | 46 | ||||
-rw-r--r-- | compiler/debug/elf_debug_writer.cc | 45 | ||||
-rw-r--r-- | compiler/debug/elf_debug_writer.h | 7 | ||||
-rw-r--r-- | compiler/debug/elf_gnu_debugdata_writer.h | 13 | ||||
-rw-r--r-- | compiler/debug/elf_symtab_writer.h | 69 | ||||
-rw-r--r-- | compiler/linker/elf_builder.h | 53 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
-rw-r--r-- | dex2oat/linker/elf_writer.h | 5 | ||||
-rw-r--r-- | dex2oat/linker/elf_writer_quick.cc | 50 | ||||
-rw-r--r-- | dex2oat/linker/image_test.h | 2 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 12 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.h | 5 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer_test.cc | 2 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 8 |
14 files changed, 237 insertions, 85 deletions
diff --git a/compiler/debug/debug_info.h b/compiler/debug/debug_info.h new file mode 100644 index 0000000000..04c6991ea3 --- /dev/null +++ b/compiler/debug/debug_info.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_DEBUG_DEBUG_INFO_H_ +#define ART_COMPILER_DEBUG_DEBUG_INFO_H_ + +#include <map> + +#include "base/array_ref.h" +#include "method_debug_info.h" + +namespace art { +class DexFile; + +namespace debug { + +// References inputs for all debug information which can be written into the ELF file. +struct DebugInfo { + // Describes compiled code in the .text section. + ArrayRef<const MethodDebugInfo> compiled_methods; + + // Describes dex-files in the .dex section. + std::map<uint32_t, const DexFile*> dex_files; // Offset in section -> dex file content. + + bool Empty() const { + return compiled_methods.empty() && dex_files.empty(); + } +}; + +} // namespace debug +} // namespace art + +#endif // ART_COMPILER_DEBUG_DEBUG_INFO_H_ diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index a6267292bf..bb2a214ecd 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -38,18 +38,18 @@ namespace debug { template <typename ElfTypes> void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, + const DebugInfo& debug_info, dwarf::CFIFormat cfi_format, bool write_oat_patches) { // Write .strtab and .symtab. - WriteDebugSymbols(builder, method_infos, true /* with_signature */); + WriteDebugSymbols(builder, false /* mini-debug-info */, debug_info); // Write .debug_frame. - WriteCFISection(builder, method_infos, cfi_format, write_oat_patches); + WriteCFISection(builder, debug_info.compiled_methods, cfi_format, write_oat_patches); // Group the methods into compilation units based on class. std::unordered_map<const DexFile::ClassDef*, ElfCompilationUnit> class_to_compilation_unit; - for (const MethodDebugInfo& mi : method_infos) { + for (const MethodDebugInfo& mi : debug_info.compiled_methods) { if (mi.dex_file != nullptr) { auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index); ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def]; @@ -108,21 +108,27 @@ void WriteDebugInfo(linker::ElfBuilder<ElfTypes>* builder, std::vector<uint8_t> MakeMiniDebugInfo( InstructionSet isa, const InstructionSetFeatures* features, - uint64_t text_address, - size_t text_size, - const ArrayRef<const MethodDebugInfo>& method_infos) { + uint64_t text_section_address, + size_t text_section_size, + uint64_t dex_section_address, + size_t dex_section_size, + const DebugInfo& debug_info) { if (Is64BitInstructionSet(isa)) { return MakeMiniDebugInfoInternal<ElfTypes64>(isa, features, - text_address, - text_size, - method_infos); + text_section_address, + text_section_size, + dex_section_address, + dex_section_size, + debug_info); } else { return MakeMiniDebugInfoInternal<ElfTypes32>(isa, features, - text_address, - text_size, - method_infos); + text_section_address, + text_section_size, + dex_section_address, + dex_section_size, + debug_info); } } @@ -133,7 +139,8 @@ static std::vector<uint8_t> MakeElfFileForJITInternal( bool mini_debug_info, const MethodDebugInfo& mi) { CHECK_EQ(mi.is_code_address_text_relative, false); - ArrayRef<const MethodDebugInfo> method_infos(&mi, 1); + DebugInfo debug_info{}; + debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(&mi, 1); std::vector<uint8_t> buffer; buffer.reserve(KB); linker::VectorOutputStream out("Debug ELF file", &buffer); @@ -146,12 +153,14 @@ static std::vector<uint8_t> MakeElfFileForJITInternal( features, mi.code_address, mi.code_size, - method_infos); + /* dex_section_address */ 0, + /* dex_section_size */ 0, + debug_info); builder->WriteSection(".gnu_debugdata", &mdi); } else { builder->GetText()->AllocateVirtualMemory(mi.code_address, mi.code_size); WriteDebugInfo(builder.get(), - method_infos, + debug_info, dwarf::DW_DEBUG_FRAME_FORMAT, false /* write_oat_patches */); } @@ -209,12 +218,12 @@ std::vector<uint8_t> WriteDebugElfFileForClasses(InstructionSet isa, // Explicit instantiations template void WriteDebugInfo<ElfTypes32>( linker::ElfBuilder<ElfTypes32>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, + const DebugInfo& debug_info, dwarf::CFIFormat cfi_format, bool write_oat_patches); template void WriteDebugInfo<ElfTypes64>( linker::ElfBuilder<ElfTypes64>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, + const DebugInfo& debug_info, dwarf::CFIFormat cfi_format, bool write_oat_patches); diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h index a47bf076b9..8ad0c4219a 100644 --- a/compiler/debug/elf_debug_writer.h +++ b/compiler/debug/elf_debug_writer.h @@ -23,6 +23,7 @@ #include "base/macros.h" #include "base/mutex.h" #include "debug/dwarf/dwarf_constants.h" +#include "debug/debug_info.h" #include "linker/elf_builder.h" namespace art { @@ -36,7 +37,7 @@ struct MethodDebugInfo; template <typename ElfTypes> void WriteDebugInfo( linker::ElfBuilder<ElfTypes>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, + const DebugInfo& debug_info, dwarf::CFIFormat cfi_format, bool write_oat_patches); @@ -45,7 +46,9 @@ std::vector<uint8_t> MakeMiniDebugInfo( const InstructionSetFeatures* features, uint64_t text_section_address, size_t text_section_size, - const ArrayRef<const MethodDebugInfo>& method_infos); + uint64_t dex_section_address, + size_t dex_section_size, + const DebugInfo& debug_info); std::vector<uint8_t> MakeElfFileForJIT( InstructionSet isa, diff --git a/compiler/debug/elf_gnu_debugdata_writer.h b/compiler/debug/elf_gnu_debugdata_writer.h index 78b8e2780c..a88c5cb213 100644 --- a/compiler/debug/elf_gnu_debugdata_writer.h +++ b/compiler/debug/elf_gnu_debugdata_writer.h @@ -82,18 +82,23 @@ static std::vector<uint8_t> MakeMiniDebugInfoInternal( const InstructionSetFeatures* features, typename ElfTypes::Addr text_section_address, size_t text_section_size, - const ArrayRef<const MethodDebugInfo>& method_infos) { + typename ElfTypes::Addr dex_section_address, + size_t dex_section_size, + const DebugInfo& debug_info) { std::vector<uint8_t> buffer; buffer.reserve(KB); linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer); std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder( new linker::ElfBuilder<ElfTypes>(isa, features, &out)); builder->Start(false /* write_program_headers */); - // Mirror .text as NOBITS section since the added symbols will reference it. + // Mirror ELF sections as NOBITS since the added symbols will reference them. builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size); - WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */); + if (dex_section_size != 0) { + builder->GetDex()->AllocateVirtualMemory(dex_section_address, dex_section_size); + } + WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info); WriteCFISection(builder.get(), - method_infos, + debug_info.compiled_methods, dwarf::DW_DEBUG_FRAME_FORMAT, false /* write_oat_paches */); builder->End(); diff --git a/compiler/debug/elf_symtab_writer.h b/compiler/debug/elf_symtab_writer.h index 57e010f232..95a0b4ff47 100644 --- a/compiler/debug/elf_symtab_writer.h +++ b/compiler/debug/elf_symtab_writer.h @@ -17,9 +17,13 @@ #ifndef ART_COMPILER_DEBUG_ELF_SYMTAB_WRITER_H_ #define ART_COMPILER_DEBUG_ELF_SYMTAB_WRITER_H_ +#include <map> #include <unordered_set> +#include "debug/debug_info.h" #include "debug/method_debug_info.h" +#include "dex/dex_file-inl.h" +#include "dex/code_item_accessors.h" #include "linker/elf_builder.h" #include "utils.h" @@ -35,22 +39,26 @@ namespace debug { // one symbol which marks the whole .text section as code. constexpr bool kGenerateSingleArmMappingSymbol = true; +// Magic name for .symtab symbols which enumerate dex files used +// by this ELF file (currently mmapped inside the .dex section). +constexpr const char* kDexFileSymbolName = "$dexfile"; + template <typename ElfTypes> static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, - const ArrayRef<const MethodDebugInfo>& method_infos, - bool with_signature) { + bool mini_debug_info, + const DebugInfo& debug_info) { uint64_t mapping_symbol_address = std::numeric_limits<uint64_t>::max(); auto* strtab = builder->GetStrTab(); auto* symtab = builder->GetSymTab(); - if (method_infos.empty()) { + if (debug_info.Empty()) { return; } // Find all addresses which contain deduped methods. // The first instance of method is not marked deduped_, but the rest is. std::unordered_set<uint64_t> deduped_addresses; - for (const MethodDebugInfo& info : method_infos) { + for (const MethodDebugInfo& info : debug_info.compiled_methods) { if (info.deduped) { deduped_addresses.insert(info.code_address); } @@ -58,9 +66,8 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, strtab->Start(); strtab->Write(""); // strtab should start with empty string. - std::string last_name; - size_t last_name_offset = 0; - for (const MethodDebugInfo& info : method_infos) { + // Add symbols for compiled methods. + for (const MethodDebugInfo& info : debug_info.compiled_methods) { if (info.deduped) { continue; // Add symbol only for the first instance. } @@ -69,14 +76,11 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, name_offset = strtab->Write(info.trampoline_name); } else { DCHECK(info.dex_file != nullptr); - std::string name = info.dex_file->PrettyMethod(info.dex_method_index, with_signature); + std::string name = info.dex_file->PrettyMethod(info.dex_method_index, !mini_debug_info); if (deduped_addresses.find(info.code_address) != deduped_addresses.end()) { name += " [DEDUPED]"; } - // If we write method names without signature, we might see the same name multiple times. - name_offset = (name == last_name ? last_name_offset : strtab->Write(name)); - last_name = std::move(name); - last_name_offset = name_offset; + name_offset = strtab->Write(name); } const auto* text = builder->GetText(); @@ -97,13 +101,46 @@ static void WriteDebugSymbols(linker::ElfBuilder<ElfTypes>* builder, } } } + // Add symbols for interpreted methods (with address range of the method's bytecode). + if (!debug_info.dex_files.empty() && builder->GetDex()->Exists()) { + auto dex = builder->GetDex(); + for (auto it : debug_info.dex_files) { + uint64_t dex_address = dex->GetAddress() + it.first /* offset within the section */; + const DexFile* dex_file = it.second; + symtab->Add(strtab->Write(kDexFileSymbolName), dex, dex_address, 0, STB_LOCAL, STT_NOTYPE); + if (mini_debug_info) { + continue; // Don't add interpreter method names to mini-debug-info for now. + } + for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { + const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); + const uint8_t* class_data = dex_file->GetClassData(class_def); + if (class_data == nullptr) { + continue; + } + for (ClassDataItemIterator item(*dex_file, class_data); item.HasNext(); item.Next()) { + if (!item.IsAtMethod()) { + continue; + } + const DexFile::CodeItem* code_item = item.GetMethodCodeItem(); + if (code_item == nullptr) { + continue; + } + CodeItemInstructionAccessor code(*dex_file, code_item); + DCHECK(code.HasCodeItem()); + std::string name = dex_file->PrettyMethod(item.GetMemberIndex(), !mini_debug_info); + size_t name_offset = strtab->Write(name); + uint64_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file->Begin(); + uint64_t address = dex_address + offset; + size_t size = code.InsnsSizeInCodeUnits() * sizeof(uint16_t); + symtab->Add(name_offset, dex, address, size, STB_GLOBAL, STT_FUNC); + } + } + } + } strtab->End(); // Symbols are buffered and written after names (because they are smaller). - // We could also do two passes in this function to avoid the buffering. - symtab->Start(); - symtab->Write(); - symtab->End(); + symtab->WriteCachedSection(); } } // namespace debug diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h index 5262ab6f3b..3145497091 100644 --- a/compiler/linker/elf_builder.h +++ b/compiler/linker/elf_builder.h @@ -196,6 +196,11 @@ class ElfBuilder FINAL { return section_index_; } + // Returns true if this section has been added. + bool Exists() const { + return section_index_ != 0; + } + private: // Add this section to the list of generated ELF sections (if not there already). // It also ensures the alignment is sufficient to generate valid program headers, @@ -304,42 +309,46 @@ class ElfBuilder FINAL { /* info */ 0, align, /* entsize */ 0), - current_offset_(0) { + current_offset_(0), + last_offset_(0) { } Elf_Word Write(const std::string& name) { if (current_offset_ == 0) { DCHECK(name.empty()); + } else if (name == last_name_) { + return last_offset_; // Very simple string de-duplication. } - Elf_Word offset = current_offset_; + last_name_ = name; + last_offset_ = current_offset_; this->WriteFully(name.c_str(), name.length() + 1); current_offset_ += name.length() + 1; - return offset; + return last_offset_; } private: Elf_Word current_offset_; + std::string last_name_; + Elf_Word last_offset_; }; // Writer of .dynsym and .symtab sections. - class SymbolSection FINAL : public CachedSection { + class SymbolSection FINAL : public Section { public: SymbolSection(ElfBuilder<ElfTypes>* owner, const std::string& name, Elf_Word type, Elf_Word flags, Section* strtab) - : CachedSection(owner, - name, - type, - flags, - strtab, - /* info */ 0, - sizeof(Elf_Off), - sizeof(Elf_Sym)) { - // The symbol table always has to start with NULL symbol. - Elf_Sym null_symbol = Elf_Sym(); - CachedSection::Add(&null_symbol, sizeof(null_symbol)); + : Section(owner, + name, + type, + flags, + strtab, + /* info */ 0, + sizeof(Elf_Off), + sizeof(Elf_Sym)) { + syms_.push_back(Elf_Sym()); // The symbol table always has to start with NULL symbol. } // Buffer symbol for this section. It will be written later. @@ -362,6 +371,7 @@ class ElfBuilder FINAL { Add(name, section_index, addr, size, binding, type); } + // Buffer symbol for this section. It will be written later. void Add(Elf_Word name, Elf_Word section_index, Elf_Addr addr, @@ -375,8 +385,19 @@ class ElfBuilder FINAL { sym.st_other = 0; sym.st_shndx = section_index; sym.st_info = (binding << 4) + (type & 0xf); - CachedSection::Add(&sym, sizeof(sym)); + syms_.push_back(sym); + } + + Elf_Word GetCacheSize() { return syms_.size() * sizeof(Elf_Sym); } + + void WriteCachedSection() { + this->Start(); + this->WriteFully(syms_.data(), syms_.size() * sizeof(Elf_Sym)); + this->End(); } + + private: + std::vector<Elf_Sym> syms_; // Buffered/cached content of the whole section. }; class AbiflagsSection FINAL : public Section { diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 8d0d89ed5c..9c15c4a194 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -2043,7 +2043,8 @@ class Dex2Oat FINAL { // We need to mirror the layout of the ELF file in the compressed debug-info. // Therefore PrepareDebugInfo() relies on the SetLoadedSectionSizes() call further above. - elf_writer->PrepareDebugInfo(oat_writer->GetMethodDebugInfo()); + debug::DebugInfo debug_info = oat_writer->GetDebugInfo(); // Keep the variable alive. + elf_writer->PrepareDebugInfo(debug_info); // Processes the data on background thread. linker::OutputStream*& rodata = rodata_[i]; DCHECK(rodata != nullptr); @@ -2077,7 +2078,7 @@ class Dex2Oat FINAL { } elf_writer->WriteDynamicSection(); - elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo()); + elf_writer->WriteDebugInfo(oat_writer->GetDebugInfo()); if (!elf_writer->End()) { LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath(); diff --git a/dex2oat/linker/elf_writer.h b/dex2oat/linker/elf_writer.h index a49112bfe6..7c4774038e 100644 --- a/dex2oat/linker/elf_writer.h +++ b/dex2oat/linker/elf_writer.h @@ -25,6 +25,7 @@ #include "base/array_ref.h" #include "base/macros.h" #include "base/mutex.h" +#include "debug/debug_info.h" #include "os.h" namespace art { @@ -66,13 +67,13 @@ class ElfWriter { size_t bss_methods_offset, size_t bss_roots_offset, size_t dex_section_size) = 0; - virtual void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0; + virtual void PrepareDebugInfo(const debug::DebugInfo& debug_info) = 0; virtual OutputStream* StartRoData() = 0; virtual void EndRoData(OutputStream* rodata) = 0; virtual OutputStream* StartText() = 0; virtual void EndText(OutputStream* text) = 0; virtual void WriteDynamicSection() = 0; - virtual void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) = 0; + virtual void WriteDebugInfo(const debug::DebugInfo& debug_info) = 0; virtual bool End() = 0; // Get the ELF writer's stream. This stream can be used for writing data directly diff --git a/dex2oat/linker/elf_writer_quick.cc b/dex2oat/linker/elf_writer_quick.cc index af11d5864d..707e877cfb 100644 --- a/dex2oat/linker/elf_writer_quick.cc +++ b/dex2oat/linker/elf_writer_quick.cc @@ -54,22 +54,28 @@ class DebugInfoTask : public Task { public: DebugInfoTask(InstructionSet isa, const InstructionSetFeatures* features, - size_t rodata_section_size, + uint64_t text_section_address, size_t text_section_size, - const ArrayRef<const debug::MethodDebugInfo>& method_infos) + uint64_t dex_section_address, + size_t dex_section_size, + const debug::DebugInfo& debug_info) : isa_(isa), instruction_set_features_(features), - rodata_section_size_(rodata_section_size), + text_section_address_(text_section_address), text_section_size_(text_section_size), - method_infos_(method_infos) { + dex_section_address_(dex_section_address), + dex_section_size_(dex_section_size), + debug_info_(debug_info) { } void Run(Thread*) { result_ = debug::MakeMiniDebugInfo(isa_, instruction_set_features_, - kPageSize + rodata_section_size_, // .text address. + text_section_address_, text_section_size_, - method_infos_); + dex_section_address_, + dex_section_size_, + debug_info_); } std::vector<uint8_t>* GetResult() { @@ -79,9 +85,11 @@ class DebugInfoTask : public Task { private: InstructionSet isa_; const InstructionSetFeatures* instruction_set_features_; - size_t rodata_section_size_; + uint64_t text_section_address_; size_t text_section_size_; - const ArrayRef<const debug::MethodDebugInfo> method_infos_; + uint64_t dex_section_address_; + size_t dex_section_size_; + const debug::DebugInfo& debug_info_; std::vector<uint8_t> result_; }; @@ -101,13 +109,13 @@ class ElfWriterQuick FINAL : public ElfWriter { size_t bss_methods_offset, size_t bss_roots_offset, size_t dex_section_size) OVERRIDE; - void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; + void PrepareDebugInfo(const debug::DebugInfo& debug_info) OVERRIDE; OutputStream* StartRoData() OVERRIDE; void EndRoData(OutputStream* rodata) OVERRIDE; OutputStream* StartText() OVERRIDE; void EndText(OutputStream* text) OVERRIDE; void WriteDynamicSection() OVERRIDE; - void WriteDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE; + void WriteDebugInfo(const debug::DebugInfo& debug_info) OVERRIDE; bool End() OVERRIDE; virtual OutputStream* GetStream() OVERRIDE; @@ -124,6 +132,7 @@ class ElfWriterQuick FINAL : public ElfWriter { size_t rodata_size_; size_t text_size_; size_t bss_size_; + size_t dex_section_size_; std::unique_ptr<BufferedOutputStream> output_stream_; std::unique_ptr<ElfBuilder<ElfTypes>> builder_; std::unique_ptr<DebugInfoTask> debug_info_task_; @@ -163,6 +172,7 @@ ElfWriterQuick<ElfTypes>::ElfWriterQuick(InstructionSet instruction_set, rodata_size_(0u), text_size_(0u), bss_size_(0u), + dex_section_size_(0u), output_stream_( std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(elf_file))), builder_(new ElfBuilder<ElfTypes>(instruction_set, features, output_stream_.get())) {} @@ -192,6 +202,8 @@ void ElfWriterQuick<ElfTypes>::PrepareDynamicSection(size_t rodata_size, text_size_ = text_size; DCHECK_EQ(bss_size_, 0u); bss_size_ = bss_size; + DCHECK_EQ(dex_section_size_, 0u); + dex_section_size_ = dex_section_size; builder_->PrepareDynamicSection(elf_file_->GetPath(), rodata_size_, text_size_, @@ -237,17 +249,18 @@ void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { } template <typename ElfTypes> -void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( - const ArrayRef<const debug::MethodDebugInfo>& method_infos) { - if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) { +void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(const debug::DebugInfo& debug_info) { + if (!debug_info.Empty() && compiler_options_->GetGenerateMiniDebugInfo()) { // Prepare the mini-debug-info in background while we do other I/O. Thread* self = Thread::Current(); debug_info_task_ = std::unique_ptr<DebugInfoTask>( new DebugInfoTask(builder_->GetIsa(), instruction_set_features_, - rodata_size_, + builder_->GetText()->GetAddress(), text_size_, - method_infos)); + builder_->GetDex()->Exists() ? builder_->GetDex()->GetAddress() : 0, + dex_section_size_, + debug_info)); debug_info_thread_pool_ = std::unique_ptr<ThreadPool>( new ThreadPool("Mini-debug-info writer", 1)); debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); @@ -256,12 +269,11 @@ void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( } template <typename ElfTypes> -void ElfWriterQuick<ElfTypes>::WriteDebugInfo( - const ArrayRef<const debug::MethodDebugInfo>& method_infos) { - if (!method_infos.empty()) { +void ElfWriterQuick<ElfTypes>::WriteDebugInfo(const debug::DebugInfo& debug_info) { + if (!debug_info.Empty()) { if (compiler_options_->GetGenerateDebugInfo()) { // Generate all the debug information we can. - debug::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */); + debug::WriteDebugInfo(builder_.get(), debug_info, kCFIFormat, true /* write_oat_patches */); } if (compiler_options_->GetGenerateMiniDebugInfo()) { // Wait for the mini-debug-info generation to finish and write it to disk. diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h index 067111824a..637578e622 100644 --- a/dex2oat/linker/image_test.h +++ b/dex2oat/linker/image_test.h @@ -339,7 +339,7 @@ inline void CompilationHelper::Compile(CompilerDriver* driver, writer->UpdateOatFileHeader(i, oat_writer->GetOatHeader()); elf_writer->WriteDynamicSection(); - elf_writer->WriteDebugInfo(oat_writer->GetMethodDebugInfo()); + elf_writer->WriteDebugInfo(oat_writer->GetDebugInfo()); bool success = elf_writer->End(); ASSERT_TRUE(success); diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 16d70daddf..e9a2553cd3 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -4160,5 +4160,17 @@ const uint8_t* OatWriter::LookupBootImageClassTableSlot(const DexFile& dex_file, UNREACHABLE(); } +debug::DebugInfo OatWriter::GetDebugInfo() const { + debug::DebugInfo debug_info{}; + debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(method_info_); + if (dex_files_ != nullptr) { + for (auto dex_file : *dex_files_) { + uint32_t offset = vdex_dex_files_offset_ + (dex_file->Begin() - (*dex_files_)[0]->Begin()); + debug_info.dex_files.emplace(offset, dex_file); + } + } + return debug_info; +} + } // namespace linker } // namespace art diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index c9deea9a4b..86b114433e 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -25,6 +25,7 @@ #include "base/array_ref.h" #include "base/dchecked_vector.h" #include "dex/compact_dex_level.h" +#include "debug/debug_info.h" #include "linker/relative_patcher.h" // For RelativePatcherTargetProvider. #include "mem_map.h" #include "method_reference.h" @@ -240,9 +241,7 @@ class OatWriter { ~OatWriter(); - ArrayRef<const debug::MethodDebugInfo> GetMethodDebugInfo() const { - return ArrayRef<const debug::MethodDebugInfo>(method_info_); - } + debug::DebugInfo GetDebugInfo() const; const CompilerDriver* GetCompilerDriver() const { return compiler_driver_; diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc index 99bc1adabb..4e35382f89 100644 --- a/dex2oat/linker/oat_writer_test.cc +++ b/dex2oat/linker/oat_writer_test.cc @@ -250,7 +250,7 @@ class OatTest : public CommonCompilerTest { } elf_writer->WriteDynamicSection(); - elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); + elf_writer->WriteDebugInfo(oat_writer.GetDebugInfo()); if (!elf_writer->End()) { return false; diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 6668dace89..d2b1c66d72 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -38,6 +38,7 @@ #include "class_linker-inl.h" #include "class_linker.h" #include "compiled_method.h" +#include "debug/debug_info.h" #include "debug/elf_debug_writer.h" #include "debug/method_debug_info.h" #include "dex/code_item_accessors-inl.h" @@ -202,8 +203,13 @@ class OatSymbolizer FINAL { // TODO: Try to symbolize link-time thunks? // This would require disassembling all methods to find branches outside the method code. + // TODO: Add symbols for dex bytecode in the .dex section. + + debug::DebugInfo debug_info{}; + debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(method_debug_infos_); + debug::WriteDebugInfo(builder_.get(), - ArrayRef<const debug::MethodDebugInfo>(method_debug_infos_), + debug_info, dwarf::DW_DEBUG_FRAME_FORMAT, true /* write_oat_patches */); |