106c3fb27SDimitry Andric //===-- SymbolFileCTF.cpp ----------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "SymbolFileCTF.h" 1006c3fb27SDimitry Andric 1106c3fb27SDimitry Andric #include "lldb/Core/Module.h" 1206c3fb27SDimitry Andric #include "lldb/Core/PluginManager.h" 1306c3fb27SDimitry Andric #include "lldb/Host/Config.h" 1406c3fb27SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 1506c3fb27SDimitry Andric #include "lldb/Symbol/Function.h" 1606c3fb27SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 1706c3fb27SDimitry Andric #include "lldb/Symbol/Symbol.h" 1806c3fb27SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 1906c3fb27SDimitry Andric #include "lldb/Symbol/Symtab.h" 2006c3fb27SDimitry Andric #include "lldb/Symbol/TypeList.h" 2106c3fb27SDimitry Andric #include "lldb/Symbol/TypeMap.h" 2206c3fb27SDimitry Andric #include "lldb/Symbol/Variable.h" 2306c3fb27SDimitry Andric #include "lldb/Symbol/VariableList.h" 2406c3fb27SDimitry Andric #include "lldb/Utility/DataExtractor.h" 2506c3fb27SDimitry Andric #include "lldb/Utility/LLDBLog.h" 2606c3fb27SDimitry Andric #include "lldb/Utility/Log.h" 2706c3fb27SDimitry Andric #include "lldb/Utility/RegularExpression.h" 285f757f3fSDimitry Andric #include "lldb/Utility/StreamBuffer.h" 2906c3fb27SDimitry Andric #include "lldb/Utility/StreamString.h" 3006c3fb27SDimitry Andric #include "lldb/Utility/Timer.h" 3106c3fb27SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 3206c3fb27SDimitry Andric 3306c3fb27SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" 3406c3fb27SDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 3506c3fb27SDimitry Andric 3606c3fb27SDimitry Andric #include <memory> 3706c3fb27SDimitry Andric #include <optional> 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric #if LLVM_ENABLE_ZLIB 4006c3fb27SDimitry Andric #include <zlib.h> 4106c3fb27SDimitry Andric #endif 4206c3fb27SDimitry Andric 4306c3fb27SDimitry Andric using namespace llvm; 4406c3fb27SDimitry Andric using namespace lldb; 4506c3fb27SDimitry Andric using namespace lldb_private; 4606c3fb27SDimitry Andric 4706c3fb27SDimitry Andric LLDB_PLUGIN_DEFINE(SymbolFileCTF) 4806c3fb27SDimitry Andric 4906c3fb27SDimitry Andric char SymbolFileCTF::ID; 5006c3fb27SDimitry Andric 5106c3fb27SDimitry Andric SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp) 5206c3fb27SDimitry Andric : SymbolFileCommon(std::move(objfile_sp)) {} 5306c3fb27SDimitry Andric 5406c3fb27SDimitry Andric void SymbolFileCTF::Initialize() { 5506c3fb27SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 5606c3fb27SDimitry Andric GetPluginDescriptionStatic(), CreateInstance); 5706c3fb27SDimitry Andric } 5806c3fb27SDimitry Andric 5906c3fb27SDimitry Andric void SymbolFileCTF::Terminate() { 6006c3fb27SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 6106c3fb27SDimitry Andric } 6206c3fb27SDimitry Andric 6306c3fb27SDimitry Andric llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() { 6406c3fb27SDimitry Andric return "Compact C Type Format Symbol Reader"; 6506c3fb27SDimitry Andric } 6606c3fb27SDimitry Andric 6706c3fb27SDimitry Andric SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) { 6806c3fb27SDimitry Andric return new SymbolFileCTF(std::move(objfile_sp)); 6906c3fb27SDimitry Andric } 7006c3fb27SDimitry Andric 7106c3fb27SDimitry Andric bool SymbolFileCTF::ParseHeader() { 7206c3fb27SDimitry Andric if (m_header) 7306c3fb27SDimitry Andric return true; 7406c3fb27SDimitry Andric 7506c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 7606c3fb27SDimitry Andric 7706c3fb27SDimitry Andric ModuleSP module_sp(m_objfile_sp->GetModule()); 7806c3fb27SDimitry Andric const SectionList *section_list = module_sp->GetSectionList(); 7906c3fb27SDimitry Andric if (!section_list) 8006c3fb27SDimitry Andric return false; 8106c3fb27SDimitry Andric 8206c3fb27SDimitry Andric SectionSP section_sp( 8306c3fb27SDimitry Andric section_list->FindSectionByType(lldb::eSectionTypeCTF, true)); 8406c3fb27SDimitry Andric if (!section_sp) 8506c3fb27SDimitry Andric return false; 8606c3fb27SDimitry Andric 8706c3fb27SDimitry Andric m_objfile_sp->ReadSectionData(section_sp.get(), m_data); 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric if (m_data.GetByteSize() == 0) 9006c3fb27SDimitry Andric return false; 9106c3fb27SDimitry Andric 9206c3fb27SDimitry Andric StreamString module_desc; 9306c3fb27SDimitry Andric GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(), 9406c3fb27SDimitry Andric lldb::eDescriptionLevelBrief); 9506c3fb27SDimitry Andric LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData()); 9606c3fb27SDimitry Andric 9706c3fb27SDimitry Andric lldb::offset_t offset = 0; 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric // Parse CTF header. 10006c3fb27SDimitry Andric constexpr size_t ctf_header_size = sizeof(ctf_header_t); 10106c3fb27SDimitry Andric if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) { 10206c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header"); 10306c3fb27SDimitry Andric return false; 10406c3fb27SDimitry Andric } 10506c3fb27SDimitry Andric 10606c3fb27SDimitry Andric m_header.emplace(); 10706c3fb27SDimitry Andric 10806c3fb27SDimitry Andric ctf_header_t &ctf_header = *m_header; 10906c3fb27SDimitry Andric ctf_header.preamble.magic = m_data.GetU16(&offset); 11006c3fb27SDimitry Andric ctf_header.preamble.version = m_data.GetU8(&offset); 11106c3fb27SDimitry Andric ctf_header.preamble.flags = m_data.GetU8(&offset); 11206c3fb27SDimitry Andric ctf_header.parlabel = m_data.GetU32(&offset); 11306c3fb27SDimitry Andric ctf_header.parname = m_data.GetU32(&offset); 11406c3fb27SDimitry Andric ctf_header.lbloff = m_data.GetU32(&offset); 11506c3fb27SDimitry Andric ctf_header.objtoff = m_data.GetU32(&offset); 11606c3fb27SDimitry Andric ctf_header.funcoff = m_data.GetU32(&offset); 11706c3fb27SDimitry Andric ctf_header.typeoff = m_data.GetU32(&offset); 11806c3fb27SDimitry Andric ctf_header.stroff = m_data.GetU32(&offset); 11906c3fb27SDimitry Andric ctf_header.strlen = m_data.GetU32(&offset); 12006c3fb27SDimitry Andric 12106c3fb27SDimitry Andric // Validate the preamble. 12206c3fb27SDimitry Andric if (ctf_header.preamble.magic != g_ctf_magic) { 12306c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}", 12406c3fb27SDimitry Andric ctf_header.preamble.magic); 12506c3fb27SDimitry Andric return false; 12606c3fb27SDimitry Andric } 12706c3fb27SDimitry Andric 12806c3fb27SDimitry Andric if (ctf_header.preamble.version != g_ctf_version) { 12906c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}", 13006c3fb27SDimitry Andric ctf_header.preamble.version); 13106c3fb27SDimitry Andric return false; 13206c3fb27SDimitry Andric } 13306c3fb27SDimitry Andric 13406c3fb27SDimitry Andric LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}", 13506c3fb27SDimitry Andric ctf_header.preamble.version, ctf_header.preamble.flags); 13606c3fb27SDimitry Andric 13706c3fb27SDimitry Andric m_body_offset = offset; 13806c3fb27SDimitry Andric 13906c3fb27SDimitry Andric if (ctf_header.preamble.flags & eFlagCompress) { 14006c3fb27SDimitry Andric // The body has been compressed with zlib deflate. Header offsets point into 14106c3fb27SDimitry Andric // the decompressed data. 14206c3fb27SDimitry Andric #if LLVM_ENABLE_ZLIB 14306c3fb27SDimitry Andric const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen; 14406c3fb27SDimitry Andric DataBufferSP decompressed_data = 14506c3fb27SDimitry Andric std::make_shared<DataBufferHeap>(decompressed_size, 0x0); 14606c3fb27SDimitry Andric 14706c3fb27SDimitry Andric z_stream zstr; 14806c3fb27SDimitry Andric memset(&zstr, 0, sizeof(zstr)); 14906c3fb27SDimitry Andric zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() + 15006c3fb27SDimitry Andric sizeof(ctf_header_t)); 15106c3fb27SDimitry Andric zstr.avail_in = m_data.BytesLeft(offset); 15206c3fb27SDimitry Andric zstr.next_out = 15306c3fb27SDimitry Andric (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes()); 15406c3fb27SDimitry Andric zstr.avail_out = decompressed_size; 15506c3fb27SDimitry Andric 15606c3fb27SDimitry Andric int rc = inflateInit(&zstr); 15706c3fb27SDimitry Andric if (rc != Z_OK) { 15806c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}", 15906c3fb27SDimitry Andric zError(rc)); 16006c3fb27SDimitry Andric return false; 16106c3fb27SDimitry Andric } 16206c3fb27SDimitry Andric 16306c3fb27SDimitry Andric rc = inflate(&zstr, Z_FINISH); 16406c3fb27SDimitry Andric if (rc != Z_STREAM_END) { 16506c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc)); 16606c3fb27SDimitry Andric return false; 16706c3fb27SDimitry Andric } 16806c3fb27SDimitry Andric 16906c3fb27SDimitry Andric rc = inflateEnd(&zstr); 17006c3fb27SDimitry Andric if (rc != Z_OK) { 17106c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc)); 17206c3fb27SDimitry Andric return false; 17306c3fb27SDimitry Andric } 17406c3fb27SDimitry Andric 17506c3fb27SDimitry Andric if (zstr.total_out != decompressed_size) { 17606c3fb27SDimitry Andric LLDB_LOG(log, 17706c3fb27SDimitry Andric "CTF parsing failed: decompressed size ({0}) doesn't match " 17806c3fb27SDimitry Andric "expected size ([1})", 17906c3fb27SDimitry Andric zstr.total_out, decompressed_size); 18006c3fb27SDimitry Andric return false; 18106c3fb27SDimitry Andric } 18206c3fb27SDimitry Andric 18306c3fb27SDimitry Andric m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(), 18406c3fb27SDimitry Andric m_data.GetAddressByteSize()); 18506c3fb27SDimitry Andric m_body_offset = 0; 18606c3fb27SDimitry Andric #else 18706c3fb27SDimitry Andric LLDB_LOG( 18806c3fb27SDimitry Andric log, 18906c3fb27SDimitry Andric "CTF parsing failed: data is compressed but no zlib inflate support"); 19006c3fb27SDimitry Andric return false; 19106c3fb27SDimitry Andric #endif 19206c3fb27SDimitry Andric } 19306c3fb27SDimitry Andric 19406c3fb27SDimitry Andric // Validate the header. 19506c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) { 19606c3fb27SDimitry Andric LLDB_LOG(log, 19706c3fb27SDimitry Andric "CTF parsing failed: invalid label section offset in header: {0}", 19806c3fb27SDimitry Andric ctf_header.lbloff); 19906c3fb27SDimitry Andric return false; 20006c3fb27SDimitry Andric } 20106c3fb27SDimitry Andric 20206c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) { 20306c3fb27SDimitry Andric LLDB_LOG(log, 20406c3fb27SDimitry Andric "CTF parsing failed: invalid object section offset in header: {0}", 20506c3fb27SDimitry Andric ctf_header.objtoff); 20606c3fb27SDimitry Andric return false; 20706c3fb27SDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) { 21006c3fb27SDimitry Andric LLDB_LOG( 21106c3fb27SDimitry Andric log, 21206c3fb27SDimitry Andric "CTF parsing failed: invalid function section offset in header: {0}", 21306c3fb27SDimitry Andric ctf_header.funcoff); 21406c3fb27SDimitry Andric return false; 21506c3fb27SDimitry Andric } 21606c3fb27SDimitry Andric 21706c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) { 21806c3fb27SDimitry Andric LLDB_LOG(log, 21906c3fb27SDimitry Andric "CTF parsing failed: invalid type section offset in header: {0}", 22006c3fb27SDimitry Andric ctf_header.typeoff); 22106c3fb27SDimitry Andric return false; 22206c3fb27SDimitry Andric } 22306c3fb27SDimitry Andric 22406c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) { 22506c3fb27SDimitry Andric LLDB_LOG(log, 22606c3fb27SDimitry Andric "CTF parsing failed: invalid string section offset in header: {0}", 22706c3fb27SDimitry Andric ctf_header.stroff); 22806c3fb27SDimitry Andric return false; 22906c3fb27SDimitry Andric } 23006c3fb27SDimitry Andric 23106c3fb27SDimitry Andric const lldb::offset_t str_end_offset = 23206c3fb27SDimitry Andric m_body_offset + ctf_header.stroff + ctf_header.strlen; 23306c3fb27SDimitry Andric if (!m_data.ValidOffset(str_end_offset - 1)) { 23406c3fb27SDimitry Andric LLDB_LOG(log, 23506c3fb27SDimitry Andric "CTF parsing failed: invalid string section length in header: {0}", 23606c3fb27SDimitry Andric ctf_header.strlen); 23706c3fb27SDimitry Andric return false; 23806c3fb27SDimitry Andric } 23906c3fb27SDimitry Andric 24006c3fb27SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parlabel > 24106c3fb27SDimitry Andric str_end_offset) { 24206c3fb27SDimitry Andric LLDB_LOG(log, 24306c3fb27SDimitry Andric "CTF parsing failed: invalid parent label offset: {0} exceeds end " 24406c3fb27SDimitry Andric "of string section ({1})", 24506c3fb27SDimitry Andric ctf_header.parlabel, str_end_offset); 24606c3fb27SDimitry Andric return false; 24706c3fb27SDimitry Andric } 24806c3fb27SDimitry Andric 24906c3fb27SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) { 25006c3fb27SDimitry Andric LLDB_LOG(log, 25106c3fb27SDimitry Andric "CTF parsing failed: invalid parent name offset: {0} exceeds end " 25206c3fb27SDimitry Andric "of string section ({1})", 25306c3fb27SDimitry Andric ctf_header.parname, str_end_offset); 25406c3fb27SDimitry Andric return false; 25506c3fb27SDimitry Andric } 25606c3fb27SDimitry Andric 25706c3fb27SDimitry Andric LLDB_LOG(log, 25806c3fb27SDimitry Andric "Parsed valid CTF header: lbloff = {0}, objtoff = {1}, funcoff = " 25906c3fb27SDimitry Andric "{2}, typeoff = {3}, stroff = {4}, strlen = {5}", 26006c3fb27SDimitry Andric ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff, 26106c3fb27SDimitry Andric ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen); 26206c3fb27SDimitry Andric 26306c3fb27SDimitry Andric return true; 26406c3fb27SDimitry Andric } 26506c3fb27SDimitry Andric 26606c3fb27SDimitry Andric void SymbolFileCTF::InitializeObject() { 26706c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 26806c3fb27SDimitry Andric 26906c3fb27SDimitry Andric auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC); 27006c3fb27SDimitry Andric if (auto err = type_system_or_err.takeError()) { 27106c3fb27SDimitry Andric LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}"); 27206c3fb27SDimitry Andric return; 27306c3fb27SDimitry Andric } 27406c3fb27SDimitry Andric 27506c3fb27SDimitry Andric auto ts = *type_system_or_err; 27606c3fb27SDimitry Andric m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 27706c3fb27SDimitry Andric LazyBool optimized = eLazyBoolNo; 27806c3fb27SDimitry Andric m_comp_unit_sp = std::make_shared<CompileUnit>( 27906c3fb27SDimitry Andric m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized); 28006c3fb27SDimitry Andric 28106c3fb27SDimitry Andric ParseTypes(*m_comp_unit_sp); 28206c3fb27SDimitry Andric } 28306c3fb27SDimitry Andric 28406c3fb27SDimitry Andric llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const { 28506c3fb27SDimitry Andric lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset; 28606c3fb27SDimitry Andric if (!m_data.ValidOffset(offset)) 28706c3fb27SDimitry Andric return "(invalid)"; 28806c3fb27SDimitry Andric const char *str = m_data.GetCStr(&offset); 28906c3fb27SDimitry Andric if (str && !*str) 29006c3fb27SDimitry Andric return "(anon)"; 29106c3fb27SDimitry Andric return llvm::StringRef(str); 29206c3fb27SDimitry Andric } 29306c3fb27SDimitry Andric 29406c3fb27SDimitry Andric /// Return the integer display representation encoded in the given data. 29506c3fb27SDimitry Andric static uint32_t GetEncoding(uint32_t data) { 29606c3fb27SDimitry Andric // Mask bits 24–31. 29706c3fb27SDimitry Andric return ((data)&0xff000000) >> 24; 29806c3fb27SDimitry Andric } 29906c3fb27SDimitry Andric 30006c3fb27SDimitry Andric /// Return the integral width in bits encoded in the given data. 30106c3fb27SDimitry Andric static uint32_t GetBits(uint32_t data) { 30206c3fb27SDimitry Andric // Mask bits 0-15. 30306c3fb27SDimitry Andric return (data)&0x0000ffff; 30406c3fb27SDimitry Andric } 30506c3fb27SDimitry Andric 30606c3fb27SDimitry Andric /// Return the type kind encoded in the given data. 30706c3fb27SDimitry Andric uint32_t GetKind(uint32_t data) { 30806c3fb27SDimitry Andric // Mask bits 26–31. 30906c3fb27SDimitry Andric return ((data)&0xf800) >> 11; 31006c3fb27SDimitry Andric } 31106c3fb27SDimitry Andric 31206c3fb27SDimitry Andric /// Return the variable length encoded in the given data. 31306c3fb27SDimitry Andric uint32_t GetVLen(uint32_t data) { 31406c3fb27SDimitry Andric // Mask bits 0–24. 31506c3fb27SDimitry Andric return (data)&0x3ff; 31606c3fb27SDimitry Andric } 31706c3fb27SDimitry Andric 31806c3fb27SDimitry Andric static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); } 31906c3fb27SDimitry Andric 3205f757f3fSDimitry Andric static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) { 32106c3fb27SDimitry Andric switch (type) { 3225f757f3fSDimitry Andric case CTFType::Kind::eStruct: 3235f757f3fSDimitry Andric return clang::TagTypeKind::Struct; 3245f757f3fSDimitry Andric case CTFType::Kind::eUnion: 3255f757f3fSDimitry Andric return clang::TagTypeKind::Union; 32606c3fb27SDimitry Andric default: 32706c3fb27SDimitry Andric lldbassert(false && "Invalid record kind!"); 3285f757f3fSDimitry Andric return clang::TagTypeKind::Struct; 32906c3fb27SDimitry Andric } 33006c3fb27SDimitry Andric } 33106c3fb27SDimitry Andric 3325f757f3fSDimitry Andric llvm::Expected<TypeSP> 3335f757f3fSDimitry Andric SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) { 3345f757f3fSDimitry Andric lldb::BasicType basic_type = 3355f757f3fSDimitry Andric TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name); 33606c3fb27SDimitry Andric if (basic_type == eBasicTypeInvalid) 33706c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 33806c3fb27SDimitry Andric llvm::formatv("unsupported integer type: no corresponding basic clang " 33906c3fb27SDimitry Andric "type for '{0}'", 3405f757f3fSDimitry Andric ctf_integer.name), 34106c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 34206c3fb27SDimitry Andric 34306c3fb27SDimitry Andric CompilerType compiler_type = m_ast->GetBasicType(basic_type); 34406c3fb27SDimitry Andric 345*0fca6ea1SDimitry Andric if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) { 34606c3fb27SDimitry Andric // Make sure the type we got is an integer type. 34706c3fb27SDimitry Andric bool compiler_type_is_signed = false; 34806c3fb27SDimitry Andric if (!compiler_type.IsIntegerType(compiler_type_is_signed)) 34906c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 35006c3fb27SDimitry Andric llvm::formatv( 35106c3fb27SDimitry Andric "Found compiler type for '{0}' but it's not an integer type: {1}", 3525f757f3fSDimitry Andric ctf_integer.name, 3535f757f3fSDimitry Andric compiler_type.GetDisplayTypeName().GetStringRef()), 35406c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 35506c3fb27SDimitry Andric 35606c3fb27SDimitry Andric // Make sure the signing matches between the CTF and the compiler type. 3575f757f3fSDimitry Andric const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned); 35806c3fb27SDimitry Andric if (compiler_type_is_signed != type_is_signed) 35906c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 36006c3fb27SDimitry Andric llvm::formatv("Found integer compiler type for {0} but compiler type " 36106c3fb27SDimitry Andric "is {1} and {0} is {2}", 3625f757f3fSDimitry Andric ctf_integer.name, 3635f757f3fSDimitry Andric compiler_type_is_signed ? "signed" : "unsigned", 36406c3fb27SDimitry Andric type_is_signed ? "signed" : "unsigned"), 36506c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 36606c3fb27SDimitry Andric } 36706c3fb27SDimitry Andric 36806c3fb27SDimitry Andric Declaration decl; 3695f757f3fSDimitry Andric return MakeType(ctf_integer.uid, ConstString(ctf_integer.name), 3705f757f3fSDimitry Andric GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID, 3715f757f3fSDimitry Andric lldb_private::Type::eEncodingIsUID, decl, compiler_type, 3725f757f3fSDimitry Andric lldb_private::Type::ResolveState::Full); 37306c3fb27SDimitry Andric } 37406c3fb27SDimitry Andric 37506c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 3765f757f3fSDimitry Andric SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) { 3775f757f3fSDimitry Andric Type *ref_type = ResolveTypeUID(ctf_modifier.type); 37806c3fb27SDimitry Andric if (!ref_type) 37906c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 3805f757f3fSDimitry Andric llvm::formatv("Could not find modified type: {0}", ctf_modifier.type), 38106c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 38206c3fb27SDimitry Andric 38306c3fb27SDimitry Andric CompilerType compiler_type; 38406c3fb27SDimitry Andric 3855f757f3fSDimitry Andric switch (ctf_modifier.kind) { 3865f757f3fSDimitry Andric case CTFType::ePointer: 38706c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().GetPointerType(); 38806c3fb27SDimitry Andric break; 3895f757f3fSDimitry Andric case CTFType::eConst: 39006c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddConstModifier(); 39106c3fb27SDimitry Andric break; 3925f757f3fSDimitry Andric case CTFType::eVolatile: 39306c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier(); 39406c3fb27SDimitry Andric break; 3955f757f3fSDimitry Andric case CTFType::eRestrict: 39606c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier(); 39706c3fb27SDimitry Andric break; 39806c3fb27SDimitry Andric default: 39906c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 4005f757f3fSDimitry Andric llvm::formatv("ParseModifier called with unsupported kind: {0}", 4015f757f3fSDimitry Andric ctf_modifier.kind), 40206c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 40306c3fb27SDimitry Andric } 40406c3fb27SDimitry Andric 40506c3fb27SDimitry Andric Declaration decl; 4065f757f3fSDimitry Andric return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, 40706c3fb27SDimitry Andric Type::eEncodingIsUID, decl, compiler_type, 40806c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 40906c3fb27SDimitry Andric } 41006c3fb27SDimitry Andric 4115f757f3fSDimitry Andric llvm::Expected<lldb::TypeSP> 4125f757f3fSDimitry Andric SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) { 4135f757f3fSDimitry Andric Type *underlying_type = ResolveTypeUID(ctf_typedef.type); 41406c3fb27SDimitry Andric if (!underlying_type) 41506c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 4165f757f3fSDimitry Andric llvm::formatv("Could not find typedef underlying type: {0}", 4175f757f3fSDimitry Andric ctf_typedef.type), 41806c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 41906c3fb27SDimitry Andric 42006c3fb27SDimitry Andric CompilerType target_ast_type = underlying_type->GetFullCompilerType(); 42106c3fb27SDimitry Andric clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl(); 42206c3fb27SDimitry Andric CompilerType ast_typedef = target_ast_type.CreateTypedef( 4235f757f3fSDimitry Andric ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0); 42406c3fb27SDimitry Andric 42506c3fb27SDimitry Andric Declaration decl; 4265f757f3fSDimitry Andric return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr, 4275f757f3fSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 4285f757f3fSDimitry Andric ast_typedef, lldb_private::Type::ResolveState::Full); 42906c3fb27SDimitry Andric } 43006c3fb27SDimitry Andric 4315f757f3fSDimitry Andric llvm::Expected<lldb::TypeSP> 4325f757f3fSDimitry Andric SymbolFileCTF::CreateArray(const CTFArray &ctf_array) { 4335f757f3fSDimitry Andric Type *element_type = ResolveTypeUID(ctf_array.type); 43406c3fb27SDimitry Andric if (!element_type) 43506c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 4365f757f3fSDimitry Andric llvm::formatv("Could not find array element type: {0}", ctf_array.type), 43706c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 43806c3fb27SDimitry Andric 43906c3fb27SDimitry Andric std::optional<uint64_t> element_size = element_type->GetByteSize(nullptr); 44006c3fb27SDimitry Andric if (!element_size) 44106c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 44206c3fb27SDimitry Andric llvm::formatv("could not get element size of type: {0}", 4435f757f3fSDimitry Andric ctf_array.type), 44406c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 44506c3fb27SDimitry Andric 44606c3fb27SDimitry Andric uint64_t size = ctf_array.nelems * *element_size; 44706c3fb27SDimitry Andric 44806c3fb27SDimitry Andric CompilerType compiler_type = m_ast->CreateArrayType( 44906c3fb27SDimitry Andric element_type->GetFullCompilerType(), ctf_array.nelems, 45006c3fb27SDimitry Andric /*is_gnu_vector*/ false); 45106c3fb27SDimitry Andric 45206c3fb27SDimitry Andric Declaration decl; 4535f757f3fSDimitry Andric return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID, 45406c3fb27SDimitry Andric Type::eEncodingIsUID, decl, compiler_type, 45506c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 45606c3fb27SDimitry Andric } 45706c3fb27SDimitry Andric 4585f757f3fSDimitry Andric llvm::Expected<lldb::TypeSP> 4595f757f3fSDimitry Andric SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) { 46006c3fb27SDimitry Andric Declaration decl; 46106c3fb27SDimitry Andric CompilerType enum_type = m_ast->CreateEnumerationType( 4625f757f3fSDimitry Andric ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), 4635f757f3fSDimitry Andric decl, m_ast->GetBasicType(eBasicTypeInt), 46406c3fb27SDimitry Andric /*is_scoped=*/false); 46506c3fb27SDimitry Andric 4665f757f3fSDimitry Andric for (const CTFEnum::Value &value : ctf_enum.values) { 46706c3fb27SDimitry Andric Declaration value_decl; 4685f757f3fSDimitry Andric m_ast->AddEnumerationValueToEnumerationType( 4695f757f3fSDimitry Andric enum_type, value_decl, value.name.data(), value.value, ctf_enum.size); 47006c3fb27SDimitry Andric } 4715f757f3fSDimitry Andric TypeSystemClang::CompleteTagDeclarationDefinition(enum_type); 47206c3fb27SDimitry Andric 4735f757f3fSDimitry Andric return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, 47406c3fb27SDimitry Andric Type::eEncodingIsUID, decl, enum_type, 47506c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 47606c3fb27SDimitry Andric } 47706c3fb27SDimitry Andric 47806c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 4795f757f3fSDimitry Andric SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) { 48006c3fb27SDimitry Andric std::vector<CompilerType> arg_types; 4815f757f3fSDimitry Andric for (uint32_t arg : ctf_function.args) { 4825f757f3fSDimitry Andric if (Type *arg_type = ResolveTypeUID(arg)) 48306c3fb27SDimitry Andric arg_types.push_back(arg_type->GetFullCompilerType()); 48406c3fb27SDimitry Andric } 48506c3fb27SDimitry Andric 4865f757f3fSDimitry Andric Type *ret_type = ResolveTypeUID(ctf_function.return_type); 48706c3fb27SDimitry Andric if (!ret_type) 48806c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 4895f757f3fSDimitry Andric llvm::formatv("Could not find function return type: {0}", 4905f757f3fSDimitry Andric ctf_function.return_type), 49106c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 49206c3fb27SDimitry Andric 49306c3fb27SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType( 49406c3fb27SDimitry Andric ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), 4955f757f3fSDimitry Andric ctf_function.variadic, 0, clang::CallingConv::CC_C); 49606c3fb27SDimitry Andric 49706c3fb27SDimitry Andric Declaration decl; 4985f757f3fSDimitry Andric return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr, 4995f757f3fSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, 50006c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 50106c3fb27SDimitry Andric } 50206c3fb27SDimitry Andric 50306c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 5045f757f3fSDimitry Andric SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) { 5055f757f3fSDimitry Andric const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind); 5065f757f3fSDimitry Andric CompilerType record_type = m_ast->CreateRecordType( 5075f757f3fSDimitry Andric nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(), 5085f757f3fSDimitry Andric llvm::to_underlying(tag_kind), eLanguageTypeC); 5095f757f3fSDimitry Andric m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record; 51006c3fb27SDimitry Andric Declaration decl; 5115f757f3fSDimitry Andric return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size, 5125f757f3fSDimitry Andric nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, 5135f757f3fSDimitry Andric decl, record_type, lldb_private::Type::ResolveState::Forward); 51406c3fb27SDimitry Andric } 51506c3fb27SDimitry Andric 5165f757f3fSDimitry Andric bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) { 5175f757f3fSDimitry Andric // Check if we have a CTF type for the given incomplete compiler type. 5185f757f3fSDimitry Andric auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType()); 5195f757f3fSDimitry Andric if (it == m_compiler_types.end()) 5205f757f3fSDimitry Andric return false; 5215f757f3fSDimitry Andric 5225f757f3fSDimitry Andric const CTFType *ctf_type = it->second; 5235f757f3fSDimitry Andric assert(ctf_type && "m_compiler_types should only contain valid CTF types"); 5245f757f3fSDimitry Andric 5255f757f3fSDimitry Andric // We only support resolving record types. 5265f757f3fSDimitry Andric assert(llvm::isa<CTFRecord>(ctf_type)); 5275f757f3fSDimitry Andric 5285f757f3fSDimitry Andric // Cast to the appropriate CTF type. 5295f757f3fSDimitry Andric const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type); 5305f757f3fSDimitry Andric 5315f757f3fSDimitry Andric // If any of the fields are incomplete, we cannot complete the type. 5325f757f3fSDimitry Andric for (const CTFRecord::Field &field : ctf_record->fields) { 5335f757f3fSDimitry Andric if (!ResolveTypeUID(field.type)) { 5345f757f3fSDimitry Andric LLDB_LOG(GetLog(LLDBLog::Symbols), 5355f757f3fSDimitry Andric "Cannot complete type {0} because field {1} is incomplete", 5365f757f3fSDimitry Andric ctf_type->uid, field.type); 5375f757f3fSDimitry Andric return false; 5385f757f3fSDimitry Andric } 5395f757f3fSDimitry Andric } 5405f757f3fSDimitry Andric 5415f757f3fSDimitry Andric // Complete the record type. 5425f757f3fSDimitry Andric m_ast->StartTagDeclarationDefinition(compiler_type); 5435f757f3fSDimitry Andric for (const CTFRecord::Field &field : ctf_record->fields) { 5445f757f3fSDimitry Andric Type *field_type = ResolveTypeUID(field.type); 5455f757f3fSDimitry Andric assert(field_type && "field must be complete"); 5465f757f3fSDimitry Andric const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0); 5475f757f3fSDimitry Andric TypeSystemClang::AddFieldToRecordType(compiler_type, field.name, 5485f757f3fSDimitry Andric field_type->GetFullCompilerType(), 5495f757f3fSDimitry Andric eAccessPublic, field_size); 5505f757f3fSDimitry Andric } 5515f757f3fSDimitry Andric m_ast->CompleteTagDeclarationDefinition(compiler_type); 5525f757f3fSDimitry Andric 5535f757f3fSDimitry Andric // Now that the compiler type is complete, we don't need to remember it 5545f757f3fSDimitry Andric // anymore and can remove the CTF record type. 5555f757f3fSDimitry Andric m_compiler_types.erase(compiler_type.GetOpaqueQualType()); 5565f757f3fSDimitry Andric m_ctf_types.erase(ctf_type->uid); 5575f757f3fSDimitry Andric 5585f757f3fSDimitry Andric return true; 5595f757f3fSDimitry Andric } 5605f757f3fSDimitry Andric 5615f757f3fSDimitry Andric llvm::Expected<lldb::TypeSP> 5625f757f3fSDimitry Andric SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) { 5635f757f3fSDimitry Andric CompilerType forward_compiler_type = m_ast->CreateRecordType( 5645f757f3fSDimitry Andric nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name, 5655f757f3fSDimitry Andric llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC); 5665f757f3fSDimitry Andric Declaration decl; 5675f757f3fSDimitry Andric return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr, 5685f757f3fSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, 5695f757f3fSDimitry Andric forward_compiler_type, Type::ResolveState::Forward); 5705f757f3fSDimitry Andric } 5715f757f3fSDimitry Andric 5725f757f3fSDimitry Andric llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) { 5735f757f3fSDimitry Andric if (!ctf_type) 5745f757f3fSDimitry Andric return llvm::make_error<llvm::StringError>( 5755f757f3fSDimitry Andric "cannot create type for unparsed type", llvm::inconvertibleErrorCode()); 5765f757f3fSDimitry Andric 5775f757f3fSDimitry Andric switch (ctf_type->kind) { 5785f757f3fSDimitry Andric case CTFType::Kind::eInteger: 5795f757f3fSDimitry Andric return CreateInteger(*static_cast<CTFInteger *>(ctf_type)); 5805f757f3fSDimitry Andric case CTFType::Kind::eConst: 5815f757f3fSDimitry Andric case CTFType::Kind::ePointer: 5825f757f3fSDimitry Andric case CTFType::Kind::eRestrict: 5835f757f3fSDimitry Andric case CTFType::Kind::eVolatile: 5845f757f3fSDimitry Andric return CreateModifier(*static_cast<CTFModifier *>(ctf_type)); 5855f757f3fSDimitry Andric case CTFType::Kind::eTypedef: 5865f757f3fSDimitry Andric return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type)); 5875f757f3fSDimitry Andric case CTFType::Kind::eArray: 5885f757f3fSDimitry Andric return CreateArray(*static_cast<CTFArray *>(ctf_type)); 5895f757f3fSDimitry Andric case CTFType::Kind::eEnum: 5905f757f3fSDimitry Andric return CreateEnum(*static_cast<CTFEnum *>(ctf_type)); 5915f757f3fSDimitry Andric case CTFType::Kind::eFunction: 5925f757f3fSDimitry Andric return CreateFunction(*static_cast<CTFFunction *>(ctf_type)); 5935f757f3fSDimitry Andric case CTFType::Kind::eStruct: 5945f757f3fSDimitry Andric case CTFType::Kind::eUnion: 5955f757f3fSDimitry Andric return CreateRecord(*static_cast<CTFRecord *>(ctf_type)); 5965f757f3fSDimitry Andric case CTFType::Kind::eForward: 5975f757f3fSDimitry Andric return CreateForward(*static_cast<CTFForward *>(ctf_type)); 5985f757f3fSDimitry Andric case CTFType::Kind::eUnknown: 5995f757f3fSDimitry Andric case CTFType::Kind::eFloat: 6005f757f3fSDimitry Andric case CTFType::Kind::eSlice: 6015f757f3fSDimitry Andric return llvm::make_error<llvm::StringError>( 6025f757f3fSDimitry Andric llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})", 6035f757f3fSDimitry Andric ctf_type->uid, ctf_type->name, ctf_type->kind), 6045f757f3fSDimitry Andric llvm::inconvertibleErrorCode()); 6055f757f3fSDimitry Andric } 6067a6dacacSDimitry Andric llvm_unreachable("Unexpected CTF type kind"); 6075f757f3fSDimitry Andric } 6085f757f3fSDimitry Andric 6095f757f3fSDimitry Andric llvm::Expected<std::unique_ptr<CTFType>> 6105f757f3fSDimitry Andric SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) { 6115f757f3fSDimitry Andric ctf_stype_t ctf_stype; 6125f757f3fSDimitry Andric ctf_stype.name = m_data.GetU32(&offset); 6135f757f3fSDimitry Andric ctf_stype.info = m_data.GetU32(&offset); 6145f757f3fSDimitry Andric ctf_stype.size = m_data.GetU32(&offset); 6155f757f3fSDimitry Andric 6165f757f3fSDimitry Andric llvm::StringRef name = ReadString(ctf_stype.name); 6175f757f3fSDimitry Andric const uint32_t kind = GetKind(ctf_stype.info); 6185f757f3fSDimitry Andric const uint32_t variable_length = GetVLen(ctf_stype.info); 6195f757f3fSDimitry Andric const uint32_t type = ctf_stype.GetType(); 6205f757f3fSDimitry Andric const uint32_t size = ctf_stype.GetSize(); 6215f757f3fSDimitry Andric 62206c3fb27SDimitry Andric switch (kind) { 6235f757f3fSDimitry Andric case TypeKind::eInteger: { 6245f757f3fSDimitry Andric const uint32_t vdata = m_data.GetU32(&offset); 6255f757f3fSDimitry Andric const uint32_t bits = GetBits(vdata); 6265f757f3fSDimitry Andric const uint32_t encoding = GetEncoding(vdata); 6275f757f3fSDimitry Andric return std::make_unique<CTFInteger>(uid, name, bits, encoding); 6285f757f3fSDimitry Andric } 62906c3fb27SDimitry Andric case TypeKind::eConst: 6305f757f3fSDimitry Andric return std::make_unique<CTFConst>(uid, type); 63106c3fb27SDimitry Andric case TypeKind::ePointer: 6325f757f3fSDimitry Andric return std::make_unique<CTFPointer>(uid, type); 63306c3fb27SDimitry Andric case TypeKind::eRestrict: 6345f757f3fSDimitry Andric return std::make_unique<CTFRestrict>(uid, type); 63506c3fb27SDimitry Andric case TypeKind::eVolatile: 6365f757f3fSDimitry Andric return std::make_unique<CTFVolatile>(uid, type); 63706c3fb27SDimitry Andric case TypeKind::eTypedef: 6385f757f3fSDimitry Andric return std::make_unique<CTFTypedef>(uid, name, type); 6395f757f3fSDimitry Andric case TypeKind::eArray: { 6405f757f3fSDimitry Andric const uint32_t type = m_data.GetU32(&offset); 6415f757f3fSDimitry Andric const uint32_t index = m_data.GetU32(&offset); 6425f757f3fSDimitry Andric const uint32_t nelems = m_data.GetU32(&offset); 6435f757f3fSDimitry Andric return std::make_unique<CTFArray>(uid, name, type, index, nelems); 6445f757f3fSDimitry Andric } 6455f757f3fSDimitry Andric case TypeKind::eEnum: { 6465f757f3fSDimitry Andric std::vector<CTFEnum::Value> values; 6475f757f3fSDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) { 6485f757f3fSDimitry Andric const uint32_t value_name = m_data.GetU32(&offset); 6495f757f3fSDimitry Andric const uint32_t value = m_data.GetU32(&offset); 6505f757f3fSDimitry Andric values.emplace_back(ReadString(value_name), value); 6515f757f3fSDimitry Andric } 6525f757f3fSDimitry Andric return std::make_unique<CTFEnum>(uid, name, variable_length, size, values); 6535f757f3fSDimitry Andric } 6545f757f3fSDimitry Andric case TypeKind::eFunction: { 6555f757f3fSDimitry Andric std::vector<uint32_t> args; 6565f757f3fSDimitry Andric bool variadic = false; 6575f757f3fSDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) { 6585f757f3fSDimitry Andric const uint32_t arg_uid = m_data.GetU32(&offset); 6595f757f3fSDimitry Andric // If the last argument is 0, this is a variadic function. 6605f757f3fSDimitry Andric if (arg_uid == 0) { 6615f757f3fSDimitry Andric variadic = true; 6625f757f3fSDimitry Andric break; 6635f757f3fSDimitry Andric } 6645f757f3fSDimitry Andric args.push_back(arg_uid); 6655f757f3fSDimitry Andric } 6665f757f3fSDimitry Andric // If the number of arguments is odd, a single uint32_t of padding is 6675f757f3fSDimitry Andric // inserted to maintain alignment. 6685f757f3fSDimitry Andric if (variable_length % 2 == 1) 6695f757f3fSDimitry Andric m_data.GetU32(&offset); 6705f757f3fSDimitry Andric return std::make_unique<CTFFunction>(uid, name, variable_length, type, args, 6715f757f3fSDimitry Andric variadic); 6725f757f3fSDimitry Andric } 67306c3fb27SDimitry Andric case TypeKind::eStruct: 6745f757f3fSDimitry Andric case TypeKind::eUnion: { 6755f757f3fSDimitry Andric std::vector<CTFRecord::Field> fields; 6765f757f3fSDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) { 6775f757f3fSDimitry Andric const uint32_t field_name = m_data.GetU32(&offset); 6785f757f3fSDimitry Andric const uint32_t type = m_data.GetU32(&offset); 6795f757f3fSDimitry Andric uint64_t field_offset = 0; 6805f757f3fSDimitry Andric if (size < g_ctf_field_threshold) { 6815f757f3fSDimitry Andric field_offset = m_data.GetU16(&offset); 6825f757f3fSDimitry Andric m_data.GetU16(&offset); // Padding 6835f757f3fSDimitry Andric } else { 6845f757f3fSDimitry Andric const uint32_t offset_hi = m_data.GetU32(&offset); 6855f757f3fSDimitry Andric const uint32_t offset_lo = m_data.GetU32(&offset); 6865f757f3fSDimitry Andric field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo); 6875f757f3fSDimitry Andric } 6885f757f3fSDimitry Andric fields.emplace_back(ReadString(field_name), type, field_offset); 6895f757f3fSDimitry Andric } 6905f757f3fSDimitry Andric return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid, 6915f757f3fSDimitry Andric name, variable_length, size, fields); 6925f757f3fSDimitry Andric } 69306c3fb27SDimitry Andric case TypeKind::eForward: 6945f757f3fSDimitry Andric return std::make_unique<CTFForward>(uid, name); 69506c3fb27SDimitry Andric case TypeKind::eUnknown: 6965f757f3fSDimitry Andric return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid, 6975f757f3fSDimitry Andric name); 6985f757f3fSDimitry Andric case TypeKind::eFloat: 6995f757f3fSDimitry Andric case TypeKind::eSlice: 70006c3fb27SDimitry Andric offset += (variable_length * sizeof(uint32_t)); 70106c3fb27SDimitry Andric break; 70206c3fb27SDimitry Andric } 7035f757f3fSDimitry Andric 70406c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 70506c3fb27SDimitry Andric llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})", 70606c3fb27SDimitry Andric name, kind, variable_length), 70706c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 70806c3fb27SDimitry Andric } 70906c3fb27SDimitry Andric 71006c3fb27SDimitry Andric size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { 71106c3fb27SDimitry Andric if (!ParseHeader()) 71206c3fb27SDimitry Andric return 0; 71306c3fb27SDimitry Andric 71406c3fb27SDimitry Andric if (!m_types.empty()) 71506c3fb27SDimitry Andric return 0; 71606c3fb27SDimitry Andric 71706c3fb27SDimitry Andric if (!m_ast) 71806c3fb27SDimitry Andric return 0; 71906c3fb27SDimitry Andric 72006c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 72106c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF types"); 72206c3fb27SDimitry Andric 72306c3fb27SDimitry Andric lldb::offset_t type_offset = m_body_offset + m_header->typeoff; 72406c3fb27SDimitry Andric const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff; 72506c3fb27SDimitry Andric 72606c3fb27SDimitry Andric lldb::user_id_t type_uid = 1; 72706c3fb27SDimitry Andric while (type_offset < type_offset_end) { 7285f757f3fSDimitry Andric llvm::Expected<std::unique_ptr<CTFType>> type_or_error = 7295f757f3fSDimitry Andric ParseType(type_offset, type_uid); 7305f757f3fSDimitry Andric if (type_or_error) { 7315f757f3fSDimitry Andric m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error); 7325f757f3fSDimitry Andric } else { 73306c3fb27SDimitry Andric LLDB_LOG_ERROR(log, type_or_error.takeError(), 73406c3fb27SDimitry Andric "Failed to parse type {1} at offset {2}: {0}", type_uid, 73506c3fb27SDimitry Andric type_offset); 73606c3fb27SDimitry Andric } 7375f757f3fSDimitry Andric type_uid++; 73806c3fb27SDimitry Andric } 73906c3fb27SDimitry Andric 7405f757f3fSDimitry Andric LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size()); 74106c3fb27SDimitry Andric 7425f757f3fSDimitry Andric for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) 7435f757f3fSDimitry Andric ResolveTypeUID(uid); 7445f757f3fSDimitry Andric 7455f757f3fSDimitry Andric LLDB_LOG(log, "Created {0} CTF types", m_types.size()); 74606c3fb27SDimitry Andric 74706c3fb27SDimitry Andric return m_types.size(); 74806c3fb27SDimitry Andric } 74906c3fb27SDimitry Andric 75006c3fb27SDimitry Andric size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { 75106c3fb27SDimitry Andric if (!ParseHeader()) 75206c3fb27SDimitry Andric return 0; 75306c3fb27SDimitry Andric 75406c3fb27SDimitry Andric if (!m_functions.empty()) 75506c3fb27SDimitry Andric return 0; 75606c3fb27SDimitry Andric 75706c3fb27SDimitry Andric if (!m_ast) 75806c3fb27SDimitry Andric return 0; 75906c3fb27SDimitry Andric 76006c3fb27SDimitry Andric Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab(); 76106c3fb27SDimitry Andric if (!symtab) 76206c3fb27SDimitry Andric return 0; 76306c3fb27SDimitry Andric 76406c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 76506c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF functions"); 76606c3fb27SDimitry Andric 76706c3fb27SDimitry Andric lldb::offset_t function_offset = m_body_offset + m_header->funcoff; 76806c3fb27SDimitry Andric const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff; 76906c3fb27SDimitry Andric 77006c3fb27SDimitry Andric uint32_t symbol_idx = 0; 77106c3fb27SDimitry Andric Declaration decl; 77206c3fb27SDimitry Andric while (function_offset < function_offset_end) { 77306c3fb27SDimitry Andric const uint32_t info = m_data.GetU32(&function_offset); 77406c3fb27SDimitry Andric const uint16_t kind = GetKind(info); 77506c3fb27SDimitry Andric const uint16_t variable_length = GetVLen(info); 77606c3fb27SDimitry Andric 77706c3fb27SDimitry Andric Symbol *symbol = symtab->FindSymbolWithType( 77806c3fb27SDimitry Andric eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx); 77906c3fb27SDimitry Andric 78006c3fb27SDimitry Andric // Skip padding. 78106c3fb27SDimitry Andric if (kind == TypeKind::eUnknown && variable_length == 0) 78206c3fb27SDimitry Andric continue; 78306c3fb27SDimitry Andric 78406c3fb27SDimitry Andric // Skip unexpected kinds. 78506c3fb27SDimitry Andric if (kind != TypeKind::eFunction) 78606c3fb27SDimitry Andric continue; 78706c3fb27SDimitry Andric 78806c3fb27SDimitry Andric const uint32_t ret_uid = m_data.GetU32(&function_offset); 78906c3fb27SDimitry Andric const uint32_t num_args = variable_length; 79006c3fb27SDimitry Andric 79106c3fb27SDimitry Andric std::vector<CompilerType> arg_types; 79206c3fb27SDimitry Andric arg_types.reserve(num_args); 79306c3fb27SDimitry Andric 79406c3fb27SDimitry Andric bool is_variadic = false; 79506c3fb27SDimitry Andric for (uint32_t i = 0; i < variable_length; i++) { 79606c3fb27SDimitry Andric const uint32_t arg_uid = m_data.GetU32(&function_offset); 79706c3fb27SDimitry Andric 79806c3fb27SDimitry Andric // If the last argument is 0, this is a variadic function. 79906c3fb27SDimitry Andric if (arg_uid == 0) { 80006c3fb27SDimitry Andric is_variadic = true; 80106c3fb27SDimitry Andric break; 80206c3fb27SDimitry Andric } 80306c3fb27SDimitry Andric 8045f757f3fSDimitry Andric Type *arg_type = ResolveTypeUID(arg_uid); 805*0fca6ea1SDimitry Andric arg_types.push_back(arg_type ? arg_type->GetFullCompilerType() 806*0fca6ea1SDimitry Andric : CompilerType()); 80706c3fb27SDimitry Andric } 80806c3fb27SDimitry Andric 80906c3fb27SDimitry Andric if (symbol) { 8105f757f3fSDimitry Andric Type *ret_type = ResolveTypeUID(ret_uid); 81106c3fb27SDimitry Andric AddressRange func_range = 81206c3fb27SDimitry Andric AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(), 81306c3fb27SDimitry Andric GetObjectFile()->GetModule()->GetSectionList()); 81406c3fb27SDimitry Andric 81506c3fb27SDimitry Andric // Create function type. 81606c3fb27SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType( 817*0fca6ea1SDimitry Andric ret_type ? ret_type->GetFullCompilerType() : CompilerType(), 818*0fca6ea1SDimitry Andric arg_types.data(), arg_types.size(), is_variadic, 0, 819*0fca6ea1SDimitry Andric clang::CallingConv::CC_C); 82006c3fb27SDimitry Andric lldb::user_id_t function_type_uid = m_types.size() + 1; 82106c3fb27SDimitry Andric TypeSP type_sp = 82206c3fb27SDimitry Andric MakeType(function_type_uid, symbol->GetName(), 0, nullptr, 82306c3fb27SDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, 82406c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 8255f757f3fSDimitry Andric m_types[function_type_uid] = type_sp; 82606c3fb27SDimitry Andric 82706c3fb27SDimitry Andric // Create function. 82806c3fb27SDimitry Andric lldb::user_id_t func_uid = m_functions.size(); 82906c3fb27SDimitry Andric FunctionSP function_sp = std::make_shared<Function>( 83006c3fb27SDimitry Andric &cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(), 83106c3fb27SDimitry Andric func_range); 83206c3fb27SDimitry Andric m_functions.emplace_back(function_sp); 83306c3fb27SDimitry Andric cu.AddFunction(function_sp); 83406c3fb27SDimitry Andric } 83506c3fb27SDimitry Andric } 83606c3fb27SDimitry Andric 83706c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size()); 83806c3fb27SDimitry Andric 83906c3fb27SDimitry Andric return m_functions.size(); 84006c3fb27SDimitry Andric } 84106c3fb27SDimitry Andric 84206c3fb27SDimitry Andric static DWARFExpression CreateDWARFExpression(ModuleSP module_sp, 84306c3fb27SDimitry Andric const Symbol &symbol) { 84406c3fb27SDimitry Andric if (!module_sp) 84506c3fb27SDimitry Andric return DWARFExpression(); 84606c3fb27SDimitry Andric 84706c3fb27SDimitry Andric const ArchSpec &architecture = module_sp->GetArchitecture(); 84806c3fb27SDimitry Andric ByteOrder byte_order = architecture.GetByteOrder(); 84906c3fb27SDimitry Andric uint32_t address_size = architecture.GetAddressByteSize(); 85006c3fb27SDimitry Andric uint32_t byte_size = architecture.GetDataByteSize(); 85106c3fb27SDimitry Andric 85206c3fb27SDimitry Andric StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); 85306c3fb27SDimitry Andric stream.PutHex8(lldb_private::dwarf::DW_OP_addr); 85406c3fb27SDimitry Andric stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order); 85506c3fb27SDimitry Andric 85606c3fb27SDimitry Andric DataBufferSP buffer = 85706c3fb27SDimitry Andric std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 85806c3fb27SDimitry Andric lldb_private::DataExtractor extractor(buffer, byte_order, address_size, 85906c3fb27SDimitry Andric byte_size); 86006c3fb27SDimitry Andric DWARFExpression result(extractor); 86106c3fb27SDimitry Andric result.SetRegisterKind(eRegisterKindDWARF); 86206c3fb27SDimitry Andric 86306c3fb27SDimitry Andric return result; 86406c3fb27SDimitry Andric } 86506c3fb27SDimitry Andric 86606c3fb27SDimitry Andric size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) { 86706c3fb27SDimitry Andric if (!ParseHeader()) 86806c3fb27SDimitry Andric return 0; 86906c3fb27SDimitry Andric 87006c3fb27SDimitry Andric if (!m_variables.empty()) 87106c3fb27SDimitry Andric return 0; 87206c3fb27SDimitry Andric 87306c3fb27SDimitry Andric if (!m_ast) 87406c3fb27SDimitry Andric return 0; 87506c3fb27SDimitry Andric 87606c3fb27SDimitry Andric ModuleSP module_sp = GetObjectFile()->GetModule(); 87706c3fb27SDimitry Andric Symtab *symtab = module_sp->GetSymtab(); 87806c3fb27SDimitry Andric if (!symtab) 87906c3fb27SDimitry Andric return 0; 88006c3fb27SDimitry Andric 88106c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 88206c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF objects"); 88306c3fb27SDimitry Andric 88406c3fb27SDimitry Andric lldb::offset_t object_offset = m_body_offset + m_header->objtoff; 88506c3fb27SDimitry Andric const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff; 88606c3fb27SDimitry Andric 88706c3fb27SDimitry Andric uint32_t symbol_idx = 0; 88806c3fb27SDimitry Andric Declaration decl; 88906c3fb27SDimitry Andric while (object_offset < object_offset_end) { 89006c3fb27SDimitry Andric const uint32_t type_uid = m_data.GetU32(&object_offset); 89106c3fb27SDimitry Andric 89206c3fb27SDimitry Andric if (Symbol *symbol = 89306c3fb27SDimitry Andric symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes, 89406c3fb27SDimitry Andric Symtab::eVisibilityAny, symbol_idx)) { 89506c3fb27SDimitry Andric Variable::RangeList ranges; 89606c3fb27SDimitry Andric ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize()); 89706c3fb27SDimitry Andric 89806c3fb27SDimitry Andric auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid); 89906c3fb27SDimitry Andric 90006c3fb27SDimitry Andric DWARFExpressionList location( 90106c3fb27SDimitry Andric module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr); 90206c3fb27SDimitry Andric 90306c3fb27SDimitry Andric lldb::user_id_t variable_type_uid = m_variables.size(); 90406c3fb27SDimitry Andric m_variables.emplace_back(std::make_shared<Variable>( 90506c3fb27SDimitry Andric variable_type_uid, symbol->GetName().AsCString(), 90606c3fb27SDimitry Andric symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal, 90706c3fb27SDimitry Andric m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(), 90806c3fb27SDimitry Andric /*artificial=*/false, 90906c3fb27SDimitry Andric /*location_is_constant_data*/ false)); 91006c3fb27SDimitry Andric } 91106c3fb27SDimitry Andric } 91206c3fb27SDimitry Andric 91306c3fb27SDimitry Andric LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size()); 91406c3fb27SDimitry Andric 91506c3fb27SDimitry Andric return m_variables.size(); 91606c3fb27SDimitry Andric } 91706c3fb27SDimitry Andric 91806c3fb27SDimitry Andric uint32_t SymbolFileCTF::CalculateAbilities() { 91906c3fb27SDimitry Andric if (!m_objfile_sp) 92006c3fb27SDimitry Andric return 0; 92106c3fb27SDimitry Andric 92206c3fb27SDimitry Andric if (!ParseHeader()) 92306c3fb27SDimitry Andric return 0; 92406c3fb27SDimitry Andric 92506c3fb27SDimitry Andric return VariableTypes | Functions | GlobalVariables; 92606c3fb27SDimitry Andric } 92706c3fb27SDimitry Andric 92806c3fb27SDimitry Andric uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr, 92906c3fb27SDimitry Andric SymbolContextItem resolve_scope, 93006c3fb27SDimitry Andric SymbolContext &sc) { 93106c3fb27SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 93206c3fb27SDimitry Andric if (m_objfile_sp->GetSymtab() == nullptr) 93306c3fb27SDimitry Andric return 0; 93406c3fb27SDimitry Andric 93506c3fb27SDimitry Andric uint32_t resolved_flags = 0; 93606c3fb27SDimitry Andric 93706c3fb27SDimitry Andric // Resolve symbols. 93806c3fb27SDimitry Andric if (resolve_scope & eSymbolContextSymbol) { 93906c3fb27SDimitry Andric sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress( 94006c3fb27SDimitry Andric so_addr.GetFileAddress()); 94106c3fb27SDimitry Andric if (sc.symbol) 94206c3fb27SDimitry Andric resolved_flags |= eSymbolContextSymbol; 94306c3fb27SDimitry Andric } 94406c3fb27SDimitry Andric 94506c3fb27SDimitry Andric // Resolve functions. 94606c3fb27SDimitry Andric if (resolve_scope & eSymbolContextFunction) { 94706c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 94806c3fb27SDimitry Andric if (function_sp->GetAddressRange().ContainsFileAddress( 94906c3fb27SDimitry Andric so_addr.GetFileAddress())) { 95006c3fb27SDimitry Andric sc.function = function_sp.get(); 95106c3fb27SDimitry Andric resolved_flags |= eSymbolContextFunction; 95206c3fb27SDimitry Andric break; 95306c3fb27SDimitry Andric } 95406c3fb27SDimitry Andric } 95506c3fb27SDimitry Andric } 95606c3fb27SDimitry Andric 95706c3fb27SDimitry Andric // Resolve variables. 95806c3fb27SDimitry Andric if (resolve_scope & eSymbolContextVariable) { 95906c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 96006c3fb27SDimitry Andric if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) { 96106c3fb27SDimitry Andric sc.variable = variable_sp.get(); 96206c3fb27SDimitry Andric break; 96306c3fb27SDimitry Andric } 96406c3fb27SDimitry Andric } 96506c3fb27SDimitry Andric } 96606c3fb27SDimitry Andric 96706c3fb27SDimitry Andric return resolved_flags; 96806c3fb27SDimitry Andric } 96906c3fb27SDimitry Andric 97006c3fb27SDimitry Andric CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) { 97106c3fb27SDimitry Andric if (idx == 0) 97206c3fb27SDimitry Andric return m_comp_unit_sp; 97306c3fb27SDimitry Andric return {}; 97406c3fb27SDimitry Andric } 97506c3fb27SDimitry Andric 97606c3fb27SDimitry Andric size_t 97706c3fb27SDimitry Andric SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { 97806c3fb27SDimitry Andric return ParseObjects(*m_comp_unit_sp); 97906c3fb27SDimitry Andric } 98006c3fb27SDimitry Andric 98106c3fb27SDimitry Andric void SymbolFileCTF::AddSymbols(Symtab &symtab) { 98206c3fb27SDimitry Andric // CTF does not encode symbols. 98306c3fb27SDimitry Andric // We rely on the existing symbol table to map symbols to type. 98406c3fb27SDimitry Andric } 98506c3fb27SDimitry Andric 98606c3fb27SDimitry Andric lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { 9875f757f3fSDimitry Andric auto type_it = m_types.find(type_uid); 9885f757f3fSDimitry Andric if (type_it != m_types.end()) 9895f757f3fSDimitry Andric return type_it->second.get(); 9905f757f3fSDimitry Andric 9915f757f3fSDimitry Andric auto ctf_type_it = m_ctf_types.find(type_uid); 9925f757f3fSDimitry Andric if (ctf_type_it == m_ctf_types.end()) 9935f757f3fSDimitry Andric return nullptr; 9945f757f3fSDimitry Andric 9955f757f3fSDimitry Andric CTFType *ctf_type = ctf_type_it->second.get(); 9965f757f3fSDimitry Andric assert(ctf_type && "m_ctf_types should only contain valid CTF types"); 9975f757f3fSDimitry Andric 9985f757f3fSDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 9995f757f3fSDimitry Andric 10005f757f3fSDimitry Andric llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type); 10015f757f3fSDimitry Andric if (!type_or_error) { 10025f757f3fSDimitry Andric LLDB_LOG_ERROR(log, type_or_error.takeError(), 10035f757f3fSDimitry Andric "Failed to create type for {1}: {0}", ctf_type->uid); 10045f757f3fSDimitry Andric return {}; 100506c3fb27SDimitry Andric } 100606c3fb27SDimitry Andric 10075f757f3fSDimitry Andric TypeSP type_sp = *type_or_error; 100806c3fb27SDimitry Andric 10095f757f3fSDimitry Andric if (log) { 10105f757f3fSDimitry Andric StreamString ss; 10115f757f3fSDimitry Andric type_sp->Dump(&ss, true); 10125f757f3fSDimitry Andric LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(), 10135f757f3fSDimitry Andric llvm::StringRef(ss.GetString()).rtrim()); 10145f757f3fSDimitry Andric } 101506c3fb27SDimitry Andric 10165f757f3fSDimitry Andric m_types[type_uid] = type_sp; 10175f757f3fSDimitry Andric 10185f757f3fSDimitry Andric // Except for record types which we'll need to complete later, we don't need 10195f757f3fSDimitry Andric // the CTF type anymore. 10205f757f3fSDimitry Andric if (!isa<CTFRecord>(ctf_type)) 10215f757f3fSDimitry Andric m_ctf_types.erase(type_uid); 10225f757f3fSDimitry Andric 10235f757f3fSDimitry Andric return type_sp.get(); 10245f757f3fSDimitry Andric } 10255f757f3fSDimitry Andric 10265f757f3fSDimitry Andric void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match, 10275f757f3fSDimitry Andric lldb_private::TypeResults &results) { 10285f757f3fSDimitry Andric // Make sure we haven't already searched this SymbolFile before. 10295f757f3fSDimitry Andric if (results.AlreadySearched(this)) 10305f757f3fSDimitry Andric return; 10315f757f3fSDimitry Andric 10325f757f3fSDimitry Andric ConstString name = match.GetTypeBasename(); 10335f757f3fSDimitry Andric for (TypeSP type_sp : GetTypeList().Types()) { 103406c3fb27SDimitry Andric if (type_sp && type_sp->GetName() == name) { 10355f757f3fSDimitry Andric results.InsertUnique(type_sp); 10365f757f3fSDimitry Andric if (results.Done(match)) 10375f757f3fSDimitry Andric return; 103806c3fb27SDimitry Andric } 103906c3fb27SDimitry Andric } 104006c3fb27SDimitry Andric } 104106c3fb27SDimitry Andric 104206c3fb27SDimitry Andric void SymbolFileCTF::FindTypesByRegex( 104306c3fb27SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches, 104406c3fb27SDimitry Andric lldb_private::TypeMap &types) { 104506c3fb27SDimitry Andric ParseTypes(*m_comp_unit_sp); 104606c3fb27SDimitry Andric 104706c3fb27SDimitry Andric size_t matches = 0; 10485f757f3fSDimitry Andric for (TypeSP type_sp : GetTypeList().Types()) { 104906c3fb27SDimitry Andric if (matches == max_matches) 105006c3fb27SDimitry Andric break; 105106c3fb27SDimitry Andric if (type_sp && regex.Execute(type_sp->GetName())) 105206c3fb27SDimitry Andric types.Insert(type_sp); 105306c3fb27SDimitry Andric matches++; 105406c3fb27SDimitry Andric } 105506c3fb27SDimitry Andric } 105606c3fb27SDimitry Andric 105706c3fb27SDimitry Andric void SymbolFileCTF::FindFunctions( 105806c3fb27SDimitry Andric const lldb_private::Module::LookupInfo &lookup_info, 105906c3fb27SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx, 106006c3fb27SDimitry Andric bool include_inlines, lldb_private::SymbolContextList &sc_list) { 106106c3fb27SDimitry Andric ParseFunctions(*m_comp_unit_sp); 106206c3fb27SDimitry Andric 106306c3fb27SDimitry Andric ConstString name = lookup_info.GetLookupName(); 106406c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 106506c3fb27SDimitry Andric if (function_sp && function_sp->GetName() == name) { 106606c3fb27SDimitry Andric lldb_private::SymbolContext sc; 106706c3fb27SDimitry Andric sc.comp_unit = m_comp_unit_sp.get(); 106806c3fb27SDimitry Andric sc.function = function_sp.get(); 106906c3fb27SDimitry Andric sc_list.Append(sc); 107006c3fb27SDimitry Andric } 107106c3fb27SDimitry Andric } 107206c3fb27SDimitry Andric } 107306c3fb27SDimitry Andric 107406c3fb27SDimitry Andric void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression ®ex, 107506c3fb27SDimitry Andric bool include_inlines, 107606c3fb27SDimitry Andric lldb_private::SymbolContextList &sc_list) { 107706c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 107806c3fb27SDimitry Andric if (function_sp && regex.Execute(function_sp->GetName())) { 107906c3fb27SDimitry Andric lldb_private::SymbolContext sc; 108006c3fb27SDimitry Andric sc.comp_unit = m_comp_unit_sp.get(); 108106c3fb27SDimitry Andric sc.function = function_sp.get(); 108206c3fb27SDimitry Andric sc_list.Append(sc); 108306c3fb27SDimitry Andric } 108406c3fb27SDimitry Andric } 108506c3fb27SDimitry Andric } 108606c3fb27SDimitry Andric 108706c3fb27SDimitry Andric void SymbolFileCTF::FindGlobalVariables( 108806c3fb27SDimitry Andric lldb_private::ConstString name, 108906c3fb27SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx, 109006c3fb27SDimitry Andric uint32_t max_matches, lldb_private::VariableList &variables) { 109106c3fb27SDimitry Andric ParseObjects(*m_comp_unit_sp); 109206c3fb27SDimitry Andric 109306c3fb27SDimitry Andric size_t matches = 0; 109406c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 109506c3fb27SDimitry Andric if (matches == max_matches) 109606c3fb27SDimitry Andric break; 109706c3fb27SDimitry Andric if (variable_sp && variable_sp->GetName() == name) { 109806c3fb27SDimitry Andric variables.AddVariable(variable_sp); 109906c3fb27SDimitry Andric matches++; 110006c3fb27SDimitry Andric } 110106c3fb27SDimitry Andric } 110206c3fb27SDimitry Andric } 110306c3fb27SDimitry Andric 110406c3fb27SDimitry Andric void SymbolFileCTF::FindGlobalVariables( 110506c3fb27SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches, 110606c3fb27SDimitry Andric lldb_private::VariableList &variables) { 110706c3fb27SDimitry Andric ParseObjects(*m_comp_unit_sp); 110806c3fb27SDimitry Andric 110906c3fb27SDimitry Andric size_t matches = 0; 111006c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 111106c3fb27SDimitry Andric if (matches == max_matches) 111206c3fb27SDimitry Andric break; 111306c3fb27SDimitry Andric if (variable_sp && regex.Execute(variable_sp->GetName())) { 111406c3fb27SDimitry Andric variables.AddVariable(variable_sp); 111506c3fb27SDimitry Andric matches++; 111606c3fb27SDimitry Andric } 111706c3fb27SDimitry Andric } 111806c3fb27SDimitry Andric } 1119