diff options
author | 2016-01-25 17:32:41 +0000 | |
---|---|---|
committer | 2016-01-26 12:50:23 +0000 | |
commit | 5b1c2ca30dad519be285f0a1e839c23cc4e3a51d (patch) | |
tree | 330ebac2bd2592ccced6a17b069516afd45fa220 | |
parent | d112827911122ba6412fd90b8d8b9a9d6db9d513 (diff) |
Revert "Revert "Add option to generate compressed backtrace info.""
This reverts commit 8546cc9aeb05e866e1fb6a9e4130d53ea330baa8.
Change-Id: I676fdf9af27fa3b16fa8921778ff8832ab8c437d
-rw-r--r-- | compiler/dex/quick/codegen_util.cc | 2 | ||||
-rw-r--r-- | compiler/driver/compiler_options.cc | 6 | ||||
-rw-r--r-- | compiler/driver/compiler_options.h | 12 | ||||
-rw-r--r-- | compiler/elf_builder.h | 17 | ||||
-rw-r--r-- | compiler/elf_writer_debug.cc | 81 | ||||
-rw-r--r-- | compiler/elf_writer_debug.h | 4 | ||||
-rw-r--r-- | compiler/elf_writer_quick.cc | 9 | ||||
-rw-r--r-- | compiler/jni/quick/jni_compiler.cc | 2 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 2 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 5 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 4 | ||||
-rw-r--r-- | test/137-cfi/expected.txt | 1 | ||||
-rwxr-xr-x | test/137-cfi/run | 6 |
14 files changed, 139 insertions, 14 deletions
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index d68835a9cf..af6f91f21d 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -1076,7 +1076,7 @@ Mir2Lir::Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena pc_rel_temp_(nullptr), dex_cache_arrays_min_offset_(std::numeric_limits<uint32_t>::max()), cfi_(&last_lir_insn_, - cu->compiler_driver->GetCompilerOptions().GetGenerateDebugInfo(), + cu->compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo(), arena), in_to_reg_storage_mapping_(arena) { switch_tables_.reserve(4); diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc index 2644528e56..e0b1d8b2b2 100644 --- a/compiler/driver/compiler_options.cc +++ b/compiler/driver/compiler_options.cc @@ -37,6 +37,7 @@ CompilerOptions::CompilerOptions() debuggable_(false), native_debuggable_(kDefaultNativeDebuggable), generate_debug_info_(kDefaultGenerateDebugInfo), + generate_mini_debug_info_(kDefaultGenerateMiniDebugInfo), implicit_null_checks_(true), implicit_so_checks_(true), implicit_suspend_checks_(false), @@ -91,6 +92,7 @@ CompilerOptions::CompilerOptions(CompilerFilter compiler_filter, debuggable_(debuggable), native_debuggable_(kDefaultNativeDebuggable), generate_debug_info_(generate_debug_info), + generate_mini_debug_info_(kDefaultGenerateMiniDebugInfo), implicit_null_checks_(implicit_null_checks), implicit_so_checks_(implicit_so_checks), implicit_suspend_checks_(implicit_suspend_checks), @@ -215,6 +217,10 @@ bool CompilerOptions::ParseCompilerOption(const StringPiece& option, UsageFn Usa generate_debug_info_ = true; } else if (option == "--no-generate-debug-info") { generate_debug_info_ = false; + } else if (option == "--generate-mini-debug-info") { + generate_mini_debug_info_ = true; + } else if (option == "--no-generate-mini-debug-info") { + generate_mini_debug_info_ = false; } else if (option == "--debuggable") { debuggable_ = true; } else if (option == "--native-debuggable") { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index d47fc2ad4b..5294af8b2c 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -51,6 +51,7 @@ class CompilerOptions FINAL { static constexpr double kDefaultTopKProfileThreshold = 90.0; static const bool kDefaultNativeDebuggable = false; static const bool kDefaultGenerateDebugInfo = false; + static const bool kDefaultGenerateMiniDebugInfo = false; static const bool kDefaultIncludePatchInformation = false; static const size_t kDefaultInlineDepthLimit = 3; static const size_t kDefaultInlineMaxCodeUnits = 32; @@ -170,10 +171,20 @@ class CompilerOptions FINAL { return native_debuggable_; } + // This flag controls whether the compiler collects debugging information. + // The other flags control how the information is written to disk. + bool GenerateAnyDebugInfo() const { + return GetGenerateDebugInfo() || GetGenerateMiniDebugInfo(); + } + bool GetGenerateDebugInfo() const { return generate_debug_info_; } + bool GetGenerateMiniDebugInfo() const { + return generate_mini_debug_info_; + } + bool GetImplicitNullChecks() const { return implicit_null_checks_; } @@ -266,6 +277,7 @@ class CompilerOptions FINAL { bool debuggable_; bool native_debuggable_; bool generate_debug_info_; + bool generate_mini_debug_info_; bool implicit_null_checks_; bool implicit_so_checks_; bool implicit_suspend_checks_; diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index 46484b1cd6..3d24d19919 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -165,10 +165,15 @@ class ElfBuilder FINAL { } } - // Set desired allocation size for .bss section. - void SetSize(Elf_Word size) { - CHECK_EQ(header_.sh_type, (Elf_Word)SHT_NOBITS); + // Write this section as "NOBITS" section. (used for the .bss section) + // This means that the ELF file does not contain the initial data for this section + // and it will be zero-initialized when the ELF file is loaded in the running program. + void WriteNoBitsSection(Elf_Word size) { + DCHECK_NE(header_.sh_flags & SHF_ALLOC, 0u); + Start(); + header_.sh_type = SHT_NOBITS; header_.sh_size = size; + End(); } // This function always succeeds to simplify code. @@ -346,6 +351,12 @@ class ElfBuilder FINAL { other_sections_.push_back(std::move(s)); } + // Set where the next section will be allocated in the virtual address space. + void SetVirtualAddress(Elf_Addr address) { + DCHECK_GE(address, virtual_address_); + virtual_address_ = address; + } + void Start() { // Reserve space for ELF header and program headers. // We do not know the number of headers until later, so 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 diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h index e4bc856c5e..e19da088da 100644 --- a/compiler/elf_writer_debug.h +++ b/compiler/elf_writer_debug.h @@ -35,6 +35,10 @@ void WriteDebugInfo(ElfBuilder<ElfTypes>* builder, const ArrayRef<const MethodDebugInfo>& method_infos, CFIFormat cfi_format); +template <typename ElfTypes> +void WriteMiniDebugInfo(ElfBuilder<ElfTypes>* builder, + const ArrayRef<const MethodDebugInfo>& method_infos); + ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo& method_info); ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa, diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 7b1bdd72e5..6bf080a083 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -137,9 +137,7 @@ template <typename ElfTypes> void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) { auto* bss = builder_->GetBss(); if (bss_size != 0u) { - bss->Start(); - bss->SetSize(bss_size); - bss->End(); + bss->WriteNoBitsSection(bss_size); } } @@ -152,8 +150,13 @@ template <typename ElfTypes> void ElfWriterQuick<ElfTypes>::WriteDebugInfo( const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) { if (compiler_options_->GetGenerateDebugInfo()) { + // Generate all the debug information we can. dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat); } + if (compiler_options_->GetGenerateMiniDebugInfo()) { + // Generate only some information and compress it. + dwarf::WriteMiniDebugInfo(builder_.get(), method_infos); + } } template <typename ElfTypes> diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc index 52a238233b..e92046057c 100644 --- a/compiler/jni/quick/jni_compiler.cc +++ b/compiler/jni/quick/jni_compiler.cc @@ -95,7 +95,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver, // Assembler that holds generated instructions std::unique_ptr<Assembler> jni_asm(Assembler::Create(instruction_set, instruction_set_features)); - jni_asm->cfi().SetEnabled(driver->GetCompilerOptions().GetGenerateDebugInfo()); + jni_asm->cfi().SetEnabled(driver->GetCompilerOptions().GenerateAnyDebugInfo()); // Offsets into data structures // TODO: if cross compiling these offsets are for the host not the target diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index a5421622b7..569e0f4e19 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -806,7 +806,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } } - if (writer_->compiler_driver_->GetCompilerOptions().GetGenerateDebugInfo()) { + if (writer_->compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo()) { // Record debug information for this function if we are doing that. const uint32_t quick_code_start = quick_code_offset - writer_->oat_header_->GetExecutableOffset() - thumb_offset; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index fffd00535c..3fac914017 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -676,7 +676,7 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena, return nullptr; } codegen->GetAssembler()->cfi().SetEnabled( - compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()); + compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo()); PassObserver pass_observer(graph, codegen.get(), diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 86f51e1131..00941edc17 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -318,6 +318,11 @@ NO_RETURN static void Usage(const char* fmt, ...) { UsageError(""); UsageError(" --no-generate-debug-info: Do not generate debug information for native debugging."); UsageError(""); + UsageError(" --generate-mini-debug-info: Generate minimal amount of LZMA-compressed"); + UsageError(" debug information necessary to print backtraces. (disabled by default)"); + UsageError(""); + UsageError(" --no-generate-mini-debug-info: Do do generated backtrace info."); + UsageError(""); UsageError(" --debuggable: Produce code debuggable with Java debugger."); UsageError(""); UsageError(" --native-debuggable: Produce code debuggable with native debugger (like LLDB)."); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 7b9ce5bd1b..61d415276b 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -142,9 +142,7 @@ class OatSymbolizer FINAL { text->End(); if (oat_file_->BssSize() != 0) { - bss->Start(); - bss->SetSize(oat_file_->BssSize()); - bss->End(); + bss->WriteNoBitsSection(oat_file_->BssSize()); } builder_->WriteDynamicSection(elf_file->GetPath()); diff --git a/test/137-cfi/expected.txt b/test/137-cfi/expected.txt index 6a5618ebc6..8db7853696 100644 --- a/test/137-cfi/expected.txt +++ b/test/137-cfi/expected.txt @@ -1 +1,2 @@ JNI_OnLoad called +JNI_OnLoad called diff --git a/test/137-cfi/run b/test/137-cfi/run index 9c567b6813..66575fcd27 100755 --- a/test/137-cfi/run +++ b/test/137-cfi/run @@ -14,4 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -exec ${RUN} "$@" -Xcompiler-option --generate-debug-info +# Test with full DWARF debugging information. +${RUN} "$@" -Xcompiler-option --generate-debug-info + +# Test with minimal compressed debugging information. +${RUN} "$@" -Xcompiler-option --generate-mini-debug-info |