aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Expression/IRExecutionUnit.cpp
diff options
context:
space:
mode:
authorMichael Buch <michaelbuch12@gmail.com>2025-08-01 07:21:41 +0100
committerGitHub <noreply@github.com>2025-08-01 07:21:41 +0100
commitf89059140bd54699771fe076da30dd1db060cc93 (patch)
tree72153acd56a2705a89dcee5061a538ffa5828af0 /lldb/source/Expression/IRExecutionUnit.cpp
parente20413c045249651f09515808ce89024fde9abbf (diff)
downloadllvm-f89059140bd54699771fe076da30dd1db060cc93.tar.gz
llvm-f89059140bd54699771fe076da30dd1db060cc93.tar.bz2
llvm-f89059140bd54699771fe076da30dd1db060cc93.zip
[lldb][Expression] Encode Module and DIE UIDs into function AsmLabels (#148877)
LLDB currently attaches `AsmLabel`s to `FunctionDecl`s such that that the `IRExecutionUnit` can determine which mangled name to call (we can't rely on Clang deriving the correct mangled name to call because the debug-info AST doesn't contain all the info that would be encoded in the DWARF linkage names). However, we don't attach `AsmLabel`s for structors because they have multiple variants and thus it's not clear which mangled name to use. In the [RFC on fixing expression evaluation of abi-tagged structors](https://discourse.llvm.org/t/rfc-lldb-handling-abi-tagged-constructors-destructors-in-expression-evaluator/82816) we discussed encoding the structor variant into the `AsmLabel`s. Specifically in [this thread](https://discourse.llvm.org/t/rfc-lldb-handling-abi-tagged-constructors-destructors-in-expression-evaluator/82816/7) we discussed that the contents of the `AsmLabel` are completely under LLDB's control and we could make use of it to uniquely identify a function by encoding the exact module and DIE that the function is associated with (mangled names need not be enough since two identical mangled symbols may live in different modules). So if we already have a custom `AsmLabel` format, we can encode the structor variant in a follow-up (the current idea is to append the structor variant as a suffix to our custom `AsmLabel` when Clang emits the mangled name into the JITted IR). Then we would just have to teach the `IRExecutionUnit` to pick the correct structor variant DIE during symbol resolution. The draft of this is available [here](https://github.com/llvm/llvm-project/pull/149827) This patch sets up the infrastructure for the custom `AsmLabel` format by encoding the module id, DIE id and mangled name in it. **Implementation** The flow is as follows: 1. Create the label in `DWARFASTParserClang`. The format is: `$__lldb_func:module_id:die_id:mangled_name` 2. When resolving external symbols in `IRExecutionUnit`, we parse this label and then do a lookup by DIE ID (or mangled name into the module if the encoded DIE is a declaration). Depends on https://github.com/llvm/llvm-project/pull/151355
Diffstat (limited to 'lldb/source/Expression/IRExecutionUnit.cpp')
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 6f812b91a8b1..5e40df282e7b 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -13,6 +13,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,6 +21,7 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/ObjectFileJIT.h"
#include "lldb/Host/HostInfo.h"
@@ -36,6 +38,7 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
+#include "lldb/lldb-defines.h"
#include <optional>
@@ -771,6 +774,40 @@ private:
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
};
+/// Returns address of the function referred to by the special function call
+/// label \c label.
+static llvm::Expected<lldb::addr_t>
+ResolveFunctionCallLabel(const FunctionCallLabel &label,
+ const lldb_private::SymbolContext &sc,
+ bool &symbol_was_missing_weak) {
+ symbol_was_missing_weak = false;
+
+ if (!sc.target_sp)
+ return llvm::createStringError("target not available.");
+
+ auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id);
+ if (!module_sp)
+ return llvm::createStringError(
+ llvm::formatv("failed to find module by UID {0}", label.module_id));
+
+ auto *symbol_file = module_sp->GetSymbolFile();
+ if (!symbol_file)
+ return llvm::createStringError(
+ llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get()));
+
+ auto sc_or_err = symbol_file->ResolveFunctionCallLabel(label);
+ if (!sc_or_err)
+ return llvm::joinErrors(
+ llvm::createStringError("failed to resolve function by UID"),
+ sc_or_err.takeError());
+
+ SymbolContextList sc_list;
+ sc_list.Append(*sc_or_err);
+
+ LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak);
+ return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS);
+}
+
lldb::addr_t
IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
const lldb_private::SymbolContext &sc,
@@ -906,6 +943,34 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
bool &missing_weak) {
+ if (name.GetStringRef().starts_with(FunctionCallLabelPrefix)) {
+ auto label_or_err = FunctionCallLabel::fromString(name);
+ if (!label_or_err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), label_or_err.takeError(),
+ "failed to create FunctionCallLabel from '{1}': {0}",
+ name.GetStringRef());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ if (auto addr_or_err =
+ ResolveFunctionCallLabel(*label_or_err, m_sym_ctx, missing_weak)) {
+ return *addr_or_err;
+ } else {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(),
+ "Failed to resolve function call label '{1}': {0}",
+ name.GetStringRef());
+
+ // Fall back to lookup by name despite error in resolving the label.
+ // May happen in practice if the definition of a function lives in
+ // a different lldb_private::Module than it's declaration. Meaning
+ // we couldn't pin-point it using the information encoded in the label.
+ name.SetString(label_or_err->lookup_name);
+ }
+ }
+
+ // TODO: now with function call labels, do we still need to
+ // generate alternate manglings?
+
std::vector<ConstString> candidate_C_names;
std::vector<ConstString> candidate_CPlusPlus_names;