brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.1 KiB · 591fded Raw
1136 lines · cpp
1//===-- SymbolFileCTF.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SymbolFileCTF.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Core/PluginManager.h"13#include "lldb/Host/Config.h"14#include "lldb/Symbol/CompileUnit.h"15#include "lldb/Symbol/Function.h"16#include "lldb/Symbol/ObjectFile.h"17#include "lldb/Symbol/Symbol.h"18#include "lldb/Symbol/SymbolContext.h"19#include "lldb/Symbol/Symtab.h"20#include "lldb/Symbol/TypeList.h"21#include "lldb/Symbol/TypeMap.h"22#include "lldb/Symbol/Variable.h"23#include "lldb/Symbol/VariableList.h"24#include "lldb/Utility/DataExtractor.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/Log.h"27#include "lldb/Utility/RegularExpression.h"28#include "lldb/Utility/StreamBuffer.h"29#include "lldb/Utility/StreamString.h"30#include "lldb/Utility/Timer.h"31#include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_ZLIB32#include "llvm/Support/MemoryBuffer.h"33 34#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"35#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"36 37#include <memory>38#include <optional>39 40#if LLVM_ENABLE_ZLIB41#include <zlib.h>42#endif43 44using namespace llvm;45using namespace lldb;46using namespace lldb_private;47 48LLDB_PLUGIN_DEFINE(SymbolFileCTF)49 50char SymbolFileCTF::ID;51 52SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp)53    : SymbolFileCommon(std::move(objfile_sp)) {}54 55void SymbolFileCTF::Initialize() {56  PluginManager::RegisterPlugin(GetPluginNameStatic(),57                                GetPluginDescriptionStatic(), CreateInstance);58}59 60void SymbolFileCTF::Terminate() {61  PluginManager::UnregisterPlugin(CreateInstance);62}63 64llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() {65  return "Compact C Type Format Symbol Reader";66}67 68SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) {69  return new SymbolFileCTF(std::move(objfile_sp));70}71 72bool SymbolFileCTF::ParseHeader() {73  if (m_header)74    return true;75 76  Log *log = GetLog(LLDBLog::Symbols);77 78  ModuleSP module_sp(m_objfile_sp->GetModule());79  const SectionList *section_list = module_sp->GetSectionList();80  if (!section_list)81    return false;82 83  SectionSP section_sp(84      section_list->FindSectionByType(lldb::eSectionTypeCTF, true));85  if (!section_sp)86    return false;87 88  m_objfile_sp->ReadSectionData(section_sp.get(), m_data);89 90  if (m_data.GetByteSize() == 0)91    return false;92 93  StreamString module_desc;94  GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),95                                               lldb::eDescriptionLevelBrief);96  LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData());97 98  lldb::offset_t offset = 0;99 100  // Parse CTF header.101  constexpr size_t ctf_header_size = sizeof(ctf_header_t);102  if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) {103    LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header");104    return false;105  }106 107  m_header.emplace();108 109  ctf_header_t &ctf_header = *m_header;110  ctf_header.preamble.magic = m_data.GetU16(&offset);111  ctf_header.preamble.version = m_data.GetU8(&offset);112  ctf_header.preamble.flags = m_data.GetU8(&offset);113  ctf_header.parlabel = m_data.GetU32(&offset);114  ctf_header.parname = m_data.GetU32(&offset);115  ctf_header.lbloff = m_data.GetU32(&offset);116  ctf_header.objtoff = m_data.GetU32(&offset);117  ctf_header.funcoff = m_data.GetU32(&offset);118  ctf_header.typeoff = m_data.GetU32(&offset);119  ctf_header.stroff = m_data.GetU32(&offset);120  ctf_header.strlen = m_data.GetU32(&offset);121 122  // Validate the preamble.123  if (ctf_header.preamble.magic != g_ctf_magic) {124    LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}",125             ctf_header.preamble.magic);126    return false;127  }128 129  if (ctf_header.preamble.version != g_ctf_version) {130    LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}",131             ctf_header.preamble.version);132    return false;133  }134 135  LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}",136           ctf_header.preamble.version, ctf_header.preamble.flags);137 138  m_body_offset = offset;139 140  if (ctf_header.preamble.flags & eFlagCompress) {141    // The body has been compressed with zlib deflate. Header offsets point into142    // the decompressed data.143#if LLVM_ENABLE_ZLIB144    const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen;145    DataBufferSP decompressed_data =146        std::make_shared<DataBufferHeap>(decompressed_size, 0x0);147 148    z_stream zstr;149    memset(&zstr, 0, sizeof(zstr));150    zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() +151                                                  sizeof(ctf_header_t));152    zstr.avail_in = m_data.BytesLeft(offset);153    zstr.next_out =154        (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes());155    zstr.avail_out = decompressed_size;156 157    int rc = inflateInit(&zstr);158    if (rc != Z_OK) {159      LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}",160               zError(rc));161      return false;162    }163 164    rc = inflate(&zstr, Z_FINISH);165    if (rc != Z_STREAM_END) {166      LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc));167      return false;168    }169 170    rc = inflateEnd(&zstr);171    if (rc != Z_OK) {172      LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc));173      return false;174    }175 176    if (zstr.total_out != decompressed_size) {177      LLDB_LOG(log,178               "CTF parsing failed: decompressed size ({0}) doesn't match "179               "expected size ([1})",180               zstr.total_out, decompressed_size);181      return false;182    }183 184    m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(),185                           m_data.GetAddressByteSize());186    m_body_offset = 0;187#else188    LLDB_LOG(189        log,190        "CTF parsing failed: data is compressed but no zlib inflate support");191    return false;192#endif193  }194 195  // Validate the header.196  if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) {197    LLDB_LOG(log,198             "CTF parsing failed: invalid label section offset in header: {0}",199             ctf_header.lbloff);200    return false;201  }202 203  if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) {204    LLDB_LOG(log,205             "CTF parsing failed: invalid object section offset in header: {0}",206             ctf_header.objtoff);207    return false;208  }209 210  if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) {211    LLDB_LOG(212        log,213        "CTF parsing failed: invalid function section offset in header: {0}",214        ctf_header.funcoff);215    return false;216  }217 218  if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) {219    LLDB_LOG(log,220             "CTF parsing failed: invalid type section offset in header: {0}",221             ctf_header.typeoff);222    return false;223  }224 225  if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) {226    LLDB_LOG(log,227             "CTF parsing failed: invalid string section offset in header: {0}",228             ctf_header.stroff);229    return false;230  }231 232  const lldb::offset_t str_end_offset =233      m_body_offset + ctf_header.stroff + ctf_header.strlen;234  if (!m_data.ValidOffset(str_end_offset - 1)) {235    LLDB_LOG(log,236             "CTF parsing failed: invalid string section length in header: {0}",237             ctf_header.strlen);238    return false;239  }240 241  if (m_body_offset + ctf_header.stroff + ctf_header.parlabel >242      str_end_offset) {243    LLDB_LOG(log,244             "CTF parsing failed: invalid parent label offset: {0} exceeds end "245             "of string section ({1})",246             ctf_header.parlabel, str_end_offset);247    return false;248  }249 250  if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) {251    LLDB_LOG(log,252             "CTF parsing failed: invalid parent name offset: {0} exceeds end "253             "of string section ({1})",254             ctf_header.parname, str_end_offset);255    return false;256  }257 258  LLDB_LOG(log,259           "Parsed valid CTF header: lbloff  = {0}, objtoff = {1}, funcoff = "260           "{2}, typeoff = {3}, stroff = {4}, strlen = {5}",261           ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff,262           ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen);263 264  return true;265}266 267void SymbolFileCTF::InitializeObject() {268  Log *log = GetLog(LLDBLog::Symbols);269 270  auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC);271  if (auto err = type_system_or_err.takeError()) {272    LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}");273    return;274  }275 276  auto ts = *type_system_or_err;277  m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());278  LazyBool optimized = eLazyBoolNo;279  m_comp_unit_sp = std::make_shared<CompileUnit>(280      m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized);281 282  ParseTypes(*m_comp_unit_sp);283}284 285llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const {286  lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset;287  if (!m_data.ValidOffset(offset))288    return "(invalid)";289  const char *str = m_data.GetCStr(&offset);290  if (str && !*str)291    return "(anon)";292  return llvm::StringRef(str);293}294 295/// Return the integer display representation encoded in the given data.296static uint32_t GetEncoding(uint32_t data) {297  // Mask bits 24–31.298  return ((data)&0xff000000) >> 24;299}300 301/// Return the integral width in bits encoded in the given data.302static uint32_t GetBits(uint32_t data) {303  // Mask bits 0-15.304  return (data)&0x0000ffff;305}306 307/// Return the type kind encoded in the given data.308uint32_t GetKind(uint32_t data) {309  // Mask bits 26–31.310  return ((data)&0xf800) >> 11;311}312 313/// Return the variable length encoded in the given data.314uint32_t GetVLen(uint32_t data) {315  // Mask bits 0–24.316  return (data)&0x3ff;317}318 319static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); }320 321static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) {322  switch (type) {323  case CTFType::Kind::eStruct:324    return clang::TagTypeKind::Struct;325  case CTFType::Kind::eUnion:326    return clang::TagTypeKind::Union;327  default:328    lldbassert(false && "Invalid record kind!");329    return clang::TagTypeKind::Struct;330  }331}332 333llvm::Expected<TypeSP>334SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) {335  lldb::BasicType basic_type =336      TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name);337  if (basic_type == eBasicTypeInvalid)338    return llvm::make_error<llvm::StringError>(339        llvm::formatv("unsupported integer type: no corresponding basic clang "340                      "type for '{0}'",341                      ctf_integer.name),342        llvm::inconvertibleErrorCode());343 344  CompilerType compiler_type = m_ast->GetBasicType(basic_type);345 346  if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) {347    // Make sure the type we got is an integer type.348    bool compiler_type_is_signed = false;349    if (!compiler_type.IsIntegerType(compiler_type_is_signed))350      return llvm::make_error<llvm::StringError>(351          llvm::formatv(352              "Found compiler type for '{0}' but it's not an integer type: {1}",353              ctf_integer.name,354              compiler_type.GetDisplayTypeName().GetStringRef()),355          llvm::inconvertibleErrorCode());356 357    // Make sure the signing matches between the CTF and the compiler type.358    const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned);359    if (compiler_type_is_signed != type_is_signed)360      return llvm::make_error<llvm::StringError>(361          llvm::formatv("Found integer compiler type for {0} but compiler type "362                        "is {1} and {0} is {2}",363                        ctf_integer.name,364                        compiler_type_is_signed ? "signed" : "unsigned",365                        type_is_signed ? "signed" : "unsigned"),366          llvm::inconvertibleErrorCode());367  }368 369  Declaration decl;370  return MakeType(ctf_integer.uid, ConstString(ctf_integer.name),371                  GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID,372                  lldb_private::Type::eEncodingIsUID, decl, compiler_type,373                  lldb_private::Type::ResolveState::Full);374}375 376llvm::Expected<lldb::TypeSP>377SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) {378  Type *ref_type = ResolveTypeUID(ctf_modifier.type);379  if (!ref_type)380    return llvm::make_error<llvm::StringError>(381        llvm::formatv("Could not find modified type: {0}", ctf_modifier.type),382        llvm::inconvertibleErrorCode());383 384  CompilerType compiler_type;385 386  switch (ctf_modifier.kind) {387  case CTFType::ePointer:388    compiler_type = ref_type->GetFullCompilerType().GetPointerType();389    break;390  case CTFType::eConst:391    compiler_type = ref_type->GetFullCompilerType().AddConstModifier();392    break;393  case CTFType::eVolatile:394    compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier();395    break;396  case CTFType::eRestrict:397    compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier();398    break;399  default:400    return llvm::make_error<llvm::StringError>(401        llvm::formatv("ParseModifier called with unsupported kind: {0}",402                      ctf_modifier.kind),403        llvm::inconvertibleErrorCode());404  }405 406  Declaration decl;407  return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,408                  Type::eEncodingIsUID, decl, compiler_type,409                  lldb_private::Type::ResolveState::Full);410}411 412llvm::Expected<lldb::TypeSP>413SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) {414  Type *underlying_type = ResolveTypeUID(ctf_typedef.type);415  if (!underlying_type)416    return llvm::make_error<llvm::StringError>(417        llvm::formatv("Could not find typedef underlying type: {0}",418                      ctf_typedef.type),419        llvm::inconvertibleErrorCode());420 421  CompilerType target_ast_type = underlying_type->GetFullCompilerType();422  clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl();423  CompilerType ast_typedef = target_ast_type.CreateTypedef(424      ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0);425 426  Declaration decl;427  return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr,428                  LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,429                  ast_typedef, lldb_private::Type::ResolveState::Full);430}431 432llvm::Expected<lldb::TypeSP>433SymbolFileCTF::CreateArray(const CTFArray &ctf_array) {434  Type *element_type = ResolveTypeUID(ctf_array.type);435  if (!element_type)436    return llvm::make_error<llvm::StringError>(437        llvm::formatv("Could not find array element type: {0}", ctf_array.type),438        llvm::inconvertibleErrorCode());439 440  auto element_size_or_err = element_type->GetByteSize(nullptr);441  if (!element_size_or_err)442    return element_size_or_err.takeError();443 444  uint64_t size = ctf_array.nelems * *element_size_or_err;445 446  CompilerType compiler_type = m_ast->CreateArrayType(447      element_type->GetFullCompilerType(), ctf_array.nelems,448      /*is_gnu_vector*/ false);449 450  Declaration decl;451  return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID,452                  Type::eEncodingIsUID, decl, compiler_type,453                  lldb_private::Type::ResolveState::Full);454}455 456llvm::Expected<lldb::TypeSP>457SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) {458  Declaration decl;459  CompilerType enum_type = m_ast->CreateEnumerationType(460      ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(),461      decl, m_ast->GetBasicType(eBasicTypeInt),462      /*is_scoped=*/false);463 464  for (const CTFEnum::Value &value : ctf_enum.values) {465    Declaration value_decl;466    m_ast->AddEnumerationValueToEnumerationType(467        enum_type, value_decl, value.name.data(), value.value, ctf_enum.size);468  }469  TypeSystemClang::CompleteTagDeclarationDefinition(enum_type);470 471  return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,472                  Type::eEncodingIsUID, decl, enum_type,473                  lldb_private::Type::ResolveState::Full);474}475 476llvm::Expected<lldb::TypeSP>477SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) {478  std::vector<CompilerType> arg_types;479  for (uint32_t arg : ctf_function.args) {480    if (Type *arg_type = ResolveTypeUID(arg))481      arg_types.push_back(arg_type->GetFullCompilerType());482  }483 484  Type *ret_type = ResolveTypeUID(ctf_function.return_type);485  if (!ret_type)486    return llvm::make_error<llvm::StringError>(487        llvm::formatv("Could not find function return type: {0}",488                      ctf_function.return_type),489        llvm::inconvertibleErrorCode());490 491  CompilerType func_type = m_ast->CreateFunctionType(492      ret_type->GetFullCompilerType(), arg_types, ctf_function.variadic, 0,493      clang::CallingConv::CC_C);494 495  Declaration decl;496  return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr,497                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,498                  lldb_private::Type::ResolveState::Full);499}500 501llvm::Expected<lldb::TypeSP>502SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) {503  const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind);504  CompilerType record_type = m_ast->CreateRecordType(505      nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(),506      llvm::to_underlying(tag_kind), eLanguageTypeC);507  m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record;508  Declaration decl;509  return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,510                  nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,511                  decl, record_type, lldb_private::Type::ResolveState::Forward);512}513 514bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {515  // Check if we have a CTF type for the given incomplete compiler type.516  auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType());517  if (it == m_compiler_types.end())518    return false;519 520  const CTFType *ctf_type = it->second;521  assert(ctf_type && "m_compiler_types should only contain valid CTF types");522 523  // We only support resolving record types.524  assert(llvm::isa<CTFRecord>(ctf_type));525 526  // Cast to the appropriate CTF type.527  const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);528 529  // If any of the fields are incomplete, we cannot complete the type.530  for (const CTFRecord::Field &field : ctf_record->fields) {531    if (!ResolveTypeUID(field.type)) {532      LLDB_LOG(GetLog(LLDBLog::Symbols),533               "Cannot complete type {0} because field {1} is incomplete",534               ctf_type->uid, field.type);535      return false;536    }537  }538 539  // Complete the record type.540  m_ast->StartTagDeclarationDefinition(compiler_type);541  for (const CTFRecord::Field &field : ctf_record->fields) {542    Type *field_type = ResolveTypeUID(field.type);543    assert(field_type && "field must be complete");544    const uint32_t field_size =545        llvm::expectedToOptional(field_type->GetByteSize(nullptr)).value_or(0);546    TypeSystemClang::AddFieldToRecordType(compiler_type, field.name,547                                          field_type->GetFullCompilerType(),548                                          eAccessPublic, field_size);549  }550  m_ast->CompleteTagDeclarationDefinition(compiler_type);551 552  // Now that the compiler type is complete, we don't need to remember it553  // anymore and can remove the CTF record type.554  m_compiler_types.erase(compiler_type.GetOpaqueQualType());555  m_ctf_types.erase(ctf_type->uid);556 557  return true;558}559 560llvm::Expected<lldb::TypeSP>561SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) {562  CompilerType forward_compiler_type = m_ast->CreateRecordType(563      nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name,564      llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC);565  Declaration decl;566  return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr,567                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl,568                  forward_compiler_type, Type::ResolveState::Forward);569}570 571llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) {572  if (!ctf_type)573    return llvm::make_error<llvm::StringError>(574        "cannot create type for unparsed type", llvm::inconvertibleErrorCode());575 576  switch (ctf_type->kind) {577  case CTFType::Kind::eInteger:578    return CreateInteger(*static_cast<CTFInteger *>(ctf_type));579  case CTFType::Kind::eConst:580  case CTFType::Kind::ePointer:581  case CTFType::Kind::eRestrict:582  case CTFType::Kind::eVolatile:583    return CreateModifier(*static_cast<CTFModifier *>(ctf_type));584  case CTFType::Kind::eTypedef:585    return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type));586  case CTFType::Kind::eArray:587    return CreateArray(*static_cast<CTFArray *>(ctf_type));588  case CTFType::Kind::eEnum:589    return CreateEnum(*static_cast<CTFEnum *>(ctf_type));590  case CTFType::Kind::eFunction:591    return CreateFunction(*static_cast<CTFFunction *>(ctf_type));592  case CTFType::Kind::eStruct:593  case CTFType::Kind::eUnion:594    return CreateRecord(*static_cast<CTFRecord *>(ctf_type));595  case CTFType::Kind::eForward:596    return CreateForward(*static_cast<CTFForward *>(ctf_type));597  case CTFType::Kind::eUnknown:598  case CTFType::Kind::eFloat:599  case CTFType::Kind::eSlice:600    return llvm::make_error<llvm::StringError>(601        llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})",602                      ctf_type->uid, ctf_type->name, ctf_type->kind),603        llvm::inconvertibleErrorCode());604  }605  llvm_unreachable("Unexpected CTF type kind");606}607 608llvm::Expected<std::unique_ptr<CTFType>>609SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) {610  ctf_stype_t ctf_stype;611  ctf_stype.name = m_data.GetU32(&offset);612  ctf_stype.info = m_data.GetU32(&offset);613  ctf_stype.size = m_data.GetU32(&offset);614 615  llvm::StringRef name = ReadString(ctf_stype.name);616  const uint32_t kind = GetKind(ctf_stype.info);617  const uint32_t variable_length = GetVLen(ctf_stype.info);618  const uint32_t type = ctf_stype.GetType();619  const uint32_t size = ctf_stype.GetSize();620 621  switch (kind) {622  case TypeKind::eInteger: {623    const uint32_t vdata = m_data.GetU32(&offset);624    const uint32_t bits = GetBits(vdata);625    const uint32_t encoding = GetEncoding(vdata);626    return std::make_unique<CTFInteger>(uid, name, bits, encoding);627  }628  case TypeKind::eConst:629    return std::make_unique<CTFConst>(uid, type);630  case TypeKind::ePointer:631    return std::make_unique<CTFPointer>(uid, type);632  case TypeKind::eRestrict:633    return std::make_unique<CTFRestrict>(uid, type);634  case TypeKind::eVolatile:635    return std::make_unique<CTFVolatile>(uid, type);636  case TypeKind::eTypedef:637    return std::make_unique<CTFTypedef>(uid, name, type);638  case TypeKind::eArray: {639    const uint32_t type = m_data.GetU32(&offset);640    const uint32_t index = m_data.GetU32(&offset);641    const uint32_t nelems = m_data.GetU32(&offset);642    return std::make_unique<CTFArray>(uid, name, type, index, nelems);643  }644  case TypeKind::eEnum: {645    std::vector<CTFEnum::Value> values;646    for (uint32_t i = 0; i < variable_length; ++i) {647      const uint32_t value_name = m_data.GetU32(&offset);648      const uint32_t value = m_data.GetU32(&offset);649      values.emplace_back(ReadString(value_name), value);650    }651    return std::make_unique<CTFEnum>(uid, name, variable_length, size, values);652  }653  case TypeKind::eFunction: {654    std::vector<uint32_t> args;655    bool variadic = false;656    for (uint32_t i = 0; i < variable_length; ++i) {657      const uint32_t arg_uid = m_data.GetU32(&offset);658      // If the last argument is 0, this is a variadic function.659      if (arg_uid == 0) {660        variadic = true;661        break;662      }663      args.push_back(arg_uid);664    }665    // If the number of arguments is odd, a single uint32_t of padding is666    // inserted to maintain alignment.667    if (variable_length % 2 == 1)668      m_data.GetU32(&offset);669    return std::make_unique<CTFFunction>(uid, name, variable_length, type, args,670                                         variadic);671  }672  case TypeKind::eStruct:673  case TypeKind::eUnion: {674    std::vector<CTFRecord::Field> fields;675    for (uint32_t i = 0; i < variable_length; ++i) {676      const uint32_t field_name = m_data.GetU32(&offset);677      const uint32_t type = m_data.GetU32(&offset);678      uint64_t field_offset = 0;679      if (size < g_ctf_field_threshold) {680        field_offset = m_data.GetU16(&offset);681        m_data.GetU16(&offset); // Padding682      } else {683        const uint32_t offset_hi = m_data.GetU32(&offset);684        const uint32_t offset_lo = m_data.GetU32(&offset);685        field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo);686      }687      fields.emplace_back(ReadString(field_name), type, field_offset);688    }689    return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid,690                                       name, variable_length, size, fields);691  }692  case TypeKind::eForward:693    return std::make_unique<CTFForward>(uid, name);694  case TypeKind::eUnknown:695    return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid,696                                     name);697  case TypeKind::eFloat:698  case TypeKind::eSlice:699    offset += (variable_length * sizeof(uint32_t));700    break;701  }702 703  return llvm::make_error<llvm::StringError>(704      llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})",705                    name, kind, variable_length),706      llvm::inconvertibleErrorCode());707}708 709size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {710  if (!ParseHeader())711    return 0;712 713  if (!m_types.empty())714    return 0;715 716  if (!m_ast)717    return 0;718 719  Log *log = GetLog(LLDBLog::Symbols);720  LLDB_LOG(log, "Parsing CTF types");721 722  lldb::offset_t type_offset = m_body_offset + m_header->typeoff;723  const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff;724 725  lldb::user_id_t type_uid = 1;726  while (type_offset < type_offset_end) {727    llvm::Expected<std::unique_ptr<CTFType>> type_or_error =728        ParseType(type_offset, type_uid);729    if (type_or_error) {730      m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error);731    } else {732      LLDB_LOG_ERROR(log, type_or_error.takeError(),733                     "Failed to parse type {1} at offset {2}: {0}", type_uid,734                     type_offset);735    }736    type_uid++;737  }738 739  LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size());740 741  for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) {742    ResolveTypeUID(uid);743 744    // Remove the CTF type because we don't need it anymore, except for record745    // types which we may need to complete later.746    auto ctf_type_it = m_ctf_types.find(uid);747    if (ctf_type_it != m_ctf_types.end()) {748      CTFType *ctf_type = ctf_type_it->second.get();749      if (!llvm::isa<CTFRecord>(ctf_type))750        m_ctf_types.erase(uid);751    }752  }753 754#ifndef NDEBUG755  // Verify that the only CTF types left at this point are record types.756  for (auto &t : m_ctf_types) {757    CTFType *ctf_type = t.second.get();758    assert(ctf_type && "invalid type in m_ctf_types");759    assert(llvm::isa<CTFRecord>(ctf_type) && "leaking non record type");760  }761 762#endif763 764  LLDB_LOG(log, "Created {0} CTF types", m_types.size());765 766  return m_types.size();767}768 769size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) {770  if (!ParseHeader())771    return 0;772 773  if (!m_functions.empty())774    return 0;775 776  if (!m_ast)777    return 0;778 779  Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab();780  if (!symtab)781    return 0;782 783  Log *log = GetLog(LLDBLog::Symbols);784  LLDB_LOG(log, "Parsing CTF functions");785 786  lldb::offset_t function_offset = m_body_offset + m_header->funcoff;787  const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff;788 789  uint32_t symbol_idx = 0;790  Declaration decl;791  while (function_offset < function_offset_end) {792    const uint32_t info = m_data.GetU32(&function_offset);793    const uint16_t kind = GetKind(info);794    const uint16_t variable_length = GetVLen(info);795 796    Symbol *symbol = symtab->FindSymbolWithType(797        eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx);798 799    // Skip padding.800    if (kind == TypeKind::eUnknown && variable_length == 0)801      continue;802 803    // Skip unexpected kinds.804    if (kind != TypeKind::eFunction)805      continue;806 807    const uint32_t ret_uid = m_data.GetU32(&function_offset);808    const uint32_t num_args = variable_length;809 810    std::vector<CompilerType> arg_types;811    arg_types.reserve(num_args);812 813    bool is_variadic = false;814    for (uint32_t i = 0; i < variable_length; i++) {815      const uint32_t arg_uid = m_data.GetU32(&function_offset);816 817      // If the last argument is 0, this is a variadic function.818      if (arg_uid == 0) {819        is_variadic = true;820        break;821      }822 823      Type *arg_type = ResolveTypeUID(arg_uid);824      arg_types.push_back(arg_type ? arg_type->GetFullCompilerType()825                                   : CompilerType());826    }827 828    if (symbol) {829      Type *ret_type = ResolveTypeUID(ret_uid);830      AddressRange func_range =831          AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(),832                       GetObjectFile()->GetModule()->GetSectionList());833 834      // Create function type.835      CompilerType func_type = m_ast->CreateFunctionType(836          ret_type ? ret_type->GetFullCompilerType() : CompilerType(),837          arg_types, is_variadic, 0, clang::CallingConv::CC_C);838      lldb::user_id_t function_type_uid = m_types.size() + 1;839      TypeSP type_sp =840          MakeType(function_type_uid, symbol->GetName(), 0, nullptr,841                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,842                   lldb_private::Type::ResolveState::Full);843      m_types[function_type_uid] = type_sp;844 845      // Create function.846      lldb::user_id_t func_uid = m_functions.size();847      FunctionSP function_sp = std::make_shared<Function>(848          &cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(),849          symbol->GetAddress(), AddressRanges{func_range});850      m_functions.emplace_back(function_sp);851      cu.AddFunction(function_sp);852    }853  }854 855  LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size());856 857  return m_functions.size();858}859 860static DWARFExpression CreateDWARFExpression(ModuleSP module_sp,861                                             const Symbol &symbol) {862  if (!module_sp)863    return DWARFExpression();864 865  const ArchSpec &architecture = module_sp->GetArchitecture();866  ByteOrder byte_order = architecture.GetByteOrder();867  uint32_t address_size = architecture.GetAddressByteSize();868  uint32_t byte_size = architecture.GetDataByteSize();869 870  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);871  stream.PutHex8(llvm::dwarf::DW_OP_addr);872  stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order);873 874  DataBufferSP buffer =875      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());876  lldb_private::DataExtractor extractor(buffer, byte_order, address_size,877                                        byte_size);878  DWARFExpression result(extractor);879  result.SetRegisterKind(eRegisterKindDWARF);880 881  return result;882}883 884size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) {885  if (!ParseHeader())886    return 0;887 888  if (!m_variables.empty())889    return 0;890 891  if (!m_ast)892    return 0;893 894  ModuleSP module_sp = GetObjectFile()->GetModule();895  Symtab *symtab = module_sp->GetSymtab();896  if (!symtab)897    return 0;898 899  Log *log = GetLog(LLDBLog::Symbols);900  LLDB_LOG(log, "Parsing CTF objects");901 902  lldb::offset_t object_offset = m_body_offset + m_header->objtoff;903  const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff;904 905  uint32_t symbol_idx = 0;906  Declaration decl;907  while (object_offset < object_offset_end) {908    const uint32_t type_uid = m_data.GetU32(&object_offset);909 910    if (Symbol *symbol =911            symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes,912                                       Symtab::eVisibilityAny, symbol_idx)) {913      Variable::RangeList ranges;914      ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize());915 916      auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid);917 918      DWARFExpressionList location(919          module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr);920 921      lldb::user_id_t variable_type_uid = m_variables.size();922      m_variables.emplace_back(std::make_shared<Variable>(923          variable_type_uid, symbol->GetName().AsCString(),924          symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal,925          m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(),926          /*artificial=*/false,927          /*location_is_constant_data*/ false));928    }929  }930 931  LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size());932 933  return m_variables.size();934}935 936uint32_t SymbolFileCTF::CalculateAbilities() {937  if (!m_objfile_sp)938    return 0;939 940  if (!ParseHeader())941    return 0;942 943  return VariableTypes | Functions | GlobalVariables;944}945 946uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr,947                                             SymbolContextItem resolve_scope,948                                             SymbolContext &sc) {949  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());950  if (m_objfile_sp->GetSymtab() == nullptr)951    return 0;952 953  uint32_t resolved_flags = 0;954 955  // Resolve symbols.956  if (resolve_scope & eSymbolContextSymbol) {957    sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(958        so_addr.GetFileAddress());959    if (sc.symbol)960      resolved_flags |= eSymbolContextSymbol;961  }962 963  // Resolve functions.964  if (resolve_scope & eSymbolContextFunction) {965    for (FunctionSP function_sp : m_functions) {966      if (llvm::any_of(967              function_sp->GetAddressRanges(), [&](const AddressRange range) {968                return range.ContainsFileAddress(so_addr.GetFileAddress());969              })) {970        sc.function = function_sp.get();971        resolved_flags |= eSymbolContextFunction;972        break;973      }974    }975  }976 977  // Resolve variables.978  if (resolve_scope & eSymbolContextVariable) {979    for (VariableSP variable_sp : m_variables) {980      if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) {981        sc.variable = variable_sp.get();982        break;983      }984    }985  }986 987  return resolved_flags;988}989 990CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) {991  if (idx == 0)992    return m_comp_unit_sp;993  return {};994}995 996size_t997SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {998  return ParseObjects(*m_comp_unit_sp);999}1000 1001void SymbolFileCTF::AddSymbols(Symtab &symtab) {1002  // CTF does not encode symbols.1003  // We rely on the existing symbol table to map symbols to type.1004}1005 1006lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {1007  auto type_it = m_types.find(type_uid);1008  if (type_it != m_types.end())1009    return type_it->second.get();1010 1011  auto ctf_type_it = m_ctf_types.find(type_uid);1012  if (ctf_type_it == m_ctf_types.end())1013    return nullptr;1014 1015  CTFType *ctf_type = ctf_type_it->second.get();1016  assert(ctf_type && "m_ctf_types should only contain valid CTF types");1017  assert(ctf_type->uid == type_uid &&1018         "CTF type UID doesn't match UID in m_ctf_types");1019 1020  Log *log = GetLog(LLDBLog::Symbols);1021 1022  llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type);1023  if (!type_or_error) {1024    LLDB_LOG_ERROR(log, type_or_error.takeError(),1025                   "Failed to create type for {1}: {0}", ctf_type->uid);1026    return {};1027  }1028 1029  TypeSP type_sp = *type_or_error;1030 1031  if (log) {1032    StreamString ss;1033    type_sp->Dump(&ss, true);1034    LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(),1035              llvm::StringRef(ss.GetString()).rtrim());1036  }1037 1038  m_types[type_uid] = type_sp;1039 1040  return type_sp.get();1041}1042 1043void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,1044                              lldb_private::TypeResults &results) {1045  // Make sure we haven't already searched this SymbolFile before.1046  if (results.AlreadySearched(this))1047    return;1048 1049  ConstString name = match.GetTypeBasename();1050  for (TypeSP type_sp : GetTypeList().Types()) {1051    if (type_sp && type_sp->GetName() == name) {1052      results.InsertUnique(type_sp);1053      if (results.Done(match))1054        return;1055    }1056  }1057}1058 1059void SymbolFileCTF::FindTypesByRegex(1060    const lldb_private::RegularExpression &regex, uint32_t max_matches,1061    lldb_private::TypeMap &types) {1062  ParseTypes(*m_comp_unit_sp);1063 1064  size_t matches = 0;1065  for (TypeSP type_sp : GetTypeList().Types()) {1066    if (matches == max_matches)1067      break;1068    if (type_sp && regex.Execute(type_sp->GetName()))1069      types.Insert(type_sp);1070    matches++;1071  }1072}1073 1074void SymbolFileCTF::FindFunctions(1075    const lldb_private::Module::LookupInfo &lookup_info,1076    const lldb_private::CompilerDeclContext &parent_decl_ctx,1077    bool include_inlines, lldb_private::SymbolContextList &sc_list) {1078  ParseFunctions(*m_comp_unit_sp);1079 1080  ConstString name = lookup_info.GetLookupName();1081  for (FunctionSP function_sp : m_functions) {1082    if (function_sp && function_sp->GetName() == name) {1083      lldb_private::SymbolContext sc;1084      sc.comp_unit = m_comp_unit_sp.get();1085      sc.function = function_sp.get();1086      sc_list.Append(sc);1087    }1088  }1089}1090 1091void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression &regex,1092                                  bool include_inlines,1093                                  lldb_private::SymbolContextList &sc_list) {1094  for (FunctionSP function_sp : m_functions) {1095    if (function_sp && regex.Execute(function_sp->GetName())) {1096      lldb_private::SymbolContext sc;1097      sc.comp_unit = m_comp_unit_sp.get();1098      sc.function = function_sp.get();1099      sc_list.Append(sc);1100    }1101  }1102}1103 1104void SymbolFileCTF::FindGlobalVariables(1105    lldb_private::ConstString name,1106    const lldb_private::CompilerDeclContext &parent_decl_ctx,1107    uint32_t max_matches, lldb_private::VariableList &variables) {1108  ParseObjects(*m_comp_unit_sp);1109 1110  size_t matches = 0;1111  for (VariableSP variable_sp : m_variables) {1112    if (matches == max_matches)1113      break;1114    if (variable_sp && variable_sp->GetName() == name) {1115      variables.AddVariable(variable_sp);1116      matches++;1117    }1118  }1119}1120 1121void SymbolFileCTF::FindGlobalVariables(1122    const lldb_private::RegularExpression &regex, uint32_t max_matches,1123    lldb_private::VariableList &variables) {1124  ParseObjects(*m_comp_unit_sp);1125 1126  size_t matches = 0;1127  for (VariableSP variable_sp : m_variables) {1128    if (matches == max_matches)1129      break;1130    if (variable_sp && regex.Execute(variable_sp->GetName())) {1131      variables.AddVariable(variable_sp);1132      matches++;1133    }1134  }1135}1136