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