| //===----------------------------------------------------------------------===// | |
| // | |
| // 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "CommonABIRuntime.h" | |
| #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" | |
| #include "lldb/Core/Module.h" | |
| #include "lldb/Utility/LLDBLog.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| CommonABIRuntime::CommonABIRuntime(Process *process) : m_process(process) {} | |
| lldb::TypeSP CommonABIRuntime::LookupTypeByName(llvm::StringRef type_name, | |
| lldb::ModuleSP preferred_module, | |
| bool &any_found) const { | |
| Log *log = GetLog(LLDBLog::Object); | |
| any_found = false; | |
| ConstString const_lookup_name(type_name); | |
| TypeList class_types; | |
| // First look in the module that the vtable symbol came from and | |
| // look for a single exact match. | |
| TypeResults results; | |
| TypeQuery query(const_lookup_name.GetStringRef(), | |
| TypeQueryOptions::e_exact_match | | |
| TypeQueryOptions::e_strict_namespaces | | |
| TypeQueryOptions::e_find_one); | |
| if (preferred_module) { | |
| preferred_module->FindTypes(query, results); | |
| TypeSP type_sp = results.GetFirstType(); | |
| if (type_sp) | |
| class_types.Insert(type_sp); | |
| } | |
| // If we didn't find a symbol, then move on to the entire module | |
| // list in the target and get as many unique matches as possible | |
| if (class_types.Empty()) { | |
| query.SetFindOne(false); | |
| m_process->GetTarget().GetImages().FindTypes(nullptr, query, results); | |
| for (const auto &type_sp : results.GetTypeMap().Types()) | |
| class_types.Insert(type_sp); | |
| } | |
| lldb::TypeSP type_sp; | |
| if (class_types.Empty()) { | |
| LLDB_LOG(log, "Failed to find '{0}'", type_name); | |
| return {}; | |
| } | |
| any_found = true; | |
| if (class_types.GetSize() == 1) { | |
| type_sp = class_types.GetTypeAtIndex(0); | |
| if (!type_sp) | |
| return {}; | |
| if (!TypeSystemClang::IsCXXClassType(type_sp->GetForwardCompilerType())) | |
| return {}; | |
| return type_sp; | |
| } | |
| if (log) { | |
| LLDB_LOG(log, | |
| "'{0}' has multiple matching dynamic " | |
| "types:", | |
| type_name); | |
| for (size_t i = 0; i < class_types.GetSize(); i++) { | |
| type_sp = class_types.GetTypeAtIndex(i); | |
| if (type_sp) { | |
| LLDB_LOG(log, "[{0}]: uid={1:x}, type-name='{2}'", i, type_sp->GetID(), | |
| type_sp->GetName()); | |
| } | |
| } | |
| } | |
| for (size_t i = 0; i < class_types.GetSize(); i++) { | |
| type_sp = class_types.GetTypeAtIndex(i); | |
| if (type_sp) { | |
| if (TypeSystemClang::IsCXXClassType(type_sp->GetForwardCompilerType())) { | |
| LLDB_LOG(log, | |
| "'{0}' has multiple matching dynamic types, " | |
| "picking this one: [{1}] uid={2:x}, type-name='{3}'\n", | |
| type_name, i, type_sp->GetID(), type_sp->GetName()); | |
| return type_sp; | |
| } | |
| } | |
| } | |
| LLDB_LOG(log, | |
| "'{0}' has multiple matching dynamic types, didn't find a C++ match", | |
| type_name); | |
| return {}; | |
| } | |
| TypeAndOrName | |
| CommonABIRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr) { | |
| std::lock_guard<std::mutex> locker(m_mutex); | |
| DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr); | |
| if (pos == m_dynamic_type_map.end()) | |
| return TypeAndOrName(); | |
| return pos->second; | |
| } | |
| void CommonABIRuntime::SetDynamicTypeInfo( | |
| const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) { | |
| std::lock_guard<std::mutex> locker(m_mutex); | |
| m_dynamic_type_map[vtable_addr] = type_info; | |
| } |