17fa27ce4SDimitry Andric //===-- SymbolFileCTF.cpp ----------------------------------------------===//
27fa27ce4SDimitry Andric //
37fa27ce4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fa27ce4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57fa27ce4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fa27ce4SDimitry Andric //
77fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
87fa27ce4SDimitry Andric
97fa27ce4SDimitry Andric #include "SymbolFileCTF.h"
107fa27ce4SDimitry Andric
117fa27ce4SDimitry Andric #include "lldb/Core/Module.h"
127fa27ce4SDimitry Andric #include "lldb/Core/PluginManager.h"
137fa27ce4SDimitry Andric #include "lldb/Host/Config.h"
147fa27ce4SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
157fa27ce4SDimitry Andric #include "lldb/Symbol/Function.h"
167fa27ce4SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
177fa27ce4SDimitry Andric #include "lldb/Symbol/Symbol.h"
187fa27ce4SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
197fa27ce4SDimitry Andric #include "lldb/Symbol/Symtab.h"
207fa27ce4SDimitry Andric #include "lldb/Symbol/TypeList.h"
217fa27ce4SDimitry Andric #include "lldb/Symbol/TypeMap.h"
227fa27ce4SDimitry Andric #include "lldb/Symbol/Variable.h"
237fa27ce4SDimitry Andric #include "lldb/Symbol/VariableList.h"
247fa27ce4SDimitry Andric #include "lldb/Utility/DataExtractor.h"
257fa27ce4SDimitry Andric #include "lldb/Utility/LLDBLog.h"
267fa27ce4SDimitry Andric #include "lldb/Utility/Log.h"
277fa27ce4SDimitry Andric #include "lldb/Utility/RegularExpression.h"
28b1c73532SDimitry Andric #include "lldb/Utility/StreamBuffer.h"
297fa27ce4SDimitry Andric #include "lldb/Utility/StreamString.h"
307fa27ce4SDimitry Andric #include "lldb/Utility/Timer.h"
317fa27ce4SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
327fa27ce4SDimitry Andric
337fa27ce4SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
347fa27ce4SDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
357fa27ce4SDimitry Andric
367fa27ce4SDimitry Andric #include <memory>
377fa27ce4SDimitry Andric #include <optional>
387fa27ce4SDimitry Andric
397fa27ce4SDimitry Andric #if LLVM_ENABLE_ZLIB
407fa27ce4SDimitry Andric #include <zlib.h>
417fa27ce4SDimitry Andric #endif
427fa27ce4SDimitry Andric
437fa27ce4SDimitry Andric using namespace llvm;
447fa27ce4SDimitry Andric using namespace lldb;
457fa27ce4SDimitry Andric using namespace lldb_private;
467fa27ce4SDimitry Andric
477fa27ce4SDimitry Andric LLDB_PLUGIN_DEFINE(SymbolFileCTF)
487fa27ce4SDimitry Andric
497fa27ce4SDimitry Andric char SymbolFileCTF::ID;
507fa27ce4SDimitry Andric
SymbolFileCTF(lldb::ObjectFileSP objfile_sp)517fa27ce4SDimitry Andric SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp)
527fa27ce4SDimitry Andric : SymbolFileCommon(std::move(objfile_sp)) {}
537fa27ce4SDimitry Andric
Initialize()547fa27ce4SDimitry Andric void SymbolFileCTF::Initialize() {
557fa27ce4SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(),
567fa27ce4SDimitry Andric GetPluginDescriptionStatic(), CreateInstance);
577fa27ce4SDimitry Andric }
587fa27ce4SDimitry Andric
Terminate()597fa27ce4SDimitry Andric void SymbolFileCTF::Terminate() {
607fa27ce4SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance);
617fa27ce4SDimitry Andric }
627fa27ce4SDimitry Andric
GetPluginDescriptionStatic()637fa27ce4SDimitry Andric llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() {
647fa27ce4SDimitry Andric return "Compact C Type Format Symbol Reader";
657fa27ce4SDimitry Andric }
667fa27ce4SDimitry Andric
CreateInstance(ObjectFileSP objfile_sp)677fa27ce4SDimitry Andric SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) {
687fa27ce4SDimitry Andric return new SymbolFileCTF(std::move(objfile_sp));
697fa27ce4SDimitry Andric }
707fa27ce4SDimitry Andric
ParseHeader()717fa27ce4SDimitry Andric bool SymbolFileCTF::ParseHeader() {
727fa27ce4SDimitry Andric if (m_header)
737fa27ce4SDimitry Andric return true;
747fa27ce4SDimitry Andric
757fa27ce4SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
767fa27ce4SDimitry Andric
777fa27ce4SDimitry Andric ModuleSP module_sp(m_objfile_sp->GetModule());
787fa27ce4SDimitry Andric const SectionList *section_list = module_sp->GetSectionList();
797fa27ce4SDimitry Andric if (!section_list)
807fa27ce4SDimitry Andric return false;
817fa27ce4SDimitry Andric
827fa27ce4SDimitry Andric SectionSP section_sp(
837fa27ce4SDimitry Andric section_list->FindSectionByType(lldb::eSectionTypeCTF, true));
847fa27ce4SDimitry Andric if (!section_sp)
857fa27ce4SDimitry Andric return false;
867fa27ce4SDimitry Andric
877fa27ce4SDimitry Andric m_objfile_sp->ReadSectionData(section_sp.get(), m_data);
887fa27ce4SDimitry Andric
897fa27ce4SDimitry Andric if (m_data.GetByteSize() == 0)
907fa27ce4SDimitry Andric return false;
917fa27ce4SDimitry Andric
927fa27ce4SDimitry Andric StreamString module_desc;
937fa27ce4SDimitry Andric GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
947fa27ce4SDimitry Andric lldb::eDescriptionLevelBrief);
957fa27ce4SDimitry Andric LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData());
967fa27ce4SDimitry Andric
977fa27ce4SDimitry Andric lldb::offset_t offset = 0;
987fa27ce4SDimitry Andric
997fa27ce4SDimitry Andric // Parse CTF header.
1007fa27ce4SDimitry Andric constexpr size_t ctf_header_size = sizeof(ctf_header_t);
1017fa27ce4SDimitry Andric if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) {
1027fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header");
1037fa27ce4SDimitry Andric return false;
1047fa27ce4SDimitry Andric }
1057fa27ce4SDimitry Andric
1067fa27ce4SDimitry Andric m_header.emplace();
1077fa27ce4SDimitry Andric
1087fa27ce4SDimitry Andric ctf_header_t &ctf_header = *m_header;
1097fa27ce4SDimitry Andric ctf_header.preamble.magic = m_data.GetU16(&offset);
1107fa27ce4SDimitry Andric ctf_header.preamble.version = m_data.GetU8(&offset);
1117fa27ce4SDimitry Andric ctf_header.preamble.flags = m_data.GetU8(&offset);
1127fa27ce4SDimitry Andric ctf_header.parlabel = m_data.GetU32(&offset);
1137fa27ce4SDimitry Andric ctf_header.parname = m_data.GetU32(&offset);
1147fa27ce4SDimitry Andric ctf_header.lbloff = m_data.GetU32(&offset);
1157fa27ce4SDimitry Andric ctf_header.objtoff = m_data.GetU32(&offset);
1167fa27ce4SDimitry Andric ctf_header.funcoff = m_data.GetU32(&offset);
1177fa27ce4SDimitry Andric ctf_header.typeoff = m_data.GetU32(&offset);
1187fa27ce4SDimitry Andric ctf_header.stroff = m_data.GetU32(&offset);
1197fa27ce4SDimitry Andric ctf_header.strlen = m_data.GetU32(&offset);
1207fa27ce4SDimitry Andric
1217fa27ce4SDimitry Andric // Validate the preamble.
1227fa27ce4SDimitry Andric if (ctf_header.preamble.magic != g_ctf_magic) {
1237fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}",
1247fa27ce4SDimitry Andric ctf_header.preamble.magic);
1257fa27ce4SDimitry Andric return false;
1267fa27ce4SDimitry Andric }
1277fa27ce4SDimitry Andric
1287fa27ce4SDimitry Andric if (ctf_header.preamble.version != g_ctf_version) {
1297fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}",
1307fa27ce4SDimitry Andric ctf_header.preamble.version);
1317fa27ce4SDimitry Andric return false;
1327fa27ce4SDimitry Andric }
1337fa27ce4SDimitry Andric
1347fa27ce4SDimitry Andric LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}",
1357fa27ce4SDimitry Andric ctf_header.preamble.version, ctf_header.preamble.flags);
1367fa27ce4SDimitry Andric
1377fa27ce4SDimitry Andric m_body_offset = offset;
1387fa27ce4SDimitry Andric
1397fa27ce4SDimitry Andric if (ctf_header.preamble.flags & eFlagCompress) {
1407fa27ce4SDimitry Andric // The body has been compressed with zlib deflate. Header offsets point into
1417fa27ce4SDimitry Andric // the decompressed data.
1427fa27ce4SDimitry Andric #if LLVM_ENABLE_ZLIB
1437fa27ce4SDimitry Andric const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen;
1447fa27ce4SDimitry Andric DataBufferSP decompressed_data =
1457fa27ce4SDimitry Andric std::make_shared<DataBufferHeap>(decompressed_size, 0x0);
1467fa27ce4SDimitry Andric
1477fa27ce4SDimitry Andric z_stream zstr;
1487fa27ce4SDimitry Andric memset(&zstr, 0, sizeof(zstr));
1497fa27ce4SDimitry Andric zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() +
1507fa27ce4SDimitry Andric sizeof(ctf_header_t));
1517fa27ce4SDimitry Andric zstr.avail_in = m_data.BytesLeft(offset);
1527fa27ce4SDimitry Andric zstr.next_out =
1537fa27ce4SDimitry Andric (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes());
1547fa27ce4SDimitry Andric zstr.avail_out = decompressed_size;
1557fa27ce4SDimitry Andric
1567fa27ce4SDimitry Andric int rc = inflateInit(&zstr);
1577fa27ce4SDimitry Andric if (rc != Z_OK) {
1587fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}",
1597fa27ce4SDimitry Andric zError(rc));
1607fa27ce4SDimitry Andric return false;
1617fa27ce4SDimitry Andric }
1627fa27ce4SDimitry Andric
1637fa27ce4SDimitry Andric rc = inflate(&zstr, Z_FINISH);
1647fa27ce4SDimitry Andric if (rc != Z_STREAM_END) {
1657fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc));
1667fa27ce4SDimitry Andric return false;
1677fa27ce4SDimitry Andric }
1687fa27ce4SDimitry Andric
1697fa27ce4SDimitry Andric rc = inflateEnd(&zstr);
1707fa27ce4SDimitry Andric if (rc != Z_OK) {
1717fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc));
1727fa27ce4SDimitry Andric return false;
1737fa27ce4SDimitry Andric }
1747fa27ce4SDimitry Andric
1757fa27ce4SDimitry Andric if (zstr.total_out != decompressed_size) {
1767fa27ce4SDimitry Andric LLDB_LOG(log,
1777fa27ce4SDimitry Andric "CTF parsing failed: decompressed size ({0}) doesn't match "
1787fa27ce4SDimitry Andric "expected size ([1})",
1797fa27ce4SDimitry Andric zstr.total_out, decompressed_size);
1807fa27ce4SDimitry Andric return false;
1817fa27ce4SDimitry Andric }
1827fa27ce4SDimitry Andric
1837fa27ce4SDimitry Andric m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(),
1847fa27ce4SDimitry Andric m_data.GetAddressByteSize());
1857fa27ce4SDimitry Andric m_body_offset = 0;
1867fa27ce4SDimitry Andric #else
1877fa27ce4SDimitry Andric LLDB_LOG(
1887fa27ce4SDimitry Andric log,
1897fa27ce4SDimitry Andric "CTF parsing failed: data is compressed but no zlib inflate support");
1907fa27ce4SDimitry Andric return false;
1917fa27ce4SDimitry Andric #endif
1927fa27ce4SDimitry Andric }
1937fa27ce4SDimitry Andric
1947fa27ce4SDimitry Andric // Validate the header.
1957fa27ce4SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) {
1967fa27ce4SDimitry Andric LLDB_LOG(log,
1977fa27ce4SDimitry Andric "CTF parsing failed: invalid label section offset in header: {0}",
1987fa27ce4SDimitry Andric ctf_header.lbloff);
1997fa27ce4SDimitry Andric return false;
2007fa27ce4SDimitry Andric }
2017fa27ce4SDimitry Andric
2027fa27ce4SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) {
2037fa27ce4SDimitry Andric LLDB_LOG(log,
2047fa27ce4SDimitry Andric "CTF parsing failed: invalid object section offset in header: {0}",
2057fa27ce4SDimitry Andric ctf_header.objtoff);
2067fa27ce4SDimitry Andric return false;
2077fa27ce4SDimitry Andric }
2087fa27ce4SDimitry Andric
2097fa27ce4SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) {
2107fa27ce4SDimitry Andric LLDB_LOG(
2117fa27ce4SDimitry Andric log,
2127fa27ce4SDimitry Andric "CTF parsing failed: invalid function section offset in header: {0}",
2137fa27ce4SDimitry Andric ctf_header.funcoff);
2147fa27ce4SDimitry Andric return false;
2157fa27ce4SDimitry Andric }
2167fa27ce4SDimitry Andric
2177fa27ce4SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) {
2187fa27ce4SDimitry Andric LLDB_LOG(log,
2197fa27ce4SDimitry Andric "CTF parsing failed: invalid type section offset in header: {0}",
2207fa27ce4SDimitry Andric ctf_header.typeoff);
2217fa27ce4SDimitry Andric return false;
2227fa27ce4SDimitry Andric }
2237fa27ce4SDimitry Andric
2247fa27ce4SDimitry Andric if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) {
2257fa27ce4SDimitry Andric LLDB_LOG(log,
2267fa27ce4SDimitry Andric "CTF parsing failed: invalid string section offset in header: {0}",
2277fa27ce4SDimitry Andric ctf_header.stroff);
2287fa27ce4SDimitry Andric return false;
2297fa27ce4SDimitry Andric }
2307fa27ce4SDimitry Andric
2317fa27ce4SDimitry Andric const lldb::offset_t str_end_offset =
2327fa27ce4SDimitry Andric m_body_offset + ctf_header.stroff + ctf_header.strlen;
2337fa27ce4SDimitry Andric if (!m_data.ValidOffset(str_end_offset - 1)) {
2347fa27ce4SDimitry Andric LLDB_LOG(log,
2357fa27ce4SDimitry Andric "CTF parsing failed: invalid string section length in header: {0}",
2367fa27ce4SDimitry Andric ctf_header.strlen);
2377fa27ce4SDimitry Andric return false;
2387fa27ce4SDimitry Andric }
2397fa27ce4SDimitry Andric
2407fa27ce4SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parlabel >
2417fa27ce4SDimitry Andric str_end_offset) {
2427fa27ce4SDimitry Andric LLDB_LOG(log,
2437fa27ce4SDimitry Andric "CTF parsing failed: invalid parent label offset: {0} exceeds end "
2447fa27ce4SDimitry Andric "of string section ({1})",
2457fa27ce4SDimitry Andric ctf_header.parlabel, str_end_offset);
2467fa27ce4SDimitry Andric return false;
2477fa27ce4SDimitry Andric }
2487fa27ce4SDimitry Andric
2497fa27ce4SDimitry Andric if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) {
2507fa27ce4SDimitry Andric LLDB_LOG(log,
2517fa27ce4SDimitry Andric "CTF parsing failed: invalid parent name offset: {0} exceeds end "
2527fa27ce4SDimitry Andric "of string section ({1})",
2537fa27ce4SDimitry Andric ctf_header.parname, str_end_offset);
2547fa27ce4SDimitry Andric return false;
2557fa27ce4SDimitry Andric }
2567fa27ce4SDimitry Andric
2577fa27ce4SDimitry Andric LLDB_LOG(log,
2587fa27ce4SDimitry Andric "Parsed valid CTF header: lbloff = {0}, objtoff = {1}, funcoff = "
2597fa27ce4SDimitry Andric "{2}, typeoff = {3}, stroff = {4}, strlen = {5}",
2607fa27ce4SDimitry Andric ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff,
2617fa27ce4SDimitry Andric ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen);
2627fa27ce4SDimitry Andric
2637fa27ce4SDimitry Andric return true;
2647fa27ce4SDimitry Andric }
2657fa27ce4SDimitry Andric
InitializeObject()2667fa27ce4SDimitry Andric void SymbolFileCTF::InitializeObject() {
2677fa27ce4SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
2687fa27ce4SDimitry Andric
2697fa27ce4SDimitry Andric auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC);
2707fa27ce4SDimitry Andric if (auto err = type_system_or_err.takeError()) {
2717fa27ce4SDimitry Andric LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}");
2727fa27ce4SDimitry Andric return;
2737fa27ce4SDimitry Andric }
2747fa27ce4SDimitry Andric
2757fa27ce4SDimitry Andric auto ts = *type_system_or_err;
2767fa27ce4SDimitry Andric m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
2777fa27ce4SDimitry Andric LazyBool optimized = eLazyBoolNo;
2787fa27ce4SDimitry Andric m_comp_unit_sp = std::make_shared<CompileUnit>(
2797fa27ce4SDimitry Andric m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized);
2807fa27ce4SDimitry Andric
2817fa27ce4SDimitry Andric ParseTypes(*m_comp_unit_sp);
2827fa27ce4SDimitry Andric }
2837fa27ce4SDimitry Andric
ReadString(lldb::offset_t str_offset) const2847fa27ce4SDimitry Andric llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const {
2857fa27ce4SDimitry Andric lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset;
2867fa27ce4SDimitry Andric if (!m_data.ValidOffset(offset))
2877fa27ce4SDimitry Andric return "(invalid)";
2887fa27ce4SDimitry Andric const char *str = m_data.GetCStr(&offset);
2897fa27ce4SDimitry Andric if (str && !*str)
2907fa27ce4SDimitry Andric return "(anon)";
2917fa27ce4SDimitry Andric return llvm::StringRef(str);
2927fa27ce4SDimitry Andric }
2937fa27ce4SDimitry Andric
2947fa27ce4SDimitry Andric /// Return the integer display representation encoded in the given data.
GetEncoding(uint32_t data)2957fa27ce4SDimitry Andric static uint32_t GetEncoding(uint32_t data) {
2967fa27ce4SDimitry Andric // Mask bits 24–31.
2977fa27ce4SDimitry Andric return ((data)&0xff000000) >> 24;
2987fa27ce4SDimitry Andric }
2997fa27ce4SDimitry Andric
3007fa27ce4SDimitry Andric /// Return the integral width in bits encoded in the given data.
GetBits(uint32_t data)3017fa27ce4SDimitry Andric static uint32_t GetBits(uint32_t data) {
3027fa27ce4SDimitry Andric // Mask bits 0-15.
3037fa27ce4SDimitry Andric return (data)&0x0000ffff;
3047fa27ce4SDimitry Andric }
3057fa27ce4SDimitry Andric
3067fa27ce4SDimitry Andric /// Return the type kind encoded in the given data.
GetKind(uint32_t data)3077fa27ce4SDimitry Andric uint32_t GetKind(uint32_t data) {
3087fa27ce4SDimitry Andric // Mask bits 26–31.
3097fa27ce4SDimitry Andric return ((data)&0xf800) >> 11;
3107fa27ce4SDimitry Andric }
3117fa27ce4SDimitry Andric
3127fa27ce4SDimitry Andric /// Return the variable length encoded in the given data.
GetVLen(uint32_t data)3137fa27ce4SDimitry Andric uint32_t GetVLen(uint32_t data) {
3147fa27ce4SDimitry Andric // Mask bits 0–24.
3157fa27ce4SDimitry Andric return (data)&0x3ff;
3167fa27ce4SDimitry Andric }
3177fa27ce4SDimitry Andric
GetBytes(uint32_t bits)3187fa27ce4SDimitry Andric static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); }
3197fa27ce4SDimitry Andric
TranslateRecordKind(CTFType::Kind type)320b1c73532SDimitry Andric static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) {
3217fa27ce4SDimitry Andric switch (type) {
322b1c73532SDimitry Andric case CTFType::Kind::eStruct:
323b1c73532SDimitry Andric return clang::TagTypeKind::Struct;
324b1c73532SDimitry Andric case CTFType::Kind::eUnion:
325b1c73532SDimitry Andric return clang::TagTypeKind::Union;
3267fa27ce4SDimitry Andric default:
3277fa27ce4SDimitry Andric lldbassert(false && "Invalid record kind!");
328b1c73532SDimitry Andric return clang::TagTypeKind::Struct;
3297fa27ce4SDimitry Andric }
3307fa27ce4SDimitry Andric }
3317fa27ce4SDimitry Andric
332b1c73532SDimitry Andric llvm::Expected<TypeSP>
CreateInteger(const CTFInteger & ctf_integer)333b1c73532SDimitry Andric SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) {
334b1c73532SDimitry Andric lldb::BasicType basic_type =
335b1c73532SDimitry Andric TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name);
3367fa27ce4SDimitry Andric if (basic_type == eBasicTypeInvalid)
3377fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
3387fa27ce4SDimitry Andric llvm::formatv("unsupported integer type: no corresponding basic clang "
3397fa27ce4SDimitry Andric "type for '{0}'",
340b1c73532SDimitry Andric ctf_integer.name),
3417fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
3427fa27ce4SDimitry Andric
3437fa27ce4SDimitry Andric CompilerType compiler_type = m_ast->GetBasicType(basic_type);
3447fa27ce4SDimitry Andric
345ac9a064cSDimitry Andric if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) {
3467fa27ce4SDimitry Andric // Make sure the type we got is an integer type.
3477fa27ce4SDimitry Andric bool compiler_type_is_signed = false;
3487fa27ce4SDimitry Andric if (!compiler_type.IsIntegerType(compiler_type_is_signed))
3497fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
3507fa27ce4SDimitry Andric llvm::formatv(
3517fa27ce4SDimitry Andric "Found compiler type for '{0}' but it's not an integer type: {1}",
352b1c73532SDimitry Andric ctf_integer.name,
353b1c73532SDimitry Andric compiler_type.GetDisplayTypeName().GetStringRef()),
3547fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
3557fa27ce4SDimitry Andric
3567fa27ce4SDimitry Andric // Make sure the signing matches between the CTF and the compiler type.
357b1c73532SDimitry Andric const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned);
3587fa27ce4SDimitry Andric if (compiler_type_is_signed != type_is_signed)
3597fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
3607fa27ce4SDimitry Andric llvm::formatv("Found integer compiler type for {0} but compiler type "
3617fa27ce4SDimitry Andric "is {1} and {0} is {2}",
362b1c73532SDimitry Andric ctf_integer.name,
363b1c73532SDimitry Andric compiler_type_is_signed ? "signed" : "unsigned",
3647fa27ce4SDimitry Andric type_is_signed ? "signed" : "unsigned"),
3657fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
3667fa27ce4SDimitry Andric }
3677fa27ce4SDimitry Andric
3687fa27ce4SDimitry Andric Declaration decl;
369b1c73532SDimitry Andric return MakeType(ctf_integer.uid, ConstString(ctf_integer.name),
370b1c73532SDimitry Andric GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID,
371b1c73532SDimitry Andric lldb_private::Type::eEncodingIsUID, decl, compiler_type,
372b1c73532SDimitry Andric lldb_private::Type::ResolveState::Full);
3737fa27ce4SDimitry Andric }
3747fa27ce4SDimitry Andric
3757fa27ce4SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateModifier(const CTFModifier & ctf_modifier)376b1c73532SDimitry Andric SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) {
377b1c73532SDimitry Andric Type *ref_type = ResolveTypeUID(ctf_modifier.type);
3787fa27ce4SDimitry Andric if (!ref_type)
3797fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
380b1c73532SDimitry Andric llvm::formatv("Could not find modified type: {0}", ctf_modifier.type),
3817fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
3827fa27ce4SDimitry Andric
3837fa27ce4SDimitry Andric CompilerType compiler_type;
3847fa27ce4SDimitry Andric
385b1c73532SDimitry Andric switch (ctf_modifier.kind) {
386b1c73532SDimitry Andric case CTFType::ePointer:
3877fa27ce4SDimitry Andric compiler_type = ref_type->GetFullCompilerType().GetPointerType();
3887fa27ce4SDimitry Andric break;
389b1c73532SDimitry Andric case CTFType::eConst:
3907fa27ce4SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddConstModifier();
3917fa27ce4SDimitry Andric break;
392b1c73532SDimitry Andric case CTFType::eVolatile:
3937fa27ce4SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier();
3947fa27ce4SDimitry Andric break;
395b1c73532SDimitry Andric case CTFType::eRestrict:
3967fa27ce4SDimitry Andric compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier();
3977fa27ce4SDimitry Andric break;
3987fa27ce4SDimitry Andric default:
3997fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
400b1c73532SDimitry Andric llvm::formatv("ParseModifier called with unsupported kind: {0}",
401b1c73532SDimitry Andric ctf_modifier.kind),
4027fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
4037fa27ce4SDimitry Andric }
4047fa27ce4SDimitry Andric
4057fa27ce4SDimitry Andric Declaration decl;
406b1c73532SDimitry Andric return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,
4077fa27ce4SDimitry Andric Type::eEncodingIsUID, decl, compiler_type,
4087fa27ce4SDimitry Andric lldb_private::Type::ResolveState::Full);
4097fa27ce4SDimitry Andric }
4107fa27ce4SDimitry Andric
411b1c73532SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateTypedef(const CTFTypedef & ctf_typedef)412b1c73532SDimitry Andric SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) {
413b1c73532SDimitry Andric Type *underlying_type = ResolveTypeUID(ctf_typedef.type);
4147fa27ce4SDimitry Andric if (!underlying_type)
4157fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
416b1c73532SDimitry Andric llvm::formatv("Could not find typedef underlying type: {0}",
417b1c73532SDimitry Andric ctf_typedef.type),
4187fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
4197fa27ce4SDimitry Andric
4207fa27ce4SDimitry Andric CompilerType target_ast_type = underlying_type->GetFullCompilerType();
4217fa27ce4SDimitry Andric clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl();
4227fa27ce4SDimitry Andric CompilerType ast_typedef = target_ast_type.CreateTypedef(
423b1c73532SDimitry Andric ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0);
4247fa27ce4SDimitry Andric
4257fa27ce4SDimitry Andric Declaration decl;
426b1c73532SDimitry Andric return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr,
427b1c73532SDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
428b1c73532SDimitry Andric ast_typedef, lldb_private::Type::ResolveState::Full);
4297fa27ce4SDimitry Andric }
4307fa27ce4SDimitry Andric
431b1c73532SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateArray(const CTFArray & ctf_array)432b1c73532SDimitry Andric SymbolFileCTF::CreateArray(const CTFArray &ctf_array) {
433b1c73532SDimitry Andric Type *element_type = ResolveTypeUID(ctf_array.type);
4347fa27ce4SDimitry Andric if (!element_type)
4357fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
436b1c73532SDimitry Andric llvm::formatv("Could not find array element type: {0}", ctf_array.type),
4377fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
4387fa27ce4SDimitry Andric
4397fa27ce4SDimitry Andric std::optional<uint64_t> element_size = element_type->GetByteSize(nullptr);
4407fa27ce4SDimitry Andric if (!element_size)
4417fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
4427fa27ce4SDimitry Andric llvm::formatv("could not get element size of type: {0}",
443b1c73532SDimitry Andric ctf_array.type),
4447fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
4457fa27ce4SDimitry Andric
4467fa27ce4SDimitry Andric uint64_t size = ctf_array.nelems * *element_size;
4477fa27ce4SDimitry Andric
4487fa27ce4SDimitry Andric CompilerType compiler_type = m_ast->CreateArrayType(
4497fa27ce4SDimitry Andric element_type->GetFullCompilerType(), ctf_array.nelems,
4507fa27ce4SDimitry Andric /*is_gnu_vector*/ false);
4517fa27ce4SDimitry Andric
4527fa27ce4SDimitry Andric Declaration decl;
453b1c73532SDimitry Andric return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID,
4547fa27ce4SDimitry Andric Type::eEncodingIsUID, decl, compiler_type,
4557fa27ce4SDimitry Andric lldb_private::Type::ResolveState::Full);
4567fa27ce4SDimitry Andric }
4577fa27ce4SDimitry Andric
458b1c73532SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateEnum(const CTFEnum & ctf_enum)459b1c73532SDimitry Andric SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) {
4607fa27ce4SDimitry Andric Declaration decl;
4617fa27ce4SDimitry Andric CompilerType enum_type = m_ast->CreateEnumerationType(
462b1c73532SDimitry Andric ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(),
463b1c73532SDimitry Andric decl, m_ast->GetBasicType(eBasicTypeInt),
4647fa27ce4SDimitry Andric /*is_scoped=*/false);
4657fa27ce4SDimitry Andric
466b1c73532SDimitry Andric for (const CTFEnum::Value &value : ctf_enum.values) {
4677fa27ce4SDimitry Andric Declaration value_decl;
468b1c73532SDimitry Andric m_ast->AddEnumerationValueToEnumerationType(
469b1c73532SDimitry Andric enum_type, value_decl, value.name.data(), value.value, ctf_enum.size);
4707fa27ce4SDimitry Andric }
471b1c73532SDimitry Andric TypeSystemClang::CompleteTagDeclarationDefinition(enum_type);
4727fa27ce4SDimitry Andric
473b1c73532SDimitry Andric return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,
4747fa27ce4SDimitry Andric Type::eEncodingIsUID, decl, enum_type,
4757fa27ce4SDimitry Andric lldb_private::Type::ResolveState::Full);
4767fa27ce4SDimitry Andric }
4777fa27ce4SDimitry Andric
4787fa27ce4SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateFunction(const CTFFunction & ctf_function)479b1c73532SDimitry Andric SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) {
4807fa27ce4SDimitry Andric std::vector<CompilerType> arg_types;
481b1c73532SDimitry Andric for (uint32_t arg : ctf_function.args) {
482b1c73532SDimitry Andric if (Type *arg_type = ResolveTypeUID(arg))
4837fa27ce4SDimitry Andric arg_types.push_back(arg_type->GetFullCompilerType());
4847fa27ce4SDimitry Andric }
4857fa27ce4SDimitry Andric
486b1c73532SDimitry Andric Type *ret_type = ResolveTypeUID(ctf_function.return_type);
4877fa27ce4SDimitry Andric if (!ret_type)
4887fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
489b1c73532SDimitry Andric llvm::formatv("Could not find function return type: {0}",
490b1c73532SDimitry Andric ctf_function.return_type),
4917fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
4927fa27ce4SDimitry Andric
4937fa27ce4SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType(
4947fa27ce4SDimitry Andric ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(),
495b1c73532SDimitry Andric ctf_function.variadic, 0, clang::CallingConv::CC_C);
4967fa27ce4SDimitry Andric
4977fa27ce4SDimitry Andric Declaration decl;
498b1c73532SDimitry Andric return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr,
499b1c73532SDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,
5007fa27ce4SDimitry Andric lldb_private::Type::ResolveState::Full);
5017fa27ce4SDimitry Andric }
5027fa27ce4SDimitry Andric
5037fa27ce4SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateRecord(const CTFRecord & ctf_record)504b1c73532SDimitry Andric SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) {
505b1c73532SDimitry Andric const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind);
506b1c73532SDimitry Andric CompilerType record_type = m_ast->CreateRecordType(
507b1c73532SDimitry Andric nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(),
508b1c73532SDimitry Andric llvm::to_underlying(tag_kind), eLanguageTypeC);
509b1c73532SDimitry Andric m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record;
5107fa27ce4SDimitry Andric Declaration decl;
511b1c73532SDimitry Andric return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,
512b1c73532SDimitry Andric nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
513b1c73532SDimitry Andric decl, record_type, lldb_private::Type::ResolveState::Forward);
5147fa27ce4SDimitry Andric }
5157fa27ce4SDimitry Andric
CompleteType(CompilerType & compiler_type)516b1c73532SDimitry Andric bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {
517b1c73532SDimitry Andric // Check if we have a CTF type for the given incomplete compiler type.
518b1c73532SDimitry Andric auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType());
519b1c73532SDimitry Andric if (it == m_compiler_types.end())
520b1c73532SDimitry Andric return false;
521b1c73532SDimitry Andric
522b1c73532SDimitry Andric const CTFType *ctf_type = it->second;
523b1c73532SDimitry Andric assert(ctf_type && "m_compiler_types should only contain valid CTF types");
524b1c73532SDimitry Andric
525b1c73532SDimitry Andric // We only support resolving record types.
526b1c73532SDimitry Andric assert(llvm::isa<CTFRecord>(ctf_type));
527b1c73532SDimitry Andric
528b1c73532SDimitry Andric // Cast to the appropriate CTF type.
529b1c73532SDimitry Andric const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);
530b1c73532SDimitry Andric
531b1c73532SDimitry Andric // If any of the fields are incomplete, we cannot complete the type.
532b1c73532SDimitry Andric for (const CTFRecord::Field &field : ctf_record->fields) {
533b1c73532SDimitry Andric if (!ResolveTypeUID(field.type)) {
534b1c73532SDimitry Andric LLDB_LOG(GetLog(LLDBLog::Symbols),
535b1c73532SDimitry Andric "Cannot complete type {0} because field {1} is incomplete",
536b1c73532SDimitry Andric ctf_type->uid, field.type);
537b1c73532SDimitry Andric return false;
538b1c73532SDimitry Andric }
539b1c73532SDimitry Andric }
540b1c73532SDimitry Andric
541b1c73532SDimitry Andric // Complete the record type.
542b1c73532SDimitry Andric m_ast->StartTagDeclarationDefinition(compiler_type);
543b1c73532SDimitry Andric for (const CTFRecord::Field &field : ctf_record->fields) {
544b1c73532SDimitry Andric Type *field_type = ResolveTypeUID(field.type);
545b1c73532SDimitry Andric assert(field_type && "field must be complete");
546b1c73532SDimitry Andric const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0);
547b1c73532SDimitry Andric TypeSystemClang::AddFieldToRecordType(compiler_type, field.name,
548b1c73532SDimitry Andric field_type->GetFullCompilerType(),
549b1c73532SDimitry Andric eAccessPublic, field_size);
550b1c73532SDimitry Andric }
551b1c73532SDimitry Andric m_ast->CompleteTagDeclarationDefinition(compiler_type);
552b1c73532SDimitry Andric
553b1c73532SDimitry Andric // Now that the compiler type is complete, we don't need to remember it
554b1c73532SDimitry Andric // anymore and can remove the CTF record type.
555b1c73532SDimitry Andric m_compiler_types.erase(compiler_type.GetOpaqueQualType());
556b1c73532SDimitry Andric m_ctf_types.erase(ctf_type->uid);
557b1c73532SDimitry Andric
558b1c73532SDimitry Andric return true;
559b1c73532SDimitry Andric }
560b1c73532SDimitry Andric
561b1c73532SDimitry Andric llvm::Expected<lldb::TypeSP>
CreateForward(const CTFForward & ctf_forward)562b1c73532SDimitry Andric SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) {
563b1c73532SDimitry Andric CompilerType forward_compiler_type = m_ast->CreateRecordType(
564b1c73532SDimitry Andric nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name,
565b1c73532SDimitry Andric llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC);
566b1c73532SDimitry Andric Declaration decl;
567b1c73532SDimitry Andric return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr,
568b1c73532SDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
569b1c73532SDimitry Andric forward_compiler_type, Type::ResolveState::Forward);
570b1c73532SDimitry Andric }
571b1c73532SDimitry Andric
CreateType(CTFType * ctf_type)572b1c73532SDimitry Andric llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) {
573b1c73532SDimitry Andric if (!ctf_type)
574b1c73532SDimitry Andric return llvm::make_error<llvm::StringError>(
575b1c73532SDimitry Andric "cannot create type for unparsed type", llvm::inconvertibleErrorCode());
576b1c73532SDimitry Andric
577b1c73532SDimitry Andric switch (ctf_type->kind) {
578b1c73532SDimitry Andric case CTFType::Kind::eInteger:
579b1c73532SDimitry Andric return CreateInteger(*static_cast<CTFInteger *>(ctf_type));
580b1c73532SDimitry Andric case CTFType::Kind::eConst:
581b1c73532SDimitry Andric case CTFType::Kind::ePointer:
582b1c73532SDimitry Andric case CTFType::Kind::eRestrict:
583b1c73532SDimitry Andric case CTFType::Kind::eVolatile:
584b1c73532SDimitry Andric return CreateModifier(*static_cast<CTFModifier *>(ctf_type));
585b1c73532SDimitry Andric case CTFType::Kind::eTypedef:
586b1c73532SDimitry Andric return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type));
587b1c73532SDimitry Andric case CTFType::Kind::eArray:
588b1c73532SDimitry Andric return CreateArray(*static_cast<CTFArray *>(ctf_type));
589b1c73532SDimitry Andric case CTFType::Kind::eEnum:
590b1c73532SDimitry Andric return CreateEnum(*static_cast<CTFEnum *>(ctf_type));
591b1c73532SDimitry Andric case CTFType::Kind::eFunction:
592b1c73532SDimitry Andric return CreateFunction(*static_cast<CTFFunction *>(ctf_type));
593b1c73532SDimitry Andric case CTFType::Kind::eStruct:
594b1c73532SDimitry Andric case CTFType::Kind::eUnion:
595b1c73532SDimitry Andric return CreateRecord(*static_cast<CTFRecord *>(ctf_type));
596b1c73532SDimitry Andric case CTFType::Kind::eForward:
597b1c73532SDimitry Andric return CreateForward(*static_cast<CTFForward *>(ctf_type));
598b1c73532SDimitry Andric case CTFType::Kind::eUnknown:
599b1c73532SDimitry Andric case CTFType::Kind::eFloat:
600b1c73532SDimitry Andric case CTFType::Kind::eSlice:
601b1c73532SDimitry Andric return llvm::make_error<llvm::StringError>(
602b1c73532SDimitry Andric llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})",
603b1c73532SDimitry Andric ctf_type->uid, ctf_type->name, ctf_type->kind),
604b1c73532SDimitry Andric llvm::inconvertibleErrorCode());
605b1c73532SDimitry Andric }
6064df029ccSDimitry Andric llvm_unreachable("Unexpected CTF type kind");
607b1c73532SDimitry Andric }
608b1c73532SDimitry Andric
609b1c73532SDimitry Andric llvm::Expected<std::unique_ptr<CTFType>>
ParseType(lldb::offset_t & offset,lldb::user_id_t uid)610b1c73532SDimitry Andric SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) {
611b1c73532SDimitry Andric ctf_stype_t ctf_stype;
612b1c73532SDimitry Andric ctf_stype.name = m_data.GetU32(&offset);
613b1c73532SDimitry Andric ctf_stype.info = m_data.GetU32(&offset);
614b1c73532SDimitry Andric ctf_stype.size = m_data.GetU32(&offset);
615b1c73532SDimitry Andric
616b1c73532SDimitry Andric llvm::StringRef name = ReadString(ctf_stype.name);
617b1c73532SDimitry Andric const uint32_t kind = GetKind(ctf_stype.info);
618b1c73532SDimitry Andric const uint32_t variable_length = GetVLen(ctf_stype.info);
619b1c73532SDimitry Andric const uint32_t type = ctf_stype.GetType();
620b1c73532SDimitry Andric const uint32_t size = ctf_stype.GetSize();
621b1c73532SDimitry Andric
6227fa27ce4SDimitry Andric switch (kind) {
623b1c73532SDimitry Andric case TypeKind::eInteger: {
624b1c73532SDimitry Andric const uint32_t vdata = m_data.GetU32(&offset);
625b1c73532SDimitry Andric const uint32_t bits = GetBits(vdata);
626b1c73532SDimitry Andric const uint32_t encoding = GetEncoding(vdata);
627b1c73532SDimitry Andric return std::make_unique<CTFInteger>(uid, name, bits, encoding);
628b1c73532SDimitry Andric }
6297fa27ce4SDimitry Andric case TypeKind::eConst:
630b1c73532SDimitry Andric return std::make_unique<CTFConst>(uid, type);
6317fa27ce4SDimitry Andric case TypeKind::ePointer:
632b1c73532SDimitry Andric return std::make_unique<CTFPointer>(uid, type);
6337fa27ce4SDimitry Andric case TypeKind::eRestrict:
634b1c73532SDimitry Andric return std::make_unique<CTFRestrict>(uid, type);
6357fa27ce4SDimitry Andric case TypeKind::eVolatile:
636b1c73532SDimitry Andric return std::make_unique<CTFVolatile>(uid, type);
6377fa27ce4SDimitry Andric case TypeKind::eTypedef:
638b1c73532SDimitry Andric return std::make_unique<CTFTypedef>(uid, name, type);
639b1c73532SDimitry Andric case TypeKind::eArray: {
640b1c73532SDimitry Andric const uint32_t type = m_data.GetU32(&offset);
641b1c73532SDimitry Andric const uint32_t index = m_data.GetU32(&offset);
642b1c73532SDimitry Andric const uint32_t nelems = m_data.GetU32(&offset);
643b1c73532SDimitry Andric return std::make_unique<CTFArray>(uid, name, type, index, nelems);
644b1c73532SDimitry Andric }
645b1c73532SDimitry Andric case TypeKind::eEnum: {
646b1c73532SDimitry Andric std::vector<CTFEnum::Value> values;
647b1c73532SDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) {
648b1c73532SDimitry Andric const uint32_t value_name = m_data.GetU32(&offset);
649b1c73532SDimitry Andric const uint32_t value = m_data.GetU32(&offset);
650b1c73532SDimitry Andric values.emplace_back(ReadString(value_name), value);
651b1c73532SDimitry Andric }
652b1c73532SDimitry Andric return std::make_unique<CTFEnum>(uid, name, variable_length, size, values);
653b1c73532SDimitry Andric }
654b1c73532SDimitry Andric case TypeKind::eFunction: {
655b1c73532SDimitry Andric std::vector<uint32_t> args;
656b1c73532SDimitry Andric bool variadic = false;
657b1c73532SDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) {
658b1c73532SDimitry Andric const uint32_t arg_uid = m_data.GetU32(&offset);
659b1c73532SDimitry Andric // If the last argument is 0, this is a variadic function.
660b1c73532SDimitry Andric if (arg_uid == 0) {
661b1c73532SDimitry Andric variadic = true;
662b1c73532SDimitry Andric break;
663b1c73532SDimitry Andric }
664b1c73532SDimitry Andric args.push_back(arg_uid);
665b1c73532SDimitry Andric }
666b1c73532SDimitry Andric // If the number of arguments is odd, a single uint32_t of padding is
667b1c73532SDimitry Andric // inserted to maintain alignment.
668b1c73532SDimitry Andric if (variable_length % 2 == 1)
669b1c73532SDimitry Andric m_data.GetU32(&offset);
670b1c73532SDimitry Andric return std::make_unique<CTFFunction>(uid, name, variable_length, type, args,
671b1c73532SDimitry Andric variadic);
672b1c73532SDimitry Andric }
6737fa27ce4SDimitry Andric case TypeKind::eStruct:
674b1c73532SDimitry Andric case TypeKind::eUnion: {
675b1c73532SDimitry Andric std::vector<CTFRecord::Field> fields;
676b1c73532SDimitry Andric for (uint32_t i = 0; i < variable_length; ++i) {
677b1c73532SDimitry Andric const uint32_t field_name = m_data.GetU32(&offset);
678b1c73532SDimitry Andric const uint32_t type = m_data.GetU32(&offset);
679b1c73532SDimitry Andric uint64_t field_offset = 0;
680b1c73532SDimitry Andric if (size < g_ctf_field_threshold) {
681b1c73532SDimitry Andric field_offset = m_data.GetU16(&offset);
682b1c73532SDimitry Andric m_data.GetU16(&offset); // Padding
683b1c73532SDimitry Andric } else {
684b1c73532SDimitry Andric const uint32_t offset_hi = m_data.GetU32(&offset);
685b1c73532SDimitry Andric const uint32_t offset_lo = m_data.GetU32(&offset);
686b1c73532SDimitry Andric field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo);
687b1c73532SDimitry Andric }
688b1c73532SDimitry Andric fields.emplace_back(ReadString(field_name), type, field_offset);
689b1c73532SDimitry Andric }
690b1c73532SDimitry Andric return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid,
691b1c73532SDimitry Andric name, variable_length, size, fields);
692b1c73532SDimitry Andric }
6937fa27ce4SDimitry Andric case TypeKind::eForward:
694b1c73532SDimitry Andric return std::make_unique<CTFForward>(uid, name);
6957fa27ce4SDimitry Andric case TypeKind::eUnknown:
696b1c73532SDimitry Andric return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid,
697b1c73532SDimitry Andric name);
698b1c73532SDimitry Andric case TypeKind::eFloat:
699b1c73532SDimitry Andric case TypeKind::eSlice:
7007fa27ce4SDimitry Andric offset += (variable_length * sizeof(uint32_t));
7017fa27ce4SDimitry Andric break;
7027fa27ce4SDimitry Andric }
703b1c73532SDimitry Andric
7047fa27ce4SDimitry Andric return llvm::make_error<llvm::StringError>(
7057fa27ce4SDimitry Andric llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})",
7067fa27ce4SDimitry Andric name, kind, variable_length),
7077fa27ce4SDimitry Andric llvm::inconvertibleErrorCode());
7087fa27ce4SDimitry Andric }
7097fa27ce4SDimitry Andric
ParseTypes(CompileUnit & cu)7107fa27ce4SDimitry Andric size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {
7117fa27ce4SDimitry Andric if (!ParseHeader())
7127fa27ce4SDimitry Andric return 0;
7137fa27ce4SDimitry Andric
7147fa27ce4SDimitry Andric if (!m_types.empty())
7157fa27ce4SDimitry Andric return 0;
7167fa27ce4SDimitry Andric
7177fa27ce4SDimitry Andric if (!m_ast)
7187fa27ce4SDimitry Andric return 0;
7197fa27ce4SDimitry Andric
7207fa27ce4SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
7217fa27ce4SDimitry Andric LLDB_LOG(log, "Parsing CTF types");
7227fa27ce4SDimitry Andric
7237fa27ce4SDimitry Andric lldb::offset_t type_offset = m_body_offset + m_header->typeoff;
7247fa27ce4SDimitry Andric const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff;
7257fa27ce4SDimitry Andric
7267fa27ce4SDimitry Andric lldb::user_id_t type_uid = 1;
7277fa27ce4SDimitry Andric while (type_offset < type_offset_end) {
728b1c73532SDimitry Andric llvm::Expected<std::unique_ptr<CTFType>> type_or_error =
729b1c73532SDimitry Andric ParseType(type_offset, type_uid);
730b1c73532SDimitry Andric if (type_or_error) {
731b1c73532SDimitry Andric m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error);
732b1c73532SDimitry Andric } else {
7337fa27ce4SDimitry Andric LLDB_LOG_ERROR(log, type_or_error.takeError(),
7347fa27ce4SDimitry Andric "Failed to parse type {1} at offset {2}: {0}", type_uid,
7357fa27ce4SDimitry Andric type_offset);
7367fa27ce4SDimitry Andric }
737b1c73532SDimitry Andric type_uid++;
7387fa27ce4SDimitry Andric }
7397fa27ce4SDimitry Andric
740b1c73532SDimitry Andric LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size());
7417fa27ce4SDimitry Andric
742b1c73532SDimitry Andric for (lldb::user_id_t uid = 1; uid < type_uid; ++uid)
743b1c73532SDimitry Andric ResolveTypeUID(uid);
744b1c73532SDimitry Andric
745b1c73532SDimitry Andric LLDB_LOG(log, "Created {0} CTF types", m_types.size());
7467fa27ce4SDimitry Andric
7477fa27ce4SDimitry Andric return m_types.size();
7487fa27ce4SDimitry Andric }
7497fa27ce4SDimitry Andric
ParseFunctions(CompileUnit & cu)7507fa27ce4SDimitry Andric size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) {
7517fa27ce4SDimitry Andric if (!ParseHeader())
7527fa27ce4SDimitry Andric return 0;
7537fa27ce4SDimitry Andric
7547fa27ce4SDimitry Andric if (!m_functions.empty())
7557fa27ce4SDimitry Andric return 0;
7567fa27ce4SDimitry Andric
7577fa27ce4SDimitry Andric if (!m_ast)
7587fa27ce4SDimitry Andric return 0;
7597fa27ce4SDimitry Andric
7607fa27ce4SDimitry Andric Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab();
7617fa27ce4SDimitry Andric if (!symtab)
7627fa27ce4SDimitry Andric return 0;
7637fa27ce4SDimitry Andric
7647fa27ce4SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
7657fa27ce4SDimitry Andric LLDB_LOG(log, "Parsing CTF functions");
7667fa27ce4SDimitry Andric
7677fa27ce4SDimitry Andric lldb::offset_t function_offset = m_body_offset + m_header->funcoff;
7687fa27ce4SDimitry Andric const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff;
7697fa27ce4SDimitry Andric
7707fa27ce4SDimitry Andric uint32_t symbol_idx = 0;
7717fa27ce4SDimitry Andric Declaration decl;
7727fa27ce4SDimitry Andric while (function_offset < function_offset_end) {
7737fa27ce4SDimitry Andric const uint32_t info = m_data.GetU32(&function_offset);
7747fa27ce4SDimitry Andric const uint16_t kind = GetKind(info);
7757fa27ce4SDimitry Andric const uint16_t variable_length = GetVLen(info);
7767fa27ce4SDimitry Andric
7777fa27ce4SDimitry Andric Symbol *symbol = symtab->FindSymbolWithType(
7787fa27ce4SDimitry Andric eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx);
7797fa27ce4SDimitry Andric
7807fa27ce4SDimitry Andric // Skip padding.
7817fa27ce4SDimitry Andric if (kind == TypeKind::eUnknown && variable_length == 0)
7827fa27ce4SDimitry Andric continue;
7837fa27ce4SDimitry Andric
7847fa27ce4SDimitry Andric // Skip unexpected kinds.
7857fa27ce4SDimitry Andric if (kind != TypeKind::eFunction)
7867fa27ce4SDimitry Andric continue;
7877fa27ce4SDimitry Andric
7887fa27ce4SDimitry Andric const uint32_t ret_uid = m_data.GetU32(&function_offset);
7897fa27ce4SDimitry Andric const uint32_t num_args = variable_length;
7907fa27ce4SDimitry Andric
7917fa27ce4SDimitry Andric std::vector<CompilerType> arg_types;
7927fa27ce4SDimitry Andric arg_types.reserve(num_args);
7937fa27ce4SDimitry Andric
7947fa27ce4SDimitry Andric bool is_variadic = false;
7957fa27ce4SDimitry Andric for (uint32_t i = 0; i < variable_length; i++) {
7967fa27ce4SDimitry Andric const uint32_t arg_uid = m_data.GetU32(&function_offset);
7977fa27ce4SDimitry Andric
7987fa27ce4SDimitry Andric // If the last argument is 0, this is a variadic function.
7997fa27ce4SDimitry Andric if (arg_uid == 0) {
8007fa27ce4SDimitry Andric is_variadic = true;
8017fa27ce4SDimitry Andric break;
8027fa27ce4SDimitry Andric }
8037fa27ce4SDimitry Andric
804b1c73532SDimitry Andric Type *arg_type = ResolveTypeUID(arg_uid);
805ac9a064cSDimitry Andric arg_types.push_back(arg_type ? arg_type->GetFullCompilerType()
806ac9a064cSDimitry Andric : CompilerType());
8077fa27ce4SDimitry Andric }
8087fa27ce4SDimitry Andric
8097fa27ce4SDimitry Andric if (symbol) {
810b1c73532SDimitry Andric Type *ret_type = ResolveTypeUID(ret_uid);
8117fa27ce4SDimitry Andric AddressRange func_range =
8127fa27ce4SDimitry Andric AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(),
8137fa27ce4SDimitry Andric GetObjectFile()->GetModule()->GetSectionList());
8147fa27ce4SDimitry Andric
8157fa27ce4SDimitry Andric // Create function type.
8167fa27ce4SDimitry Andric CompilerType func_type = m_ast->CreateFunctionType(
817ac9a064cSDimitry Andric ret_type ? ret_type->GetFullCompilerType() : CompilerType(),
818ac9a064cSDimitry Andric arg_types.data(), arg_types.size(), is_variadic, 0,
819ac9a064cSDimitry Andric clang::CallingConv::CC_C);
8207fa27ce4SDimitry Andric lldb::user_id_t function_type_uid = m_types.size() + 1;
8217fa27ce4SDimitry Andric TypeSP type_sp =
8227fa27ce4SDimitry Andric MakeType(function_type_uid, symbol->GetName(), 0, nullptr,
8237fa27ce4SDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,
8247fa27ce4SDimitry Andric lldb_private::Type::ResolveState::Full);
825b1c73532SDimitry Andric m_types[function_type_uid] = type_sp;
8267fa27ce4SDimitry Andric
8277fa27ce4SDimitry Andric // Create function.
8287fa27ce4SDimitry Andric lldb::user_id_t func_uid = m_functions.size();
8297fa27ce4SDimitry Andric FunctionSP function_sp = std::make_shared<Function>(
8307fa27ce4SDimitry Andric &cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(),
8317fa27ce4SDimitry Andric func_range);
8327fa27ce4SDimitry Andric m_functions.emplace_back(function_sp);
8337fa27ce4SDimitry Andric cu.AddFunction(function_sp);
8347fa27ce4SDimitry Andric }
8357fa27ce4SDimitry Andric }
8367fa27ce4SDimitry Andric
8377fa27ce4SDimitry Andric LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size());
8387fa27ce4SDimitry Andric
8397fa27ce4SDimitry Andric return m_functions.size();
8407fa27ce4SDimitry Andric }
8417fa27ce4SDimitry Andric
CreateDWARFExpression(ModuleSP module_sp,const Symbol & symbol)8427fa27ce4SDimitry Andric static DWARFExpression CreateDWARFExpression(ModuleSP module_sp,
8437fa27ce4SDimitry Andric const Symbol &symbol) {
8447fa27ce4SDimitry Andric if (!module_sp)
8457fa27ce4SDimitry Andric return DWARFExpression();
8467fa27ce4SDimitry Andric
8477fa27ce4SDimitry Andric const ArchSpec &architecture = module_sp->GetArchitecture();
8487fa27ce4SDimitry Andric ByteOrder byte_order = architecture.GetByteOrder();
8497fa27ce4SDimitry Andric uint32_t address_size = architecture.GetAddressByteSize();
8507fa27ce4SDimitry Andric uint32_t byte_size = architecture.GetDataByteSize();
8517fa27ce4SDimitry Andric
8527fa27ce4SDimitry Andric StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
8537fa27ce4SDimitry Andric stream.PutHex8(lldb_private::dwarf::DW_OP_addr);
8547fa27ce4SDimitry Andric stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order);
8557fa27ce4SDimitry Andric
8567fa27ce4SDimitry Andric DataBufferSP buffer =
8577fa27ce4SDimitry Andric std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
8587fa27ce4SDimitry Andric lldb_private::DataExtractor extractor(buffer, byte_order, address_size,
8597fa27ce4SDimitry Andric byte_size);
8607fa27ce4SDimitry Andric DWARFExpression result(extractor);
8617fa27ce4SDimitry Andric result.SetRegisterKind(eRegisterKindDWARF);
8627fa27ce4SDimitry Andric
8637fa27ce4SDimitry Andric return result;
8647fa27ce4SDimitry Andric }
8657fa27ce4SDimitry Andric
ParseObjects(CompileUnit & comp_unit)8667fa27ce4SDimitry Andric size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) {
8677fa27ce4SDimitry Andric if (!ParseHeader())
8687fa27ce4SDimitry Andric return 0;
8697fa27ce4SDimitry Andric
8707fa27ce4SDimitry Andric if (!m_variables.empty())
8717fa27ce4SDimitry Andric return 0;
8727fa27ce4SDimitry Andric
8737fa27ce4SDimitry Andric if (!m_ast)
8747fa27ce4SDimitry Andric return 0;
8757fa27ce4SDimitry Andric
8767fa27ce4SDimitry Andric ModuleSP module_sp = GetObjectFile()->GetModule();
8777fa27ce4SDimitry Andric Symtab *symtab = module_sp->GetSymtab();
8787fa27ce4SDimitry Andric if (!symtab)
8797fa27ce4SDimitry Andric return 0;
8807fa27ce4SDimitry Andric
8817fa27ce4SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
8827fa27ce4SDimitry Andric LLDB_LOG(log, "Parsing CTF objects");
8837fa27ce4SDimitry Andric
8847fa27ce4SDimitry Andric lldb::offset_t object_offset = m_body_offset + m_header->objtoff;
8857fa27ce4SDimitry Andric const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff;
8867fa27ce4SDimitry Andric
8877fa27ce4SDimitry Andric uint32_t symbol_idx = 0;
8887fa27ce4SDimitry Andric Declaration decl;
8897fa27ce4SDimitry Andric while (object_offset < object_offset_end) {
8907fa27ce4SDimitry Andric const uint32_t type_uid = m_data.GetU32(&object_offset);
8917fa27ce4SDimitry Andric
8927fa27ce4SDimitry Andric if (Symbol *symbol =
8937fa27ce4SDimitry Andric symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes,
8947fa27ce4SDimitry Andric Symtab::eVisibilityAny, symbol_idx)) {
8957fa27ce4SDimitry Andric Variable::RangeList ranges;
8967fa27ce4SDimitry Andric ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize());
8977fa27ce4SDimitry Andric
8987fa27ce4SDimitry Andric auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid);
8997fa27ce4SDimitry Andric
9007fa27ce4SDimitry Andric DWARFExpressionList location(
9017fa27ce4SDimitry Andric module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr);
9027fa27ce4SDimitry Andric
9037fa27ce4SDimitry Andric lldb::user_id_t variable_type_uid = m_variables.size();
9047fa27ce4SDimitry Andric m_variables.emplace_back(std::make_shared<Variable>(
9057fa27ce4SDimitry Andric variable_type_uid, symbol->GetName().AsCString(),
9067fa27ce4SDimitry Andric symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal,
9077fa27ce4SDimitry Andric m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(),
9087fa27ce4SDimitry Andric /*artificial=*/false,
9097fa27ce4SDimitry Andric /*location_is_constant_data*/ false));
9107fa27ce4SDimitry Andric }
9117fa27ce4SDimitry Andric }
9127fa27ce4SDimitry Andric
9137fa27ce4SDimitry Andric LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size());
9147fa27ce4SDimitry Andric
9157fa27ce4SDimitry Andric return m_variables.size();
9167fa27ce4SDimitry Andric }
9177fa27ce4SDimitry Andric
CalculateAbilities()9187fa27ce4SDimitry Andric uint32_t SymbolFileCTF::CalculateAbilities() {
9197fa27ce4SDimitry Andric if (!m_objfile_sp)
9207fa27ce4SDimitry Andric return 0;
9217fa27ce4SDimitry Andric
9227fa27ce4SDimitry Andric if (!ParseHeader())
9237fa27ce4SDimitry Andric return 0;
9247fa27ce4SDimitry Andric
9257fa27ce4SDimitry Andric return VariableTypes | Functions | GlobalVariables;
9267fa27ce4SDimitry Andric }
9277fa27ce4SDimitry Andric
ResolveSymbolContext(const Address & so_addr,SymbolContextItem resolve_scope,SymbolContext & sc)9287fa27ce4SDimitry Andric uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr,
9297fa27ce4SDimitry Andric SymbolContextItem resolve_scope,
9307fa27ce4SDimitry Andric SymbolContext &sc) {
9317fa27ce4SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
9327fa27ce4SDimitry Andric if (m_objfile_sp->GetSymtab() == nullptr)
9337fa27ce4SDimitry Andric return 0;
9347fa27ce4SDimitry Andric
9357fa27ce4SDimitry Andric uint32_t resolved_flags = 0;
9367fa27ce4SDimitry Andric
9377fa27ce4SDimitry Andric // Resolve symbols.
9387fa27ce4SDimitry Andric if (resolve_scope & eSymbolContextSymbol) {
9397fa27ce4SDimitry Andric sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(
9407fa27ce4SDimitry Andric so_addr.GetFileAddress());
9417fa27ce4SDimitry Andric if (sc.symbol)
9427fa27ce4SDimitry Andric resolved_flags |= eSymbolContextSymbol;
9437fa27ce4SDimitry Andric }
9447fa27ce4SDimitry Andric
9457fa27ce4SDimitry Andric // Resolve functions.
9467fa27ce4SDimitry Andric if (resolve_scope & eSymbolContextFunction) {
9477fa27ce4SDimitry Andric for (FunctionSP function_sp : m_functions) {
9487fa27ce4SDimitry Andric if (function_sp->GetAddressRange().ContainsFileAddress(
9497fa27ce4SDimitry Andric so_addr.GetFileAddress())) {
9507fa27ce4SDimitry Andric sc.function = function_sp.get();
9517fa27ce4SDimitry Andric resolved_flags |= eSymbolContextFunction;
9527fa27ce4SDimitry Andric break;
9537fa27ce4SDimitry Andric }
9547fa27ce4SDimitry Andric }
9557fa27ce4SDimitry Andric }
9567fa27ce4SDimitry Andric
9577fa27ce4SDimitry Andric // Resolve variables.
9587fa27ce4SDimitry Andric if (resolve_scope & eSymbolContextVariable) {
9597fa27ce4SDimitry Andric for (VariableSP variable_sp : m_variables) {
9607fa27ce4SDimitry Andric if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) {
9617fa27ce4SDimitry Andric sc.variable = variable_sp.get();
9627fa27ce4SDimitry Andric break;
9637fa27ce4SDimitry Andric }
9647fa27ce4SDimitry Andric }
9657fa27ce4SDimitry Andric }
9667fa27ce4SDimitry Andric
9677fa27ce4SDimitry Andric return resolved_flags;
9687fa27ce4SDimitry Andric }
9697fa27ce4SDimitry Andric
ParseCompileUnitAtIndex(uint32_t idx)9707fa27ce4SDimitry Andric CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) {
9717fa27ce4SDimitry Andric if (idx == 0)
9727fa27ce4SDimitry Andric return m_comp_unit_sp;
9737fa27ce4SDimitry Andric return {};
9747fa27ce4SDimitry Andric }
9757fa27ce4SDimitry Andric
9767fa27ce4SDimitry Andric size_t
ParseVariablesForContext(const lldb_private::SymbolContext & sc)9777fa27ce4SDimitry Andric SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
9787fa27ce4SDimitry Andric return ParseObjects(*m_comp_unit_sp);
9797fa27ce4SDimitry Andric }
9807fa27ce4SDimitry Andric
AddSymbols(Symtab & symtab)9817fa27ce4SDimitry Andric void SymbolFileCTF::AddSymbols(Symtab &symtab) {
9827fa27ce4SDimitry Andric // CTF does not encode symbols.
9837fa27ce4SDimitry Andric // We rely on the existing symbol table to map symbols to type.
9847fa27ce4SDimitry Andric }
9857fa27ce4SDimitry Andric
ResolveTypeUID(lldb::user_id_t type_uid)9867fa27ce4SDimitry Andric lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
987b1c73532SDimitry Andric auto type_it = m_types.find(type_uid);
988b1c73532SDimitry Andric if (type_it != m_types.end())
989b1c73532SDimitry Andric return type_it->second.get();
990b1c73532SDimitry Andric
991b1c73532SDimitry Andric auto ctf_type_it = m_ctf_types.find(type_uid);
992b1c73532SDimitry Andric if (ctf_type_it == m_ctf_types.end())
993b1c73532SDimitry Andric return nullptr;
994b1c73532SDimitry Andric
995b1c73532SDimitry Andric CTFType *ctf_type = ctf_type_it->second.get();
996b1c73532SDimitry Andric assert(ctf_type && "m_ctf_types should only contain valid CTF types");
997b1c73532SDimitry Andric
998b1c73532SDimitry Andric Log *log = GetLog(LLDBLog::Symbols);
999b1c73532SDimitry Andric
1000b1c73532SDimitry Andric llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type);
1001b1c73532SDimitry Andric if (!type_or_error) {
1002b1c73532SDimitry Andric LLDB_LOG_ERROR(log, type_or_error.takeError(),
1003b1c73532SDimitry Andric "Failed to create type for {1}: {0}", ctf_type->uid);
1004b1c73532SDimitry Andric return {};
1005b1c73532SDimitry Andric }
1006b1c73532SDimitry Andric
1007b1c73532SDimitry Andric TypeSP type_sp = *type_or_error;
1008b1c73532SDimitry Andric
1009b1c73532SDimitry Andric if (log) {
1010b1c73532SDimitry Andric StreamString ss;
1011b1c73532SDimitry Andric type_sp->Dump(&ss, true);
1012b1c73532SDimitry Andric LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(),
1013b1c73532SDimitry Andric llvm::StringRef(ss.GetString()).rtrim());
1014b1c73532SDimitry Andric }
1015b1c73532SDimitry Andric
1016b1c73532SDimitry Andric m_types[type_uid] = type_sp;
1017b1c73532SDimitry Andric
1018b1c73532SDimitry Andric // Except for record types which we'll need to complete later, we don't need
1019b1c73532SDimitry Andric // the CTF type anymore.
1020b1c73532SDimitry Andric if (!isa<CTFRecord>(ctf_type))
1021b1c73532SDimitry Andric m_ctf_types.erase(type_uid);
1022b1c73532SDimitry Andric
1023b1c73532SDimitry Andric return type_sp.get();
10247fa27ce4SDimitry Andric }
10257fa27ce4SDimitry Andric
FindTypes(const lldb_private::TypeQuery & match,lldb_private::TypeResults & results)1026312c0ed1SDimitry Andric void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,
1027312c0ed1SDimitry Andric lldb_private::TypeResults &results) {
1028312c0ed1SDimitry Andric // Make sure we haven't already searched this SymbolFile before.
1029312c0ed1SDimitry Andric if (results.AlreadySearched(this))
1030312c0ed1SDimitry Andric return;
10317fa27ce4SDimitry Andric
1032312c0ed1SDimitry Andric ConstString name = match.GetTypeBasename();
1033b1c73532SDimitry Andric for (TypeSP type_sp : GetTypeList().Types()) {
10347fa27ce4SDimitry Andric if (type_sp && type_sp->GetName() == name) {
1035312c0ed1SDimitry Andric results.InsertUnique(type_sp);
1036312c0ed1SDimitry Andric if (results.Done(match))
1037312c0ed1SDimitry Andric return;
10387fa27ce4SDimitry Andric }
10397fa27ce4SDimitry Andric }
10407fa27ce4SDimitry Andric }
10417fa27ce4SDimitry Andric
FindTypesByRegex(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::TypeMap & types)10427fa27ce4SDimitry Andric void SymbolFileCTF::FindTypesByRegex(
10437fa27ce4SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches,
10447fa27ce4SDimitry Andric lldb_private::TypeMap &types) {
10457fa27ce4SDimitry Andric ParseTypes(*m_comp_unit_sp);
10467fa27ce4SDimitry Andric
10477fa27ce4SDimitry Andric size_t matches = 0;
1048b1c73532SDimitry Andric for (TypeSP type_sp : GetTypeList().Types()) {
10497fa27ce4SDimitry Andric if (matches == max_matches)
10507fa27ce4SDimitry Andric break;
10517fa27ce4SDimitry Andric if (type_sp && regex.Execute(type_sp->GetName()))
10527fa27ce4SDimitry Andric types.Insert(type_sp);
10537fa27ce4SDimitry Andric matches++;
10547fa27ce4SDimitry Andric }
10557fa27ce4SDimitry Andric }
10567fa27ce4SDimitry Andric
FindFunctions(const lldb_private::Module::LookupInfo & lookup_info,const lldb_private::CompilerDeclContext & parent_decl_ctx,bool include_inlines,lldb_private::SymbolContextList & sc_list)10577fa27ce4SDimitry Andric void SymbolFileCTF::FindFunctions(
10587fa27ce4SDimitry Andric const lldb_private::Module::LookupInfo &lookup_info,
10597fa27ce4SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx,
10607fa27ce4SDimitry Andric bool include_inlines, lldb_private::SymbolContextList &sc_list) {
10617fa27ce4SDimitry Andric ParseFunctions(*m_comp_unit_sp);
10627fa27ce4SDimitry Andric
10637fa27ce4SDimitry Andric ConstString name = lookup_info.GetLookupName();
10647fa27ce4SDimitry Andric for (FunctionSP function_sp : m_functions) {
10657fa27ce4SDimitry Andric if (function_sp && function_sp->GetName() == name) {
10667fa27ce4SDimitry Andric lldb_private::SymbolContext sc;
10677fa27ce4SDimitry Andric sc.comp_unit = m_comp_unit_sp.get();
10687fa27ce4SDimitry Andric sc.function = function_sp.get();
10697fa27ce4SDimitry Andric sc_list.Append(sc);
10707fa27ce4SDimitry Andric }
10717fa27ce4SDimitry Andric }
10727fa27ce4SDimitry Andric }
10737fa27ce4SDimitry Andric
FindFunctions(const lldb_private::RegularExpression & regex,bool include_inlines,lldb_private::SymbolContextList & sc_list)10747fa27ce4SDimitry Andric void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression ®ex,
10757fa27ce4SDimitry Andric bool include_inlines,
10767fa27ce4SDimitry Andric lldb_private::SymbolContextList &sc_list) {
10777fa27ce4SDimitry Andric for (FunctionSP function_sp : m_functions) {
10787fa27ce4SDimitry Andric if (function_sp && regex.Execute(function_sp->GetName())) {
10797fa27ce4SDimitry Andric lldb_private::SymbolContext sc;
10807fa27ce4SDimitry Andric sc.comp_unit = m_comp_unit_sp.get();
10817fa27ce4SDimitry Andric sc.function = function_sp.get();
10827fa27ce4SDimitry Andric sc_list.Append(sc);
10837fa27ce4SDimitry Andric }
10847fa27ce4SDimitry Andric }
10857fa27ce4SDimitry Andric }
10867fa27ce4SDimitry Andric
FindGlobalVariables(lldb_private::ConstString name,const lldb_private::CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,lldb_private::VariableList & variables)10877fa27ce4SDimitry Andric void SymbolFileCTF::FindGlobalVariables(
10887fa27ce4SDimitry Andric lldb_private::ConstString name,
10897fa27ce4SDimitry Andric const lldb_private::CompilerDeclContext &parent_decl_ctx,
10907fa27ce4SDimitry Andric uint32_t max_matches, lldb_private::VariableList &variables) {
10917fa27ce4SDimitry Andric ParseObjects(*m_comp_unit_sp);
10927fa27ce4SDimitry Andric
10937fa27ce4SDimitry Andric size_t matches = 0;
10947fa27ce4SDimitry Andric for (VariableSP variable_sp : m_variables) {
10957fa27ce4SDimitry Andric if (matches == max_matches)
10967fa27ce4SDimitry Andric break;
10977fa27ce4SDimitry Andric if (variable_sp && variable_sp->GetName() == name) {
10987fa27ce4SDimitry Andric variables.AddVariable(variable_sp);
10997fa27ce4SDimitry Andric matches++;
11007fa27ce4SDimitry Andric }
11017fa27ce4SDimitry Andric }
11027fa27ce4SDimitry Andric }
11037fa27ce4SDimitry Andric
FindGlobalVariables(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::VariableList & variables)11047fa27ce4SDimitry Andric void SymbolFileCTF::FindGlobalVariables(
11057fa27ce4SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches,
11067fa27ce4SDimitry Andric lldb_private::VariableList &variables) {
11077fa27ce4SDimitry Andric ParseObjects(*m_comp_unit_sp);
11087fa27ce4SDimitry Andric
11097fa27ce4SDimitry Andric size_t matches = 0;
11107fa27ce4SDimitry Andric for (VariableSP variable_sp : m_variables) {
11117fa27ce4SDimitry Andric if (matches == max_matches)
11127fa27ce4SDimitry Andric break;
11137fa27ce4SDimitry Andric if (variable_sp && regex.Execute(variable_sp->GetName())) {
11147fa27ce4SDimitry Andric variables.AddVariable(variable_sp);
11157fa27ce4SDimitry Andric matches++;
11167fa27ce4SDimitry Andric }
11177fa27ce4SDimitry Andric }
11187fa27ce4SDimitry Andric }
1119