diff options
| -rw-r--r-- | compiler/elf_writer.h | 3 | ||||
| -rw-r--r-- | compiler/elf_writer_quick.cc | 70 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 6 |
3 files changed, 72 insertions, 7 deletions
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h index c5a0fd50bd..5dbf7360f8 100644 --- a/compiler/elf_writer.h +++ b/compiler/elf_writer.h @@ -52,6 +52,9 @@ class ElfWriter { virtual ~ElfWriter() {} virtual void Start() = 0; + virtual void PrepareDebugInfo(size_t rodata_section_size, + size_t text_section_size, + const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) = 0; virtual OutputStream* StartRoData() = 0; virtual void EndRoData(OutputStream* rodata) = 0; virtual OutputStream* StartText() = 0; diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 05ac21913d..759a6d633a 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -33,6 +33,8 @@ #include "leb128.h" #include "linker/buffered_output_stream.h" #include "linker/file_output_stream.h" +#include "thread-inl.h" +#include "thread_pool.h" #include "utils.h" namespace art { @@ -46,6 +48,37 @@ namespace art { // Let's use .debug_frame because it is easier to strip or compress. constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT; +class DebugInfoTask : public Task { + public: + DebugInfoTask(InstructionSet isa, + size_t rodata_section_size, + size_t text_section_size, + const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) + : isa_(isa), + rodata_section_size_(rodata_section_size), + text_section_size_(text_section_size), + method_infos_(method_infos) { + } + + void Run(Thread*) { + result_ = dwarf::MakeMiniDebugInfo(isa_, + rodata_section_size_, + text_section_size_, + method_infos_); + } + + std::vector<uint8_t>* GetResult() { + return &result_; + } + + private: + InstructionSet isa_; + size_t rodata_section_size_; + size_t text_section_size_; + const ArrayRef<const dwarf::MethodDebugInfo>& method_infos_; + std::vector<uint8_t> result_; +}; + template <typename ElfTypes> class ElfWriterQuick FINAL : public ElfWriter { public: @@ -55,6 +88,9 @@ class ElfWriterQuick FINAL : public ElfWriter { ~ElfWriterQuick(); void Start() OVERRIDE; + void PrepareDebugInfo(size_t rodata_section_size, + size_t text_section_size, + const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE; OutputStream* StartRoData() OVERRIDE; void EndRoData(OutputStream* rodata) OVERRIDE; OutputStream* StartText() OVERRIDE; @@ -75,6 +111,8 @@ class ElfWriterQuick FINAL : public ElfWriter { File* const elf_file_; std::unique_ptr<BufferedOutputStream> output_stream_; std::unique_ptr<ElfBuilder<ElfTypes>> builder_; + std::unique_ptr<DebugInfoTask> debug_info_task_; + std::unique_ptr<ThreadPool> debug_info_thread_pool_; DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); }; @@ -147,6 +185,26 @@ void ElfWriterQuick<ElfTypes>::WriteDynamicSection() { } template <typename ElfTypes> +void ElfWriterQuick<ElfTypes>::PrepareDebugInfo( + size_t rodata_section_size, + size_t text_section_size, + const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { + if (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(), + rodata_section_size, + text_section_size, + method_infos)); + 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()); + debug_info_thread_pool_->StartWorkers(self); + } +} + +template <typename ElfTypes> void ElfWriterQuick<ElfTypes>::WriteDebugInfo( const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { if (compiler_options_->GetGenerateDebugInfo()) { @@ -154,13 +212,11 @@ void ElfWriterQuick<ElfTypes>::WriteDebugInfo( dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */); } if (compiler_options_->GetGenerateMiniDebugInfo()) { - // Generate only some information and compress it. - std::vector<uint8_t> xz_elf_file = MakeMiniDebugInfo( - builder_->GetIsa(), - builder_->GetRoData()->GetSize(), - builder_->GetText()->GetSize(), - method_infos); - builder_->WriteSection(".gnu_debugdata", &xz_elf_file); + // Wait for the mini-debug-info generation to finish and write it to disk. + Thread* self = Thread::Current(); + DCHECK(debug_info_thread_pool_ != nullptr); + debug_info_thread_pool_->Wait(self, true, false); + builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult()); } } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index d30f69764b..b1f71cee3d 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1687,6 +1687,12 @@ class Dex2Oat FINAL { std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i]; oat_writer->PrepareLayout(driver_.get(), image_writer_.get(), dex_files); + // We need to mirror the layout of the ELF file in the compressed debug-info. + // Therefore we need to propagate the sizes of at least those sections. + size_t rodata_size = oat_writer->GetOatHeader().GetExecutableOffset(); + size_t text_size = oat_writer->GetSize() - rodata_size; + elf_writer->PrepareDebugInfo(rodata_size, text_size, oat_writer->GetMethodDebugInfo()); + OutputStream*& rodata = rodata_[i]; DCHECK(rodata != nullptr); if (!oat_writer->WriteRodata(rodata)) { |