Michael Buch 0a7b0c844c
[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.
2025-06-17 15:24:26 +01:00

127 lines
3.9 KiB
C++

//===-- IRDynamicChecks.h ---------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRDYNAMICCHECKS_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRDYNAMICCHECKS_H
#include "lldb/Expression/DynamicCheckerFunctions.h"
#include "lldb/lldb-types.h"
#include "llvm/Pass.h"
namespace llvm {
class BasicBlock;
class Module;
}
namespace lldb_private {
class ExecutionContext;
class Stream;
class ClangDynamicCheckerFunctions
: public lldb_private::DynamicCheckerFunctions {
public:
/// Constructor
ClangDynamicCheckerFunctions();
/// Destructor
~ClangDynamicCheckerFunctions() override;
static bool classof(const DynamicCheckerFunctions *checker_funcs) {
return checker_funcs->GetKind() == DCF_Clang;
}
/// Install the utility functions into a process. This binds the instance
/// of DynamicCheckerFunctions to that process.
///
/// \param[in] diagnostic_manager
/// A diagnostic manager to report errors to.
///
/// \param[in] exe_ctx
/// The execution context to install the functions into.
///
/// \return
/// Either llvm::ErrorSuccess or Error with llvm::ErrorInfo
///
llvm::Error Install(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx) override;
bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message) override;
std::shared_ptr<UtilityFunction> m_objc_object_check;
};
/// \class IRDynamicChecks IRDynamicChecks.h
/// "lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered
/// expression to reduce its likelihood of crashing
///
/// When an IR function is executed in the target process, it may cause
/// crashes or hangs by dereferencing NULL pointers, trying to call
/// Objective-C methods on objects that do not respond to them, and so forth.
///
/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions to
/// appropriate locations in an expression's IR.
class IRDynamicChecks : public llvm::ModulePass {
public:
/// Constructor
///
/// \param[in] checker_functions
/// The checker functions for the target process.
///
/// \param[in] func_name
/// The name of the function to prepare for execution in the target.
IRDynamicChecks(ClangDynamicCheckerFunctions &checker_functions,
const char *func_name = "$__lldb_expr");
/// Destructor
~IRDynamicChecks() override;
/// Run this IR transformer on a single module
///
/// \param[in] M
/// The module to run on. This module is searched for the function
/// $__lldb_expr, and that function is passed to the passes one by
/// one.
///
/// \return
/// True on success; false otherwise
bool runOnModule(llvm::Module &M) override;
/// Interface stub
void assignPassManager(
llvm::PMStack &PMS,
llvm::PassManagerType T = llvm::PMT_ModulePassManager) override;
/// Returns PMT_ModulePassManager
llvm::PassManagerType getPotentialPassManagerType() const override;
private:
/// A basic block-level pass to find all pointer dereferences and
/// validate them before use.
/// The top-level pass implementation
///
/// \param[in] M
/// The module currently being processed.
///
/// \param[in] BB
/// The basic block currently being processed.
///
/// \return
/// True on success; false otherwise
bool FindDataLoads(llvm::Module &M, llvm::BasicBlock &BB);
std::string m_func_name; ///< The name of the function to add checks to
ClangDynamicCheckerFunctions
&m_checker_functions; ///< The checker functions for the process
};
} // namespace lldb_private
#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_IRDYNAMICCHECKS_H