1*06c3fb27SDimitry Andric //===-- SymbolFileCTF.cpp ----------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "SymbolFileCTF.h" 10*06c3fb27SDimitry Andric 11*06c3fb27SDimitry Andric #include "lldb/Core/Module.h" 12*06c3fb27SDimitry Andric #include "lldb/Core/PluginManager.h" 13*06c3fb27SDimitry Andric #include "lldb/Core/StreamBuffer.h" 14*06c3fb27SDimitry Andric #include "lldb/Host/Config.h" 15*06c3fb27SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 16*06c3fb27SDimitry Andric #include "lldb/Symbol/Function.h" 17*06c3fb27SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 18*06c3fb27SDimitry Andric #include "lldb/Symbol/Symbol.h" 19*06c3fb27SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 20*06c3fb27SDimitry Andric #include "lldb/Symbol/Symtab.h" 21*06c3fb27SDimitry Andric #include "lldb/Symbol/TypeList.h" 22*06c3fb27SDimitry Andric #include "lldb/Symbol/TypeMap.h" 23*06c3fb27SDimitry Andric #include "lldb/Symbol/Variable.h" 24*06c3fb27SDimitry Andric #include "lldb/Symbol/VariableList.h" 25*06c3fb27SDimitry Andric #include "lldb/Utility/DataExtractor.h" 26*06c3fb27SDimitry Andric #include "lldb/Utility/LLDBLog.h" 27*06c3fb27SDimitry Andric #include "lldb/Utility/Log.h" 28*06c3fb27SDimitry Andric #include "lldb/Utility/RegularExpression.h" 29*06c3fb27SDimitry Andric #include "lldb/Utility/StreamString.h" 30*06c3fb27SDimitry Andric #include "lldb/Utility/Timer.h" 31*06c3fb27SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 32*06c3fb27SDimitry Andric 33*06c3fb27SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" 34*06c3fb27SDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 35*06c3fb27SDimitry Andric 36*06c3fb27SDimitry Andric #include <memory> 37*06c3fb27SDimitry Andric #include <optional> 38*06c3fb27SDimitry Andric 39*06c3fb27SDimitry Andric #if LLVM_ENABLE_ZLIB 40*06c3fb27SDimitry Andric #include <zlib.h> 41*06c3fb27SDimitry Andric #endif 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric using namespace llvm; 44*06c3fb27SDimitry Andric using namespace lldb; 45*06c3fb27SDimitry Andric using namespace lldb_private; 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric LLDB_PLUGIN_DEFINE(SymbolFileCTF) 48*06c3fb27SDimitry Andric 49*06c3fb27SDimitry Andric char SymbolFileCTF::ID; 50*06c3fb27SDimitry Andric 51*06c3fb27SDimitry Andric SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp) 52*06c3fb27SDimitry Andric : SymbolFileCommon(std::move(objfile_sp)) {} 53*06c3fb27SDimitry Andric 54*06c3fb27SDimitry Andric void SymbolFileCTF::Initialize() { 55*06c3fb27SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 56*06c3fb27SDimitry Andric GetPluginDescriptionStatic(), CreateInstance); 57*06c3fb27SDimitry Andric } 58*06c3fb27SDimitry Andric 59*06c3fb27SDimitry Andric void SymbolFileCTF::Terminate() { 60*06c3fb27SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 61*06c3fb27SDimitry Andric } 62*06c3fb27SDimitry Andric 63*06c3fb27SDimitry Andric llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() { 64*06c3fb27SDimitry Andric return "Compact C Type Format Symbol Reader"; 65*06c3fb27SDimitry Andric } 66*06c3fb27SDimitry Andric 67*06c3fb27SDimitry Andric SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) { 68*06c3fb27SDimitry Andric return new SymbolFileCTF(std::move(objfile_sp)); 69*06c3fb27SDimitry Andric } 70*06c3fb27SDimitry Andric 71*06c3fb27SDimitry Andric bool SymbolFileCTF::ParseHeader() { 72*06c3fb27SDimitry Andric if (m_header) 73*06c3fb27SDimitry Andric return true; 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 76*06c3fb27SDimitry Andric 77*06c3fb27SDimitry Andric ModuleSP module_sp(m_objfile_sp->GetModule()); 78*06c3fb27SDimitry Andric const SectionList *section_list = module_sp->GetSectionList(); 79*06c3fb27SDimitry Andric if (!section_list) 80*06c3fb27SDimitry Andric return false; 81*06c3fb27SDimitry Andric 82*06c3fb27SDimitry Andric SectionSP section_sp( 83*06c3fb27SDimitry Andric section_list->FindSectionByType(lldb::eSectionTypeCTF, true)); 84*06c3fb27SDimitry Andric if (!section_sp) 85*06c3fb27SDimitry Andric return false; 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric m_objfile_sp->ReadSectionData(section_sp.get(), m_data); 88*06c3fb27SDimitry Andric 89*06c3fb27SDimitry Andric if (m_data.GetByteSize() == 0) 90*06c3fb27SDimitry Andric return false; 91*06c3fb27SDimitry Andric 92*06c3fb27SDimitry Andric StreamString module_desc; 93*06c3fb27SDimitry Andric GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(), 94*06c3fb27SDimitry Andric lldb::eDescriptionLevelBrief); 95*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData()); 96*06c3fb27SDimitry Andric 97*06c3fb27SDimitry Andric lldb::offset_t offset = 0; 98*06c3fb27SDimitry Andric 99*06c3fb27SDimitry Andric // Parse CTF header. 100*06c3fb27SDimitry Andric constexpr size_t ctf_header_size = sizeof(ctf_header_t); 101*06c3fb27SDimitry Andric if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) { 102*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header"); 103*06c3fb27SDimitry Andric return false; 104*06c3fb27SDimitry Andric } 105*06c3fb27SDimitry Andric 106*06c3fb27SDimitry Andric m_header.emplace(); 107*06c3fb27SDimitry Andric 108*06c3fb27SDimitry Andric ctf_header_t &ctf_header = *m_header; 109*06c3fb27SDimitry Andric ctf_header.preamble.magic = m_data.GetU16(&offset); 110*06c3fb27SDimitry Andric ctf_header.preamble.version = m_data.GetU8(&offset); 111*06c3fb27SDimitry Andric ctf_header.preamble.flags = m_data.GetU8(&offset); 112*06c3fb27SDimitry Andric ctf_header.parlabel = m_data.GetU32(&offset); 113*06c3fb27SDimitry Andric ctf_header.parname = m_data.GetU32(&offset); 114*06c3fb27SDimitry Andric ctf_header.lbloff = m_data.GetU32(&offset); 115*06c3fb27SDimitry Andric ctf_header.objtoff = m_data.GetU32(&offset); 116*06c3fb27SDimitry Andric ctf_header.funcoff = m_data.GetU32(&offset); 117*06c3fb27SDimitry Andric ctf_header.typeoff = m_data.GetU32(&offset); 118*06c3fb27SDimitry Andric ctf_header.stroff = m_data.GetU32(&offset); 119*06c3fb27SDimitry Andric ctf_header.strlen = m_data.GetU32(&offset); 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric // Validate the preamble. 122*06c3fb27SDimitry Andric if (ctf_header.preamble.magic != g_ctf_magic) { 123*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}", 124*06c3fb27SDimitry Andric ctf_header.preamble.magic); 125*06c3fb27SDimitry Andric return false; 126*06c3fb27SDimitry Andric } 127*06c3fb27SDimitry Andric 128*06c3fb27SDimitry Andric if (ctf_header.preamble.version != g_ctf_version) { 129*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}", 130*06c3fb27SDimitry Andric ctf_header.preamble.version); 131*06c3fb27SDimitry Andric return false; 132*06c3fb27SDimitry Andric } 133*06c3fb27SDimitry Andric 134*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}", 135*06c3fb27SDimitry Andric ctf_header.preamble.version, ctf_header.preamble.flags); 136*06c3fb27SDimitry Andric 137*06c3fb27SDimitry Andric m_body_offset = offset; 138*06c3fb27SDimitry Andric 139*06c3fb27SDimitry Andric if (ctf_header.preamble.flags & eFlagCompress) { 140*06c3fb27SDimitry Andric // The body has been compressed with zlib deflate. Header offsets point into 141*06c3fb27SDimitry Andric // the decompressed data. 142*06c3fb27SDimitry Andric #if LLVM_ENABLE_ZLIB 143*06c3fb27SDimitry Andric const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen; 144*06c3fb27SDimitry Andric DataBufferSP decompressed_data = 145*06c3fb27SDimitry Andric std::make_shared<DataBufferHeap>(decompressed_size, 0x0); 146*06c3fb27SDimitry Andric 147*06c3fb27SDimitry Andric z_stream zstr; 148*06c3fb27SDimitry Andric memset(&zstr, 0, sizeof(zstr)); 149*06c3fb27SDimitry Andric zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() + 150*06c3fb27SDimitry Andric sizeof(ctf_header_t)); 151*06c3fb27SDimitry Andric zstr.avail_in = m_data.BytesLeft(offset); 152*06c3fb27SDimitry Andric zstr.next_out = 153*06c3fb27SDimitry Andric (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes()); 154*06c3fb27SDimitry Andric zstr.avail_out = decompressed_size; 155*06c3fb27SDimitry Andric 156*06c3fb27SDimitry Andric int rc = inflateInit(&zstr); 157*06c3fb27SDimitry Andric if (rc != Z_OK) { 158*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}", 159*06c3fb27SDimitry Andric zError(rc)); 160*06c3fb27SDimitry Andric return false; 161*06c3fb27SDimitry Andric } 162*06c3fb27SDimitry Andric 163*06c3fb27SDimitry Andric rc = inflate(&zstr, Z_FINISH); 164*06c3fb27SDimitry Andric if (rc != Z_STREAM_END) { 165*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc)); 166*06c3fb27SDimitry Andric return false; 167*06c3fb27SDimitry Andric } 168*06c3fb27SDimitry Andric 169*06c3fb27SDimitry Andric rc = inflateEnd(&zstr); 170*06c3fb27SDimitry Andric if (rc != Z_OK) { 171*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc)); 172*06c3fb27SDimitry Andric return false; 173*06c3fb27SDimitry Andric } 174*06c3fb27SDimitry Andric 175*06c3fb27SDimitry Andric if (zstr.total_out != decompressed_size) { 176*06c3fb27SDimitry Andric LLDB_LOG(log, 177*06c3fb27SDimitry Andric "CTF parsing failed: decompressed size ({0}) doesn't match " 178*06c3fb27SDimitry Andric "expected size ([1})", 179*06c3fb27SDimitry Andric zstr.total_out, decompressed_size); 180*06c3fb27SDimitry Andric return false; 181*06c3fb27SDimitry Andric } 182*06c3fb27SDimitry Andric 183*06c3fb27SDimitry Andric m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(), 184*06c3fb27SDimitry Andric m_data.GetAddressByteSize()); 185*06c3fb27SDimitry Andric m_body_offset = 0; 186*06c3fb27SDimitry Andric #else 187*06c3fb27SDimitry Andric LLDB_LOG( 188*06c3fb27SDimitry Andric log, 189*06c3fb27SDimitry Andric "CTF parsing failed: data is compressed but no zlib inflate support"); 190*06c3fb27SDimitry Andric return false; 191*06c3fb27SDimitry Andric #endif 192*06c3fb27SDimitry Andric } 193*06c3fb27SDimitry Andric 194*06c3fb27SDimitry Andric // Validate the header. 195*06c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) { 196*06c3fb27SDimitry Andric LLDB_LOG(log, 197*06c3fb27SDimitry Andric "CTF parsing failed: invalid label section offset in header: {0}", 198*06c3fb27SDimitry Andric ctf_header.lbloff); 199*06c3fb27SDimitry Andric return false; 200*06c3fb27SDimitry Andric } 201*06c3fb27SDimitry Andric 202*06c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) { 203*06c3fb27SDimitry Andric LLDB_LOG(log, 204*06c3fb27SDimitry Andric "CTF parsing failed: invalid object section offset in header: {0}", 205*06c3fb27SDimitry Andric ctf_header.objtoff); 206*06c3fb27SDimitry Andric return false; 207*06c3fb27SDimitry Andric } 208*06c3fb27SDimitry Andric 209*06c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) { 210*06c3fb27SDimitry Andric LLDB_LOG( 211*06c3fb27SDimitry Andric log, 212*06c3fb27SDimitry Andric "CTF parsing failed: invalid function section offset in header: {0}", 213*06c3fb27SDimitry Andric ctf_header.funcoff); 214*06c3fb27SDimitry Andric return false; 215*06c3fb27SDimitry Andric } 216*06c3fb27SDimitry Andric 217*06c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) { 218*06c3fb27SDimitry Andric LLDB_LOG(log, 219*06c3fb27SDimitry Andric "CTF parsing failed: invalid type section offset in header: {0}", 220*06c3fb27SDimitry Andric ctf_header.typeoff); 221*06c3fb27SDimitry Andric return false; 222*06c3fb27SDimitry Andric } 223*06c3fb27SDimitry Andric 224*06c3fb27SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) { 225*06c3fb27SDimitry Andric LLDB_LOG(log, 226*06c3fb27SDimitry Andric "CTF parsing failed: invalid string section offset in header: {0}", 227*06c3fb27SDimitry Andric ctf_header.stroff); 228*06c3fb27SDimitry Andric return false; 229*06c3fb27SDimitry Andric } 230*06c3fb27SDimitry Andric 231*06c3fb27SDimitry Andric const lldb::offset_t str_end_offset = 232*06c3fb27SDimitry Andric m_body_offset + ctf_header.stroff + ctf_header.strlen; 233*06c3fb27SDimitry Andric if (!m_data.ValidOffset(str_end_offset - 1)) { 234*06c3fb27SDimitry Andric LLDB_LOG(log, 235*06c3fb27SDimitry Andric "CTF parsing failed: invalid string section length in header: {0}", 236*06c3fb27SDimitry Andric ctf_header.strlen); 237*06c3fb27SDimitry Andric return false; 238*06c3fb27SDimitry Andric } 239*06c3fb27SDimitry Andric 240*06c3fb27SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parlabel > 241*06c3fb27SDimitry Andric str_end_offset) { 242*06c3fb27SDimitry Andric LLDB_LOG(log, 243*06c3fb27SDimitry Andric "CTF parsing failed: invalid parent label offset: {0} exceeds end " 244*06c3fb27SDimitry Andric "of string section ({1})", 245*06c3fb27SDimitry Andric ctf_header.parlabel, str_end_offset); 246*06c3fb27SDimitry Andric return false; 247*06c3fb27SDimitry Andric } 248*06c3fb27SDimitry Andric 249*06c3fb27SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) { 250*06c3fb27SDimitry Andric LLDB_LOG(log, 251*06c3fb27SDimitry Andric "CTF parsing failed: invalid parent name offset: {0} exceeds end " 252*06c3fb27SDimitry Andric "of string section ({1})", 253*06c3fb27SDimitry Andric ctf_header.parname, str_end_offset); 254*06c3fb27SDimitry Andric return false; 255*06c3fb27SDimitry Andric } 256*06c3fb27SDimitry Andric 257*06c3fb27SDimitry Andric LLDB_LOG(log, 258*06c3fb27SDimitry Andric "Parsed valid CTF header: lbloff = {0}, objtoff = {1}, funcoff = " 259*06c3fb27SDimitry Andric "{2}, typeoff = {3}, stroff = {4}, strlen = {5}", 260*06c3fb27SDimitry Andric ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff, 261*06c3fb27SDimitry Andric ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen); 262*06c3fb27SDimitry Andric 263*06c3fb27SDimitry Andric return true; 264*06c3fb27SDimitry Andric } 265*06c3fb27SDimitry Andric 266*06c3fb27SDimitry Andric void SymbolFileCTF::InitializeObject() { 267*06c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 268*06c3fb27SDimitry Andric 269*06c3fb27SDimitry Andric auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC); 270*06c3fb27SDimitry Andric if (auto err = type_system_or_err.takeError()) { 271*06c3fb27SDimitry Andric LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}"); 272*06c3fb27SDimitry Andric return; 273*06c3fb27SDimitry Andric } 274*06c3fb27SDimitry Andric 275*06c3fb27SDimitry Andric auto ts = *type_system_or_err; 276*06c3fb27SDimitry Andric m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 277*06c3fb27SDimitry Andric LazyBool optimized = eLazyBoolNo; 278*06c3fb27SDimitry Andric m_comp_unit_sp = std::make_shared<CompileUnit>( 279*06c3fb27SDimitry Andric m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized); 280*06c3fb27SDimitry Andric 281*06c3fb27SDimitry Andric ParseTypes(*m_comp_unit_sp); 282*06c3fb27SDimitry Andric } 283*06c3fb27SDimitry Andric 284*06c3fb27SDimitry Andric llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const { 285*06c3fb27SDimitry Andric lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset; 286*06c3fb27SDimitry Andric if (!m_data.ValidOffset(offset)) 287*06c3fb27SDimitry Andric return "(invalid)"; 288*06c3fb27SDimitry Andric const char *str = m_data.GetCStr(&offset); 289*06c3fb27SDimitry Andric if (str && !*str) 290*06c3fb27SDimitry Andric return "(anon)"; 291*06c3fb27SDimitry Andric return llvm::StringRef(str); 292*06c3fb27SDimitry Andric } 293*06c3fb27SDimitry Andric 294*06c3fb27SDimitry Andric /// Return the integer display representation encoded in the given data. 295*06c3fb27SDimitry Andric static uint32_t GetEncoding(uint32_t data) { 296*06c3fb27SDimitry Andric // Mask bits 24–31. 297*06c3fb27SDimitry Andric return ((data)&0xff000000) >> 24; 298*06c3fb27SDimitry Andric } 299*06c3fb27SDimitry Andric 300*06c3fb27SDimitry Andric /// Return the integral width in bits encoded in the given data. 301*06c3fb27SDimitry Andric static uint32_t GetBits(uint32_t data) { 302*06c3fb27SDimitry Andric // Mask bits 0-15. 303*06c3fb27SDimitry Andric return (data)&0x0000ffff; 304*06c3fb27SDimitry Andric } 305*06c3fb27SDimitry Andric 306*06c3fb27SDimitry Andric /// Return the type kind encoded in the given data. 307*06c3fb27SDimitry Andric uint32_t GetKind(uint32_t data) { 308*06c3fb27SDimitry Andric // Mask bits 26–31. 309*06c3fb27SDimitry Andric return ((data)&0xf800) >> 11; 310*06c3fb27SDimitry Andric } 311*06c3fb27SDimitry Andric 312*06c3fb27SDimitry Andric /// Return the variable length encoded in the given data. 313*06c3fb27SDimitry Andric uint32_t GetVLen(uint32_t data) { 314*06c3fb27SDimitry Andric // Mask bits 0–24. 315*06c3fb27SDimitry Andric return (data)&0x3ff; 316*06c3fb27SDimitry Andric } 317*06c3fb27SDimitry Andric 318*06c3fb27SDimitry Andric static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); } 319*06c3fb27SDimitry Andric 320*06c3fb27SDimitry Andric static clang::TagTypeKind TranslateRecordKind(SymbolFileCTF::TypeKind type) { 321*06c3fb27SDimitry Andric switch (type) { 322*06c3fb27SDimitry Andric case SymbolFileCTF::TypeKind::eStruct: 323*06c3fb27SDimitry Andric return clang::TTK_Struct; 324*06c3fb27SDimitry Andric case SymbolFileCTF::TypeKind::eUnion: 325*06c3fb27SDimitry Andric return clang::TTK_Union; 326*06c3fb27SDimitry Andric default: 327*06c3fb27SDimitry Andric lldbassert(false && "Invalid record kind!"); 328*06c3fb27SDimitry Andric return clang::TTK_Struct; 329*06c3fb27SDimitry Andric } 330*06c3fb27SDimitry Andric } 331*06c3fb27SDimitry Andric 332*06c3fb27SDimitry Andric llvm::Expected<TypeSP> SymbolFileCTF::ParseInteger(lldb::offset_t &offset, 333*06c3fb27SDimitry Andric lldb::user_id_t uid, 334*06c3fb27SDimitry Andric llvm::StringRef name) { 335*06c3fb27SDimitry Andric const uint32_t vdata = m_data.GetU32(&offset); 336*06c3fb27SDimitry Andric const uint32_t bits = GetBits(vdata); 337*06c3fb27SDimitry Andric const uint32_t encoding = GetEncoding(vdata); 338*06c3fb27SDimitry Andric 339*06c3fb27SDimitry Andric lldb::BasicType basic_type = TypeSystemClang::GetBasicTypeEnumeration(name); 340*06c3fb27SDimitry Andric if (basic_type == eBasicTypeInvalid) 341*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 342*06c3fb27SDimitry Andric llvm::formatv("unsupported integer type: no corresponding basic clang " 343*06c3fb27SDimitry Andric "type for '{0}'", 344*06c3fb27SDimitry Andric name), 345*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 346*06c3fb27SDimitry Andric 347*06c3fb27SDimitry Andric CompilerType compiler_type = m_ast->GetBasicType(basic_type); 348*06c3fb27SDimitry Andric 349*06c3fb27SDimitry Andric if (basic_type != eBasicTypeVoid) { 350*06c3fb27SDimitry Andric // Make sure the type we got is an integer type. 351*06c3fb27SDimitry Andric bool compiler_type_is_signed = false; 352*06c3fb27SDimitry Andric if (!compiler_type.IsIntegerType(compiler_type_is_signed)) 353*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 354*06c3fb27SDimitry Andric llvm::formatv( 355*06c3fb27SDimitry Andric "Found compiler type for '{0}' but it's not an integer type: {1}", 356*06c3fb27SDimitry Andric name, compiler_type.GetDisplayTypeName().GetStringRef()), 357*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 358*06c3fb27SDimitry Andric 359*06c3fb27SDimitry Andric // Make sure the signing matches between the CTF and the compiler type. 360*06c3fb27SDimitry Andric const bool type_is_signed = (encoding & IntEncoding::eSigned); 361*06c3fb27SDimitry Andric if (compiler_type_is_signed != type_is_signed) 362*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 363*06c3fb27SDimitry Andric llvm::formatv("Found integer compiler type for {0} but compiler type " 364*06c3fb27SDimitry Andric "is {1} and {0} is {2}", 365*06c3fb27SDimitry Andric name, compiler_type_is_signed ? "signed" : "unsigned", 366*06c3fb27SDimitry Andric type_is_signed ? "signed" : "unsigned"), 367*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 368*06c3fb27SDimitry Andric } 369*06c3fb27SDimitry Andric 370*06c3fb27SDimitry Andric Declaration decl; 371*06c3fb27SDimitry Andric return MakeType(uid, ConstString(name), GetBytes(bits), nullptr, 372*06c3fb27SDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 373*06c3fb27SDimitry Andric compiler_type, lldb_private::Type::ResolveState::Full); 374*06c3fb27SDimitry Andric } 375*06c3fb27SDimitry Andric 376*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 377*06c3fb27SDimitry Andric SymbolFileCTF::ParseModifierType(lldb::offset_t &offset, lldb::user_id_t uid, 378*06c3fb27SDimitry Andric uint32_t kind, uint32_t type) { 379*06c3fb27SDimitry Andric TypeSP ref_type = GetTypeForUID(type); 380*06c3fb27SDimitry Andric if (!ref_type) 381*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 382*06c3fb27SDimitry Andric llvm::formatv("Could not find modified type: {0}", type), 383*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 384*06c3fb27SDimitry Andric 385*06c3fb27SDimitry Andric CompilerType compiler_type; 386*06c3fb27SDimitry Andric 387*06c3fb27SDimitry Andric switch (kind) { 388*06c3fb27SDimitry Andric case TypeKind::ePointer: 389*06c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().GetPointerType(); 390*06c3fb27SDimitry Andric break; 391*06c3fb27SDimitry Andric case TypeKind::eConst: 392*06c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddConstModifier(); 393*06c3fb27SDimitry Andric break; 394*06c3fb27SDimitry Andric case TypeKind::eVolatile: 395*06c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier(); 396*06c3fb27SDimitry Andric break; 397*06c3fb27SDimitry Andric case TypeKind::eRestrict: 398*06c3fb27SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier(); 399*06c3fb27SDimitry Andric break; 400*06c3fb27SDimitry Andric default: 401*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 402*06c3fb27SDimitry Andric llvm::formatv("ParseModifierType called with unsupported kind: {0}", 403*06c3fb27SDimitry Andric kind), 404*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 405*06c3fb27SDimitry Andric } 406*06c3fb27SDimitry Andric 407*06c3fb27SDimitry Andric Declaration decl; 408*06c3fb27SDimitry Andric return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, 409*06c3fb27SDimitry Andric Type::eEncodingIsUID, decl, compiler_type, 410*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 411*06c3fb27SDimitry Andric } 412*06c3fb27SDimitry Andric 413*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseTypedef(lldb::offset_t &offset, 414*06c3fb27SDimitry Andric lldb::user_id_t uid, 415*06c3fb27SDimitry Andric llvm::StringRef name, 416*06c3fb27SDimitry Andric uint32_t type) { 417*06c3fb27SDimitry Andric TypeSP underlying_type = GetTypeForUID(type); 418*06c3fb27SDimitry Andric if (!underlying_type) 419*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 420*06c3fb27SDimitry Andric llvm::formatv("Could not find typedef underlying type: {0}", type), 421*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 422*06c3fb27SDimitry Andric 423*06c3fb27SDimitry Andric CompilerType target_ast_type = underlying_type->GetFullCompilerType(); 424*06c3fb27SDimitry Andric clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl(); 425*06c3fb27SDimitry Andric CompilerType ast_typedef = target_ast_type.CreateTypedef( 426*06c3fb27SDimitry Andric name.data(), m_ast->CreateDeclContext(decl_ctx), 0); 427*06c3fb27SDimitry Andric 428*06c3fb27SDimitry Andric Declaration decl; 429*06c3fb27SDimitry Andric return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, 430*06c3fb27SDimitry Andric lldb_private::Type::eEncodingIsUID, decl, ast_typedef, 431*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 432*06c3fb27SDimitry Andric } 433*06c3fb27SDimitry Andric 434*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseArray(lldb::offset_t &offset, 435*06c3fb27SDimitry Andric lldb::user_id_t uid, 436*06c3fb27SDimitry Andric llvm::StringRef name) { 437*06c3fb27SDimitry Andric ctf_array_t ctf_array; 438*06c3fb27SDimitry Andric ctf_array.contents = m_data.GetU32(&offset); 439*06c3fb27SDimitry Andric ctf_array.index = m_data.GetU32(&offset); 440*06c3fb27SDimitry Andric ctf_array.nelems = m_data.GetU32(&offset); 441*06c3fb27SDimitry Andric 442*06c3fb27SDimitry Andric TypeSP element_type = GetTypeForUID(ctf_array.contents); 443*06c3fb27SDimitry Andric if (!element_type) 444*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 445*06c3fb27SDimitry Andric llvm::formatv("Could not find array element type: {0}", 446*06c3fb27SDimitry Andric ctf_array.contents), 447*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 448*06c3fb27SDimitry Andric 449*06c3fb27SDimitry Andric std::optional<uint64_t> element_size = element_type->GetByteSize(nullptr); 450*06c3fb27SDimitry Andric if (!element_size) 451*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 452*06c3fb27SDimitry Andric llvm::formatv("could not get element size of type: {0}", 453*06c3fb27SDimitry Andric ctf_array.contents), 454*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 455*06c3fb27SDimitry Andric 456*06c3fb27SDimitry Andric uint64_t size = ctf_array.nelems * *element_size; 457*06c3fb27SDimitry Andric 458*06c3fb27SDimitry Andric CompilerType compiler_type = m_ast->CreateArrayType( 459*06c3fb27SDimitry Andric element_type->GetFullCompilerType(), ctf_array.nelems, 460*06c3fb27SDimitry Andric /*is_gnu_vector*/ false); 461*06c3fb27SDimitry Andric 462*06c3fb27SDimitry Andric Declaration decl; 463*06c3fb27SDimitry Andric return MakeType(uid, ConstString(), size, nullptr, LLDB_INVALID_UID, 464*06c3fb27SDimitry Andric Type::eEncodingIsUID, decl, compiler_type, 465*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 466*06c3fb27SDimitry Andric } 467*06c3fb27SDimitry Andric 468*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> SymbolFileCTF::ParseEnum(lldb::offset_t &offset, 469*06c3fb27SDimitry Andric lldb::user_id_t uid, 470*06c3fb27SDimitry Andric llvm::StringRef name, 471*06c3fb27SDimitry Andric uint32_t elements, 472*06c3fb27SDimitry Andric uint32_t size) { 473*06c3fb27SDimitry Andric Declaration decl; 474*06c3fb27SDimitry Andric CompilerType enum_type = m_ast->CreateEnumerationType( 475*06c3fb27SDimitry Andric name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl, 476*06c3fb27SDimitry Andric m_ast->GetBasicType(eBasicTypeInt), 477*06c3fb27SDimitry Andric /*is_scoped=*/false); 478*06c3fb27SDimitry Andric 479*06c3fb27SDimitry Andric for (uint32_t i = 0; i < elements; ++i) { 480*06c3fb27SDimitry Andric ctf_enum_t ctf_enum; 481*06c3fb27SDimitry Andric ctf_enum.name = m_data.GetU32(&offset); 482*06c3fb27SDimitry Andric ctf_enum.value = m_data.GetU32(&offset); 483*06c3fb27SDimitry Andric 484*06c3fb27SDimitry Andric llvm::StringRef value_name = ReadString(ctf_enum.name); 485*06c3fb27SDimitry Andric const uint32_t value = ctf_enum.value; 486*06c3fb27SDimitry Andric 487*06c3fb27SDimitry Andric Declaration value_decl; 488*06c3fb27SDimitry Andric m_ast->AddEnumerationValueToEnumerationType(enum_type, value_decl, 489*06c3fb27SDimitry Andric value_name.data(), value, size); 490*06c3fb27SDimitry Andric } 491*06c3fb27SDimitry Andric 492*06c3fb27SDimitry Andric return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, 493*06c3fb27SDimitry Andric Type::eEncodingIsUID, decl, enum_type, 494*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 495*06c3fb27SDimitry Andric } 496*06c3fb27SDimitry Andric 497*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 498*06c3fb27SDimitry Andric SymbolFileCTF::ParseFunction(lldb::offset_t &offset, lldb::user_id_t uid, 499*06c3fb27SDimitry Andric llvm::StringRef name, uint32_t num_args, 500*06c3fb27SDimitry Andric uint32_t type) { 501*06c3fb27SDimitry Andric std::vector<CompilerType> arg_types; 502*06c3fb27SDimitry Andric arg_types.reserve(num_args); 503*06c3fb27SDimitry Andric 504*06c3fb27SDimitry Andric bool is_variadic = false; 505*06c3fb27SDimitry Andric for (uint32_t i = 0; i < num_args; ++i) { 506*06c3fb27SDimitry Andric const uint32_t arg_uid = m_data.GetU32(&offset); 507*06c3fb27SDimitry Andric 508*06c3fb27SDimitry Andric // If the last argument is 0, this is a variadic function. 509*06c3fb27SDimitry Andric if (arg_uid == 0) { 510*06c3fb27SDimitry Andric is_variadic = true; 511*06c3fb27SDimitry Andric break; 512*06c3fb27SDimitry Andric } 513*06c3fb27SDimitry Andric 514*06c3fb27SDimitry Andric if (TypeSP arg_type = GetTypeForUID(arg_uid)) 515*06c3fb27SDimitry Andric arg_types.push_back(arg_type->GetFullCompilerType()); 516*06c3fb27SDimitry Andric } 517*06c3fb27SDimitry Andric 518*06c3fb27SDimitry Andric // If the number of arguments is odd, a single uint32_t of padding is inserted 519*06c3fb27SDimitry Andric // to maintain alignment. 520*06c3fb27SDimitry Andric if (num_args % 2 == 1) 521*06c3fb27SDimitry Andric m_data.GetU32(&offset); 522*06c3fb27SDimitry Andric 523*06c3fb27SDimitry Andric TypeSP ret_type = GetTypeForUID(type); 524*06c3fb27SDimitry Andric if (!ret_type) 525*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 526*06c3fb27SDimitry Andric llvm::formatv("Could not find function return type: {0}", type), 527*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 528*06c3fb27SDimitry Andric 529*06c3fb27SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType( 530*06c3fb27SDimitry Andric ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), 531*06c3fb27SDimitry Andric is_variadic, 0, clang::CallingConv::CC_C); 532*06c3fb27SDimitry Andric 533*06c3fb27SDimitry Andric Declaration decl; 534*06c3fb27SDimitry Andric return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, 535*06c3fb27SDimitry Andric Type::eEncodingIsUID, decl, func_type, 536*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 537*06c3fb27SDimitry Andric } 538*06c3fb27SDimitry Andric 539*06c3fb27SDimitry Andric llvm::Expected<lldb::TypeSP> 540*06c3fb27SDimitry Andric SymbolFileCTF::ParseRecord(lldb::offset_t &offset, lldb::user_id_t uid, 541*06c3fb27SDimitry Andric llvm::StringRef name, uint32_t kind, uint32_t fields, 542*06c3fb27SDimitry Andric uint32_t size) { 543*06c3fb27SDimitry Andric const clang::TagTypeKind tag_kind = 544*06c3fb27SDimitry Andric TranslateRecordKind(static_cast<TypeKind>(kind)); 545*06c3fb27SDimitry Andric 546*06c3fb27SDimitry Andric CompilerType union_type = 547*06c3fb27SDimitry Andric m_ast->CreateRecordType(nullptr, OptionalClangModuleID(), eAccessPublic, 548*06c3fb27SDimitry Andric name.data(), tag_kind, eLanguageTypeC); 549*06c3fb27SDimitry Andric 550*06c3fb27SDimitry Andric m_ast->StartTagDeclarationDefinition(union_type); 551*06c3fb27SDimitry Andric for (uint32_t i = 0; i < fields; ++i) { 552*06c3fb27SDimitry Andric ctf_member_t ctf_member; 553*06c3fb27SDimitry Andric ctf_member.name = m_data.GetU32(&offset); 554*06c3fb27SDimitry Andric ctf_member.type = m_data.GetU32(&offset); 555*06c3fb27SDimitry Andric ctf_member.offset = m_data.GetU16(&offset); 556*06c3fb27SDimitry Andric ctf_member.padding = m_data.GetU16(&offset); 557*06c3fb27SDimitry Andric 558*06c3fb27SDimitry Andric llvm::StringRef member_name = ReadString(ctf_member.name); 559*06c3fb27SDimitry Andric const uint32_t member_type_uid = ctf_member.type; 560*06c3fb27SDimitry Andric 561*06c3fb27SDimitry Andric if (TypeSP member_type = GetTypeForUID(member_type_uid)) { 562*06c3fb27SDimitry Andric const uint32_t member_size = 563*06c3fb27SDimitry Andric member_type->GetByteSize(nullptr).value_or(0); 564*06c3fb27SDimitry Andric TypeSystemClang::AddFieldToRecordType(union_type, member_name, 565*06c3fb27SDimitry Andric member_type->GetFullCompilerType(), 566*06c3fb27SDimitry Andric eAccessPublic, member_size); 567*06c3fb27SDimitry Andric } 568*06c3fb27SDimitry Andric } 569*06c3fb27SDimitry Andric m_ast->CompleteTagDeclarationDefinition(union_type); 570*06c3fb27SDimitry Andric 571*06c3fb27SDimitry Andric Declaration decl; 572*06c3fb27SDimitry Andric return MakeType(uid, ConstString(name), size, nullptr, LLDB_INVALID_UID, 573*06c3fb27SDimitry Andric lldb_private::Type::eEncodingIsUID, decl, union_type, 574*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 575*06c3fb27SDimitry Andric } 576*06c3fb27SDimitry Andric 577*06c3fb27SDimitry Andric llvm::Expected<TypeSP> SymbolFileCTF::ParseType( 578*06c3fb27SDimitry Andric lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name, 579*06c3fb27SDimitry Andric uint32_t kind, uint32_t variable_length, uint32_t type, uint32_t size) { 580*06c3fb27SDimitry Andric switch (kind) { 581*06c3fb27SDimitry Andric case TypeKind::eInteger: 582*06c3fb27SDimitry Andric return ParseInteger(offset, uid, name); 583*06c3fb27SDimitry Andric case TypeKind::eConst: 584*06c3fb27SDimitry Andric case TypeKind::ePointer: 585*06c3fb27SDimitry Andric case TypeKind::eRestrict: 586*06c3fb27SDimitry Andric case TypeKind::eVolatile: 587*06c3fb27SDimitry Andric return ParseModifierType(offset, uid, kind, type); 588*06c3fb27SDimitry Andric case TypeKind::eTypedef: 589*06c3fb27SDimitry Andric return ParseTypedef(offset, uid, name, type); 590*06c3fb27SDimitry Andric case TypeKind::eArray: 591*06c3fb27SDimitry Andric return ParseArray(offset, uid, name); 592*06c3fb27SDimitry Andric case TypeKind::eEnum: 593*06c3fb27SDimitry Andric return ParseEnum(offset, uid, name, variable_length, size); 594*06c3fb27SDimitry Andric case TypeKind::eFunction: 595*06c3fb27SDimitry Andric return ParseFunction(offset, uid, name, variable_length, size); 596*06c3fb27SDimitry Andric case TypeKind::eStruct: 597*06c3fb27SDimitry Andric case TypeKind::eUnion: 598*06c3fb27SDimitry Andric return ParseRecord(offset, uid, name, kind, variable_length, size); 599*06c3fb27SDimitry Andric case TypeKind::eFloat: 600*06c3fb27SDimitry Andric case TypeKind::eForward: 601*06c3fb27SDimitry Andric case TypeKind::eSlice: 602*06c3fb27SDimitry Andric case TypeKind::eUnknown: 603*06c3fb27SDimitry Andric offset += (variable_length * sizeof(uint32_t)); 604*06c3fb27SDimitry Andric break; 605*06c3fb27SDimitry Andric } 606*06c3fb27SDimitry Andric return llvm::make_error<llvm::StringError>( 607*06c3fb27SDimitry Andric llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})", 608*06c3fb27SDimitry Andric name, kind, variable_length), 609*06c3fb27SDimitry Andric llvm::inconvertibleErrorCode()); 610*06c3fb27SDimitry Andric } 611*06c3fb27SDimitry Andric 612*06c3fb27SDimitry Andric size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { 613*06c3fb27SDimitry Andric if (!ParseHeader()) 614*06c3fb27SDimitry Andric return 0; 615*06c3fb27SDimitry Andric 616*06c3fb27SDimitry Andric if (!m_types.empty()) 617*06c3fb27SDimitry Andric return 0; 618*06c3fb27SDimitry Andric 619*06c3fb27SDimitry Andric if (!m_ast) 620*06c3fb27SDimitry Andric return 0; 621*06c3fb27SDimitry Andric 622*06c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 623*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF types"); 624*06c3fb27SDimitry Andric 625*06c3fb27SDimitry Andric lldb::offset_t type_offset = m_body_offset + m_header->typeoff; 626*06c3fb27SDimitry Andric const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff; 627*06c3fb27SDimitry Andric 628*06c3fb27SDimitry Andric lldb::user_id_t type_uid = 1; 629*06c3fb27SDimitry Andric while (type_offset < type_offset_end) { 630*06c3fb27SDimitry Andric ctf_stype_t ctf_stype; 631*06c3fb27SDimitry Andric ctf_stype.name = m_data.GetU32(&type_offset); 632*06c3fb27SDimitry Andric ctf_stype.info = m_data.GetU32(&type_offset); 633*06c3fb27SDimitry Andric ctf_stype.size = m_data.GetU32(&type_offset); 634*06c3fb27SDimitry Andric 635*06c3fb27SDimitry Andric llvm::StringRef name = ReadString(ctf_stype.name); 636*06c3fb27SDimitry Andric const uint32_t kind = GetKind(ctf_stype.info); 637*06c3fb27SDimitry Andric const uint32_t variable_length = GetVLen(ctf_stype.info); 638*06c3fb27SDimitry Andric const uint32_t type = ctf_stype.GetType(); 639*06c3fb27SDimitry Andric const uint32_t size = ctf_stype.GetSize(); 640*06c3fb27SDimitry Andric 641*06c3fb27SDimitry Andric TypeSP type_sp; 642*06c3fb27SDimitry Andric llvm::Expected<TypeSP> type_or_error = ParseType( 643*06c3fb27SDimitry Andric type_offset, type_uid, name, kind, variable_length, type, size); 644*06c3fb27SDimitry Andric if (!type_or_error) { 645*06c3fb27SDimitry Andric LLDB_LOG_ERROR(log, type_or_error.takeError(), 646*06c3fb27SDimitry Andric "Failed to parse type {1} at offset {2}: {0}", type_uid, 647*06c3fb27SDimitry Andric type_offset); 648*06c3fb27SDimitry Andric } else { 649*06c3fb27SDimitry Andric type_sp = *type_or_error; 650*06c3fb27SDimitry Andric if (log) { 651*06c3fb27SDimitry Andric StreamString ss; 652*06c3fb27SDimitry Andric type_sp->Dump(&ss, true); 653*06c3fb27SDimitry Andric LLDB_LOGV(log, "Adding type {0}: {1}", type_uid, 654*06c3fb27SDimitry Andric llvm::StringRef(ss.GetString()).rtrim()); 655*06c3fb27SDimitry Andric } 656*06c3fb27SDimitry Andric } 657*06c3fb27SDimitry Andric 658*06c3fb27SDimitry Andric AddTypeForUID(type_uid++, type_sp); 659*06c3fb27SDimitry Andric } 660*06c3fb27SDimitry Andric 661*06c3fb27SDimitry Andric if (log) { 662*06c3fb27SDimitry Andric size_t skipped_types = 0; 663*06c3fb27SDimitry Andric for (auto &type : m_types) { 664*06c3fb27SDimitry Andric if (!type) 665*06c3fb27SDimitry Andric skipped_types++; 666*06c3fb27SDimitry Andric } 667*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsed {0} CTF types ({1} skipped)", m_types.size(), 668*06c3fb27SDimitry Andric skipped_types); 669*06c3fb27SDimitry Andric } 670*06c3fb27SDimitry Andric 671*06c3fb27SDimitry Andric return m_types.size(); 672*06c3fb27SDimitry Andric } 673*06c3fb27SDimitry Andric 674*06c3fb27SDimitry Andric size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { 675*06c3fb27SDimitry Andric if (!ParseHeader()) 676*06c3fb27SDimitry Andric return 0; 677*06c3fb27SDimitry Andric 678*06c3fb27SDimitry Andric if (!m_functions.empty()) 679*06c3fb27SDimitry Andric return 0; 680*06c3fb27SDimitry Andric 681*06c3fb27SDimitry Andric if (!m_ast) 682*06c3fb27SDimitry Andric return 0; 683*06c3fb27SDimitry Andric 684*06c3fb27SDimitry Andric Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab(); 685*06c3fb27SDimitry Andric if (!symtab) 686*06c3fb27SDimitry Andric return 0; 687*06c3fb27SDimitry Andric 688*06c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 689*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF functions"); 690*06c3fb27SDimitry Andric 691*06c3fb27SDimitry Andric lldb::offset_t function_offset = m_body_offset + m_header->funcoff; 692*06c3fb27SDimitry Andric const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff; 693*06c3fb27SDimitry Andric 694*06c3fb27SDimitry Andric uint32_t symbol_idx = 0; 695*06c3fb27SDimitry Andric Declaration decl; 696*06c3fb27SDimitry Andric while (function_offset < function_offset_end) { 697*06c3fb27SDimitry Andric const uint32_t info = m_data.GetU32(&function_offset); 698*06c3fb27SDimitry Andric const uint16_t kind = GetKind(info); 699*06c3fb27SDimitry Andric const uint16_t variable_length = GetVLen(info); 700*06c3fb27SDimitry Andric 701*06c3fb27SDimitry Andric Symbol *symbol = symtab->FindSymbolWithType( 702*06c3fb27SDimitry Andric eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx); 703*06c3fb27SDimitry Andric 704*06c3fb27SDimitry Andric // Skip padding. 705*06c3fb27SDimitry Andric if (kind == TypeKind::eUnknown && variable_length == 0) 706*06c3fb27SDimitry Andric continue; 707*06c3fb27SDimitry Andric 708*06c3fb27SDimitry Andric // Skip unexpected kinds. 709*06c3fb27SDimitry Andric if (kind != TypeKind::eFunction) 710*06c3fb27SDimitry Andric continue; 711*06c3fb27SDimitry Andric 712*06c3fb27SDimitry Andric const uint32_t ret_uid = m_data.GetU32(&function_offset); 713*06c3fb27SDimitry Andric const uint32_t num_args = variable_length; 714*06c3fb27SDimitry Andric 715*06c3fb27SDimitry Andric std::vector<CompilerType> arg_types; 716*06c3fb27SDimitry Andric arg_types.reserve(num_args); 717*06c3fb27SDimitry Andric 718*06c3fb27SDimitry Andric bool is_variadic = false; 719*06c3fb27SDimitry Andric for (uint32_t i = 0; i < variable_length; i++) { 720*06c3fb27SDimitry Andric const uint32_t arg_uid = m_data.GetU32(&function_offset); 721*06c3fb27SDimitry Andric 722*06c3fb27SDimitry Andric // If the last argument is 0, this is a variadic function. 723*06c3fb27SDimitry Andric if (arg_uid == 0) { 724*06c3fb27SDimitry Andric is_variadic = true; 725*06c3fb27SDimitry Andric break; 726*06c3fb27SDimitry Andric } 727*06c3fb27SDimitry Andric 728*06c3fb27SDimitry Andric TypeSP arg_type = GetTypeForUID(arg_uid); 729*06c3fb27SDimitry Andric arg_types.push_back(arg_type->GetFullCompilerType()); 730*06c3fb27SDimitry Andric } 731*06c3fb27SDimitry Andric 732*06c3fb27SDimitry Andric if (symbol) { 733*06c3fb27SDimitry Andric TypeSP ret_type = GetTypeForUID(ret_uid); 734*06c3fb27SDimitry Andric AddressRange func_range = 735*06c3fb27SDimitry Andric AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(), 736*06c3fb27SDimitry Andric GetObjectFile()->GetModule()->GetSectionList()); 737*06c3fb27SDimitry Andric 738*06c3fb27SDimitry Andric // Create function type. 739*06c3fb27SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType( 740*06c3fb27SDimitry Andric ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), 741*06c3fb27SDimitry Andric is_variadic, 0, clang::CallingConv::CC_C); 742*06c3fb27SDimitry Andric lldb::user_id_t function_type_uid = m_types.size() + 1; 743*06c3fb27SDimitry Andric TypeSP type_sp = 744*06c3fb27SDimitry Andric MakeType(function_type_uid, symbol->GetName(), 0, nullptr, 745*06c3fb27SDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, 746*06c3fb27SDimitry Andric lldb_private::Type::ResolveState::Full); 747*06c3fb27SDimitry Andric AddTypeForUID(function_type_uid, type_sp); 748*06c3fb27SDimitry Andric 749*06c3fb27SDimitry Andric // Create function. 750*06c3fb27SDimitry Andric lldb::user_id_t func_uid = m_functions.size(); 751*06c3fb27SDimitry Andric FunctionSP function_sp = std::make_shared<Function>( 752*06c3fb27SDimitry Andric &cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(), 753*06c3fb27SDimitry Andric func_range); 754*06c3fb27SDimitry Andric m_functions.emplace_back(function_sp); 755*06c3fb27SDimitry Andric cu.AddFunction(function_sp); 756*06c3fb27SDimitry Andric } 757*06c3fb27SDimitry Andric } 758*06c3fb27SDimitry Andric 759*06c3fb27SDimitry Andric LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size()); 760*06c3fb27SDimitry Andric 761*06c3fb27SDimitry Andric return m_functions.size(); 762*06c3fb27SDimitry Andric } 763*06c3fb27SDimitry Andric 764*06c3fb27SDimitry Andric static DWARFExpression CreateDWARFExpression(ModuleSP module_sp, 765*06c3fb27SDimitry Andric const Symbol &symbol) { 766*06c3fb27SDimitry Andric if (!module_sp) 767*06c3fb27SDimitry Andric return DWARFExpression(); 768*06c3fb27SDimitry Andric 769*06c3fb27SDimitry Andric const ArchSpec &architecture = module_sp->GetArchitecture(); 770*06c3fb27SDimitry Andric ByteOrder byte_order = architecture.GetByteOrder(); 771*06c3fb27SDimitry Andric uint32_t address_size = architecture.GetAddressByteSize(); 772*06c3fb27SDimitry Andric uint32_t byte_size = architecture.GetDataByteSize(); 773*06c3fb27SDimitry Andric 774*06c3fb27SDimitry Andric StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order); 775*06c3fb27SDimitry Andric stream.PutHex8(lldb_private::dwarf::DW_OP_addr); 776*06c3fb27SDimitry Andric stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order); 777*06c3fb27SDimitry Andric 778*06c3fb27SDimitry Andric DataBufferSP buffer = 779*06c3fb27SDimitry Andric std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize()); 780*06c3fb27SDimitry Andric lldb_private::DataExtractor extractor(buffer, byte_order, address_size, 781*06c3fb27SDimitry Andric byte_size); 782*06c3fb27SDimitry Andric DWARFExpression result(extractor); 783*06c3fb27SDimitry Andric result.SetRegisterKind(eRegisterKindDWARF); 784*06c3fb27SDimitry Andric 785*06c3fb27SDimitry Andric return result; 786*06c3fb27SDimitry Andric } 787*06c3fb27SDimitry Andric 788*06c3fb27SDimitry Andric size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) { 789*06c3fb27SDimitry Andric if (!ParseHeader()) 790*06c3fb27SDimitry Andric return 0; 791*06c3fb27SDimitry Andric 792*06c3fb27SDimitry Andric if (!m_variables.empty()) 793*06c3fb27SDimitry Andric return 0; 794*06c3fb27SDimitry Andric 795*06c3fb27SDimitry Andric if (!m_ast) 796*06c3fb27SDimitry Andric return 0; 797*06c3fb27SDimitry Andric 798*06c3fb27SDimitry Andric ModuleSP module_sp = GetObjectFile()->GetModule(); 799*06c3fb27SDimitry Andric Symtab *symtab = module_sp->GetSymtab(); 800*06c3fb27SDimitry Andric if (!symtab) 801*06c3fb27SDimitry Andric return 0; 802*06c3fb27SDimitry Andric 803*06c3fb27SDimitry Andric Log *log = GetLog(LLDBLog::Symbols); 804*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsing CTF objects"); 805*06c3fb27SDimitry Andric 806*06c3fb27SDimitry Andric lldb::offset_t object_offset = m_body_offset + m_header->objtoff; 807*06c3fb27SDimitry Andric const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff; 808*06c3fb27SDimitry Andric 809*06c3fb27SDimitry Andric uint32_t symbol_idx = 0; 810*06c3fb27SDimitry Andric Declaration decl; 811*06c3fb27SDimitry Andric while (object_offset < object_offset_end) { 812*06c3fb27SDimitry Andric const uint32_t type_uid = m_data.GetU32(&object_offset); 813*06c3fb27SDimitry Andric 814*06c3fb27SDimitry Andric if (Symbol *symbol = 815*06c3fb27SDimitry Andric symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes, 816*06c3fb27SDimitry Andric Symtab::eVisibilityAny, symbol_idx)) { 817*06c3fb27SDimitry Andric 818*06c3fb27SDimitry Andric Variable::RangeList ranges; 819*06c3fb27SDimitry Andric ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize()); 820*06c3fb27SDimitry Andric 821*06c3fb27SDimitry Andric auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid); 822*06c3fb27SDimitry Andric 823*06c3fb27SDimitry Andric DWARFExpressionList location( 824*06c3fb27SDimitry Andric module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr); 825*06c3fb27SDimitry Andric 826*06c3fb27SDimitry Andric lldb::user_id_t variable_type_uid = m_variables.size(); 827*06c3fb27SDimitry Andric m_variables.emplace_back(std::make_shared<Variable>( 828*06c3fb27SDimitry Andric variable_type_uid, symbol->GetName().AsCString(), 829*06c3fb27SDimitry Andric symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal, 830*06c3fb27SDimitry Andric m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(), 831*06c3fb27SDimitry Andric /*artificial=*/false, 832*06c3fb27SDimitry Andric /*location_is_constant_data*/ false)); 833*06c3fb27SDimitry Andric } 834*06c3fb27SDimitry Andric } 835*06c3fb27SDimitry Andric 836*06c3fb27SDimitry Andric LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size()); 837*06c3fb27SDimitry Andric 838*06c3fb27SDimitry Andric return m_variables.size(); 839*06c3fb27SDimitry Andric } 840*06c3fb27SDimitry Andric 841*06c3fb27SDimitry Andric uint32_t SymbolFileCTF::CalculateAbilities() { 842*06c3fb27SDimitry Andric if (!m_objfile_sp) 843*06c3fb27SDimitry Andric return 0; 844*06c3fb27SDimitry Andric 845*06c3fb27SDimitry Andric if (!ParseHeader()) 846*06c3fb27SDimitry Andric return 0; 847*06c3fb27SDimitry Andric 848*06c3fb27SDimitry Andric return VariableTypes | Functions | GlobalVariables; 849*06c3fb27SDimitry Andric } 850*06c3fb27SDimitry Andric 851*06c3fb27SDimitry Andric uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr, 852*06c3fb27SDimitry Andric SymbolContextItem resolve_scope, 853*06c3fb27SDimitry Andric SymbolContext &sc) { 854*06c3fb27SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 855*06c3fb27SDimitry Andric if (m_objfile_sp->GetSymtab() == nullptr) 856*06c3fb27SDimitry Andric return 0; 857*06c3fb27SDimitry Andric 858*06c3fb27SDimitry Andric uint32_t resolved_flags = 0; 859*06c3fb27SDimitry Andric 860*06c3fb27SDimitry Andric // Resolve symbols. 861*06c3fb27SDimitry Andric if (resolve_scope & eSymbolContextSymbol) { 862*06c3fb27SDimitry Andric sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress( 863*06c3fb27SDimitry Andric so_addr.GetFileAddress()); 864*06c3fb27SDimitry Andric if (sc.symbol) 865*06c3fb27SDimitry Andric resolved_flags |= eSymbolContextSymbol; 866*06c3fb27SDimitry Andric } 867*06c3fb27SDimitry Andric 868*06c3fb27SDimitry Andric // Resolve functions. 869*06c3fb27SDimitry Andric if (resolve_scope & eSymbolContextFunction) { 870*06c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 871*06c3fb27SDimitry Andric if (function_sp->GetAddressRange().ContainsFileAddress( 872*06c3fb27SDimitry Andric so_addr.GetFileAddress())) { 873*06c3fb27SDimitry Andric sc.function = function_sp.get(); 874*06c3fb27SDimitry Andric resolved_flags |= eSymbolContextFunction; 875*06c3fb27SDimitry Andric break; 876*06c3fb27SDimitry Andric } 877*06c3fb27SDimitry Andric } 878*06c3fb27SDimitry Andric } 879*06c3fb27SDimitry Andric 880*06c3fb27SDimitry Andric // Resolve variables. 881*06c3fb27SDimitry Andric if (resolve_scope & eSymbolContextVariable) { 882*06c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 883*06c3fb27SDimitry Andric if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) { 884*06c3fb27SDimitry Andric sc.variable = variable_sp.get(); 885*06c3fb27SDimitry Andric break; 886*06c3fb27SDimitry Andric } 887*06c3fb27SDimitry Andric } 888*06c3fb27SDimitry Andric } 889*06c3fb27SDimitry Andric 890*06c3fb27SDimitry Andric return resolved_flags; 891*06c3fb27SDimitry Andric } 892*06c3fb27SDimitry Andric 893*06c3fb27SDimitry Andric CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) { 894*06c3fb27SDimitry Andric if (idx == 0) 895*06c3fb27SDimitry Andric return m_comp_unit_sp; 896*06c3fb27SDimitry Andric return {}; 897*06c3fb27SDimitry Andric } 898*06c3fb27SDimitry Andric 899*06c3fb27SDimitry Andric size_t 900*06c3fb27SDimitry Andric SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { 901*06c3fb27SDimitry Andric return ParseObjects(*m_comp_unit_sp); 902*06c3fb27SDimitry Andric } 903*06c3fb27SDimitry Andric 904*06c3fb27SDimitry Andric void SymbolFileCTF::AddSymbols(Symtab &symtab) { 905*06c3fb27SDimitry Andric // CTF does not encode symbols. 906*06c3fb27SDimitry Andric // We rely on the existing symbol table to map symbols to type. 907*06c3fb27SDimitry Andric } 908*06c3fb27SDimitry Andric 909*06c3fb27SDimitry Andric void SymbolFileCTF::AddTypeForUID(lldb::user_id_t type_uid, lldb::TypeSP type) { 910*06c3fb27SDimitry Andric assert(type_uid == m_types.size() + 1); 911*06c3fb27SDimitry Andric m_types.emplace_back(type); 912*06c3fb27SDimitry Andric } 913*06c3fb27SDimitry Andric 914*06c3fb27SDimitry Andric TypeSP SymbolFileCTF::GetTypeForUID(lldb::user_id_t type_uid) { 915*06c3fb27SDimitry Andric if (type_uid > m_types.size()) 916*06c3fb27SDimitry Andric return {}; 917*06c3fb27SDimitry Andric 918*06c3fb27SDimitry Andric if (type_uid < 1) 919*06c3fb27SDimitry Andric return {}; 920*06c3fb27SDimitry Andric 921*06c3fb27SDimitry Andric return m_types[type_uid - 1]; 922*06c3fb27SDimitry Andric } 923*06c3fb27SDimitry Andric 924*06c3fb27SDimitry Andric lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { 925*06c3fb27SDimitry Andric return GetTypeForUID(type_uid).get(); 926*06c3fb27SDimitry Andric } 927*06c3fb27SDimitry Andric 928*06c3fb27SDimitry Andric void SymbolFileCTF::FindTypes( 929*06c3fb27SDimitry Andric lldb_private::ConstString name, 930*06c3fb27SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx, 931*06c3fb27SDimitry Andric uint32_t max_matches, 932*06c3fb27SDimitry Andric llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, 933*06c3fb27SDimitry Andric lldb_private::TypeMap &types) { 934*06c3fb27SDimitry Andric 935*06c3fb27SDimitry Andric searched_symbol_files.clear(); 936*06c3fb27SDimitry Andric searched_symbol_files.insert(this); 937*06c3fb27SDimitry Andric 938*06c3fb27SDimitry Andric size_t matches = 0; 939*06c3fb27SDimitry Andric for (TypeSP type_sp : m_types) { 940*06c3fb27SDimitry Andric if (matches == max_matches) 941*06c3fb27SDimitry Andric break; 942*06c3fb27SDimitry Andric if (type_sp && type_sp->GetName() == name) { 943*06c3fb27SDimitry Andric types.Insert(type_sp); 944*06c3fb27SDimitry Andric matches++; 945*06c3fb27SDimitry Andric } 946*06c3fb27SDimitry Andric } 947*06c3fb27SDimitry Andric } 948*06c3fb27SDimitry Andric 949*06c3fb27SDimitry Andric void SymbolFileCTF::FindTypesByRegex( 950*06c3fb27SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches, 951*06c3fb27SDimitry Andric lldb_private::TypeMap &types) { 952*06c3fb27SDimitry Andric ParseTypes(*m_comp_unit_sp); 953*06c3fb27SDimitry Andric 954*06c3fb27SDimitry Andric size_t matches = 0; 955*06c3fb27SDimitry Andric for (TypeSP type_sp : m_types) { 956*06c3fb27SDimitry Andric if (matches == max_matches) 957*06c3fb27SDimitry Andric break; 958*06c3fb27SDimitry Andric if (type_sp && regex.Execute(type_sp->GetName())) 959*06c3fb27SDimitry Andric types.Insert(type_sp); 960*06c3fb27SDimitry Andric matches++; 961*06c3fb27SDimitry Andric } 962*06c3fb27SDimitry Andric } 963*06c3fb27SDimitry Andric 964*06c3fb27SDimitry Andric void SymbolFileCTF::FindFunctions( 965*06c3fb27SDimitry Andric const lldb_private::Module::LookupInfo &lookup_info, 966*06c3fb27SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx, 967*06c3fb27SDimitry Andric bool include_inlines, lldb_private::SymbolContextList &sc_list) { 968*06c3fb27SDimitry Andric ParseFunctions(*m_comp_unit_sp); 969*06c3fb27SDimitry Andric 970*06c3fb27SDimitry Andric ConstString name = lookup_info.GetLookupName(); 971*06c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 972*06c3fb27SDimitry Andric if (function_sp && function_sp->GetName() == name) { 973*06c3fb27SDimitry Andric lldb_private::SymbolContext sc; 974*06c3fb27SDimitry Andric sc.comp_unit = m_comp_unit_sp.get(); 975*06c3fb27SDimitry Andric sc.function = function_sp.get(); 976*06c3fb27SDimitry Andric sc_list.Append(sc); 977*06c3fb27SDimitry Andric } 978*06c3fb27SDimitry Andric } 979*06c3fb27SDimitry Andric } 980*06c3fb27SDimitry Andric 981*06c3fb27SDimitry Andric void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression ®ex, 982*06c3fb27SDimitry Andric bool include_inlines, 983*06c3fb27SDimitry Andric lldb_private::SymbolContextList &sc_list) { 984*06c3fb27SDimitry Andric for (FunctionSP function_sp : m_functions) { 985*06c3fb27SDimitry Andric if (function_sp && regex.Execute(function_sp->GetName())) { 986*06c3fb27SDimitry Andric lldb_private::SymbolContext sc; 987*06c3fb27SDimitry Andric sc.comp_unit = m_comp_unit_sp.get(); 988*06c3fb27SDimitry Andric sc.function = function_sp.get(); 989*06c3fb27SDimitry Andric sc_list.Append(sc); 990*06c3fb27SDimitry Andric } 991*06c3fb27SDimitry Andric } 992*06c3fb27SDimitry Andric } 993*06c3fb27SDimitry Andric 994*06c3fb27SDimitry Andric void SymbolFileCTF::FindGlobalVariables( 995*06c3fb27SDimitry Andric lldb_private::ConstString name, 996*06c3fb27SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx, 997*06c3fb27SDimitry Andric uint32_t max_matches, lldb_private::VariableList &variables) { 998*06c3fb27SDimitry Andric ParseObjects(*m_comp_unit_sp); 999*06c3fb27SDimitry Andric 1000*06c3fb27SDimitry Andric size_t matches = 0; 1001*06c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 1002*06c3fb27SDimitry Andric if (matches == max_matches) 1003*06c3fb27SDimitry Andric break; 1004*06c3fb27SDimitry Andric if (variable_sp && variable_sp->GetName() == name) { 1005*06c3fb27SDimitry Andric variables.AddVariable(variable_sp); 1006*06c3fb27SDimitry Andric matches++; 1007*06c3fb27SDimitry Andric } 1008*06c3fb27SDimitry Andric } 1009*06c3fb27SDimitry Andric } 1010*06c3fb27SDimitry Andric 1011*06c3fb27SDimitry Andric void SymbolFileCTF::FindGlobalVariables( 1012*06c3fb27SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches, 1013*06c3fb27SDimitry Andric lldb_private::VariableList &variables) { 1014*06c3fb27SDimitry Andric ParseObjects(*m_comp_unit_sp); 1015*06c3fb27SDimitry Andric 1016*06c3fb27SDimitry Andric size_t matches = 0; 1017*06c3fb27SDimitry Andric for (VariableSP variable_sp : m_variables) { 1018*06c3fb27SDimitry Andric if (matches == max_matches) 1019*06c3fb27SDimitry Andric break; 1020*06c3fb27SDimitry Andric if (variable_sp && regex.Execute(variable_sp->GetName())) { 1021*06c3fb27SDimitry Andric variables.AddVariable(variable_sp); 1022*06c3fb27SDimitry Andric matches++; 1023*06c3fb27SDimitry Andric } 1024*06c3fb27SDimitry Andric } 1025*06c3fb27SDimitry Andric } 1026