Skip to content

Commit f640bef

Browse files
committed
[lldb][Expression] Encode Module and DIE UIDs into function AsmLabels
1 parent 03b7766 commit f640bef

File tree

16 files changed

+318
-44
lines changed

16 files changed

+318
-44
lines changed

lldb/include/lldb/Core/Module.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ struct ModuleFunctionSearchOptions {
8686
///
8787
/// The module will parse more detailed information as more queries are made.
8888
class Module : public std::enable_shared_from_this<Module>,
89-
public SymbolContextScope {
89+
public SymbolContextScope,
90+
public UserID {
9091
public:
9192
class LookupInfo;
9293
// Static functions that can track the lifetime of module objects. This is
@@ -97,6 +98,7 @@ class Module : public std::enable_shared_from_this<Module>,
9798
// using the "--global" (-g for short).
9899
static size_t GetNumberAllocatedModules();
99100

101+
static Module *GetAllocatedModuleWithUID(lldb::user_id_t uid);
100102
static Module *GetAllocatedModuleAtIndex(size_t idx);
101103

102104
static std::recursive_mutex &GetAllocationModuleCollectionMutex();

lldb/include/lldb/Expression/Expression.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,41 @@ class Expression {
9696
///invalid.
9797
};
9898

99+
/// Holds parsed information about a function call label that
100+
/// LLDB attaches as an AsmLabel to function AST nodes it parses
101+
/// from debug-info.
102+
///
103+
/// The format being:
104+
///
105+
/// <prefix>:<mangled name>:<module id>:<DIE id>
106+
///
107+
/// The label string needs to stay valid for the entire lifetime
108+
/// of this object.
109+
struct FunctionCallLabel {
110+
/// Mostly for debuggability.
111+
llvm::StringRef m_pubname;
112+
113+
lldb::user_id_t m_die_id;
114+
lldb::user_id_t m_module_id;
115+
};
116+
117+
/// LLDB attaches this prefix to mangled names of functions that it get called
118+
/// from JITted expressions.
119+
inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func";
120+
121+
bool consumeFunctionCallLabelPrefix(llvm::StringRef &name);
122+
bool hasFunctionCallLabelPrefix(llvm::StringRef name);
123+
124+
/// Returns the components of the specified function call label.
125+
///
126+
/// The format of \c label is described in \c FunctionCallLabel.
127+
/// The label prefix is not one of the components.
128+
llvm::Expected<llvm::SmallVector<llvm::StringRef, 3>>
129+
splitFunctionCallLabel(llvm::StringRef label);
130+
131+
// Decodes the function label into a \c FunctionCallLabel.
132+
llvm::Expected<FunctionCallLabel> makeFunctionCallLabel(llvm::StringRef label);
133+
99134
} // namespace lldb_private
100135

101136
#endif // LLDB_EXPRESSION_EXPRESSION_H

lldb/include/lldb/Symbol/SymbolFile.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "lldb/Symbol/CompilerType.h"
1919
#include "lldb/Symbol/Function.h"
2020
#include "lldb/Symbol/SourceModule.h"
21+
#include "lldb/Symbol/SymbolContext.h"
2122
#include "lldb/Symbol/Type.h"
2223
#include "lldb/Symbol/TypeList.h"
2324
#include "lldb/Symbol/TypeSystem.h"
@@ -328,6 +329,19 @@ class SymbolFile : public PluginInterface {
328329
GetMangledNamesForFunction(const std::string &scope_qualified_name,
329330
std::vector<ConstString> &mangled_names);
330331

332+
/// Resolves the function DIE uniquely identified by \c uid within
333+
/// this SymbolFile.
334+
///
335+
/// \param[in,out] sc_list The resolved functions will be appended to this
336+
/// list.
337+
///
338+
/// \param[in] uid The UID of the function DIE to resolve.
339+
///
340+
virtual llvm::Error ResolveFunctionUID(SymbolContextList &sc_list,
341+
lldb::user_id_t uid) {
342+
return llvm::createStringError("Not implemented");
343+
}
344+
331345
virtual void GetTypes(lldb_private::SymbolContextScope *sc_scope,
332346
lldb::TypeClass type_mask,
333347
lldb_private::TypeList &type_list) = 0;

lldb/source/Core/Module.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ size_t Module::GetNumberAllocatedModules() {
121121
return GetModuleCollection().size();
122122
}
123123

124+
Module *Module::GetAllocatedModuleWithUID(lldb::user_id_t uid) {
125+
std::lock_guard<std::recursive_mutex> guard(
126+
GetAllocationModuleCollectionMutex());
127+
for (Module *mod : GetModuleCollection())
128+
if (mod->GetID() == uid)
129+
return mod;
130+
return nullptr;
131+
}
132+
124133
Module *Module::GetAllocatedModuleAtIndex(size_t idx) {
125134
std::lock_guard<std::recursive_mutex> guard(
126135
GetAllocationModuleCollectionMutex());
@@ -130,8 +139,11 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) {
130139
return nullptr;
131140
}
132141

142+
// TODO: needs a mutex
143+
static lldb::user_id_t g_unique_id = 1;
144+
133145
Module::Module(const ModuleSpec &module_spec)
134-
: m_unwind_table(*this), m_file_has_changed(false),
146+
: UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false),
135147
m_first_file_changed_log(false) {
136148
// Scope for locker below...
137149
{
@@ -236,7 +248,8 @@ Module::Module(const ModuleSpec &module_spec)
236248
Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
237249
ConstString object_name, lldb::offset_t object_offset,
238250
const llvm::sys::TimePoint<> &object_mod_time)
239-
: m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
251+
: UserID(g_unique_id++),
252+
m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
240253
m_arch(arch), m_file(file_spec), m_object_name(object_name),
241254
m_object_offset(object_offset), m_object_mod_time(object_mod_time),
242255
m_unwind_table(*this), m_file_has_changed(false),
@@ -257,7 +270,7 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
257270
}
258271

259272
Module::Module()
260-
: m_unwind_table(*this), m_file_has_changed(false),
273+
: UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false),
261274
m_first_file_changed_log(false) {
262275
std::lock_guard<std::recursive_mutex> guard(
263276
GetAllocationModuleCollectionMutex());

lldb/source/Expression/Expression.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include "lldb/Target/ExecutionContextScope.h"
1111
#include "lldb/Target/Target.h"
1212

13+
#include "llvm/ADT/SmallVector.h"
14+
#include "llvm/ADT/StringRef.h"
15+
#include "llvm/Support/Error.h"
16+
1317
using namespace lldb_private;
1418

1519
Expression::Expression(Target &target)
@@ -26,3 +30,64 @@ Expression::Expression(ExecutionContextScope &exe_scope)
2630
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
2731
assert(m_target_wp.lock());
2832
}
33+
34+
bool lldb_private::consumeFunctionCallLabelPrefix(llvm::StringRef &name) {
35+
// On Darwin mangled names get a '_' prefix.
36+
name.consume_front("_");
37+
return name.consume_front(FunctionCallLabelPrefix);
38+
}
39+
40+
bool lldb_private::hasFunctionCallLabelPrefix(llvm::StringRef name) {
41+
// On Darwin mangled names get a '_' prefix.
42+
name.consume_front("_");
43+
return name.starts_with(FunctionCallLabelPrefix);
44+
}
45+
46+
// Expected format is:
47+
// $__lldb_func:<mangled name>:<module id>:<definition/declaration DIE id>
48+
llvm::Expected<llvm::SmallVector<llvm::StringRef, 3>>
49+
lldb_private::splitFunctionCallLabel(llvm::StringRef label) {
50+
if (!consumeFunctionCallLabelPrefix(label))
51+
return llvm::createStringError(
52+
"expected function call label prefix not found in %s", label.data());
53+
54+
if (!label.consume_front(":"))
55+
return llvm::createStringError(
56+
"incorrect format: expected ':' as the first character.");
57+
58+
llvm::SmallVector<llvm::StringRef, 3> components;
59+
label.split(components, ":");
60+
61+
if (components.size() != 3)
62+
return llvm::createStringError(
63+
"incorrect format: too many label subcomponents.");
64+
65+
return components;
66+
}
67+
68+
llvm::Expected<FunctionCallLabel>
69+
lldb_private::makeFunctionCallLabel(llvm::StringRef label) {
70+
auto components_or_err = splitFunctionCallLabel(label);
71+
if (!components_or_err)
72+
return llvm::joinErrors(
73+
llvm::createStringError("Failed to decode function call label"),
74+
components_or_err.takeError());
75+
76+
const auto &components = *components_or_err;
77+
78+
llvm::StringRef module_label = components[1];
79+
llvm::StringRef die_label = components[2];
80+
81+
lldb::user_id_t module_id = 0;
82+
if (module_label.consumeInteger(0, module_id))
83+
return llvm::createStringError(llvm::formatv(
84+
"failed to parse module ID from '%s'.", components[1].data()));
85+
86+
lldb::user_id_t die_id;
87+
if (die_label.consumeInteger(/*Radix=*/0, die_id))
88+
return llvm::createStringError("failed to parse DIE ID from '%s'.",
89+
components[2].data());
90+
91+
return FunctionCallLabel{
92+
.m_pubname = components[0], .m_die_id = die_id, .m_module_id = module_id};
93+
}

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
#include "llvm/IR/DiagnosticInfo.h"
1414
#include "llvm/IR/LLVMContext.h"
1515
#include "llvm/IR/Module.h"
16+
#include "llvm/Support/Error.h"
1617
#include "llvm/Support/SourceMgr.h"
1718
#include "llvm/Support/raw_ostream.h"
1819

1920
#include "lldb/Core/Debugger.h"
2021
#include "lldb/Core/Disassembler.h"
2122
#include "lldb/Core/Module.h"
2223
#include "lldb/Core/Section.h"
24+
#include "lldb/Expression/Expression.h"
2325
#include "lldb/Expression/IRExecutionUnit.h"
2426
#include "lldb/Expression/ObjectFileJIT.h"
2527
#include "lldb/Host/HostInfo.h"
@@ -36,6 +38,7 @@
3638
#include "lldb/Utility/LLDBAssert.h"
3739
#include "lldb/Utility/LLDBLog.h"
3840
#include "lldb/Utility/Log.h"
41+
#include "lldb/lldb-defines.h"
3942

4043
#include <optional>
4144

@@ -771,6 +774,52 @@ class LoadAddressResolver {
771774
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
772775
};
773776

777+
/// Returns address of the function referred to by the special function call
778+
/// label \c label.
779+
///
780+
/// \param[in] label Function call label encoding the unique location of the
781+
/// function to look up.
782+
/// Assumes that the \c FunctionCallLabelPrefix has been
783+
/// stripped from the front of the label.
784+
static llvm::Expected<lldb::addr_t>
785+
ResolveFunctionCallLabel(llvm::StringRef name,
786+
const lldb_private::SymbolContext &sc,
787+
bool &symbol_was_missing_weak) {
788+
symbol_was_missing_weak = false;
789+
790+
auto label_or_err = makeFunctionCallLabel(name);
791+
if (!label_or_err)
792+
return llvm::joinErrors(
793+
llvm::createStringError("failed to create FunctionCallLabel from: %s",
794+
name.data()),
795+
label_or_err.takeError());
796+
797+
const auto &label = *label_or_err;
798+
799+
Module *module = Module::GetAllocatedModuleWithUID(label.m_module_id);
800+
801+
if (!module)
802+
return llvm::createStringError(
803+
llvm::formatv("failed to find module by UID {0}", label.m_module_id));
804+
805+
auto *symbol_file = module->GetSymbolFile();
806+
if (!symbol_file)
807+
return llvm::createStringError(
808+
llvm::formatv("no SymbolFile found on module {0:x}.", module));
809+
810+
SymbolContextList sc_list;
811+
if (auto err = symbol_file->ResolveFunctionUID(sc_list, label.m_die_id))
812+
return llvm::joinErrors(
813+
llvm::createStringError("failed to resolve function by UID"),
814+
std::move(err));
815+
816+
if (!sc.target_sp)
817+
return llvm::createStringError("target not available.");
818+
819+
LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak);
820+
return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS);
821+
}
822+
774823
lldb::addr_t
775824
IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
776825
const lldb_private::SymbolContext &sc,
@@ -906,6 +955,20 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
906955

907956
lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
908957
bool &missing_weak) {
958+
if (hasFunctionCallLabelPrefix(name.GetStringRef())) {
959+
if (auto addr_or_err = ResolveFunctionCallLabel(name.GetStringRef(),
960+
m_sym_ctx, missing_weak)) {
961+
return *addr_or_err;
962+
} else {
963+
LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(),
964+
"Failed to resolve function call label {1}: {0}",
965+
name.GetStringRef());
966+
return LLDB_INVALID_ADDRESS;
967+
}
968+
}
969+
970+
// TODO: do we still need the following lookups?
971+
909972
std::vector<ConstString> candidate_C_names;
910973
std::vector<ConstString> candidate_CPlusPlus_names;
911974

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1991,7 +1991,7 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context,
19911991
const bool is_artificial = false;
19921992

19931993
CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
1994-
copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
1994+
copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", std::nullopt,
19951995
method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline,
19961996
is_explicit, is_attr_used, is_artificial);
19971997

0 commit comments

Comments
 (0)