xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 &regex, 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 &regex,
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 &regex, 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