
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
78 lines
2.8 KiB
C++
78 lines
2.8 KiB
C++
//===-- Expression.cpp ----------------------------------------------------===//
|
|
//
|
|
// 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 "lldb/Expression/Expression.h"
|
|
#include "lldb/Target/ExecutionContextScope.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
using namespace lldb_private;
|
|
|
|
Expression::Expression(Target &target)
|
|
: m_target_wp(target.shared_from_this()),
|
|
m_jit_start_addr(LLDB_INVALID_ADDRESS),
|
|
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
|
|
// Can't make any kind of expression without a target.
|
|
assert(m_target_wp.lock());
|
|
}
|
|
|
|
Expression::Expression(ExecutionContextScope &exe_scope)
|
|
: m_target_wp(exe_scope.CalculateTarget()),
|
|
m_jit_start_addr(LLDB_INVALID_ADDRESS),
|
|
m_jit_end_addr(LLDB_INVALID_ADDRESS) {
|
|
assert(m_target_wp.lock());
|
|
}
|
|
|
|
llvm::Expected<FunctionCallLabel>
|
|
lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
|
|
llvm::SmallVector<llvm::StringRef, 4> components;
|
|
label.split(components, ":", /*MaxSplit=*/3);
|
|
|
|
if (components.size() != 4)
|
|
return llvm::createStringError("malformed function call label.");
|
|
|
|
if (components[0] != FunctionCallLabelPrefix)
|
|
return llvm::createStringError(llvm::formatv(
|
|
"expected function call label prefix '{0}' but found '{1}' instead.",
|
|
FunctionCallLabelPrefix, components[0]));
|
|
|
|
llvm::StringRef module_label = components[1];
|
|
llvm::StringRef die_label = components[2];
|
|
|
|
lldb::user_id_t module_id = 0;
|
|
if (!llvm::to_integer(module_label, module_id))
|
|
return llvm::createStringError(
|
|
llvm::formatv("failed to parse module ID from '{0}'.", module_label));
|
|
|
|
lldb::user_id_t die_id;
|
|
if (!llvm::to_integer(die_label, die_id))
|
|
return llvm::createStringError(
|
|
llvm::formatv("failed to parse symbol ID from '{0}'.", die_label));
|
|
|
|
return FunctionCallLabel{/*.module_id=*/module_id,
|
|
/*.symbol_id=*/die_id,
|
|
/*.lookup_name=*/components[3]};
|
|
}
|
|
|
|
std::string lldb_private::FunctionCallLabel::toString() const {
|
|
return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix,
|
|
module_id, symbol_id, lookup_name)
|
|
.str();
|
|
}
|
|
|
|
void llvm::format_provider<FunctionCallLabel>::format(
|
|
const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
|
|
OS << llvm::formatv("FunctionCallLabel{ module_id: {0:x}, symbol_id: {1:x}, "
|
|
"lookup_name: {2} }",
|
|
label.module_id, label.symbol_id, label.lookup_name);
|
|
}
|