From 4f68d9b77fdec97fe9841690ff278046a505f43f Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 24 Apr 2024 11:19:24 -0700 Subject: [PATCH 1/9] [lldb] Revert changes for dcbf7881f6a4c0ad8c8853f851f43161dc3c3236 --- .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index ab6cc81faea93..88926baa7a6e7 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -925,18 +925,23 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { return GetTypeForUID(type_uid).get(); } -void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match, - lldb_private::TypeResults &results) { - // Make sure we haven't already searched this SymbolFile before. - if (results.AlreadySearched(this)) - return; +void SymbolFileCTF::FindTypes( + lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, + lldb_private::TypeMap &types) { + + searched_symbol_files.clear(); + searched_symbol_files.insert(this); - ConstString name = match.GetTypeBasename(); - for (TypeSP type_sp : GetTypeList().Types()) { + size_t matches = 0; + for (TypeSP type_sp : m_types) { + if (matches == max_matches) + break; if (type_sp && type_sp->GetName() == name) { - results.InsertUnique(type_sp); - if (results.Done(match)) - return; + types.Insert(type_sp); + matches++; } } } From 57ee12319a98d1d3c6d98b936ef5ba94d07514e1 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 27 Jul 2023 12:07:44 -0700 Subject: [PATCH 2/9] [lldb] Split CTF parsing and type creation (NFC) Separate parsing CTF and creating LLDB types. This is a prerequisite to parsing forward references and recursive types. Differential revision: https://reviews.llvm.org/D156447 (cherry picked from commit 0a5e0d3fad8dfdebc8bb2f51f6008bdd41e27580) --- lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h | 168 +++++++ .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 426 ++++++++++-------- .../Plugins/SymbolFile/CTF/SymbolFileCTF.h | 73 +-- lldb/test/API/macosx/ctf/TestCTF.py | 11 + 4 files changed, 428 insertions(+), 250 deletions(-) create mode 100644 lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h diff --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h new file mode 100644 index 0000000000000..8c6ee278bbe35 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h @@ -0,0 +1,168 @@ +//===-- CTFTypes.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H +#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H + +#include "lldb/lldb-types.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_private { + +struct CTFType { + enum Kind : uint32_t { + eUnknown = 0, + eInteger = 1, + eFloat = 2, + ePointer = 3, + eArray = 4, + eFunction = 5, + eStruct = 6, + eUnion = 7, + eEnum = 8, + eForward = 9, + eTypedef = 10, + eVolatile = 11, + eConst = 12, + eRestrict = 13, + eSlice = 14, + }; + + Kind kind; + lldb::user_id_t uid; + llvm::StringRef name; + + CTFType(Kind kind, lldb::user_id_t uid, llvm::StringRef name) + : kind(kind), uid(uid), name(name) {} +}; + +struct CTFInteger : public CTFType { + CTFInteger(lldb::user_id_t uid, llvm::StringRef name, uint32_t bits, + uint32_t encoding) + : CTFType(eInteger, uid, name), bits(bits), encoding(encoding) {} + + uint32_t bits; + uint32_t encoding; +}; + +struct CTFModifier : public CTFType { +protected: + CTFModifier(Kind kind, lldb::user_id_t uid, uint32_t type) + : CTFType(kind, uid, ""), type(type) {} + +public: + uint32_t type; +}; + +struct CTFPointer : public CTFModifier { + CTFPointer(lldb::user_id_t uid, uint32_t type) + : CTFModifier(ePointer, uid, type) {} +}; + +struct CTFConst : public CTFModifier { + CTFConst(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eConst, uid, type) {} +}; + +struct CTFVolatile : public CTFModifier { + CTFVolatile(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eVolatile, uid, type) {} +}; + +struct CTFRestrict : public CTFModifier { + CTFRestrict(lldb::user_id_t uid, uint32_t type) + : CTFModifier(eRestrict, uid, type) {} +}; + +struct CTFTypedef : public CTFType { + CTFTypedef(lldb::user_id_t uid, llvm::StringRef name, uint32_t type) + : CTFType(eTypedef, uid, name), type(type) {} + + uint32_t type; +}; + +struct CTFArray : public CTFType { + CTFArray(lldb::user_id_t uid, llvm::StringRef name, uint32_t type, + uint32_t index, uint32_t nelems) + : CTFType(eArray, uid, name), type(type), index(index), nelems(nelems) {} + + uint32_t type; + uint32_t index; + uint32_t nelems; +}; + +struct CTFEnum : public CTFType { + struct Value { + Value(llvm::StringRef name, uint32_t value) : name(name), value(value){}; + llvm::StringRef name; + uint32_t value; + }; + + CTFEnum(lldb::user_id_t uid, llvm::StringRef name, uint32_t nelems, + uint32_t size, std::vector values) + : CTFType(eEnum, uid, name), nelems(nelems), size(size), + values(std::move(values)) { + assert(this->values.size() == nelems); + } + + uint32_t nelems; + uint32_t size; + std::vector values; +}; + +struct CTFFunction : public CTFType { + CTFFunction(lldb::user_id_t uid, llvm::StringRef name, uint32_t nargs, + uint32_t return_type, std::vector args, bool variadic) + : CTFType(eFunction, uid, name), nargs(nargs), return_type(return_type), + args(std::move(args)), variadic(variadic) {} + + uint32_t nargs; + uint32_t return_type; + + std::vector args; + bool variadic = false; +}; + +struct CTFRecord : public CTFType { +public: + struct Field { + Field(llvm::StringRef name, uint32_t type, uint16_t offset, + uint16_t padding) + : name(name), type(type), offset(offset), padding(padding) {} + + llvm::StringRef name; + uint32_t type; + uint16_t offset; + uint16_t padding; + }; + + CTFRecord(Kind kind, lldb::user_id_t uid, llvm::StringRef name, + uint32_t nfields, uint32_t size, std::vector fields) + : CTFType(kind, uid, name), nfields(nfields), size(size), + fields(std::move(fields)) {} + + uint32_t nfields; + uint32_t size; + std::vector fields; +}; + +struct CTFStruct : public CTFRecord { + CTFStruct(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, + uint32_t size, std::vector fields) + : CTFRecord(eStruct, uid, name, nfields, size, std::move(fields)){}; +}; + +struct CTFUnion : public CTFRecord { + CTFUnion(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, + uint32_t size, std::vector fields) + : CTFRecord(eUnion, uid, name, nfields, size, std::move(fields)){}; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 88926baa7a6e7..2798bc674471e 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -317,11 +317,11 @@ uint32_t GetVLen(uint32_t data) { static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); } -static clang::TagTypeKind TranslateRecordKind(SymbolFileCTF::TypeKind type) { +static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) { switch (type) { - case SymbolFileCTF::TypeKind::eStruct: + case CTFType::Kind::eStruct: return clang::TTK_Struct; - case SymbolFileCTF::TypeKind::eUnion: + case CTFType::Kind::eUnion: return clang::TTK_Union; default: lldbassert(false && "Invalid record kind!"); @@ -329,19 +329,15 @@ static clang::TagTypeKind TranslateRecordKind(SymbolFileCTF::TypeKind type) { } } -llvm::Expected SymbolFileCTF::ParseInteger(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name) { - const uint32_t vdata = m_data.GetU32(&offset); - const uint32_t bits = GetBits(vdata); - const uint32_t encoding = GetEncoding(vdata); - - lldb::BasicType basic_type = TypeSystemClang::GetBasicTypeEnumeration(name); +llvm::Expected +SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) { + lldb::BasicType basic_type = + TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name); if (basic_type == eBasicTypeInvalid) return llvm::make_error( llvm::formatv("unsupported integer type: no corresponding basic clang " "type for '{0}'", - name), + ctf_integer.name), llvm::inconvertibleErrorCode()); CompilerType compiler_type = m_ast->GetBasicType(basic_type); @@ -353,104 +349,98 @@ llvm::Expected SymbolFileCTF::ParseInteger(lldb::offset_t &offset, return llvm::make_error( llvm::formatv( "Found compiler type for '{0}' but it's not an integer type: {1}", - name, compiler_type.GetDisplayTypeName().GetStringRef()), + ctf_integer.name, + compiler_type.GetDisplayTypeName().GetStringRef()), llvm::inconvertibleErrorCode()); // Make sure the signing matches between the CTF and the compiler type. - const bool type_is_signed = (encoding & IntEncoding::eSigned); + const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned); if (compiler_type_is_signed != type_is_signed) return llvm::make_error( llvm::formatv("Found integer compiler type for {0} but compiler type " "is {1} and {0} is {2}", - name, compiler_type_is_signed ? "signed" : "unsigned", + ctf_integer.name, + compiler_type_is_signed ? "signed" : "unsigned", type_is_signed ? "signed" : "unsigned"), llvm::inconvertibleErrorCode()); } Declaration decl; - return MakeType(uid, ConstString(name), GetBytes(bits), nullptr, - LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, - compiler_type, lldb_private::Type::ResolveState::Full); + return MakeType(ctf_integer.uid, ConstString(ctf_integer.name), + GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, compiler_type, + lldb_private::Type::ResolveState::Full); } llvm::Expected -SymbolFileCTF::ParseModifierType(lldb::offset_t &offset, lldb::user_id_t uid, - uint32_t kind, uint32_t type) { - TypeSP ref_type = GetTypeForUID(type); +SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) { + Type *ref_type = ResolveTypeUID(ctf_modifier.type); if (!ref_type) return llvm::make_error( - llvm::formatv("Could not find modified type: {0}", type), + llvm::formatv("Could not find modified type: {0}", ctf_modifier.type), llvm::inconvertibleErrorCode()); CompilerType compiler_type; - switch (kind) { - case TypeKind::ePointer: + switch (ctf_modifier.kind) { + case CTFType::ePointer: compiler_type = ref_type->GetFullCompilerType().GetPointerType(); break; - case TypeKind::eConst: + case CTFType::eConst: compiler_type = ref_type->GetFullCompilerType().AddConstModifier(); break; - case TypeKind::eVolatile: + case CTFType::eVolatile: compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier(); break; - case TypeKind::eRestrict: + case CTFType::eRestrict: compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier(); break; default: return llvm::make_error( - llvm::formatv("ParseModifierType called with unsupported kind: {0}", - kind), + llvm::formatv("ParseModifier called with unsupported kind: {0}", + ctf_modifier.kind), llvm::inconvertibleErrorCode()); } Declaration decl; - return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, compiler_type, lldb_private::Type::ResolveState::Full); } -llvm::Expected SymbolFileCTF::ParseTypedef(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t type) { - TypeSP underlying_type = GetTypeForUID(type); +llvm::Expected +SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) { + Type *underlying_type = ResolveTypeUID(ctf_typedef.type); if (!underlying_type) return llvm::make_error( - llvm::formatv("Could not find typedef underlying type: {0}", type), + llvm::formatv("Could not find typedef underlying type: {0}", + ctf_typedef.type), llvm::inconvertibleErrorCode()); CompilerType target_ast_type = underlying_type->GetFullCompilerType(); clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl(); CompilerType ast_typedef = target_ast_type.CreateTypedef( - name.data(), m_ast->CreateDeclContext(decl_ctx), 0); + ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0); Declaration decl; - return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, ast_typedef, - lldb_private::Type::ResolveState::Full); + return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr, + LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, + ast_typedef, lldb_private::Type::ResolveState::Full); } -llvm::Expected SymbolFileCTF::ParseArray(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name) { - ctf_array_t ctf_array; - ctf_array.contents = m_data.GetU32(&offset); - ctf_array.index = m_data.GetU32(&offset); - ctf_array.nelems = m_data.GetU32(&offset); - - TypeSP element_type = GetTypeForUID(ctf_array.contents); +llvm::Expected +SymbolFileCTF::CreateArray(const CTFArray &ctf_array) { + Type *element_type = ResolveTypeUID(ctf_array.type); if (!element_type) return llvm::make_error( - llvm::formatv("Could not find array element type: {0}", - ctf_array.contents), + llvm::formatv("Could not find array element type: {0}", ctf_array.type), llvm::inconvertibleErrorCode()); std::optional element_size = element_type->GetByteSize(nullptr); if (!element_size) return llvm::make_error( llvm::formatv("could not get element size of type: {0}", - ctf_array.contents), + ctf_array.type), llvm::inconvertibleErrorCode()); uint64_t size = ctf_array.nelems * *element_size; @@ -460,149 +450,203 @@ llvm::Expected SymbolFileCTF::ParseArray(lldb::offset_t &offset, /*is_gnu_vector*/ false); Declaration decl; - return MakeType(uid, ConstString(), size, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, compiler_type, lldb_private::Type::ResolveState::Full); } -llvm::Expected SymbolFileCTF::ParseEnum(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t elements, - uint32_t size) { +llvm::Expected +SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) { Declaration decl; CompilerType enum_type = m_ast->CreateEnumerationType( - name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl, - m_ast->GetBasicType(eBasicTypeInt), + ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), + decl, m_ast->GetBasicType(eBasicTypeInt), /*is_scoped=*/false); - for (uint32_t i = 0; i < elements; ++i) { - ctf_enum_t ctf_enum; - ctf_enum.name = m_data.GetU32(&offset); - ctf_enum.value = m_data.GetU32(&offset); - - llvm::StringRef value_name = ReadString(ctf_enum.name); - const uint32_t value = ctf_enum.value; - + for (const CTFEnum::Value &value : ctf_enum.values) { Declaration value_decl; - m_ast->AddEnumerationValueToEnumerationType(enum_type, value_decl, - value_name.data(), value, size); + m_ast->AddEnumerationValueToEnumerationType( + enum_type, value_decl, value.name.data(), value.value, ctf_enum.size); } + TypeSystemClang::CompleteTagDeclarationDefinition(enum_type); - return MakeType(uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, + return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, enum_type, lldb_private::Type::ResolveState::Full); } llvm::Expected -SymbolFileCTF::ParseFunction(lldb::offset_t &offset, lldb::user_id_t uid, - llvm::StringRef name, uint32_t num_args, - uint32_t type) { +SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) { std::vector arg_types; - arg_types.reserve(num_args); - - bool is_variadic = false; - for (uint32_t i = 0; i < num_args; ++i) { - const uint32_t arg_uid = m_data.GetU32(&offset); - - // If the last argument is 0, this is a variadic function. - if (arg_uid == 0) { - is_variadic = true; - break; - } - - if (TypeSP arg_type = GetTypeForUID(arg_uid)) + for (uint32_t arg : ctf_function.args) { + if (Type *arg_type = ResolveTypeUID(arg)) arg_types.push_back(arg_type->GetFullCompilerType()); } - // If the number of arguments is odd, a single uint32_t of padding is inserted - // to maintain alignment. - if (num_args % 2 == 1) - m_data.GetU32(&offset); - - TypeSP ret_type = GetTypeForUID(type); + Type *ret_type = ResolveTypeUID(ctf_function.return_type); if (!ret_type) return llvm::make_error( - llvm::formatv("Could not find function return type: {0}", type), + llvm::formatv("Could not find function return type: {0}", + ctf_function.return_type), llvm::inconvertibleErrorCode()); CompilerType func_type = m_ast->CreateFunctionType( ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), - is_variadic, 0, clang::CallingConv::CC_C); + ctf_function.variadic, 0, clang::CallingConv::CC_C); Declaration decl; - return MakeType(uid, ConstString(name), 0, nullptr, LLDB_INVALID_UID, - Type::eEncodingIsUID, decl, func_type, + return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, lldb_private::Type::ResolveState::Full); } llvm::Expected -SymbolFileCTF::ParseRecord(lldb::offset_t &offset, lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, uint32_t fields, - uint32_t size) { - const clang::TagTypeKind tag_kind = - TranslateRecordKind(static_cast(kind)); +SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) { + const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind); - CompilerType union_type = + CompilerType record_type = m_ast->CreateRecordType(nullptr, OptionalClangModuleID(), eAccessPublic, - name.data(), tag_kind, eLanguageTypeC); - - m_ast->StartTagDeclarationDefinition(union_type); - for (uint32_t i = 0; i < fields; ++i) { - ctf_member_t ctf_member; - ctf_member.name = m_data.GetU32(&offset); - ctf_member.type = m_data.GetU32(&offset); - ctf_member.offset = m_data.GetU16(&offset); - ctf_member.padding = m_data.GetU16(&offset); - - llvm::StringRef member_name = ReadString(ctf_member.name); - const uint32_t member_type_uid = ctf_member.type; - - if (TypeSP member_type = GetTypeForUID(member_type_uid)) { - const uint32_t member_size = - member_type->GetByteSize(nullptr).value_or(0); - TypeSystemClang::AddFieldToRecordType(union_type, member_name, - member_type->GetFullCompilerType(), - eAccessPublic, member_size); + ctf_record.name.data(), tag_kind, eLanguageTypeC); + + m_ast->StartTagDeclarationDefinition(record_type); + for (const CTFRecord::Field &field : ctf_record.fields) { + if (Type *field_type = ResolveTypeUID(field.type)) { + const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0); + TypeSystemClang::AddFieldToRecordType(record_type, field.name, + field_type->GetFullCompilerType(), + eAccessPublic, field_size); } } - m_ast->CompleteTagDeclarationDefinition(union_type); + m_ast->CompleteTagDeclarationDefinition(record_type); Declaration decl; - return MakeType(uid, ConstString(name), size, nullptr, LLDB_INVALID_UID, - lldb_private::Type::eEncodingIsUID, decl, union_type, - lldb_private::Type::ResolveState::Full); + return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size, + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, + decl, record_type, lldb_private::Type::ResolveState::Full); } -llvm::Expected SymbolFileCTF::ParseType( - lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name, - uint32_t kind, uint32_t variable_length, uint32_t type, uint32_t size) { +llvm::Expected SymbolFileCTF::CreateType(CTFType *ctf_type) { + if (!ctf_type) + return llvm::make_error( + "cannot create type for unparsed type", llvm::inconvertibleErrorCode()); + + switch (ctf_type->kind) { + case CTFType::Kind::eInteger: + return CreateInteger(*static_cast(ctf_type)); + case CTFType::Kind::eConst: + case CTFType::Kind::ePointer: + case CTFType::Kind::eRestrict: + case CTFType::Kind::eVolatile: + return CreateModifier(*static_cast(ctf_type)); + case CTFType::Kind::eTypedef: + return CreateTypedef(*static_cast(ctf_type)); + case CTFType::Kind::eArray: + return CreateArray(*static_cast(ctf_type)); + case CTFType::Kind::eEnum: + return CreateEnum(*static_cast(ctf_type)); + case CTFType::Kind::eFunction: + return CreateFunction(*static_cast(ctf_type)); + case CTFType::Kind::eStruct: + case CTFType::Kind::eUnion: + return CreateRecord(*static_cast(ctf_type)); + case CTFType::Kind::eUnknown: + case CTFType::Kind::eFloat: + case CTFType::Kind::eForward: + case CTFType::Kind::eSlice: + return llvm::make_error( + llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})", + ctf_type->uid, ctf_type->name, ctf_type->kind), + llvm::inconvertibleErrorCode()); + } +} + +llvm::Expected> +SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) { + ctf_stype_t ctf_stype; + ctf_stype.name = m_data.GetU32(&offset); + ctf_stype.info = m_data.GetU32(&offset); + ctf_stype.size = m_data.GetU32(&offset); + + llvm::StringRef name = ReadString(ctf_stype.name); + const uint32_t kind = GetKind(ctf_stype.info); + const uint32_t variable_length = GetVLen(ctf_stype.info); + const uint32_t type = ctf_stype.GetType(); + const uint32_t size = ctf_stype.GetSize(); + switch (kind) { - case TypeKind::eInteger: - return ParseInteger(offset, uid, name); + case TypeKind::eInteger: { + const uint32_t vdata = m_data.GetU32(&offset); + const uint32_t bits = GetBits(vdata); + const uint32_t encoding = GetEncoding(vdata); + return std::make_unique(uid, name, bits, encoding); + } case TypeKind::eConst: + return std::make_unique(uid, type); case TypeKind::ePointer: + return std::make_unique(uid, type); case TypeKind::eRestrict: + return std::make_unique(uid, type); case TypeKind::eVolatile: - return ParseModifierType(offset, uid, kind, type); + return std::make_unique(uid, type); case TypeKind::eTypedef: - return ParseTypedef(offset, uid, name, type); - case TypeKind::eArray: - return ParseArray(offset, uid, name); - case TypeKind::eEnum: - return ParseEnum(offset, uid, name, variable_length, size); - case TypeKind::eFunction: - return ParseFunction(offset, uid, name, variable_length, size); + return std::make_unique(uid, name, type); + case TypeKind::eArray: { + const uint32_t type = m_data.GetU32(&offset); + const uint32_t index = m_data.GetU32(&offset); + const uint32_t nelems = m_data.GetU32(&offset); + return std::make_unique(uid, name, type, index, nelems); + } + case TypeKind::eEnum: { + std::vector values; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t value_name = m_data.GetU32(&offset); + const uint32_t value = m_data.GetU32(&offset); + values.emplace_back(ReadString(value_name), value); + } + return std::make_unique(uid, name, variable_length, size, values); + } + case TypeKind::eFunction: { + std::vector args; + bool variadic = false; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t arg_uid = m_data.GetU32(&offset); + // If the last argument is 0, this is a variadic function. + if (arg_uid == 0) { + variadic = true; + break; + } + args.push_back(arg_uid); + } + // If the number of arguments is odd, a single uint32_t of padding is + // inserted to maintain alignment. + if (variable_length % 2 == 1) + m_data.GetU32(&offset); + return std::make_unique(uid, name, variable_length, type, args, + variadic); + } case TypeKind::eStruct: - case TypeKind::eUnion: - return ParseRecord(offset, uid, name, kind, variable_length, size); + case TypeKind::eUnion: { + std::vector fields; + for (uint32_t i = 0; i < variable_length; ++i) { + const uint32_t field_name = m_data.GetU32(&offset); + const uint32_t type = m_data.GetU32(&offset); + const uint16_t field_offset = m_data.GetU16(&offset); + const uint16_t padding = m_data.GetU16(&offset); + fields.emplace_back(ReadString(field_name), type, field_offset, padding); + } + return std::make_unique(static_cast(kind), uid, + name, variable_length, size, fields); + } + case TypeKind::eUnknown: + return std::make_unique(static_cast(kind), uid, + name); case TypeKind::eFloat: case TypeKind::eForward: case TypeKind::eSlice: - case TypeKind::eUnknown: offset += (variable_length * sizeof(uint32_t)); break; } + return llvm::make_error( llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})", name, kind, variable_length), @@ -627,46 +671,25 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { lldb::user_id_t type_uid = 1; while (type_offset < type_offset_end) { - ctf_stype_t ctf_stype; - ctf_stype.name = m_data.GetU32(&type_offset); - ctf_stype.info = m_data.GetU32(&type_offset); - ctf_stype.size = m_data.GetU32(&type_offset); - - llvm::StringRef name = ReadString(ctf_stype.name); - const uint32_t kind = GetKind(ctf_stype.info); - const uint32_t variable_length = GetVLen(ctf_stype.info); - const uint32_t type = ctf_stype.GetType(); - const uint32_t size = ctf_stype.GetSize(); - - TypeSP type_sp; - llvm::Expected type_or_error = ParseType( - type_offset, type_uid, name, kind, variable_length, type, size); - if (!type_or_error) { + llvm::Expected> type_or_error = + ParseType(type_offset, type_uid); + if (type_or_error) { + m_ctf_types.emplace_back(std::move(*type_or_error)); + } else { + m_ctf_types.emplace_back(std::unique_ptr()); LLDB_LOG_ERROR(log, type_or_error.takeError(), "Failed to parse type {1} at offset {2}: {0}", type_uid, type_offset); - } else { - type_sp = *type_or_error; - if (log) { - StreamString ss; - type_sp->Dump(&ss, true); - LLDB_LOGV(log, "Adding type {0}: {1}", type_uid, - llvm::StringRef(ss.GetString()).rtrim()); - } } - - AddTypeForUID(type_uid++, type_sp); + type_uid++; } - if (log) { - size_t skipped_types = 0; - for (auto &type : m_types) { - if (!type) - skipped_types++; - } - LLDB_LOG(log, "Parsed {0} CTF types ({1} skipped)", m_types.size(), - skipped_types); - } + LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size()); + + for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) + ResolveTypeUID(uid); + + LLDB_LOG(log, "Created {0} CTF types", m_types.size()); return m_types.size(); } @@ -725,12 +748,12 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { break; } - TypeSP arg_type = GetTypeForUID(arg_uid); + Type *arg_type = ResolveTypeUID(arg_uid); arg_types.push_back(arg_type->GetFullCompilerType()); } if (symbol) { - TypeSP ret_type = GetTypeForUID(ret_uid); + Type *ret_type = ResolveTypeUID(ret_uid); AddressRange func_range = AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(), GetObjectFile()->GetModule()->GetSectionList()); @@ -744,7 +767,7 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { MakeType(function_type_uid, symbol->GetName(), 0, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type, lldb_private::Type::ResolveState::Full); - AddTypeForUID(function_type_uid, type_sp); + m_types[function_type_uid] = type_sp; // Create function. lldb::user_id_t func_uid = m_functions.size(); @@ -906,23 +929,40 @@ void SymbolFileCTF::AddSymbols(Symtab &symtab) { // We rely on the existing symbol table to map symbols to type. } -void SymbolFileCTF::AddTypeForUID(lldb::user_id_t type_uid, lldb::TypeSP type) { - assert(type_uid == m_types.size() + 1); - m_types.emplace_back(type); -} +lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { + auto find_result = m_types.find(type_uid); + if (find_result != m_types.end()) + return find_result->second.get(); -TypeSP SymbolFileCTF::GetTypeForUID(lldb::user_id_t type_uid) { - if (type_uid > m_types.size()) - return {}; + if (type_uid == 0 || type_uid > m_ctf_types.size()) + return nullptr; - if (type_uid < 1) + CTFType *ctf_type = m_ctf_types[type_uid - 1].get(); + if (!ctf_type) + return nullptr; + + m_types[type_uid] = TypeSP(); + Log *log = GetLog(LLDBLog::Symbols); + + llvm::Expected type_or_error = CreateType(ctf_type); + if (!type_or_error) { + LLDB_LOG_ERROR(log, type_or_error.takeError(), + "Failed to create type for {1}: {0}", ctf_type->uid); return {}; + } - return m_types[type_uid - 1]; -} + TypeSP type_sp = *type_or_error; -lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { - return GetTypeForUID(type_uid).get(); + if (log) { + StreamString ss; + type_sp->Dump(&ss, true); + LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(), + llvm::StringRef(ss.GetString()).rtrim()); + } + + m_types[type_uid] = type_sp; + + return type_sp.get(); } void SymbolFileCTF::FindTypes( @@ -936,7 +976,7 @@ void SymbolFileCTF::FindTypes( searched_symbol_files.insert(this); size_t matches = 0; - for (TypeSP type_sp : m_types) { + for (TypeSP type_sp : GetTypeList().Types()) { if (matches == max_matches) break; if (type_sp && type_sp->GetName() == name) { @@ -952,7 +992,7 @@ void SymbolFileCTF::FindTypesByRegex( ParseTypes(*m_comp_unit_sp); size_t matches = 0; - for (TypeSP type_sp : m_types) { + for (TypeSP type_sp : GetTypeList().Types()) { if (matches == max_matches) break; if (type_sp && regex.Execute(type_sp->GetName())) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index 9b6195e94b94e..cd78ca157a2c5 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -13,6 +13,7 @@ #include #include +#include "CTFTypes.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolFile.h" @@ -85,9 +86,6 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - lldb::TypeSP GetTypeForUID(lldb::user_id_t type_uid); - void AddTypeForUID(lldb::user_id_t type_uid, lldb::TypeSP type); - Type *ResolveTypeUID(lldb::user_id_t type_uid) override; std::optional GetDynamicArrayInfoForUID( lldb::user_id_t type_uid, @@ -212,60 +210,17 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { uint32_t GetSize() const { return size; } }; - struct ctf_member_t { - uint32_t name; - uint32_t type; - uint16_t offset; - uint16_t padding; - }; - - struct ctf_array_t { - uint32_t contents; - uint32_t index; - uint32_t nelems; - }; - - struct ctf_enum_t { - uint32_t name; - int32_t value; - }; - - llvm::Expected ParseType(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, - uint32_t variable_length, - uint32_t type, uint32_t size); + llvm::Expected> ParseType(lldb::offset_t &offset, + lldb::user_id_t uid); - llvm::Expected ParseInteger(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name); - - llvm::Expected ParseModifierType(lldb::offset_t &offset, - lldb::user_id_t uid, - uint32_t kind, uint32_t type); - - llvm::Expected ParseTypedef(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t type); - - llvm::Expected - ParseArray(lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name); - - llvm::Expected ParseEnum(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t elements, uint32_t size); - - llvm::Expected ParseFunction(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, - uint32_t num_args, uint32_t type); - - llvm::Expected ParseRecord(lldb::offset_t &offset, - lldb::user_id_t uid, - llvm::StringRef name, uint32_t kind, - uint32_t fields, uint32_t size); + llvm::Expected CreateType(CTFType *ctf_type); + llvm::Expected CreateInteger(const CTFInteger &ctf_integer); + llvm::Expected CreateModifier(const CTFModifier &ctf_modifier); + llvm::Expected CreateTypedef(const CTFTypedef &ctf_typedef); + llvm::Expected CreateArray(const CTFArray &ctf_array); + llvm::Expected CreateEnum(const CTFEnum &ctf_enum); + llvm::Expected CreateFunction(const CTFFunction &ctf_function); + llvm::Expected CreateRecord(const CTFRecord &ctf_record); llvm::StringRef ReadString(lldb::offset_t offset) const; @@ -284,7 +239,11 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { lldb::CompUnitSP m_comp_unit_sp; std::optional m_header; - std::vector m_types; + + std::vector> m_ctf_types; + + llvm::DenseMap m_types; + std::vector m_functions; std::vector m_variables; diff --git a/lldb/test/API/macosx/ctf/TestCTF.py b/lldb/test/API/macosx/ctf/TestCTF.py index fc8328a73c308..9f8583bccb7a5 100644 --- a/lldb/test/API/macosx/ctf/TestCTF.py +++ b/lldb/test/API/macosx/ctf/TestCTF.py @@ -78,3 +78,14 @@ def do_test(self): "target variable foo.f", substrs=["(void (*)(int)) foo.f = 0x0000000000000000"], ) + + self.expect( + "type lookup MyEnum", + substrs=[ + "enum MyEnum {", + "eOne,", + "eTwo,", + "eThree", + "}", + ], + ) From 2c60f927ab7e9ebc3426dd44165fc02471da9b74 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 28 Jul 2023 14:13:41 -0700 Subject: [PATCH 3/9] [lldb] Support CTF forward declarations Add support for parsing CTF forward declarations and converting them into LLDB types. Differential revision: https://reviews.llvm.org/D156483 (cherry picked from commit 9c70a3d9178f46c3eccb2243286deb1830c276f4) --- lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h | 5 +++++ .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 17 +++++++++++++++-- .../Plugins/SymbolFile/CTF/SymbolFileCTF.h | 1 + lldb/test/API/macosx/ctf/test.c | 4 ++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h index 8c6ee278bbe35..b2cf5cf3191b6 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h +++ b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h @@ -163,6 +163,11 @@ struct CTFUnion : public CTFRecord { : CTFRecord(eUnion, uid, name, nfields, size, std::move(fields)){}; }; +struct CTFForward : public CTFType { + CTFForward(lldb::user_id_t uid, llvm::StringRef name) + : CTFType(eForward, uid, name) {} +}; + } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_CTF_CTFTYPES_H diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 2798bc674471e..f737db3ed4e4b 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -525,6 +525,17 @@ SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) { decl, record_type, lldb_private::Type::ResolveState::Full); } +llvm::Expected +SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) { + CompilerType forward_compiler_type = m_ast->CreateRecordType( + nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name, + clang::TTK_Struct, eLanguageTypeC); + Declaration decl; + return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, + forward_compiler_type, Type::ResolveState::Forward); +} + llvm::Expected SymbolFileCTF::CreateType(CTFType *ctf_type) { if (!ctf_type) return llvm::make_error( @@ -549,9 +560,10 @@ llvm::Expected SymbolFileCTF::CreateType(CTFType *ctf_type) { case CTFType::Kind::eStruct: case CTFType::Kind::eUnion: return CreateRecord(*static_cast(ctf_type)); + case CTFType::Kind::eForward: + return CreateForward(*static_cast(ctf_type)); case CTFType::Kind::eUnknown: case CTFType::Kind::eFloat: - case CTFType::Kind::eForward: case CTFType::Kind::eSlice: return llvm::make_error( llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})", @@ -637,11 +649,12 @@ SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) { return std::make_unique(static_cast(kind), uid, name, variable_length, size, fields); } + case TypeKind::eForward: + return std::make_unique(uid, name); case TypeKind::eUnknown: return std::make_unique(static_cast(kind), uid, name); case TypeKind::eFloat: - case TypeKind::eForward: case TypeKind::eSlice: offset += (variable_length * sizeof(uint32_t)); break; diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index cd78ca157a2c5..92872488a47ef 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -221,6 +221,7 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { llvm::Expected CreateEnum(const CTFEnum &ctf_enum); llvm::Expected CreateFunction(const CTFFunction &ctf_function); llvm::Expected CreateRecord(const CTFRecord &ctf_record); + llvm::Expected CreateForward(const CTFForward &ctf_forward); llvm::StringRef ReadString(lldb::offset_t offset) const; diff --git a/lldb/test/API/macosx/ctf/test.c b/lldb/test/API/macosx/ctf/test.c index a844a01f82a3d..30be60320c47f 100644 --- a/lldb/test/API/macosx/ctf/test.c +++ b/lldb/test/API/macosx/ctf/test.c @@ -1,5 +1,7 @@ #include +struct ForwardDecl; + typedef int MyInt; void populate(MyInt i); @@ -30,6 +32,7 @@ typedef struct MyStruct { } MyStructT; MyStructT foo; +struct ForwardDecl *forward; void populate(MyInt i) { foo.n.i = i; @@ -41,6 +44,7 @@ void populate(MyInt i) { foo.n.a[3] = 'd'; foo.n.e = eOne; foo.f = NULL; + forward = NULL; } int main(int argc, char** argv) { From 7e81da40a0997d7ed7483c88541bfaf35a94d775 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sat, 29 Jul 2023 11:17:54 -0700 Subject: [PATCH 4/9] [lldb] Fix CTF parsing of large structs Fix parsing of large structs. If the size of a struct exceeds a certain threshold, the offset is encoded using two 32-bit integers instead of one. Differential revision: https://reviews.llvm.org/D156490 (cherry picked from commit b9867df64a312b2fe248d536d943733b8817ed4f) --- lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h | 8 +++----- .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 14 ++++++++++---- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h | 1 + lldb/test/API/macosx/ctf/Makefile | 1 + lldb/test/API/macosx/ctf/TestCTF.py | 4 +++- lldb/test/API/macosx/ctf/test.c | 7 +++++++ 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h index b2cf5cf3191b6..99a74dbe674ae 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h +++ b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h @@ -131,14 +131,12 @@ struct CTFFunction : public CTFType { struct CTFRecord : public CTFType { public: struct Field { - Field(llvm::StringRef name, uint32_t type, uint16_t offset, - uint16_t padding) - : name(name), type(type), offset(offset), padding(padding) {} + Field(llvm::StringRef name, uint32_t type, uint64_t offset) + : name(name), type(type), offset(offset) {} llvm::StringRef name; uint32_t type; - uint16_t offset; - uint16_t padding; + uint64_t offset; }; CTFRecord(Kind kind, lldb::user_id_t uid, llvm::StringRef name, diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index f737db3ed4e4b..1c4de94e06d7b 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -642,9 +642,16 @@ SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) { for (uint32_t i = 0; i < variable_length; ++i) { const uint32_t field_name = m_data.GetU32(&offset); const uint32_t type = m_data.GetU32(&offset); - const uint16_t field_offset = m_data.GetU16(&offset); - const uint16_t padding = m_data.GetU16(&offset); - fields.emplace_back(ReadString(field_name), type, field_offset, padding); + uint64_t field_offset = 0; + if (size < g_ctf_field_threshold) { + field_offset = m_data.GetU16(&offset); + m_data.GetU16(&offset); // Padding + } else { + const uint32_t offset_hi = m_data.GetU32(&offset); + const uint32_t offset_lo = m_data.GetU32(&offset); + field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo); + } + fields.emplace_back(ReadString(field_name), type, field_offset); } return std::make_unique(static_cast(kind), uid, name, variable_length, size, fields); @@ -850,7 +857,6 @@ size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) { if (Symbol *symbol = symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx)) { - Variable::RangeList ranges; ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize()); diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index 92872488a47ef..1f718d9a8b2e5 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -250,6 +250,7 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { static constexpr uint16_t g_ctf_magic = 0xcff1; static constexpr uint8_t g_ctf_version = 4; + static constexpr uint16_t g_ctf_field_threshold = 0x2000; }; } // namespace lldb_private diff --git a/lldb/test/API/macosx/ctf/Makefile b/lldb/test/API/macosx/ctf/Makefile index efe1043cc584a..afe6ab1b5db06 100644 --- a/lldb/test/API/macosx/ctf/Makefile +++ b/lldb/test/API/macosx/ctf/Makefile @@ -28,3 +28,4 @@ a.ctf: a.out.dSYM -R __DWARF,__apple_objc \ a.ctf a.ctf rm -rf a.out.dSYM + rm -rf test.o diff --git a/lldb/test/API/macosx/ctf/TestCTF.py b/lldb/test/API/macosx/ctf/TestCTF.py index 9f8583bccb7a5..470d35f74d1d9 100644 --- a/lldb/test/API/macosx/ctf/TestCTF.py +++ b/lldb/test/API/macosx/ctf/TestCTF.py @@ -37,6 +37,9 @@ def do_test(self): symbol_file = self.getBuildArtifact("a.ctf") + if self.TraceOn(): + self.runCmd("log enable -v lldb symbol") + self.runCmd("target symbols add {}".format(symbol_file)) self.expect( "target variable foo", @@ -53,7 +56,6 @@ def do_test(self): "f = 0x0000000000000000", ], ) - self.expect("target variable foo.n.i", substrs=["(MyInt) foo.n.i = 1"]) self.expect( "target variable foo.n.s", substrs=["(const char *) foo.n.s", '"foo"'] diff --git a/lldb/test/API/macosx/ctf/test.c b/lldb/test/API/macosx/ctf/test.c index 30be60320c47f..71433e941c5b4 100644 --- a/lldb/test/API/macosx/ctf/test.c +++ b/lldb/test/API/macosx/ctf/test.c @@ -31,8 +31,14 @@ typedef struct MyStruct { void (*f)(int); } MyStructT; +struct LargeStruct { + char buffer[9000]; + int b; +}; + MyStructT foo; struct ForwardDecl *forward; +struct LargeStruct bar; void populate(MyInt i) { foo.n.i = i; @@ -45,6 +51,7 @@ void populate(MyInt i) { foo.n.e = eOne; foo.f = NULL; forward = NULL; + bar.b = i; } int main(int argc, char** argv) { From 8dc745ec3e6c9070f92957c5e464ecd37c200540 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sat, 29 Jul 2023 21:32:40 -0700 Subject: [PATCH 5/9] [lldb] Support recursive record types in CTF Support recursive record types in CTF, for example a struct that contains a pointer to itself: struct S { struct S *n; }; We are now more lazy when creating LLDB types. When encountering a record type (struct or union) we create a forward declaration and only complete it when requested. Differential revision: https://reviews.llvm.org/D156498 (cherry picked from commit 12f3d97fc68b304e0efbe183665c0183d9a372b3) --- .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 60 ++++++++++++++----- .../Plugins/SymbolFile/CTF/SymbolFileCTF.h | 7 ++- lldb/test/API/macosx/ctf/TestCTF.py | 2 + lldb/test/API/macosx/ctf/test.c | 6 ++ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 1c4de94e06d7b..55e3a1ddb9616 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -503,26 +503,59 @@ SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) { llvm::Expected SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) { const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind); - CompilerType record_type = m_ast->CreateRecordType(nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(), tag_kind, eLanguageTypeC); + m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record; + Declaration decl; + return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size, + nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, + decl, record_type, lldb_private::Type::ResolveState::Forward); +} + +bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) { + // Check if we have a CTF type for the given incomplete compiler type. + auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType()); + if (it == m_compiler_types.end()) + return false; + + const CTFType *ctf_type = it->second; + assert(ctf_type && "m_compiler_types should only contain valid CTF types"); + + // We only support resolving record types. + assert(ctf_type->kind == CTFType::Kind::eStruct || + ctf_type->kind == CTFType::Kind::eUnion); - m_ast->StartTagDeclarationDefinition(record_type); - for (const CTFRecord::Field &field : ctf_record.fields) { - if (Type *field_type = ResolveTypeUID(field.type)) { - const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0); - TypeSystemClang::AddFieldToRecordType(record_type, field.name, - field_type->GetFullCompilerType(), - eAccessPublic, field_size); + // Cast to the appropriate CTF type. + const CTFRecord *ctf_record = static_cast(ctf_type); + + // If any of the fields are incomplete, we cannot complete the type. + for (const CTFRecord::Field &field : ctf_record->fields) { + if (!ResolveTypeUID(field.type)) { + LLDB_LOG(GetLog(LLDBLog::Symbols), + "Cannot complete type {0} because field {1} is incomplete", + ctf_type->uid, field.type); + return false; } } - m_ast->CompleteTagDeclarationDefinition(record_type); - Declaration decl; - return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size, - nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, - decl, record_type, lldb_private::Type::ResolveState::Full); + // Complete the record type. + m_ast->StartTagDeclarationDefinition(compiler_type); + for (const CTFRecord::Field &field : ctf_record->fields) { + Type *field_type = ResolveTypeUID(field.type); + assert(field_type && "field must be complete"); + const uint32_t field_size = field_type->GetByteSize(nullptr).value_or(0); + TypeSystemClang::AddFieldToRecordType(compiler_type, field.name, + field_type->GetFullCompilerType(), + eAccessPublic, field_size); + } + m_ast->CompleteTagDeclarationDefinition(compiler_type); + + // Now that the compiler type is no longer incomplete we don't need to + // remember it anymore. + m_compiler_types.erase(compiler_type.GetOpaqueQualType()); + + return true; } llvm::Expected @@ -960,7 +993,6 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { if (!ctf_type) return nullptr; - m_types[type_uid] = TypeSP(); Log *log = GetLog(LLDBLog::Symbols); llvm::Expected type_or_error = CreateType(ctf_type); diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index 1f718d9a8b2e5..a37078c9e3993 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -93,7 +93,7 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { return std::nullopt; } - bool CompleteType(CompilerType &compiler_type) override { return false; } + bool CompleteType(CompilerType &compiler_type) override; uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, lldb::SymbolContextItem resolve_scope, @@ -243,6 +243,11 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { std::vector> m_ctf_types; + /// To complete types, we need a way to map (imcomplete) compiler types back + /// to parsed CTF types. + llvm::DenseMap + m_compiler_types; + llvm::DenseMap m_types; std::vector m_functions; diff --git a/lldb/test/API/macosx/ctf/TestCTF.py b/lldb/test/API/macosx/ctf/TestCTF.py index 470d35f74d1d9..f5fd29f6ed968 100644 --- a/lldb/test/API/macosx/ctf/TestCTF.py +++ b/lldb/test/API/macosx/ctf/TestCTF.py @@ -91,3 +91,5 @@ def do_test(self): "}", ], ) + + self.expect("type lookup RecursiveStruct", substrs=["RecursiveStruct *n;"]) diff --git a/lldb/test/API/macosx/ctf/test.c b/lldb/test/API/macosx/ctf/test.c index 71433e941c5b4..358006646e766 100644 --- a/lldb/test/API/macosx/ctf/test.c +++ b/lldb/test/API/macosx/ctf/test.c @@ -36,9 +36,14 @@ struct LargeStruct { int b; }; +struct RecursiveStruct { + struct RecursiveStruct *n; +}; + MyStructT foo; struct ForwardDecl *forward; struct LargeStruct bar; +struct RecursiveStruct ke; void populate(MyInt i) { foo.n.i = i; @@ -52,6 +57,7 @@ void populate(MyInt i) { foo.f = NULL; forward = NULL; bar.b = i; + ke.n = NULL; } int main(int argc, char** argv) { From 43f674cea4160d8bcc044a47f6f1be66b6505913 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 31 Jul 2023 09:41:11 -0700 Subject: [PATCH 6/9] [lldb] Improve memory usage by freeing CTF types (NFC) Improve memory usage by reducing the lifetime of CTF types. Once a CTF type has been converted to a (complete) LLDB type, there's no need to keep it in memory anymore. For most types, we can free them right after creating the corresponding LLDB types. The only exception is record types, which are only completed lazily. Differential revision: https://reviews.llvm.org/D156606 (cherry picked from commit 68918125c11648379b473d8b2d297872cea9f504) --- lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h | 32 +++++++++++++++++++ .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 30 +++++++++-------- .../Plugins/SymbolFile/CTF/SymbolFileCTF.h | 8 +++-- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h index 99a74dbe674ae..c1016b2af0c6b 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h +++ b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h @@ -46,6 +46,8 @@ struct CTFInteger : public CTFType { uint32_t encoding) : CTFType(eInteger, uid, name), bits(bits), encoding(encoding) {} + static bool classof(const CTFType *T) { return T->kind == eInteger; } + uint32_t bits; uint32_t encoding; }; @@ -55,6 +57,11 @@ struct CTFModifier : public CTFType { CTFModifier(Kind kind, lldb::user_id_t uid, uint32_t type) : CTFType(kind, uid, ""), type(type) {} + static bool classof(const CTFType *T) { + return T->kind == ePointer || T->kind == eConst || T->kind == eVolatile || + T->kind == eRestrict; + } + public: uint32_t type; }; @@ -62,27 +69,36 @@ struct CTFModifier : public CTFType { struct CTFPointer : public CTFModifier { CTFPointer(lldb::user_id_t uid, uint32_t type) : CTFModifier(ePointer, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == ePointer; } }; struct CTFConst : public CTFModifier { CTFConst(lldb::user_id_t uid, uint32_t type) : CTFModifier(eConst, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == eConst; } }; struct CTFVolatile : public CTFModifier { CTFVolatile(lldb::user_id_t uid, uint32_t type) : CTFModifier(eVolatile, uid, type) {} + + static bool classof(const CTFType *T) { return T->kind == eVolatile; } }; struct CTFRestrict : public CTFModifier { CTFRestrict(lldb::user_id_t uid, uint32_t type) : CTFModifier(eRestrict, uid, type) {} + static bool classof(const CTFType *T) { return T->kind == eRestrict; } }; struct CTFTypedef : public CTFType { CTFTypedef(lldb::user_id_t uid, llvm::StringRef name, uint32_t type) : CTFType(eTypedef, uid, name), type(type) {} + static bool classof(const CTFType *T) { return T->kind == eTypedef; } + uint32_t type; }; @@ -91,6 +107,8 @@ struct CTFArray : public CTFType { uint32_t index, uint32_t nelems) : CTFType(eArray, uid, name), type(type), index(index), nelems(nelems) {} + static bool classof(const CTFType *T) { return T->kind == eArray; } + uint32_t type; uint32_t index; uint32_t nelems; @@ -110,6 +128,8 @@ struct CTFEnum : public CTFType { assert(this->values.size() == nelems); } + static bool classof(const CTFType *T) { return T->kind == eEnum; } + uint32_t nelems; uint32_t size; std::vector values; @@ -121,6 +141,8 @@ struct CTFFunction : public CTFType { : CTFType(eFunction, uid, name), nargs(nargs), return_type(return_type), args(std::move(args)), variadic(variadic) {} + static bool classof(const CTFType *T) { return T->kind == eFunction; } + uint32_t nargs; uint32_t return_type; @@ -144,6 +166,10 @@ struct CTFRecord : public CTFType { : CTFType(kind, uid, name), nfields(nfields), size(size), fields(std::move(fields)) {} + static bool classof(const CTFType *T) { + return T->kind == eStruct || T->kind == eUnion; + } + uint32_t nfields; uint32_t size; std::vector fields; @@ -153,17 +179,23 @@ struct CTFStruct : public CTFRecord { CTFStruct(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, uint32_t size, std::vector fields) : CTFRecord(eStruct, uid, name, nfields, size, std::move(fields)){}; + + static bool classof(const CTFType *T) { return T->kind == eStruct; } }; struct CTFUnion : public CTFRecord { CTFUnion(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields, uint32_t size, std::vector fields) : CTFRecord(eUnion, uid, name, nfields, size, std::move(fields)){}; + + static bool classof(const CTFType *T) { return T->kind == eUnion; } }; struct CTFForward : public CTFType { CTFForward(lldb::user_id_t uid, llvm::StringRef name) : CTFType(eForward, uid, name) {} + + static bool classof(const CTFType *T) { return T->kind == eForward; } }; } // namespace lldb_private diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 55e3a1ddb9616..89329d1abf5dc 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -523,8 +523,7 @@ bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) { assert(ctf_type && "m_compiler_types should only contain valid CTF types"); // We only support resolving record types. - assert(ctf_type->kind == CTFType::Kind::eStruct || - ctf_type->kind == CTFType::Kind::eUnion); + assert(llvm::isa(ctf_type)); // Cast to the appropriate CTF type. const CTFRecord *ctf_record = static_cast(ctf_type); @@ -551,9 +550,10 @@ bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) { } m_ast->CompleteTagDeclarationDefinition(compiler_type); - // Now that the compiler type is no longer incomplete we don't need to - // remember it anymore. + // Now that the compiler type is complete, we don't need to remember it + // anymore and can remove the CTF record type. m_compiler_types.erase(compiler_type.GetOpaqueQualType()); + m_ctf_types.erase(ctf_type->uid); return true; } @@ -727,9 +727,8 @@ size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) { llvm::Expected> type_or_error = ParseType(type_offset, type_uid); if (type_or_error) { - m_ctf_types.emplace_back(std::move(*type_or_error)); + m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error); } else { - m_ctf_types.emplace_back(std::unique_ptr()); LLDB_LOG_ERROR(log, type_or_error.takeError(), "Failed to parse type {1} at offset {2}: {0}", type_uid, type_offset); @@ -982,16 +981,16 @@ void SymbolFileCTF::AddSymbols(Symtab &symtab) { } lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { - auto find_result = m_types.find(type_uid); - if (find_result != m_types.end()) - return find_result->second.get(); + auto type_it = m_types.find(type_uid); + if (type_it != m_types.end()) + return type_it->second.get(); - if (type_uid == 0 || type_uid > m_ctf_types.size()) + auto ctf_type_it = m_ctf_types.find(type_uid); + if (ctf_type_it == m_ctf_types.end()) return nullptr; - CTFType *ctf_type = m_ctf_types[type_uid - 1].get(); - if (!ctf_type) - return nullptr; + CTFType *ctf_type = ctf_type_it->second.get(); + assert(ctf_type && "m_ctf_types should only contain valid CTF types"); Log *log = GetLog(LLDBLog::Symbols); @@ -1013,6 +1012,11 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { m_types[type_uid] = type_sp; + // Except for record types which we'll need to complete later, we don't need + // the CTF type anymore. + if (!isa(ctf_type)) + m_ctf_types.erase(type_uid); + return type_sp.get(); } diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index a37078c9e3993..3a80138fffbc3 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -241,15 +241,17 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { std::optional m_header; - std::vector> m_ctf_types; + /// Parsed CTF types. + llvm::DenseMap> m_ctf_types; + + /// Parsed LLDB types. + llvm::DenseMap m_types; /// To complete types, we need a way to map (imcomplete) compiler types back /// to parsed CTF types. llvm::DenseMap m_compiler_types; - llvm::DenseMap m_types; - std::vector m_functions; std::vector m_variables; From f6f6bcb9cc6d421bfde550816a691108d354c2c6 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 24 Apr 2024 11:22:05 -0700 Subject: [PATCH 7/9] [lldb] Re-apply changes for dcbf7881f6a4c0ad8c8853f851f43161dc3c3236 --- .../Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 89329d1abf5dc..6aad028459680 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -1020,23 +1020,18 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { return type_sp.get(); } -void SymbolFileCTF::FindTypes( - lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet &searched_symbol_files, - lldb_private::TypeMap &types) { - - searched_symbol_files.clear(); - searched_symbol_files.insert(this); +void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) { + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) + return; - size_t matches = 0; + ConstString name = match.GetTypeBasename(); for (TypeSP type_sp : GetTypeList().Types()) { - if (matches == max_matches) - break; if (type_sp && type_sp->GetName() == name) { - types.Insert(type_sp); - matches++; + results.InsertUnique(type_sp); + if (results.Done(match)) + return; } } } From d33ad22024bea25fde7457a985805c82d46a813c Mon Sep 17 00:00:00 2001 From: Alexandre Ganea Date: Thu, 18 Jan 2024 09:33:23 -0500 Subject: [PATCH 8/9] [lldb] Silence warning with latest MSVC on Windows Fixes: ``` [3465/3822] Building CXX object tools\lldb\source\Plugins\SymbolFile\CTF\CMakeFiles\lldbPluginSymbolFileCTF.dir\SymbolFileCTF.cpp.obj C:\git\llvm-project\lldb\source\Plugins\SymbolFile\CTF\SymbolFileCTF.cpp(606) : warning C4715: 'lldb_private::SymbolFileCTF::CreateType': not all control paths return a value ``` (cherry picked from commit bafdaa171a2806ceff628ed7b64ace2b92c05578) --- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 6aad028459680..59933646b45ea 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -603,6 +603,7 @@ llvm::Expected SymbolFileCTF::CreateType(CTFType *ctf_type) { ctf_type->uid, ctf_type->name, ctf_type->kind), llvm::inconvertibleErrorCode()); } + llvm_unreachable("Unexpected CTF type kind"); } llvm::Expected> From 18e12db74c58687213a8e345d5d0c9d461552296 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Tue, 23 Apr 2024 16:50:22 -0700 Subject: [PATCH 9/9] [lldb] Fix crash in SymbolFileCTF::ParseFunctions (#89845) Make SymbolFileCTF::ParseFunctions resilient against not being able to resolve the argument or return type of a function. ResolveTypeUID can fail for a variety of reasons so we should always check its result. The type that caused the crash was `_Bool` which we didn't recognize as a basic type. This commit also fixes the underlying issue and adds a test. rdar://126943722 (cherry picked from commit fd4399cb11f4069888bc7eac01f74493b5a2af48) --- lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp | 10 ++++++---- .../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 5 ++++- lldb/test/API/macosx/ctf/Makefile | 2 +- lldb/test/API/macosx/ctf/TestCTF.py | 1 + lldb/test/API/macosx/ctf/test.c | 3 +++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 59933646b45ea..616c1221264f6 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -342,7 +342,7 @@ SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) { CompilerType compiler_type = m_ast->GetBasicType(basic_type); - if (basic_type != eBasicTypeVoid) { + if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) { // Make sure the type we got is an integer type. bool compiler_type_is_signed = false; if (!compiler_type.IsIntegerType(compiler_type_is_signed)) @@ -802,7 +802,8 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { } Type *arg_type = ResolveTypeUID(arg_uid); - arg_types.push_back(arg_type->GetFullCompilerType()); + arg_types.push_back(arg_type ? arg_type->GetFullCompilerType() + : CompilerType()); } if (symbol) { @@ -813,8 +814,9 @@ size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) { // Create function type. CompilerType func_type = m_ast->CreateFunctionType( - ret_type->GetFullCompilerType(), arg_types.data(), arg_types.size(), - is_variadic, 0, clang::CallingConv::CC_C); + ret_type ? ret_type->GetFullCompilerType() : CompilerType(), + arg_types.data(), arg_types.size(), is_variadic, 0, + clang::CallingConv::CC_C); lldb::user_id_t function_type_uid = m_types.size() + 1; TypeSP type_sp = MakeType(function_type_uid, symbol->GetName(), 0, nullptr, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 3760d9f736d06..a83a0e0de7c41 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -955,8 +955,11 @@ lldb::BasicType TypeSystemClang::GetBasicTypeEnumeration(llvm::StringRef name) { {"__int128_t", eBasicTypeInt128}, {"__uint128_t", eBasicTypeUnsignedInt128}, - // Miscellaneous + // "bool" {"bool", eBasicTypeBool}, + {"_Bool", eBasicTypeBool}, + + // Miscellaneous {"float", eBasicTypeFloat}, {"double", eBasicTypeDouble}, {"long double", eBasicTypeLongDouble}, diff --git a/lldb/test/API/macosx/ctf/Makefile b/lldb/test/API/macosx/ctf/Makefile index afe6ab1b5db06..0857e234837e5 100644 --- a/lldb/test/API/macosx/ctf/Makefile +++ b/lldb/test/API/macosx/ctf/Makefile @@ -4,7 +4,7 @@ MAKE_DSYM := YES ifeq "$(COMPRESS_CTF)" "YES" COMPRESS := -c else - COMPRESS := + COMPRESS := endif all: a.out a.ctf diff --git a/lldb/test/API/macosx/ctf/TestCTF.py b/lldb/test/API/macosx/ctf/TestCTF.py index f5fd29f6ed968..fed3a8886dd30 100644 --- a/lldb/test/API/macosx/ctf/TestCTF.py +++ b/lldb/test/API/macosx/ctf/TestCTF.py @@ -53,6 +53,7 @@ def do_test(self): "[2] = 'b'", "[3] = 'c'", 'u = (i = 1, s = "")', + "b = false", "f = 0x0000000000000000", ], ) diff --git a/lldb/test/API/macosx/ctf/test.c b/lldb/test/API/macosx/ctf/test.c index 358006646e766..a15f7a5161334 100644 --- a/lldb/test/API/macosx/ctf/test.c +++ b/lldb/test/API/macosx/ctf/test.c @@ -1,3 +1,4 @@ +#include #include struct ForwardDecl; @@ -24,6 +25,7 @@ typedef struct MyNestedStruct { char a[4]; MyEnumT e; MyUnionT u; + _Bool b; } MyNestedStructT; typedef struct MyStruct { @@ -54,6 +56,7 @@ void populate(MyInt i) { foo.n.a[2] = 'c'; foo.n.a[3] = 'd'; foo.n.e = eOne; + foo.n.b = false; foo.f = NULL; forward = NULL; bar.b = i;