LLDB  mainline
IRDynamicChecks.cpp
Go to the documentation of this file.
1 //===-- IRDynamicChecks.cpp -------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/IR/Constants.h"
10 #include "llvm/IR/DataLayout.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/IR/Value.h"
15 #include "llvm/Support/raw_ostream.h"
16 
18 
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
26 #include "lldb/Utility/Log.h"
27 
28 using namespace llvm;
29 using namespace lldb_private;
30 
31 static char ID;
32 
33 #define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
34 #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
35 
36 static const char g_valid_pointer_check_text[] =
37  "extern \"C\" void\n"
38  "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
39  "{\n"
40  " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
41  "}";
42 
43 DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
44 
45 DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
46 
47 bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
48  ExecutionContext &exe_ctx) {
49  Status error;
50  m_valid_pointer_check.reset(
53  VALID_POINTER_CHECK_NAME, error));
54  if (error.Fail())
55  return false;
56 
57  if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
58  return false;
59 
60  Process *process = exe_ctx.GetProcessPtr();
61 
62  if (process) {
63  ObjCLanguageRuntime *objc_language_runtime =
64  process->GetObjCLanguageRuntime();
65 
66  if (objc_language_runtime) {
67  m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(
69 
70  if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
71  return false;
72  }
73  }
74 
75  return true;
76 }
77 
78 bool DynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
79  Stream &message) {
80  // FIXME: We have to get the checkers to know why they scotched the call in
81  // more detail,
82  // so we can print a better message here.
83  if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
84  message.Printf("Attempted to dereference an invalid pointer.");
85  return true;
86  } else if (m_objc_object_check &&
87  m_objc_object_check->ContainsAddress(addr)) {
88  message.Printf("Attempted to dereference an invalid ObjC Object or send it "
89  "an unrecognized selector");
90  return true;
91  }
92  return false;
93 }
94 
95 static std::string PrintValue(llvm::Value *V, bool truncate = false) {
96  std::string s;
97  raw_string_ostream rso(s);
98  V->print(rso);
99  rso.flush();
100  if (truncate)
101  s.resize(s.length() - 1);
102  return s;
103 }
104 
105 /// \class Instrumenter IRDynamicChecks.cpp
106 /// Finds and instruments individual LLVM IR instructions
107 ///
108 /// When instrumenting LLVM IR, it is frequently desirable to first search for
109 /// instructions, and then later modify them. This way iterators remain
110 /// intact, and multiple passes can look at the same code base without
111 /// treading on each other's toes.
112 ///
113 /// The Instrumenter class implements this functionality. A client first
114 /// calls Inspect on a function, which populates a list of instructions to be
115 /// instrumented. Then, later, when all passes' Inspect functions have been
116 /// called, the client calls Instrument, which adds the desired
117 /// instrumentation.
118 ///
119 /// A subclass of Instrumenter must override InstrumentInstruction, which
120 /// is responsible for adding whatever instrumentation is necessary.
121 ///
122 /// A subclass of Instrumenter may override:
123 ///
124 /// - InspectInstruction [default: does nothing]
125 ///
126 /// - InspectBasicBlock [default: iterates through the instructions in a
127 /// basic block calling InspectInstruction]
128 ///
129 /// - InspectFunction [default: iterates through the basic blocks in a
130 /// function calling InspectBasicBlock]
132 public:
133  /// Constructor
134  ///
135  /// \param[in] module
136  /// The module being instrumented.
137  Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
138  : m_module(module), m_checker_functions(checker_functions),
139  m_i8ptr_ty(nullptr), m_intptr_ty(nullptr) {}
140 
141  virtual ~Instrumenter() = default;
142 
143  /// Inspect a function to find instructions to instrument
144  ///
145  /// \param[in] function
146  /// The function to inspect.
147  ///
148  /// \return
149  /// True on success; false on error.
150  bool Inspect(llvm::Function &function) { return InspectFunction(function); }
151 
152  /// Instrument all the instructions found by Inspect()
153  ///
154  /// \return
155  /// True on success; false on error.
156  bool Instrument() {
157  for (InstIterator ii = m_to_instrument.begin(),
158  last_ii = m_to_instrument.end();
159  ii != last_ii; ++ii) {
160  if (!InstrumentInstruction(*ii))
161  return false;
162  }
163 
164  return true;
165  }
166 
167 protected:
168  /// Add instrumentation to a single instruction
169  ///
170  /// \param[in] inst
171  /// The instruction to be instrumented.
172  ///
173  /// \return
174  /// True on success; false otherwise.
175  virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
176 
177  /// Register a single instruction to be instrumented
178  ///
179  /// \param[in] inst
180  /// The instruction to be instrumented.
181  void RegisterInstruction(llvm::Instruction &i) {
182  m_to_instrument.push_back(&i);
183  }
184 
185  /// Determine whether a single instruction is interesting to instrument,
186  /// and, if so, call RegisterInstruction
187  ///
188  /// \param[in] i
189  /// The instruction to be inspected.
190  ///
191  /// \return
192  /// False if there was an error scanning; true otherwise.
193  virtual bool InspectInstruction(llvm::Instruction &i) { return true; }
194 
195  /// Scan a basic block to see if any instructions are interesting
196  ///
197  /// \param[in] bb
198  /// The basic block to be inspected.
199  ///
200  /// \return
201  /// False if there was an error scanning; true otherwise.
202  virtual bool InspectBasicBlock(llvm::BasicBlock &bb) {
203  for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
204  ii != last_ii; ++ii) {
205  if (!InspectInstruction(*ii))
206  return false;
207  }
208 
209  return true;
210  }
211 
212  /// Scan a function to see if any instructions are interesting
213  ///
214  /// \param[in] f
215  /// The function to be inspected.
216  ///
217  /// \return
218  /// False if there was an error scanning; true otherwise.
219  virtual bool InspectFunction(llvm::Function &f) {
220  for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
221  bbi != last_bbi; ++bbi) {
222  if (!InspectBasicBlock(*bbi))
223  return false;
224  }
225 
226  return true;
227  }
228 
229  /// Build a function pointer for a function with signature void
230  /// (*)(uint8_t*) with a given address
231  ///
232  /// \param[in] start_address
233  /// The address of the function.
234  ///
235  /// \return
236  /// The function pointer, for use in a CallInst.
237  llvm::FunctionCallee BuildPointerValidatorFunc(lldb::addr_t start_address) {
238  llvm::Type *param_array[1];
239 
240  param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
241 
242  ArrayRef<llvm::Type *> params(param_array, 1);
243 
244  FunctionType *fun_ty = FunctionType::get(
245  llvm::Type::getVoidTy(m_module.getContext()), params, true);
246  PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
247  Constant *fun_addr_int =
248  ConstantInt::get(GetIntptrTy(), start_address, false);
249  return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
250  }
251 
252  /// Build a function pointer for a function with signature void
253  /// (*)(uint8_t*, uint8_t*) with a given address
254  ///
255  /// \param[in] start_address
256  /// The address of the function.
257  ///
258  /// \return
259  /// The function pointer, for use in a CallInst.
260  llvm::FunctionCallee BuildObjectCheckerFunc(lldb::addr_t start_address) {
261  llvm::Type *param_array[2];
262 
263  param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
264  param_array[1] = const_cast<llvm::PointerType *>(GetI8PtrTy());
265 
266  ArrayRef<llvm::Type *> params(param_array, 2);
267 
268  FunctionType *fun_ty = FunctionType::get(
269  llvm::Type::getVoidTy(m_module.getContext()), params, true);
270  PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
271  Constant *fun_addr_int =
272  ConstantInt::get(GetIntptrTy(), start_address, false);
273  return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
274  }
275 
276  PointerType *GetI8PtrTy() {
277  if (!m_i8ptr_ty)
278  m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
279 
280  return m_i8ptr_ty;
281  }
282 
283  IntegerType *GetIntptrTy() {
284  if (!m_intptr_ty) {
285  llvm::DataLayout data_layout(&m_module);
286 
287  m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
288  data_layout.getPointerSizeInBits());
289  }
290 
291  return m_intptr_ty;
292  }
293 
294  typedef std::vector<llvm::Instruction *> InstVector;
295  typedef InstVector::iterator InstIterator;
296 
297  InstVector m_to_instrument; ///< List of instructions the inspector found
298  llvm::Module &m_module; ///< The module which is being instrumented
300  &m_checker_functions; ///< The dynamic checker functions for the process
301 
302 private:
303  PointerType *m_i8ptr_ty;
304  IntegerType *m_intptr_ty;
305 };
306 
308 public:
309  ValidPointerChecker(llvm::Module &module,
310  DynamicCheckerFunctions &checker_functions)
311  : Instrumenter(module, checker_functions),
312  m_valid_pointer_check_func(nullptr) {}
313 
314  ~ValidPointerChecker() override = default;
315 
316 protected:
317  bool InstrumentInstruction(llvm::Instruction *inst) override {
319 
320  if (log)
321  log->Printf("Instrumenting load/store instruction: %s\n",
322  PrintValue(inst).c_str());
323 
324  if (!m_valid_pointer_check_func)
325  m_valid_pointer_check_func = BuildPointerValidatorFunc(
326  m_checker_functions.m_valid_pointer_check->StartAddress());
327 
328  llvm::Value *dereferenced_ptr = nullptr;
329 
330  if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
331  dereferenced_ptr = li->getPointerOperand();
332  else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
333  dereferenced_ptr = si->getPointerOperand();
334  else
335  return false;
336 
337  // Insert an instruction to cast the loaded value to int8_t*
338 
339  BitCastInst *bit_cast =
340  new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst);
341 
342  // Insert an instruction to call the helper with the result
343 
344  llvm::Value *arg_array[1];
345 
346  arg_array[0] = bit_cast;
347 
348  llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
349 
350  CallInst::Create(m_valid_pointer_check_func, args, "", inst);
351 
352  return true;
353  }
354 
355  bool InspectInstruction(llvm::Instruction &i) override {
356  if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i))
357  RegisterInstruction(i);
358 
359  return true;
360  }
361 
362 private:
363  llvm::FunctionCallee m_valid_pointer_check_func;
364 };
365 
367 public:
368  ObjcObjectChecker(llvm::Module &module,
369  DynamicCheckerFunctions &checker_functions)
370  : Instrumenter(module, checker_functions),
371  m_objc_object_check_func(nullptr) {}
372 
373  ~ObjcObjectChecker() override = default;
374 
376  eMsgSend = 0,
380  eMsgSend_stret
381  };
382 
383  std::map<llvm::Instruction *, msgSend_type> msgSend_types;
384 
385 protected:
386  bool InstrumentInstruction(llvm::Instruction *inst) override {
387  CallInst *call_inst = dyn_cast<CallInst>(inst);
388 
389  if (!call_inst)
390  return false; // call_inst really shouldn't be nullptr, because otherwise
391  // InspectInstruction wouldn't have registered it
392 
393  if (!m_objc_object_check_func)
394  m_objc_object_check_func = BuildObjectCheckerFunc(
395  m_checker_functions.m_objc_object_check->StartAddress());
396 
397  // id objc_msgSend(id theReceiver, SEL theSelector, ...)
398 
399  llvm::Value *target_object;
400  llvm::Value *selector;
401 
402  switch (msgSend_types[inst]) {
403  case eMsgSend:
404  case eMsgSend_fpret:
405  // On arm64, clang uses objc_msgSend for scalar and struct return
406  // calls. The call instruction will record which was used.
407  if (call_inst->hasStructRetAttr()) {
408  target_object = call_inst->getArgOperand(1);
409  selector = call_inst->getArgOperand(2);
410  } else {
411  target_object = call_inst->getArgOperand(0);
412  selector = call_inst->getArgOperand(1);
413  }
414  break;
415  case eMsgSend_stret:
416  target_object = call_inst->getArgOperand(1);
417  selector = call_inst->getArgOperand(2);
418  break;
419  case eMsgSendSuper:
420  case eMsgSendSuper_stret:
421  return true;
422  }
423 
424  // These objects should always be valid according to Sean Calannan
425  assert(target_object);
426  assert(selector);
427 
428  // Insert an instruction to cast the receiver id to int8_t*
429 
430  BitCastInst *bit_cast =
431  new BitCastInst(target_object, GetI8PtrTy(), "", inst);
432 
433  // Insert an instruction to call the helper with the result
434 
435  llvm::Value *arg_array[2];
436 
437  arg_array[0] = bit_cast;
438  arg_array[1] = selector;
439 
440  ArrayRef<llvm::Value *> args(arg_array, 2);
441 
442  CallInst::Create(m_objc_object_check_func, args, "", inst);
443 
444  return true;
445  }
446 
447  static llvm::Function *GetFunction(llvm::Value *value) {
448  if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
449  return function;
450  }
451 
452  if (llvm::ConstantExpr *const_expr =
453  llvm::dyn_cast<llvm::ConstantExpr>(value)) {
454  switch (const_expr->getOpcode()) {
455  default:
456  return nullptr;
457  case llvm::Instruction::BitCast:
458  return GetFunction(const_expr->getOperand(0));
459  }
460  }
461 
462  return nullptr;
463  }
464 
465  static llvm::Function *GetCalledFunction(llvm::CallInst *inst) {
466  return GetFunction(inst->getCalledValue());
467  }
468 
469  bool InspectInstruction(llvm::Instruction &i) override {
471 
472  CallInst *call_inst = dyn_cast<CallInst>(&i);
473 
474  if (call_inst) {
475  const llvm::Function *called_function = GetCalledFunction(call_inst);
476 
477  if (!called_function)
478  return true;
479 
480  std::string name_str = called_function->getName().str();
481  const char *name_cstr = name_str.c_str();
482 
483  if (log)
484  log->Printf("Found call to %s: %s\n", name_cstr,
485  PrintValue(call_inst).c_str());
486 
487  if (name_str.find("objc_msgSend") == std::string::npos)
488  return true;
489 
490  if (!strcmp(name_cstr, "objc_msgSend")) {
491  RegisterInstruction(i);
492  msgSend_types[&i] = eMsgSend;
493  return true;
494  }
495 
496  if (!strcmp(name_cstr, "objc_msgSend_stret")) {
497  RegisterInstruction(i);
498  msgSend_types[&i] = eMsgSend_stret;
499  return true;
500  }
501 
502  if (!strcmp(name_cstr, "objc_msgSend_fpret")) {
503  RegisterInstruction(i);
504  msgSend_types[&i] = eMsgSend_fpret;
505  return true;
506  }
507 
508  if (!strcmp(name_cstr, "objc_msgSendSuper")) {
509  RegisterInstruction(i);
510  msgSend_types[&i] = eMsgSendSuper;
511  return true;
512  }
513 
514  if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) {
515  RegisterInstruction(i);
516  msgSend_types[&i] = eMsgSendSuper_stret;
517  return true;
518  }
519 
520  if (log)
521  log->Printf(
522  "Function name '%s' contains 'objc_msgSend' but is not handled",
523  name_str.c_str());
524 
525  return true;
526  }
527 
528  return true;
529  }
530 
531 private:
532  llvm::FunctionCallee m_objc_object_check_func;
533 };
534 
535 IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
536  const char *func_name)
537  : ModulePass(ID), m_func_name(func_name),
538  m_checker_functions(checker_functions) {}
539 
541 
544 
545  llvm::Function *function = M.getFunction(StringRef(m_func_name));
546 
547  if (!function) {
548  if (log)
549  log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
550 
551  return false;
552  }
553 
554  if (m_checker_functions.m_valid_pointer_check) {
555  ValidPointerChecker vpc(M, m_checker_functions);
556 
557  if (!vpc.Inspect(*function))
558  return false;
559 
560  if (!vpc.Instrument())
561  return false;
562  }
563 
564  if (m_checker_functions.m_objc_object_check) {
565  ObjcObjectChecker ooc(M, m_checker_functions);
566 
567  if (!ooc.Inspect(*function))
568  return false;
569 
570  if (!ooc.Instrument())
571  return false;
572  }
573 
574  if (log && log->GetVerbose()) {
575  std::string s;
576  raw_string_ostream oss(s);
577 
578  M.print(oss, nullptr);
579 
580  oss.flush();
581 
582  log->Printf("Module after dynamic checks: \n%s", s.c_str());
583  }
584 
585  return true;
586 }
587 
588 void IRDynamicChecks::assignPassManager(PMStack &PMS, PassManagerType T) {}
589 
591  return PMT_ModulePassManager;
592 }
llvm::PassManagerType getPotentialPassManagerType() const override
Returns PMT_ModulePassManager.
static const char g_valid_pointer_check_text[]
bool InspectInstruction(llvm::Instruction &i) override
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
#define VALID_OBJC_OBJECT_CHECK_NAME
Definition: Debugger.h:71
IntegerType * GetIntptrTy()
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
DynamicCheckerFunctions & m_checker_functions
The dynamic checker functions for the process.
bool InspectInstruction(llvm::Instruction &i) override
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
bool Inspect(llvm::Function &function)
Inspect a function to find instructions to instrument.
std::vector< llvm::Instruction * > InstVector
ObjcObjectChecker(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
void RegisterInstruction(llvm::Instruction &i)
Register a single instruction to be instrumented.
InstVector::iterator InstIterator
static llvm::Function * GetCalledFunction(llvm::CallInst *inst)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
virtual ObjCLanguageRuntime * GetObjCLanguageRuntime(bool retry_if_null=true)
Definition: Process.cpp:1573
std::map< llvm::Instruction *, msgSend_type > msgSend_types
bool Instrument()
Instrument all the instructions found by Inspect()
Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
Constructor.
virtual UtilityFunction * CreateObjectChecker(const char *)=0
virtual bool InspectBasicBlock(llvm::BasicBlock &bb)
Scan a basic block to see if any instructions are interesting.
"lldb/Expression/IRDynamicChecks.h" Encapsulates dynamic check functions used by expressions.
bool InstrumentInstruction(llvm::Instruction *inst) override
Add instrumentation to a single instruction.
ValidPointerChecker(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
void assignPassManager(llvm::PMStack &PMS, llvm::PassManagerType T=llvm::PMT_ModulePassManager) override
Interface stub.
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
bool runOnModule(llvm::Module &M) override
Run this IR transformer on a single module.
llvm::FunctionCallee BuildPointerValidatorFunc(lldb::addr_t start_address)
Build a function pointer for a function with signature void (*)(uint8_t*) with a given address...
std::unique_ptr< UtilityFunction > m_objc_object_check
InstVector m_to_instrument
List of instructions the inspector found.
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
Process * GetProcessPtr() const
Returns a pointer to the process object.
llvm::Module & m_module
The module which is being instrumented.
virtual bool InspectInstruction(llvm::Instruction &i)
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool GetVerbose() const
Definition: Log.cpp:250
static char ID
bool InstrumentInstruction(llvm::Instruction *inst) override
Add instrumentation to a single instruction.
uint64_t addr_t
Definition: lldb-types.h:83
PointerType * GetI8PtrTy()
virtual bool InspectFunction(llvm::Function &f)
Scan a function to see if any instructions are interesting.
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
Finds and instruments individual LLVM IR instructions.
Target & GetTargetRef() const
Returns a reference to the target object.
Non-standardized C, such as K&R.
static llvm::Function * GetFunction(llvm::Value *value)
static std::string PrintValue(llvm::Value *V, bool truncate=false)
llvm::FunctionCallee BuildObjectCheckerFunc(lldb::addr_t start_address)
Build a function pointer for a function with signature void (*)(uint8_t*, uint8_t*) with a given addr...
#define LIBLLDB_LOG_EXPRESSIONS
Definition: Logging.h:22
std::unique_ptr< UtilityFunction > m_valid_pointer_check
#define VALID_POINTER_CHECK_NAME
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
UtilityFunction * GetUtilityFunctionForLanguage(const char *expr, lldb::LanguageType language, const char *name, Status &error)
Definition: Target.cpp:2274
~IRDynamicChecks() override
Destructor.
An error handling class.
Definition: Status.h:44