aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Expression
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Expression')
-rw-r--r--lldb/source/Expression/DWARFExpression.cpp10
-rw-r--r--lldb/source/Expression/Expression.cpp49
-rw-r--r--lldb/source/Expression/IRExecutionUnit.cpp65
-rw-r--r--lldb/source/Expression/IRInterpreter.cpp4
-rw-r--r--lldb/source/Expression/Materializer.cpp21
5 files changed, 134 insertions, 15 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 79bc6c8..391e277 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -91,9 +91,10 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
m_reg_kind = reg_kind;
}
-static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
- lldb::RegisterKind reg_kind,
- uint32_t reg_num, Value &value) {
+llvm::Error
+DWARFExpression::ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
+ lldb::RegisterKind reg_kind,
+ uint32_t reg_num, Value &value) {
if (reg_ctx == nullptr)
return llvm::createStringError("no register context in frame");
@@ -2302,7 +2303,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
default:
if (dwarf_cu) {
- if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, stack)) {
+ if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, reg_ctx,
+ reg_kind, stack)) {
break;
}
}
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
index 93f585e..796851f 100644
--- a/lldb/source/Expression/Expression.cpp
+++ b/lldb/source/Expression/Expression.cpp
@@ -10,6 +10,11 @@
#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)
@@ -26,3 +31,47 @@ Expression::Expression(ExecutionContextScope &exe_scope)
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);
+}
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 6f812b9..5e40df2 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;
diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp
index fa74e88..9140483 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -259,7 +259,9 @@ public:
break;
case Value::FunctionVal:
if (const Function *constant_func = dyn_cast<Function>(constant)) {
- lldb_private::ConstString name(constant_func->getName());
+ lldb_private::ConstString name(
+ llvm::GlobalValue::dropLLVMManglingEscape(
+ constant_func->getName()));
bool missing_weak = false;
lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
if (addr == LLDB_INVALID_ADDRESS)
diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp
index 17ea159..329768d 100644
--- a/lldb/source/Expression/Materializer.cpp
+++ b/lldb/source/Expression/Materializer.cpp
@@ -102,22 +102,23 @@ public:
m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
map.GetAddressByteSize());
- if (m_persistent_variable_sp->m_flags &
- ExpressionVariable::EVKeepInTarget) {
- if (used_policy == IRMemoryMap::eAllocationPolicyMirror) {
+ if (used_policy == IRMemoryMap::eAllocationPolicyMirror) {
+ if (m_persistent_variable_sp->m_flags &
+ ExpressionVariable::EVKeepInTarget) {
// Clear the flag if the variable will never be deallocated.
Status leak_error;
map.Leak(mem, leak_error);
m_persistent_variable_sp->m_flags &=
~ExpressionVariable::EVNeedsAllocation;
- } else {
- // If the variable cannot be kept in target, clear this flag...
- m_persistent_variable_sp->m_flags &=
- ~ExpressionVariable::EVKeepInTarget;
- // ...and set the flag to copy the value during dematerialization.
- m_persistent_variable_sp->m_flags |=
- ExpressionVariable::EVNeedsFreezeDry;
}
+ } else {
+ // If we cannot allocate memory in the process,
+ // - clear the 'EVKeepInTarget' flag to ensure that 'm_live_sp' is reset
+ // during dematerialization,
+ m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVKeepInTarget;
+ // - set the 'EVNeedsFreezeDry' flag so that the value is copied to
+ // 'm_frozen_sp' during dematerialization.
+ m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry;
}
// Write the contents of the variable to the area.