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 "linker/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 31namespace art { 32namespace debug { 33 34static 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 79template <typename ElfTypes> 80static std::vector<uint8_t> MakeMiniDebugInfoInternal( 81 InstructionSet isa, 82 const InstructionSetFeatures* features, 83 typename ElfTypes::Addr text_section_address, 84 size_t text_section_size, 85 typename ElfTypes::Addr dex_section_address, 86 size_t dex_section_size, 87 const DebugInfo& debug_info) { 88 std::vector<uint8_t> buffer; 89 buffer.reserve(KB); 90 linker::VectorOutputStream out("Mini-debug-info ELF file", &buffer); 91 std::unique_ptr<linker::ElfBuilder<ElfTypes>> builder( 92 new linker::ElfBuilder<ElfTypes>(isa, features, &out)); 93 builder->Start(false /* write_program_headers */); 94 // Mirror ELF sections as NOBITS since the added symbols will reference them. 95 builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size); 96 if (dex_section_size != 0) { 97 builder->GetDex()->AllocateVirtualMemory(dex_section_address, dex_section_size); 98 } 99 WriteDebugSymbols(builder.get(), true /* mini-debug-info */, debug_info); 100 WriteCFISection(builder.get(), 101 debug_info.compiled_methods, 102 dwarf::DW_DEBUG_FRAME_FORMAT, 103 false /* write_oat_paches */); 104 builder->End(); 105 CHECK(builder->Good()); 106 std::vector<uint8_t> compressed_buffer; 107 compressed_buffer.reserve(buffer.size() / 4); 108 XzCompress(&buffer, &compressed_buffer); 109 return compressed_buffer; 110} 111 112} // namespace debug 113} // namespace art 114 115#endif // ART_COMPILER_DEBUG_ELF_GNU_DEBUGDATA_WRITER_H_ 116 117