[Lldb-commits] [lldb] 0a7b0c8 - [lldb][Expression] Remove IR pointer checker (#144483)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Jun 17 07:24:30 PDT 2025
Author: Michael Buch
Date: 2025-06-17T15:24:26+01:00
New Revision: 0a7b0c844c59189ad4f5072b73d7dfdfd78e76b7
URL: https://github.com/llvm/llvm-project/commit/0a7b0c844c59189ad4f5072b73d7dfdfd78e76b7
DIFF: https://github.com/llvm/llvm-project/commit/0a7b0c844c59189ad4f5072b73d7dfdfd78e76b7.diff
LOG: [lldb][Expression] Remove IR pointer checker (#144483)
Currently when jitting expressions, LLDB scans the IR instructions of
the `$__lldb_expr` and will insert a call to a utility function for each
load/store instruction. The purpose of the utility funciton is to
dereference the load/store operand. If that operand was an invalid
pointer the utility function would trap and LLDB asks the IR checker
whether it was responsible for the trap, in which case it prints out an
error message saying the expression dereferenced an invalid pointer.
This is a lot of setup for not much gain. In fact, creating/running this
utility expression shows up as ~2% of the expression evaluation time
(though we cache them for subsequent expressions). And the error message
we get out of it is arguably less useful than if we hadn't instrumented
the IR. It was also untested.
Before:
```
(lldb) expr int a = *returns_invalid_ptr()
error: Execution was interrupted, reason: Attempted to dereference an invalid pointer..
The process has been returned to the state before expression evaluation.
```
After:
```
(lldb) expr int a = *returns_invalid_ptr()
error: Expression execution was interrupted: EXC_BAD_ACCESS (code=1, address=0x5).
The process has been returned to the state before expression evaluation.
```
This patch removes this IR checker.
Added:
Modified:
lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp
lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp
index c7c292a8a7e42..6ef5d3f5be6d9 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp
@@ -32,31 +32,16 @@ using namespace lldb_private;
static char ID;
-#define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
-static const char g_valid_pointer_check_text[] =
- "extern \"C\" void\n"
- "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
- "{\n"
- " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
- "}";
-
ClangDynamicCheckerFunctions::ClangDynamicCheckerFunctions()
: DynamicCheckerFunctions(DCF_Clang) {}
ClangDynamicCheckerFunctions::~ClangDynamicCheckerFunctions() = default;
-llvm::Error ClangDynamicCheckerFunctions::Install(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
- Expected<std::unique_ptr<UtilityFunction>> utility_fn =
- exe_ctx.GetTargetRef().CreateUtilityFunction(
- g_valid_pointer_check_text, VALID_POINTER_CHECK_NAME,
- lldb::eLanguageTypeC, exe_ctx);
- if (!utility_fn)
- return utility_fn.takeError();
- m_valid_pointer_check = std::move(*utility_fn);
-
+llvm::Error
+ClangDynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx) {
if (Process *process = exe_ctx.GetProcessPtr()) {
ObjCLanguageRuntime *objc_language_runtime =
ObjCLanguageRuntime::Get(*process);
@@ -78,11 +63,7 @@ bool ClangDynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
// FIXME: We have to get the checkers to know why they scotched the call in
// more detail,
// so we can print a better message here.
- if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
- message.Printf("Attempted to dereference an invalid pointer.");
- return true;
- } else if (m_objc_object_check &&
- m_objc_object_check->ContainsAddress(addr)) {
+ if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr)) {
message.Printf("Attempted to dereference an invalid ObjC Object or send it "
"an unrecognized selector");
return true;
@@ -223,29 +204,6 @@ class Instrumenter {
return true;
}
- /// Build a function pointer for a function with signature void
- /// (*)(uint8_t*) with a given address
- ///
- /// \param[in] start_address
- /// The address of the function.
- ///
- /// \return
- /// The function pointer, for use in a CallInst.
- llvm::FunctionCallee BuildPointerValidatorFunc(lldb::addr_t start_address) {
- llvm::Type *param_array[1];
-
- param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
-
- ArrayRef<llvm::Type *> params(param_array, 1);
-
- FunctionType *fun_ty = FunctionType::get(
- llvm::Type::getVoidTy(m_module.getContext()), params, true);
- PointerType *fun_ptr_ty = PointerType::getUnqual(m_module.getContext());
- Constant *fun_addr_int =
- ConstantInt::get(GetIntptrTy(), start_address, false);
- return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
- }
-
/// Build a function pointer for a function with signature void
/// (*)(uint8_t*, uint8_t*) with a given address
///
@@ -300,53 +258,6 @@ class Instrumenter {
IntegerType *m_intptr_ty = nullptr;
};
-class ValidPointerChecker : public Instrumenter {
-public:
- ValidPointerChecker(llvm::Module &module,
- std::shared_ptr<UtilityFunction> checker_function)
- : Instrumenter(module, checker_function),
- m_valid_pointer_check_func(nullptr) {}
-
- ~ValidPointerChecker() override = default;
-
-protected:
- bool InstrumentInstruction(llvm::Instruction *inst) override {
- Log *log = GetLog(LLDBLog::Expressions);
-
- LLDB_LOGF(log, "Instrumenting load/store instruction: %s\n",
- PrintValue(inst).c_str());
-
- if (!m_valid_pointer_check_func)
- m_valid_pointer_check_func =
- BuildPointerValidatorFunc(m_checker_function->StartAddress());
-
- llvm::Value *dereferenced_ptr = nullptr;
-
- if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
- dereferenced_ptr = li->getPointerOperand();
- else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
- dereferenced_ptr = si->getPointerOperand();
- else
- return false;
-
- // Insert an instruction to call the helper with the result
- CallInst::Create(m_valid_pointer_check_func, dereferenced_ptr, "",
- inst->getIterator());
-
- return true;
- }
-
- bool InspectInstruction(llvm::Instruction &i) override {
- if (isa<llvm::LoadInst>(&i) || isa<llvm::StoreInst>(&i))
- RegisterInstruction(i);
-
- return true;
- }
-
-private:
- llvm::FunctionCallee m_valid_pointer_check_func;
-};
-
class ObjcObjectChecker : public Instrumenter {
public:
ObjcObjectChecker(llvm::Module &module,
@@ -527,16 +438,6 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) {
return false;
}
- if (m_checker_functions.m_valid_pointer_check) {
- ValidPointerChecker vpc(M, m_checker_functions.m_valid_pointer_check);
-
- if (!vpc.Inspect(*function))
- return false;
-
- if (!vpc.Instrument())
- return false;
- }
-
if (m_checker_functions.m_objc_object_check) {
ObjcObjectChecker ooc(M, m_checker_functions.m_objc_object_check);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
index ff20c1f08be0c..f67229afc2152 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
@@ -53,7 +53,6 @@ class ClangDynamicCheckerFunctions
bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message) override;
- std::shared_ptr<UtilityFunction> m_valid_pointer_check;
std::shared_ptr<UtilityFunction> m_objc_object_check;
};
diff --git a/lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py b/lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py
index 4045dd8fb6569..77c1e47914a39 100644
--- a/lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py
+++ b/lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py
@@ -32,13 +32,7 @@ def test_save_core(self):
# Getting dap stack trace may trigger __lldb_caller_function JIT module to be created.
self.get_stackFrames(startFrame=0)
- # Evaluating an expression that cause "_$__lldb_valid_pointer_check" JIT module to be created.
- expression = 'printf("this is a test")'
- self.dap_server.request_evaluate(expression, context="watch")
-
- # Verify "_$__lldb_valid_pointer_check" JIT module is created.
modules = self.dap_server.get_modules()
- self.assertTrue(modules["_$__lldb_valid_pointer_check"])
thread_count = len(self.dap_server.get_threads())
core_stack = self.getBuildArtifact("core.stack.dmp")
More information about the lldb-commits
mailing list