JDevlieghere created this revision. JDevlieghere added reviewers: jasonmolenda, mib. Herald added a project: All. JDevlieghere requested review of this revision.
Add support for compressed CTF data. The flags in the header can indicate whether the CTF body is compressed with zlib deflate. This patch supports uncompressing the data before parsing. https://reviews.llvm.org/D155221 Files: lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h lldb/test/API/macosx/ctf/Makefile lldb/test/API/macosx/ctf/TestCTF.py
Index: lldb/test/API/macosx/ctf/TestCTF.py =================================================================== --- lldb/test/API/macosx/ctf/TestCTF.py +++ lldb/test/API/macosx/ctf/TestCTF.py @@ -18,11 +18,17 @@ return "llvm-objcopy not found in environment" return None - @skipTestIfFn(no_ctf_convert) - @skipTestIfFn(no_objcopy) def test(self): self.build() + self.do_test() + + def test_compressed(self): + self.build(dictionary={"COMPRESS_CTF": "YES"}) + self.do_test() + @skipTestIfFn(no_ctf_convert) + @skipTestIfFn(no_objcopy) + def do_test(self): lldbutil.run_to_name_breakpoint(self, "printf") symbol_file = self.getBuildArtifact("a.ctf") Index: lldb/test/API/macosx/ctf/Makefile =================================================================== --- lldb/test/API/macosx/ctf/Makefile +++ lldb/test/API/macosx/ctf/Makefile @@ -1,12 +1,18 @@ C_SOURCES := test.c MAKE_DSYM := YES +ifeq "$(COMPRESS_CTF)" "YES" + COMPRESS := -c +else + COMPRESS := +endif + all: a.out a.ctf include Makefile.rules a.ctf: a.out.dSYM - ctfconvert -l a -o a.ctf a.out.dSYM/Contents/Resources/DWARF/a.out + ctfconvert -l a $(COMPRESS) -o a.ctf a.out.dSYM/Contents/Resources/DWARF/a.out $(OBJCOPY) \ -R __DWARF,__debug_line \ -R __DWARF,__debug_aranges \ Index: lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h =================================================================== --- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -155,6 +155,13 @@ }; private: + enum Flags : uint32_t { + eFlagCompress = (1u << 0), + eFlagNewFuncInfo = (1u << 1), + eFlagIdxSorted = (1u << 2), + eFlagDynStr = (1u << 3), + }; + enum IntEncoding : uint32_t { eSigned = 0x1, eChar = 0x2, @@ -270,6 +277,13 @@ uint32_t fields, uint32_t struct_size); DataExtractor m_data; + + /// The start offset of the CTF body into m_data. If the body is uncompressed, + /// m_data contains the header and the body and the body starts after the + /// header. If the body is compressed, m_data only contains the body and the + /// offset is zero. + lldb::offset_t m_body_offset = 0; + TypeSystemClang *m_ast; lldb::CompUnitSP m_comp_unit_sp; Index: lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamBuffer.h" +#include "lldb/Host/Config.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -35,6 +36,10 @@ #include <memory> #include <optional> +#if LLVM_ENABLE_ZLIB +#include <zlib.h> +#endif + using namespace llvm; using namespace lldb; using namespace lldb_private; @@ -129,24 +134,79 @@ LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}", ctf_header.preamble.version, ctf_header.preamble.flags); - const lldb::offset_t header_offset = offset; + m_body_offset = offset; + + if (ctf_header.preamble.flags & eFlagCompress) { + // The body has been compressed with zlib deflate. Header offsets point into + // the decompressed data. +#if LLVM_ENABLE_ZLIB + const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen; + DataBufferSP decompressed_data = + std::make_shared<DataBufferHeap>(decompressed_size, 0x0); + + z_stream zstr; + memset(&zstr, 0, sizeof(zstr)); + zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() + + sizeof(ctf_header_t)); + zstr.avail_in = m_data.GetByteSize(); + zstr.next_out = + (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes()); + zstr.avail_out = decompressed_size; + + int rc = inflateInit(&zstr); + if (rc != Z_OK) { + LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}", + zError(rc)); + return false; + } + + rc = inflate(&zstr, Z_FINISH); + if (rc != Z_STREAM_END) { + LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc)); + return false; + } + + rc = inflateEnd(&zstr); + if (rc != Z_OK) { + LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc)); + return false; + } + + if (zstr.total_out != decompressed_size) { + LLDB_LOG(log, + "CTF parsing failed: decompressed size ({0}) doesn't match " + "expected size ([1})", + zstr.total_out, decompressed_size); + return false; + } + + m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(), + m_data.GetAddressByteSize()); + m_body_offset = 0; +#else + LLDB_LOG( + log, + "CTF parsing failed: data is compressed but no zlib inflate support"); + return false; +#endif + } // Validate the header. - if (!m_data.ValidOffset(header_offset + ctf_header.lbloff)) { + if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) { LLDB_LOG(log, "CTF parsing failed: invalid label section offset in header: {0}", ctf_header.lbloff); return false; } - if (!m_data.ValidOffset(header_offset + ctf_header.objtoff)) { + if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) { LLDB_LOG(log, "CTF parsing failed: invalid object section offset in header: {0}", ctf_header.objtoff); return false; } - if (!m_data.ValidOffset(header_offset + ctf_header.funcoff)) { + if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) { LLDB_LOG( log, "CTF parsing failed: invalid function section offset in header: {0}", @@ -154,14 +214,14 @@ return false; } - if (!m_data.ValidOffset(header_offset + ctf_header.typeoff)) { + if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) { LLDB_LOG(log, "CTF parsing failed: invalid type section offset in header: {0}", ctf_header.typeoff); return false; } - if (!m_data.ValidOffset(header_offset + ctf_header.stroff)) { + if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) { LLDB_LOG(log, "CTF parsing failed: invalid string section offset in header: {0}", ctf_header.stroff); @@ -169,7 +229,7 @@ } const lldb::offset_t str_end_offset = - header_offset + ctf_header.stroff + ctf_header.strlen; + m_body_offset + ctf_header.stroff + ctf_header.strlen; if (!m_data.ValidOffset(str_end_offset - 1)) { LLDB_LOG(log, "CTF parsing failed: invalid string section length in header: {0}", @@ -177,7 +237,7 @@ return false; } - if (header_offset + ctf_header.stroff + ctf_header.parlabel > + if (m_body_offset + ctf_header.stroff + ctf_header.parlabel > str_end_offset) { LLDB_LOG(log, "CTF parsing failed: invalid parent label offset: {0} exceeds end " @@ -186,7 +246,7 @@ return false; } - if (header_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) { + if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) { LLDB_LOG(log, "CTF parsing failed: invalid parent name offset: {0} exceeds end " "of string section ({1})", @@ -222,7 +282,7 @@ } llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const { - lldb::offset_t offset = sizeof(ctf_header_t) + m_header->stroff + str_offset; + lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset; if (!m_data.ValidOffset(offset)) return "(invalid)"; const char *str = m_data.GetCStr(&offset); @@ -539,9 +599,8 @@ Log *log = GetLog(LLDBLog::Symbols); LLDB_LOG(log, "Parsing CTF types"); - lldb::offset_t type_offset = sizeof(ctf_header_t) + m_header->typeoff; - const lldb::offset_t type_offset_end = - sizeof(ctf_header_t) + m_header->stroff; + lldb::offset_t type_offset = m_body_offset + m_header->typeoff; + const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff; lldb::user_id_t type_uid = 1; while (type_offset < type_offset_end) { @@ -597,9 +656,8 @@ Log *log = GetLog(LLDBLog::Symbols); LLDB_LOG(log, "Parsing CTF functions"); - lldb::offset_t function_offset = sizeof(ctf_header_t) + m_header->funcoff; - const lldb::offset_t function_offset_end = - sizeof(ctf_header_t) + m_header->typeoff; + lldb::offset_t function_offset = m_body_offset + m_header->funcoff; + const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff; uint32_t symbol_idx = 0; Declaration decl; @@ -713,9 +771,8 @@ Log *log = GetLog(LLDBLog::Symbols); LLDB_LOG(log, "Parsing CTF objects"); - lldb::offset_t object_offset = sizeof(ctf_header_t) + m_header->objtoff; - const lldb::offset_t object_offset_end = - sizeof(ctf_header_t) + m_header->funcoff; + lldb::offset_t object_offset = m_body_offset + m_header->objtoff; + const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff; uint32_t symbol_idx = 0; Declaration decl;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits