[Lldb-commits] [lldb] 0a5e0d3 - [lldb] Split CTF parsing and type creation (NFC)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 28 09:41:52 PDT 2023
Author: Jonas Devlieghere
Date: 2023-07-28T09:41:47-07:00
New Revision: 0a5e0d3fad8dfdebc8bb2f51f6008bdd41e27580
URL: https://github.com/llvm/llvm-project/commit/0a5e0d3fad8dfdebc8bb2f51f6008bdd41e27580
DIFF: https://github.com/llvm/llvm-project/commit/0a5e0d3fad8dfdebc8bb2f51f6008bdd41e27580.diff
LOG: [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
Added:
lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
Modified:
lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
lldb/test/API/macosx/ctf/TestCTF.py
Removed:
################################################################################
diff --git a/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h b/lldb/source/Plugins/SymbolFile/CTF/CTFTypes.h
new file mode 100644
index 00000000000000..8c6ee278bbe356
--- /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<Value> 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<Value> values;
+};
+
+struct CTFFunction : public CTFType {
+ CTFFunction(lldb::user_id_t uid, llvm::StringRef name, uint32_t nargs,
+ uint32_t return_type, std::vector<uint32_t> 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<uint32_t> 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<Field> fields)
+ : CTFType(kind, uid, name), nfields(nfields), size(size),
+ fields(std::move(fields)) {}
+
+ uint32_t nfields;
+ uint32_t size;
+ std::vector<Field> fields;
+};
+
+struct CTFStruct : public CTFRecord {
+ CTFStruct(lldb::user_id_t uid, llvm::StringRef name, uint32_t nfields,
+ uint32_t size, std::vector<Field> 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<Field> 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 88926baa7a6e7f..2798bc674471e1 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<TypeSP> 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<TypeSP>
+SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) {
+ lldb::BasicType basic_type =
+ TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name);
if (basic_type == eBasicTypeInvalid)
return llvm::make_error<llvm::StringError>(
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<TypeSP> SymbolFileCTF::ParseInteger(lldb::offset_t &offset,
return llvm::make_error<llvm::StringError>(
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::StringError>(
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<lldb::TypeSP>
-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::StringError>(
- 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::StringError>(
- 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<lldb::TypeSP> SymbolFileCTF::ParseTypedef(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name,
- uint32_t type) {
- TypeSP underlying_type = GetTypeForUID(type);
+llvm::Expected<lldb::TypeSP>
+SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) {
+ Type *underlying_type = ResolveTypeUID(ctf_typedef.type);
if (!underlying_type)
return llvm::make_error<llvm::StringError>(
- 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<lldb::TypeSP> 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<lldb::TypeSP>
+SymbolFileCTF::CreateArray(const CTFArray &ctf_array) {
+ Type *element_type = ResolveTypeUID(ctf_array.type);
if (!element_type)
return llvm::make_error<llvm::StringError>(
- 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<uint64_t> element_size = element_type->GetByteSize(nullptr);
if (!element_size)
return llvm::make_error<llvm::StringError>(
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<lldb::TypeSP> 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<lldb::TypeSP> SymbolFileCTF::ParseEnum(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name,
- uint32_t elements,
- uint32_t size) {
+llvm::Expected<lldb::TypeSP>
+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<lldb::TypeSP>
-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<CompilerType> 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::StringError>(
- 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<lldb::TypeSP>
-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<TypeKind>(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<TypeSP> 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<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) {
+ if (!ctf_type)
+ return llvm::make_error<llvm::StringError>(
+ "cannot create type for unparsed type", llvm::inconvertibleErrorCode());
+
+ switch (ctf_type->kind) {
+ case CTFType::Kind::eInteger:
+ return CreateInteger(*static_cast<CTFInteger *>(ctf_type));
+ case CTFType::Kind::eConst:
+ case CTFType::Kind::ePointer:
+ case CTFType::Kind::eRestrict:
+ case CTFType::Kind::eVolatile:
+ return CreateModifier(*static_cast<CTFModifier *>(ctf_type));
+ case CTFType::Kind::eTypedef:
+ return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type));
+ case CTFType::Kind::eArray:
+ return CreateArray(*static_cast<CTFArray *>(ctf_type));
+ case CTFType::Kind::eEnum:
+ return CreateEnum(*static_cast<CTFEnum *>(ctf_type));
+ case CTFType::Kind::eFunction:
+ return CreateFunction(*static_cast<CTFFunction *>(ctf_type));
+ case CTFType::Kind::eStruct:
+ case CTFType::Kind::eUnion:
+ return CreateRecord(*static_cast<CTFRecord *>(ctf_type));
+ case CTFType::Kind::eUnknown:
+ case CTFType::Kind::eFloat:
+ case CTFType::Kind::eForward:
+ case CTFType::Kind::eSlice:
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})",
+ ctf_type->uid, ctf_type->name, ctf_type->kind),
+ llvm::inconvertibleErrorCode());
+ }
+}
+
+llvm::Expected<std::unique_ptr<CTFType>>
+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<CTFInteger>(uid, name, bits, encoding);
+ }
case TypeKind::eConst:
+ return std::make_unique<CTFConst>(uid, type);
case TypeKind::ePointer:
+ return std::make_unique<CTFPointer>(uid, type);
case TypeKind::eRestrict:
+ return std::make_unique<CTFRestrict>(uid, type);
case TypeKind::eVolatile:
- return ParseModifierType(offset, uid, kind, type);
+ return std::make_unique<CTFVolatile>(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<CTFTypedef>(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<CTFArray>(uid, name, type, index, nelems);
+ }
+ case TypeKind::eEnum: {
+ std::vector<CTFEnum::Value> 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<CTFEnum>(uid, name, variable_length, size, values);
+ }
+ case TypeKind::eFunction: {
+ std::vector<uint32_t> 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<CTFFunction>(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<CTFRecord::Field> 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<CTFRecord>(static_cast<CTFType::Kind>(kind), uid,
+ name, variable_length, size, fields);
+ }
+ case TypeKind::eUnknown:
+ return std::make_unique<CTFType>(static_cast<CTFType::Kind>(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::StringError>(
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<TypeSP> type_or_error = ParseType(
- type_offset, type_uid, name, kind, variable_length, type, size);
- if (!type_or_error) {
+ llvm::Expected<std::unique_ptr<CTFType>> 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<CTFType>());
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<TypeSP> 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 bdd6dcdc3fda32..73854275ff674b 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
@@ -13,6 +13,7 @@
#include <optional>
#include <vector>
+#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<ArrayInfo> GetDynamicArrayInfoForUID(
lldb::user_id_t type_uid,
@@ -216,60 +214,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<lldb::TypeSP> 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<std::unique_ptr<CTFType>> ParseType(lldb::offset_t &offset,
+ lldb::user_id_t uid);
- llvm::Expected<lldb::TypeSP> ParseInteger(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name);
-
- llvm::Expected<lldb::TypeSP> ParseModifierType(lldb::offset_t &offset,
- lldb::user_id_t uid,
- uint32_t kind, uint32_t type);
-
- llvm::Expected<lldb::TypeSP> ParseTypedef(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name,
- uint32_t type);
-
- llvm::Expected<lldb::TypeSP>
- ParseArray(lldb::offset_t &offset, lldb::user_id_t uid, llvm::StringRef name);
-
- llvm::Expected<lldb::TypeSP> ParseEnum(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name,
- uint32_t elements, uint32_t size);
-
- llvm::Expected<lldb::TypeSP> ParseFunction(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name,
- uint32_t num_args, uint32_t type);
-
- llvm::Expected<lldb::TypeSP> ParseRecord(lldb::offset_t &offset,
- lldb::user_id_t uid,
- llvm::StringRef name, uint32_t kind,
- uint32_t fields, uint32_t size);
+ llvm::Expected<lldb::TypeSP> CreateType(CTFType *ctf_type);
+ llvm::Expected<lldb::TypeSP> CreateInteger(const CTFInteger &ctf_integer);
+ llvm::Expected<lldb::TypeSP> CreateModifier(const CTFModifier &ctf_modifier);
+ llvm::Expected<lldb::TypeSP> CreateTypedef(const CTFTypedef &ctf_typedef);
+ llvm::Expected<lldb::TypeSP> CreateArray(const CTFArray &ctf_array);
+ llvm::Expected<lldb::TypeSP> CreateEnum(const CTFEnum &ctf_enum);
+ llvm::Expected<lldb::TypeSP> CreateFunction(const CTFFunction &ctf_function);
+ llvm::Expected<lldb::TypeSP> CreateRecord(const CTFRecord &ctf_record);
llvm::StringRef ReadString(lldb::offset_t offset) const;
@@ -288,7 +243,11 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon {
lldb::CompUnitSP m_comp_unit_sp;
std::optional<ctf_header_t> m_header;
- std::vector<lldb::TypeSP> m_types;
+
+ std::vector<std::unique_ptr<CTFType>> m_ctf_types;
+
+ llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
+
std::vector<lldb::FunctionSP> m_functions;
std::vector<lldb::VariableSP> m_variables;
diff --git a/lldb/test/API/macosx/ctf/TestCTF.py b/lldb/test/API/macosx/ctf/TestCTF.py
index fc8328a73c3083..9f8583bccb7a5b 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",
+ "}",
+ ],
+ )
More information about the lldb-commits
mailing list