summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/debug/debug_info.h46
-rw-r--r--compiler/debug/elf_debug_writer.cc45
-rw-r--r--compiler/debug/elf_debug_writer.h7
-rw-r--r--compiler/debug/elf_gnu_debugdata_writer.h13
-rw-r--r--compiler/debug/elf_symtab_writer.h69
-rw-r--r--compiler/linker/elf_builder.h53
-rw-r--r--dex2oat/dex2oat.cc5
-rw-r--r--dex2oat/linker/elf_writer.h5
-rw-r--r--dex2oat/linker/elf_writer_quick.cc50
-rw-r--r--dex2oat/linker/image_test.h2
-rw-r--r--dex2oat/linker/oat_writer.cc12
-rw-r--r--dex2oat/linker/oat_writer.h5
-rw-r--r--dex2oat/linker/oat_writer_test.cc2
-rw-r--r--oatdump/oatdump.cc8
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 */);