Skip to content

Commit da3efb2

Browse files
committed
[lldb][Expression] Remove IR pointer checker (llvm#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. (cherry picked from commit 0a7b0c8)
1 parent 5fbc818 commit da3efb2

File tree

3 files changed

+4
-110
lines changed

3 files changed

+4
-110
lines changed

lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.cpp

Lines changed: 4 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -32,31 +32,16 @@ using namespace lldb_private;
3232

3333
static char ID;
3434

35-
#define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
3635
#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
3736

38-
static const char g_valid_pointer_check_text[] =
39-
"extern \"C\" void\n"
40-
"_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
41-
"{\n"
42-
" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
43-
"}";
44-
4537
ClangDynamicCheckerFunctions::ClangDynamicCheckerFunctions()
4638
: DynamicCheckerFunctions(DCF_Clang) {}
4739

4840
ClangDynamicCheckerFunctions::~ClangDynamicCheckerFunctions() = default;
4941

50-
llvm::Error ClangDynamicCheckerFunctions::Install(
51-
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
52-
Expected<std::unique_ptr<UtilityFunction>> utility_fn =
53-
exe_ctx.GetTargetRef().CreateUtilityFunction(
54-
g_valid_pointer_check_text, VALID_POINTER_CHECK_NAME,
55-
lldb::eLanguageTypeC, exe_ctx);
56-
if (!utility_fn)
57-
return utility_fn.takeError();
58-
m_valid_pointer_check = std::move(*utility_fn);
59-
42+
llvm::Error
43+
ClangDynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
44+
ExecutionContext &exe_ctx) {
6045
if (Process *process = exe_ctx.GetProcessPtr()) {
6146
ObjCLanguageRuntime *objc_language_runtime =
6247
ObjCLanguageRuntime::Get(*process);
@@ -78,11 +63,7 @@ bool ClangDynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
7863
// FIXME: We have to get the checkers to know why they scotched the call in
7964
// more detail,
8065
// so we can print a better message here.
81-
if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
82-
message.Printf("Attempted to dereference an invalid pointer.");
83-
return true;
84-
} else if (m_objc_object_check &&
85-
m_objc_object_check->ContainsAddress(addr)) {
66+
if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr)) {
8667
message.Printf("Attempted to dereference an invalid ObjC Object or send it "
8768
"an unrecognized selector");
8869
return true;
@@ -224,29 +205,6 @@ class Instrumenter {
224205
return true;
225206
}
226207

227-
/// Build a function pointer for a function with signature void
228-
/// (*)(uint8_t*) with a given address
229-
///
230-
/// \param[in] start_address
231-
/// The address of the function.
232-
///
233-
/// \return
234-
/// The function pointer, for use in a CallInst.
235-
llvm::FunctionCallee BuildPointerValidatorFunc(lldb::addr_t start_address) {
236-
llvm::Type *param_array[1];
237-
238-
param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
239-
240-
ArrayRef<llvm::Type *> params(param_array, 1);
241-
242-
FunctionType *fun_ty = FunctionType::get(
243-
llvm::Type::getVoidTy(m_module.getContext()), params, true);
244-
PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
245-
Constant *fun_addr_int =
246-
ConstantInt::get(GetIntptrTy(), start_address, false);
247-
return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
248-
}
249-
250208
/// Build a function pointer for a function with signature void
251209
/// (*)(uint8_t*, uint8_t*) with a given address
252210
///
@@ -301,53 +259,6 @@ class Instrumenter {
301259
IntegerType *m_intptr_ty = nullptr;
302260
};
303261

304-
class ValidPointerChecker : public Instrumenter {
305-
public:
306-
ValidPointerChecker(llvm::Module &module,
307-
std::shared_ptr<UtilityFunction> checker_function)
308-
: Instrumenter(module, checker_function),
309-
m_valid_pointer_check_func(nullptr) {}
310-
311-
~ValidPointerChecker() override = default;
312-
313-
protected:
314-
bool InstrumentInstruction(llvm::Instruction *inst) override {
315-
Log *log = GetLog(LLDBLog::Expressions);
316-
317-
LLDB_LOGF(log, "Instrumenting load/store instruction: %s\n",
318-
PrintValue(inst).c_str());
319-
320-
if (!m_valid_pointer_check_func)
321-
m_valid_pointer_check_func =
322-
BuildPointerValidatorFunc(m_checker_function->StartAddress());
323-
324-
llvm::Value *dereferenced_ptr = nullptr;
325-
326-
if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
327-
dereferenced_ptr = li->getPointerOperand();
328-
else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
329-
dereferenced_ptr = si->getPointerOperand();
330-
else
331-
return false;
332-
333-
// Insert an instruction to call the helper with the result
334-
CallInst::Create(m_valid_pointer_check_func, dereferenced_ptr, "",
335-
inst->getIterator());
336-
337-
return true;
338-
}
339-
340-
bool InspectInstruction(llvm::Instruction &i) override {
341-
if (isa<llvm::LoadInst>(&i) || isa<llvm::StoreInst>(&i))
342-
RegisterInstruction(i);
343-
344-
return true;
345-
}
346-
347-
private:
348-
llvm::FunctionCallee m_valid_pointer_check_func;
349-
};
350-
351262
class ObjcObjectChecker : public Instrumenter {
352263
public:
353264
ObjcObjectChecker(llvm::Module &module,
@@ -528,16 +439,6 @@ bool IRDynamicChecks::runOnModule(llvm::Module &M) {
528439
return false;
529440
}
530441

531-
if (m_checker_functions.m_valid_pointer_check) {
532-
ValidPointerChecker vpc(M, m_checker_functions.m_valid_pointer_check);
533-
534-
if (!vpc.Inspect(*function))
535-
return false;
536-
537-
if (!vpc.Instrument())
538-
return false;
539-
}
540-
541442
if (m_checker_functions.m_objc_object_check) {
542443
ObjcObjectChecker ooc(M, m_checker_functions.m_objc_object_check);
543444

lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ class ClangDynamicCheckerFunctions
5353

5454
bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message) override;
5555

56-
std::shared_ptr<UtilityFunction> m_valid_pointer_check;
5756
std::shared_ptr<UtilityFunction> m_objc_object_check;
5857
};
5958

lldb/test/API/tools/lldb-dap/save-core/TestDAP_save_core.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,7 @@ def test_save_core(self):
3333
# Getting dap stack trace may trigger __lldb_caller_function JIT module to be created.
3434
self.get_stackFrames(startFrame=0)
3535

36-
# Evaluating an expression that cause "_$__lldb_valid_pointer_check" JIT module to be created.
37-
expression = 'printf("this is a test")'
38-
self.dap_server.request_evaluate(expression, context="watch")
39-
40-
# Verify "_$__lldb_valid_pointer_check" JIT module is created.
4136
modules = self.dap_server.get_modules()
42-
self.assertTrue(modules["_$__lldb_valid_pointer_check"])
4337
thread_count = len(self.dap_server.get_threads())
4438

4539
core_stack = self.getBuildArtifact("core.stack.dmp")

0 commit comments

Comments
 (0)