Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
39644 views
//===-- SymbolFileCTF.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "SymbolFileCTF.h"910#include "lldb/Core/Module.h"11#include "lldb/Core/PluginManager.h"12#include "lldb/Host/Config.h"13#include "lldb/Symbol/CompileUnit.h"14#include "lldb/Symbol/Function.h"15#include "lldb/Symbol/ObjectFile.h"16#include "lldb/Symbol/Symbol.h"17#include "lldb/Symbol/SymbolContext.h"18#include "lldb/Symbol/Symtab.h"19#include "lldb/Symbol/TypeList.h"20#include "lldb/Symbol/TypeMap.h"21#include "lldb/Symbol/Variable.h"22#include "lldb/Symbol/VariableList.h"23#include "lldb/Utility/DataExtractor.h"24#include "lldb/Utility/LLDBLog.h"25#include "lldb/Utility/Log.h"26#include "lldb/Utility/RegularExpression.h"27#include "lldb/Utility/StreamBuffer.h"28#include "lldb/Utility/StreamString.h"29#include "lldb/Utility/Timer.h"30#include "llvm/Support/MemoryBuffer.h"3132#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"33#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"3435#include <memory>36#include <optional>3738#if LLVM_ENABLE_ZLIB39#include <zlib.h>40#endif4142using namespace llvm;43using namespace lldb;44using namespace lldb_private;4546LLDB_PLUGIN_DEFINE(SymbolFileCTF)4748char SymbolFileCTF::ID;4950SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp)51: SymbolFileCommon(std::move(objfile_sp)) {}5253void SymbolFileCTF::Initialize() {54PluginManager::RegisterPlugin(GetPluginNameStatic(),55GetPluginDescriptionStatic(), CreateInstance);56}5758void SymbolFileCTF::Terminate() {59PluginManager::UnregisterPlugin(CreateInstance);60}6162llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() {63return "Compact C Type Format Symbol Reader";64}6566SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) {67return new SymbolFileCTF(std::move(objfile_sp));68}6970bool SymbolFileCTF::ParseHeader() {71if (m_header)72return true;7374Log *log = GetLog(LLDBLog::Symbols);7576ModuleSP module_sp(m_objfile_sp->GetModule());77const SectionList *section_list = module_sp->GetSectionList();78if (!section_list)79return false;8081SectionSP section_sp(82section_list->FindSectionByType(lldb::eSectionTypeCTF, true));83if (!section_sp)84return false;8586m_objfile_sp->ReadSectionData(section_sp.get(), m_data);8788if (m_data.GetByteSize() == 0)89return false;9091StreamString module_desc;92GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),93lldb::eDescriptionLevelBrief);94LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData());9596lldb::offset_t offset = 0;9798// Parse CTF header.99constexpr size_t ctf_header_size = sizeof(ctf_header_t);100if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) {101LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header");102return false;103}104105m_header.emplace();106107ctf_header_t &ctf_header = *m_header;108ctf_header.preamble.magic = m_data.GetU16(&offset);109ctf_header.preamble.version = m_data.GetU8(&offset);110ctf_header.preamble.flags = m_data.GetU8(&offset);111ctf_header.parlabel = m_data.GetU32(&offset);112ctf_header.parname = m_data.GetU32(&offset);113ctf_header.lbloff = m_data.GetU32(&offset);114ctf_header.objtoff = m_data.GetU32(&offset);115ctf_header.funcoff = m_data.GetU32(&offset);116ctf_header.typeoff = m_data.GetU32(&offset);117ctf_header.stroff = m_data.GetU32(&offset);118ctf_header.strlen = m_data.GetU32(&offset);119120// Validate the preamble.121if (ctf_header.preamble.magic != g_ctf_magic) {122LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}",123ctf_header.preamble.magic);124return false;125}126127if (ctf_header.preamble.version != g_ctf_version) {128LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}",129ctf_header.preamble.version);130return false;131}132133LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}",134ctf_header.preamble.version, ctf_header.preamble.flags);135136m_body_offset = offset;137138if (ctf_header.preamble.flags & eFlagCompress) {139// The body has been compressed with zlib deflate. Header offsets point into140// the decompressed data.141#if LLVM_ENABLE_ZLIB142const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen;143DataBufferSP decompressed_data =144std::make_shared<DataBufferHeap>(decompressed_size, 0x0);145146z_stream zstr;147memset(&zstr, 0, sizeof(zstr));148zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() +149sizeof(ctf_header_t));150zstr.avail_in = m_data.BytesLeft(offset);151zstr.next_out =152(Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes());153zstr.avail_out = decompressed_size;154155int rc = inflateInit(&zstr);156if (rc != Z_OK) {157LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}",158zError(rc));159return false;160}161162rc = inflate(&zstr, Z_FINISH);163if (rc != Z_STREAM_END) {164LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc));165return false;166}167168rc = inflateEnd(&zstr);169if (rc != Z_OK) {170LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc));171return false;172}173174if (zstr.total_out != decompressed_size) {175LLDB_LOG(log,176"CTF parsing failed: decompressed size ({0}) doesn't match "177"expected size ([1})",178zstr.total_out, decompressed_size);179return false;180}181182m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(),183m_data.GetAddressByteSize());184m_body_offset = 0;185#else186LLDB_LOG(187log,188"CTF parsing failed: data is compressed but no zlib inflate support");189return false;190#endif191}192193// Validate the header.194if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) {195LLDB_LOG(log,196"CTF parsing failed: invalid label section offset in header: {0}",197ctf_header.lbloff);198return false;199}200201if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) {202LLDB_LOG(log,203"CTF parsing failed: invalid object section offset in header: {0}",204ctf_header.objtoff);205return false;206}207208if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) {209LLDB_LOG(210log,211"CTF parsing failed: invalid function section offset in header: {0}",212ctf_header.funcoff);213return false;214}215216if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) {217LLDB_LOG(log,218"CTF parsing failed: invalid type section offset in header: {0}",219ctf_header.typeoff);220return false;221}222223if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) {224LLDB_LOG(log,225"CTF parsing failed: invalid string section offset in header: {0}",226ctf_header.stroff);227return false;228}229230const lldb::offset_t str_end_offset =231m_body_offset + ctf_header.stroff + ctf_header.strlen;232if (!m_data.ValidOffset(str_end_offset - 1)) {233LLDB_LOG(log,234"CTF parsing failed: invalid string section length in header: {0}",235ctf_header.strlen);236return false;237}238239if (m_body_offset + ctf_header.stroff + ctf_header.parlabel >240str_end_offset) {241LLDB_LOG(log,242"CTF parsing failed: invalid parent label offset: {0} exceeds end "243"of string section ({1})",244ctf_header.parlabel, str_end_offset);245return false;246}247248if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) {249LLDB_LOG(log,250"CTF parsing failed: invalid parent name offset: {0} exceeds end "251"of string section ({1})",252ctf_header.parname, str_end_offset);253return false;254}255256LLDB_LOG(log,257"Parsed valid CTF header: lbloff = {0}, objtoff = {1}, funcoff = "258"{2}, typeoff = {3}, stroff = {4}, strlen = {5}",259ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff,260ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen);261262return true;263}264265void SymbolFileCTF::InitializeObject() {266Log *log = GetLog(LLDBLog::Symbols);267268auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC);269if (auto err = type_system_or_err.takeError()) {270LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}");271return;272}273274auto ts = *type_system_or_err;275m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());276LazyBool optimized = eLazyBoolNo;277m_comp_unit_sp = std::make_shared<CompileUnit>(278m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized);279280ParseTypes(*m_comp_unit_sp);281}282283llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const {284lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset;285if (!m_data.ValidOffset(offset))286return "(invalid)";287const char *str = m_data.GetCStr(&offset);288if (str && !*str)289return "(anon)";290return llvm::StringRef(str);291}292293/// Return the integer display representation encoded in the given data.294static uint32_t GetEncoding(uint32_t data) {295// Mask bits 24–31.296return ((data)&0xff000000) >> 24;297}298299/// Return the integral width in bits encoded in the given data.300static uint32_t GetBits(uint32_t data) {301// Mask bits 0-15.302return (data)&0x0000ffff;303}304305/// Return the type kind encoded in the given data.306uint32_t GetKind(uint32_t data) {307// Mask bits 26–31.308return ((data)&0xf800) >> 11;309}310311/// Return the variable length encoded in the given data.312uint32_t GetVLen(uint32_t data) {313// Mask bits 0–24.314return (data)&0x3ff;315}316317static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); }318319static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) {320switch (type) {321case CTFType::Kind::eStruct:322return clang::TagTypeKind::Struct;323case CTFType::Kind::eUnion:324return clang::TagTypeKind::Union;325default:326lldbassert(false && "Invalid record kind!");327return clang::TagTypeKind::Struct;328}329}330331llvm::Expected<TypeSP>332SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) {333lldb::BasicType basic_type =334TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name);335if (basic_type == eBasicTypeInvalid)336return llvm::make_error<llvm::StringError>(337llvm::formatv("unsupported integer type: no corresponding basic clang "338"type for '{0}'",339ctf_integer.name),340llvm::inconvertibleErrorCode());341342CompilerType compiler_type = m_ast->GetBasicType(basic_type);343344if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) {345// Make sure the type we got is an integer type.346bool compiler_type_is_signed = false;347if (!compiler_type.IsIntegerType(compiler_type_is_signed))348return llvm::make_error<llvm::StringError>(349llvm::formatv(350"Found compiler type for '{0}' but it's not an integer type: {1}",351ctf_integer.name,352compiler_type.GetDisplayTypeName().GetStringRef()),353llvm::inconvertibleErrorCode());354355// Make sure the signing matches between the CTF and the compiler type.356const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned);357if (compiler_type_is_signed != type_is_signed)358return llvm::make_error<llvm::StringError>(359llvm::formatv("Found integer compiler type for {0} but compiler type "360"is {1} and {0} is {2}",361ctf_integer.name,362compiler_type_is_signed ? "signed" : "unsigned",363type_is_signed ? "signed" : "unsigned"),364llvm::inconvertibleErrorCode());365}366367Declaration decl;368return MakeType(ctf_integer.uid, ConstString(ctf_integer.name),369GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID,370lldb_private::Type::eEncodingIsUID, decl, compiler_type,371lldb_private::Type::ResolveState::Full);372}373374llvm::Expected<lldb::TypeSP>375SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) {376Type *ref_type = ResolveTypeUID(ctf_modifier.type);377if (!ref_type)378return llvm::make_error<llvm::StringError>(379llvm::formatv("Could not find modified type: {0}", ctf_modifier.type),380llvm::inconvertibleErrorCode());381382CompilerType compiler_type;383384switch (ctf_modifier.kind) {385case CTFType::ePointer:386compiler_type = ref_type->GetFullCompilerType().GetPointerType();387break;388case CTFType::eConst:389compiler_type = ref_type->GetFullCompilerType().AddConstModifier();390break;391case CTFType::eVolatile:392compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier();393break;394case CTFType::eRestrict:395compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier();396break;397default:398return llvm::make_error<llvm::StringError>(399llvm::formatv("ParseModifier called with unsupported kind: {0}",400ctf_modifier.kind),401llvm::inconvertibleErrorCode());402}403404Declaration decl;405return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,406Type::eEncodingIsUID, decl, compiler_type,407lldb_private::Type::ResolveState::Full);408}409410llvm::Expected<lldb::TypeSP>411SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) {412Type *underlying_type = ResolveTypeUID(ctf_typedef.type);413if (!underlying_type)414return llvm::make_error<llvm::StringError>(415llvm::formatv("Could not find typedef underlying type: {0}",416ctf_typedef.type),417llvm::inconvertibleErrorCode());418419CompilerType target_ast_type = underlying_type->GetFullCompilerType();420clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl();421CompilerType ast_typedef = target_ast_type.CreateTypedef(422ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0);423424Declaration decl;425return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr,426LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,427ast_typedef, lldb_private::Type::ResolveState::Full);428}429430llvm::Expected<lldb::TypeSP>431SymbolFileCTF::CreateArray(const CTFArray &ctf_array) {432Type *element_type = ResolveTypeUID(ctf_array.type);433if (!element_type)434return llvm::make_error<llvm::StringError>(435llvm::formatv("Could not find array element type: {0}", ctf_array.type),436llvm::inconvertibleErrorCode());437438std::optional<uint64_t> element_size = element_type->GetByteSize(nullptr);439if (!element_size)440return llvm::make_error<llvm::StringError>(441llvm::formatv("could not get element size of type: {0}",442ctf_array.type),443llvm::inconvertibleErrorCode());444445uint64_t size = ctf_array.nelems * *element_size;446447CompilerType compiler_type = m_ast->CreateArrayType(448element_type->GetFullCompilerType(), ctf_array.nelems,449/*is_gnu_vector*/ false);450451Declaration decl;452return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID,453Type::eEncodingIsUID, decl, compiler_type,454lldb_private::Type::ResolveState::Full);455}456457llvm::Expected<lldb::TypeSP>458SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) {459Declaration decl;460CompilerType enum_type = m_ast->CreateEnumerationType(461ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(),462decl, m_ast->GetBasicType(eBasicTypeInt),463/*is_scoped=*/false);464465for (const CTFEnum::Value &value : ctf_enum.values) {466Declaration value_decl;467m_ast->AddEnumerationValueToEnumerationType(468enum_type, value_decl, value.name.data(), value.value, ctf_enum.size);469}470TypeSystemClang::CompleteTagDeclarationDefinition(enum_type);471472return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,473Type::eEncodingIsUID, decl, enum_type,474lldb_private::Type::ResolveState::Full);475}476477llvm::Expected<lldb::TypeSP>478SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) {479std::vector<CompilerType> arg_types;480for (uint32_t arg : ctf_function.args) {481if (Type *arg_type = ResolveTypeUID(arg))482arg_types.push_back(arg_type->GetFullCompilerType());483}484485Type *ret_type = ResolveTypeUID(ctf_function.return_type);486if (!ret_type)487return llvm::make_error<llvm::StringError>(488llvm::formatv("Could not find function return type: {0}",489ctf_function.return_type),490llvm::inconvertibleErrorCode());491492CompilerType func_type = m_ast->CreateFunctionType(493ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(),494ctf_function.variadic, 0, clang::CallingConv::CC_C);495496Declaration decl;497return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr,498LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,499lldb_private::Type::ResolveState::Full);500}501502llvm::Expected<lldb::TypeSP>503SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) {504const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind);505CompilerType record_type = m_ast->CreateRecordType(506nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(),507llvm::to_underlying(tag_kind), eLanguageTypeC);508m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record;509Declaration decl;510return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,511nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,512decl, record_type, lldb_private::Type::ResolveState::Forward);513}514515bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {516// Check if we have a CTF type for the given incomplete compiler type.517auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType());518if (it == m_compiler_types.end())519return false;520521const CTFType *ctf_type = it->second;522assert(ctf_type && "m_compiler_types should only contain valid CTF types");523524// We only support resolving record types.525assert(llvm::isa<CTFRecord>(ctf_type));526527// Cast to the appropriate CTF type.528const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);529530// If any of the fields are incomplete, we cannot complete the type.531for (const CTFRecord::Field &field : ctf_record->fields) {532if (!ResolveTypeUID(field.type)) {533LLDB_LOG(GetLog(LLDBLog::Symbols),534"Cannot complete type {0} because field {1} is incomplete",535ctf_type->uid, field.type);536return false;537}538}539540// Complete the record type.541m_ast->StartTagDeclarationDefinition(compiler_type);542for (const CTFRecord::Field &field : ctf_record->fields) {543Type *field_type = ResolveTypeUID(field.type);544assert(field_type && "field must be complete");545const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0);546TypeSystemClang::AddFieldToRecordType(compiler_type, field.name,547field_type->GetFullCompilerType(),548eAccessPublic, field_size);549}550m_ast->CompleteTagDeclarationDefinition(compiler_type);551552// Now that the compiler type is complete, we don't need to remember it553// anymore and can remove the CTF record type.554m_compiler_types.erase(compiler_type.GetOpaqueQualType());555m_ctf_types.erase(ctf_type->uid);556557return true;558}559560llvm::Expected<lldb::TypeSP>561SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) {562CompilerType forward_compiler_type = m_ast->CreateRecordType(563nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name,564llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC);565Declaration decl;566return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr,567LLDB_INVALID_UID, Type::eEncodingIsUID, decl,568forward_compiler_type, Type::ResolveState::Forward);569}570571llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) {572if (!ctf_type)573return llvm::make_error<llvm::StringError>(574"cannot create type for unparsed type", llvm::inconvertibleErrorCode());575576switch (ctf_type->kind) {577case CTFType::Kind::eInteger:578return CreateInteger(*static_cast<CTFInteger *>(ctf_type));579case CTFType::Kind::eConst:580case CTFType::Kind::ePointer:581case CTFType::Kind::eRestrict:582case CTFType::Kind::eVolatile:583return CreateModifier(*static_cast<CTFModifier *>(ctf_type));584case CTFType::Kind::eTypedef:585return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type));586case CTFType::Kind::eArray:587return CreateArray(*static_cast<CTFArray *>(ctf_type));588case CTFType::Kind::eEnum:589return CreateEnum(*static_cast<CTFEnum *>(ctf_type));590case CTFType::Kind::eFunction:591return CreateFunction(*static_cast<CTFFunction *>(ctf_type));592case CTFType::Kind::eStruct:593case CTFType::Kind::eUnion:594return CreateRecord(*static_cast<CTFRecord *>(ctf_type));595case CTFType::Kind::eForward:596return CreateForward(*static_cast<CTFForward *>(ctf_type));597case CTFType::Kind::eUnknown:598case CTFType::Kind::eFloat:599case CTFType::Kind::eSlice:600return llvm::make_error<llvm::StringError>(601llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})",602ctf_type->uid, ctf_type->name, ctf_type->kind),603llvm::inconvertibleErrorCode());604}605llvm_unreachable("Unexpected CTF type kind");606}607608llvm::Expected<std::unique_ptr<CTFType>>609SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) {610ctf_stype_t ctf_stype;611ctf_stype.name = m_data.GetU32(&offset);612ctf_stype.info = m_data.GetU32(&offset);613ctf_stype.size = m_data.GetU32(&offset);614615llvm::StringRef name = ReadString(ctf_stype.name);616const uint32_t kind = GetKind(ctf_stype.info);617const uint32_t variable_length = GetVLen(ctf_stype.info);618const uint32_t type = ctf_stype.GetType();619const uint32_t size = ctf_stype.GetSize();620621switch (kind) {622case TypeKind::eInteger: {623const uint32_t vdata = m_data.GetU32(&offset);624const uint32_t bits = GetBits(vdata);625const uint32_t encoding = GetEncoding(vdata);626return std::make_unique<CTFInteger>(uid, name, bits, encoding);627}628case TypeKind::eConst:629return std::make_unique<CTFConst>(uid, type);630case TypeKind::ePointer:631return std::make_unique<CTFPointer>(uid, type);632case TypeKind::eRestrict:633return std::make_unique<CTFRestrict>(uid, type);634case TypeKind::eVolatile:635return std::make_unique<CTFVolatile>(uid, type);636case TypeKind::eTypedef:637return std::make_unique<CTFTypedef>(uid, name, type);638case TypeKind::eArray: {639const uint32_t type = m_data.GetU32(&offset);640const uint32_t index = m_data.GetU32(&offset);641const uint32_t nelems = m_data.GetU32(&offset);642return std::make_unique<CTFArray>(uid, name, type, index, nelems);643}644case TypeKind::eEnum: {645std::vector<CTFEnum::Value> values;646for (uint32_t i = 0; i < variable_length; ++i) {647const uint32_t value_name = m_data.GetU32(&offset);648const uint32_t value = m_data.GetU32(&offset);649values.emplace_back(ReadString(value_name), value);650}651return std::make_unique<CTFEnum>(uid, name, variable_length, size, values);652}653case TypeKind::eFunction: {654std::vector<uint32_t> args;655bool variadic = false;656for (uint32_t i = 0; i < variable_length; ++i) {657const uint32_t arg_uid = m_data.GetU32(&offset);658// If the last argument is 0, this is a variadic function.659if (arg_uid == 0) {660variadic = true;661break;662}663args.push_back(arg_uid);664}665// If the number of arguments is odd, a single uint32_t of padding is666// inserted to maintain alignment.667if (variable_length % 2 == 1)668m_data.GetU32(&offset);669return std::make_unique<CTFFunction>(uid, name, variable_length, type, args,670variadic);671}672case TypeKind::eStruct:673case TypeKind::eUnion: {674std::vector<CTFRecord::Field> fields;675for (uint32_t i = 0; i < variable_length; ++i) {676const uint32_t field_name = m_data.GetU32(&offset);677const uint32_t type = m_data.GetU32(&offset);678uint64_t field_offset = 0;679if (size < g_ctf_field_threshold) {680field_offset = m_data.GetU16(&offset);681m_data.GetU16(&offset); // Padding682} else {683const uint32_t offset_hi = m_data.GetU32(&offset);684const uint32_t offset_lo = m_data.GetU32(&offset);685field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo);686}687fields.emplace_back(ReadString(field_name), type, field_offset);688}689return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid,690name, variable_length, size, fields);691}692case TypeKind::eForward:693return std::make_unique<CTFForward>(uid, name);694case TypeKind::eUnknown:695return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid,696name);697case TypeKind::eFloat:698case TypeKind::eSlice:699offset += (variable_length * sizeof(uint32_t));700break;701}702703return llvm::make_error<llvm::StringError>(704llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})",705name, kind, variable_length),706llvm::inconvertibleErrorCode());707}708709size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {710if (!ParseHeader())711return 0;712713if (!m_types.empty())714return 0;715716if (!m_ast)717return 0;718719Log *log = GetLog(LLDBLog::Symbols);720LLDB_LOG(log, "Parsing CTF types");721722lldb::offset_t type_offset = m_body_offset + m_header->typeoff;723const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff;724725lldb::user_id_t type_uid = 1;726while (type_offset < type_offset_end) {727llvm::Expected<std::unique_ptr<CTFType>> type_or_error =728ParseType(type_offset, type_uid);729if (type_or_error) {730m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error);731} else {732LLDB_LOG_ERROR(log, type_or_error.takeError(),733"Failed to parse type {1} at offset {2}: {0}", type_uid,734type_offset);735}736type_uid++;737}738739LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size());740741for (lldb::user_id_t uid = 1; uid < type_uid; ++uid)742ResolveTypeUID(uid);743744LLDB_LOG(log, "Created {0} CTF types", m_types.size());745746return m_types.size();747}748749size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) {750if (!ParseHeader())751return 0;752753if (!m_functions.empty())754return 0;755756if (!m_ast)757return 0;758759Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab();760if (!symtab)761return 0;762763Log *log = GetLog(LLDBLog::Symbols);764LLDB_LOG(log, "Parsing CTF functions");765766lldb::offset_t function_offset = m_body_offset + m_header->funcoff;767const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff;768769uint32_t symbol_idx = 0;770Declaration decl;771while (function_offset < function_offset_end) {772const uint32_t info = m_data.GetU32(&function_offset);773const uint16_t kind = GetKind(info);774const uint16_t variable_length = GetVLen(info);775776Symbol *symbol = symtab->FindSymbolWithType(777eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx);778779// Skip padding.780if (kind == TypeKind::eUnknown && variable_length == 0)781continue;782783// Skip unexpected kinds.784if (kind != TypeKind::eFunction)785continue;786787const uint32_t ret_uid = m_data.GetU32(&function_offset);788const uint32_t num_args = variable_length;789790std::vector<CompilerType> arg_types;791arg_types.reserve(num_args);792793bool is_variadic = false;794for (uint32_t i = 0; i < variable_length; i++) {795const uint32_t arg_uid = m_data.GetU32(&function_offset);796797// If the last argument is 0, this is a variadic function.798if (arg_uid == 0) {799is_variadic = true;800break;801}802803Type *arg_type = ResolveTypeUID(arg_uid);804arg_types.push_back(arg_type ? arg_type->GetFullCompilerType()805: CompilerType());806}807808if (symbol) {809Type *ret_type = ResolveTypeUID(ret_uid);810AddressRange func_range =811AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(),812GetObjectFile()->GetModule()->GetSectionList());813814// Create function type.815CompilerType func_type = m_ast->CreateFunctionType(816ret_type ? ret_type->GetFullCompilerType() : CompilerType(),817arg_types.data(), arg_types.size(), is_variadic, 0,818clang::CallingConv::CC_C);819lldb::user_id_t function_type_uid = m_types.size() + 1;820TypeSP type_sp =821MakeType(function_type_uid, symbol->GetName(), 0, nullptr,822LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,823lldb_private::Type::ResolveState::Full);824m_types[function_type_uid] = type_sp;825826// Create function.827lldb::user_id_t func_uid = m_functions.size();828FunctionSP function_sp = std::make_shared<Function>(829&cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(),830func_range);831m_functions.emplace_back(function_sp);832cu.AddFunction(function_sp);833}834}835836LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size());837838return m_functions.size();839}840841static DWARFExpression CreateDWARFExpression(ModuleSP module_sp,842const Symbol &symbol) {843if (!module_sp)844return DWARFExpression();845846const ArchSpec &architecture = module_sp->GetArchitecture();847ByteOrder byte_order = architecture.GetByteOrder();848uint32_t address_size = architecture.GetAddressByteSize();849uint32_t byte_size = architecture.GetDataByteSize();850851StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);852stream.PutHex8(lldb_private::dwarf::DW_OP_addr);853stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order);854855DataBufferSP buffer =856std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());857lldb_private::DataExtractor extractor(buffer, byte_order, address_size,858byte_size);859DWARFExpression result(extractor);860result.SetRegisterKind(eRegisterKindDWARF);861862return result;863}864865size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) {866if (!ParseHeader())867return 0;868869if (!m_variables.empty())870return 0;871872if (!m_ast)873return 0;874875ModuleSP module_sp = GetObjectFile()->GetModule();876Symtab *symtab = module_sp->GetSymtab();877if (!symtab)878return 0;879880Log *log = GetLog(LLDBLog::Symbols);881LLDB_LOG(log, "Parsing CTF objects");882883lldb::offset_t object_offset = m_body_offset + m_header->objtoff;884const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff;885886uint32_t symbol_idx = 0;887Declaration decl;888while (object_offset < object_offset_end) {889const uint32_t type_uid = m_data.GetU32(&object_offset);890891if (Symbol *symbol =892symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes,893Symtab::eVisibilityAny, symbol_idx)) {894Variable::RangeList ranges;895ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize());896897auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid);898899DWARFExpressionList location(900module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr);901902lldb::user_id_t variable_type_uid = m_variables.size();903m_variables.emplace_back(std::make_shared<Variable>(904variable_type_uid, symbol->GetName().AsCString(),905symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal,906m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(),907/*artificial=*/false,908/*location_is_constant_data*/ false));909}910}911912LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size());913914return m_variables.size();915}916917uint32_t SymbolFileCTF::CalculateAbilities() {918if (!m_objfile_sp)919return 0;920921if (!ParseHeader())922return 0;923924return VariableTypes | Functions | GlobalVariables;925}926927uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr,928SymbolContextItem resolve_scope,929SymbolContext &sc) {930std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());931if (m_objfile_sp->GetSymtab() == nullptr)932return 0;933934uint32_t resolved_flags = 0;935936// Resolve symbols.937if (resolve_scope & eSymbolContextSymbol) {938sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(939so_addr.GetFileAddress());940if (sc.symbol)941resolved_flags |= eSymbolContextSymbol;942}943944// Resolve functions.945if (resolve_scope & eSymbolContextFunction) {946for (FunctionSP function_sp : m_functions) {947if (function_sp->GetAddressRange().ContainsFileAddress(948so_addr.GetFileAddress())) {949sc.function = function_sp.get();950resolved_flags |= eSymbolContextFunction;951break;952}953}954}955956// Resolve variables.957if (resolve_scope & eSymbolContextVariable) {958for (VariableSP variable_sp : m_variables) {959if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) {960sc.variable = variable_sp.get();961break;962}963}964}965966return resolved_flags;967}968969CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) {970if (idx == 0)971return m_comp_unit_sp;972return {};973}974975size_t976SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {977return ParseObjects(*m_comp_unit_sp);978}979980void SymbolFileCTF::AddSymbols(Symtab &symtab) {981// CTF does not encode symbols.982// We rely on the existing symbol table to map symbols to type.983}984985lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {986auto type_it = m_types.find(type_uid);987if (type_it != m_types.end())988return type_it->second.get();989990auto ctf_type_it = m_ctf_types.find(type_uid);991if (ctf_type_it == m_ctf_types.end())992return nullptr;993994CTFType *ctf_type = ctf_type_it->second.get();995assert(ctf_type && "m_ctf_types should only contain valid CTF types");996997Log *log = GetLog(LLDBLog::Symbols);998999llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type);1000if (!type_or_error) {1001LLDB_LOG_ERROR(log, type_or_error.takeError(),1002"Failed to create type for {1}: {0}", ctf_type->uid);1003return {};1004}10051006TypeSP type_sp = *type_or_error;10071008if (log) {1009StreamString ss;1010type_sp->Dump(&ss, true);1011LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(),1012llvm::StringRef(ss.GetString()).rtrim());1013}10141015m_types[type_uid] = type_sp;10161017// Except for record types which we'll need to complete later, we don't need1018// the CTF type anymore.1019if (!isa<CTFRecord>(ctf_type))1020m_ctf_types.erase(type_uid);10211022return type_sp.get();1023}10241025void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,1026lldb_private::TypeResults &results) {1027// Make sure we haven't already searched this SymbolFile before.1028if (results.AlreadySearched(this))1029return;10301031ConstString name = match.GetTypeBasename();1032for (TypeSP type_sp : GetTypeList().Types()) {1033if (type_sp && type_sp->GetName() == name) {1034results.InsertUnique(type_sp);1035if (results.Done(match))1036return;1037}1038}1039}10401041void SymbolFileCTF::FindTypesByRegex(1042const lldb_private::RegularExpression ®ex, uint32_t max_matches,1043lldb_private::TypeMap &types) {1044ParseTypes(*m_comp_unit_sp);10451046size_t matches = 0;1047for (TypeSP type_sp : GetTypeList().Types()) {1048if (matches == max_matches)1049break;1050if (type_sp && regex.Execute(type_sp->GetName()))1051types.Insert(type_sp);1052matches++;1053}1054}10551056void SymbolFileCTF::FindFunctions(1057const lldb_private::Module::LookupInfo &lookup_info,1058const lldb_private::CompilerDeclContext &parent_decl_ctx,1059bool include_inlines, lldb_private::SymbolContextList &sc_list) {1060ParseFunctions(*m_comp_unit_sp);10611062ConstString name = lookup_info.GetLookupName();1063for (FunctionSP function_sp : m_functions) {1064if (function_sp && function_sp->GetName() == name) {1065lldb_private::SymbolContext sc;1066sc.comp_unit = m_comp_unit_sp.get();1067sc.function = function_sp.get();1068sc_list.Append(sc);1069}1070}1071}10721073void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression ®ex,1074bool include_inlines,1075lldb_private::SymbolContextList &sc_list) {1076for (FunctionSP function_sp : m_functions) {1077if (function_sp && regex.Execute(function_sp->GetName())) {1078lldb_private::SymbolContext sc;1079sc.comp_unit = m_comp_unit_sp.get();1080sc.function = function_sp.get();1081sc_list.Append(sc);1082}1083}1084}10851086void SymbolFileCTF::FindGlobalVariables(1087lldb_private::ConstString name,1088const lldb_private::CompilerDeclContext &parent_decl_ctx,1089uint32_t max_matches, lldb_private::VariableList &variables) {1090ParseObjects(*m_comp_unit_sp);10911092size_t matches = 0;1093for (VariableSP variable_sp : m_variables) {1094if (matches == max_matches)1095break;1096if (variable_sp && variable_sp->GetName() == name) {1097variables.AddVariable(variable_sp);1098matches++;1099}1100}1101}11021103void SymbolFileCTF::FindGlobalVariables(1104const lldb_private::RegularExpression ®ex, uint32_t max_matches,1105lldb_private::VariableList &variables) {1106ParseObjects(*m_comp_unit_sp);11071108size_t matches = 0;1109for (VariableSP variable_sp : m_variables) {1110if (matches == max_matches)1111break;1112if (variable_sp && regex.Execute(variable_sp->GetName())) {1113variables.AddVariable(variable_sp);1114matches++;1115}1116}1117}111811191120