diff options
author | 2016-01-19 14:33:43 +0000 | |
---|---|---|
committer | 2016-01-22 18:10:37 +0000 | |
commit | 5fdcc3c931b70204fd8c491afa66f57f8428490f (patch) | |
tree | 729f1433c75dda8a1f0e578a1c5297eed31f7852 /compiler/elf_writer_debug.cc | |
parent | 95005291d8ebdd1d2ac58ffc5181fef4fbbf2383 (diff) |
Add option to generate compressed backtrace info.
Add flag --generate-mini-debug-info which generates
LZMA compressed .symtab and .debug_frame, which are
sufficient to print java backtraces in libunwind.
If enabled, it increases the size of boot.oat by about 3.5%.
Change-Id: Ic3c2ef7704c05fa328720c6781ca2a9b8e3935a3
Diffstat (limited to 'compiler/elf_writer_debug.cc')
-rw-r--r-- | compiler/elf_writer_debug.cc | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index a64c9f15b4..94e5d76962 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -40,6 +40,11 @@ #include "stack_map.h" #include "utils.h" +// liblzma. +#include "XzEnc.h" +#include "7zCrc.h" +#include "XzCrc64.h" + namespace art { namespace dwarf { @@ -1405,6 +1410,76 @@ void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, WriteDebugSections(builder, method_infos); } +static void XzCompress(const std::vector<uint8_t>* src, std::vector<uint8_t>* dst) { + // Configure the compression library. + CrcGenerateTable(); + Crc64GenerateTable(); + CLzma2EncProps lzma2Props; + Lzma2EncProps_Init(&lzma2Props); + lzma2Props.lzmaProps.level = 1; // Fast compression. + Lzma2EncProps_Normalize(&lzma2Props); + CXzProps props; + XzProps_Init(&props); + props.lzma2Props = &lzma2Props; + // Implement the required interface for communication (written in C so no virtual methods). + struct XzCallbacks : public ISeqInStream, public ISeqOutStream, public ICompressProgress { + static SRes ReadImpl(void* p, void* buf, size_t* size) { + auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqInStream*>(p)); + *size = std::min(*size, ctx->src_->size() - ctx->src_pos_); + memcpy(buf, ctx->src_->data() + ctx->src_pos_, *size); + ctx->src_pos_ += *size; + return SZ_OK; + } + static size_t WriteImpl(void* p, const void* buf, size_t size) { + auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqOutStream*>(p)); + const uint8_t* buffer = reinterpret_cast<const uint8_t*>(buf); + ctx->dst_->insert(ctx->dst_->end(), buffer, buffer + size); + return size; + } + static SRes ProgressImpl(void* , UInt64, UInt64) { + return SZ_OK; + } + size_t src_pos_; + const std::vector<uint8_t>* src_; + std::vector<uint8_t>* dst_; + }; + XzCallbacks callbacks; + callbacks.Read = XzCallbacks::ReadImpl; + callbacks.Write = XzCallbacks::WriteImpl; + callbacks.Progress = XzCallbacks::ProgressImpl; + callbacks.src_pos_ = 0; + callbacks.src_ = src; + callbacks.dst_ = dst; + // Compress. + SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks); + CHECK_EQ(res, SZ_OK); +} + +template <typename ElfTypes> +void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* parent_builder, + const ArrayRef<const MethodDebugInfo>& method_infos) { + const InstructionSet isa = parent_builder->GetIsa(); + std::vector<uint8_t> buffer; + buffer.reserve(KB); + VectorOutputStream out("Mini-debug-info ELF file", &buffer); + std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out)); + builder->Start(); + // Write .rodata and .text as NOBITS sections. + // This allows tools to detect virtual address relocation of the parent ELF file. + builder->SetVirtualAddress(parent_builder->GetRoData()->GetAddress()); + builder->GetRoData()->WriteNoBitsSection(parent_builder->GetRoData()->GetSize()); + builder->SetVirtualAddress(parent_builder->GetText()->GetAddress()); + builder->GetText()->WriteNoBitsSection(parent_builder->GetText()->GetSize()); + WriteDebugSymbols(builder.get(), method_infos); + WriteCFISection(builder.get(), method_infos, DW_DEBUG_FRAME_FORMAT); + builder->End(); + CHECK(builder->Good()); + std::vector<uint8_t> compressed_buffer; + compressed_buffer.reserve(buffer.size() / 4); + XzCompress(&buffer, &compressed_buffer); + parent_builder->WriteSection(".gnu_debugdata", &compressed_buffer); +} + template <typename ElfTypes> static ArrayRef<const uint8_t> WriteDebugElfFileForMethodInternal( const dwarf::MethodDebugInfo& method_info) { @@ -1477,6 +1552,12 @@ template void WriteDebugInfo<ElfTypes64>( ElfBuilder<ElfTypes64>* builder, const ArrayRef<const MethodDebugInfo>& method_infos, CFIFormat cfi_format); +template void WriteMiniDebugInfo<ElfTypes32>( + ElfBuilder<ElfTypes32>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos); +template void WriteMiniDebugInfo<ElfTypes64>( + ElfBuilder<ElfTypes64>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos); } // namespace dwarf } // namespace art |