1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_DEBUG_ELF_GNU_DEBUGDATA_WRITER_H_ 18 #define ART_COMPILER_DEBUG_ELF_GNU_DEBUGDATA_WRITER_H_ 19 20 #include <vector> 21 22 #include "arch/instruction_set.h" 23 #include "elf_builder.h" 24 #include "linker/vector_output_stream.h" 25 26 // liblzma. 27 #include "7zCrc.h" 28 #include "XzCrc64.h" 29 #include "XzEnc.h" 30 31 namespace art { 32 namespace debug { 33 34 static void XzCompress(const std::vector<uint8_t>* src, std::vector<uint8_t>* dst) { 35 // Configure the compression library. 36 CrcGenerateTable(); 37 Crc64GenerateTable(); 38 CLzma2EncProps lzma2Props; 39 Lzma2EncProps_Init(&lzma2Props); 40 lzma2Props.lzmaProps.level = 1; // Fast compression. 41 Lzma2EncProps_Normalize(&lzma2Props); 42 CXzProps props; 43 XzProps_Init(&props); 44 props.lzma2Props = &lzma2Props; 45 // Implement the required interface for communication (written in C so no virtual methods). 46 struct XzCallbacks : public ISeqInStream, public ISeqOutStream, public ICompressProgress { 47 static SRes ReadImpl(void* p, void* buf, size_t* size) { 48 auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqInStream*>(p)); 49 *size = std::min(*size, ctx->src_->size() - ctx->src_pos_); 50 memcpy(buf, ctx->src_->data() + ctx->src_pos_, *size); 51 ctx->src_pos_ += *size; 52 return SZ_OK; 53 } 54 static size_t WriteImpl(void* p, const void* buf, size_t size) { 55 auto* ctx = static_cast<XzCallbacks*>(reinterpret_cast<ISeqOutStream*>(p)); 56 const uint8_t* buffer = reinterpret_cast<const uint8_t*>(buf); 57 ctx->dst_->insert(ctx->dst_->end(), buffer, buffer + size); 58 return size; 59 } 60 static SRes ProgressImpl(void* , UInt64, UInt64) { 61 return SZ_OK; 62 } 63 size_t src_pos_; 64 const std::vector<uint8_t>* src_; 65 std::vector<uint8_t>* dst_; 66 }; 67 XzCallbacks callbacks; 68 callbacks.Read = XzCallbacks::ReadImpl; 69 callbacks.Write = XzCallbacks::WriteImpl; 70 callbacks.Progress = XzCallbacks::ProgressImpl; 71 callbacks.src_pos_ = 0; 72 callbacks.src_ = src; 73 callbacks.dst_ = dst; 74 // Compress. 75 SRes res = Xz_Encode(&callbacks, &callbacks, &props, &callbacks); 76 CHECK_EQ(res, SZ_OK); 77 } 78 79 template <typename ElfTypes> 80 static std::vector<uint8_t> MakeMiniDebugInfoInternal( 81 InstructionSet isa, 82 const InstructionSetFeatures* features, 83 size_t rodata_section_size, 84 size_t text_section_size, 85 const ArrayRef<const MethodDebugInfo>& method_infos) { 86 std::vector<uint8_t> buffer; 87 buffer.reserve(KB); 88 VectorOutputStream out("Mini-debug-info ELF file", &buffer); 89 std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, features, &out)); 90 builder->Start(); 91 // Mirror .rodata and .text as NOBITS sections. 92 // It is needed to detected relocations after compression. 93 builder->GetRoData()->WriteNoBitsSection(rodata_section_size); 94 builder->GetText()->WriteNoBitsSection(text_section_size); 95 WriteDebugSymbols(builder.get(), method_infos, false /* with_signature */); 96 WriteCFISection(builder.get(), 97 method_infos, 98 dwarf::DW_DEBUG_FRAME_FORMAT, 99 false /* write_oat_paches */); 100 builder->End(); 101 CHECK(builder->Good()); 102 std::vector<uint8_t> compressed_buffer; 103 compressed_buffer.reserve(buffer.size() / 4); 104 XzCompress(&buffer, &compressed_buffer); 105 return compressed_buffer; 106 } 107 108 } // namespace debug 109 } // namespace art 110 111 #endif // ART_COMPILER_DEBUG_ELF_GNU_DEBUGDATA_WRITER_H_ 112 113