blob: f2ce5b2d84f73030a65a595b0d15f09592a431ac [file] [log] [blame]
Sean Callananf18d91c2010-09-01 00:58:00 +00001//===-- IRDynamicChecks.cpp -------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Expression/IRDynamicChecks.h"
11#include "lldb/Expression/ClangUtilityFunction.h"
12
13#include "lldb/Core/Log.h"
14
15#include "llvm/Support/raw_ostream.h"
16#include "llvm/Function.h"
Sean Callanan05262332010-09-02 00:37:32 +000017#include "llvm/Instructions.h"
Sean Callananf18d91c2010-09-01 00:58:00 +000018#include "llvm/Module.h"
19#include "llvm/Value.h"
20
21using namespace llvm;
22using namespace lldb_private;
23
24static char ID;
25
26static const char valid_pointer_check_text[] =
27 "extern \"C\" void "
28 "___clang_valid_pointer_check (unsigned char *ptr)"
29 "{"
30 "unsigned char val = *ptr;"
31 "}";
32
33static const char valid_pointer_check_name[] =
34 "___clang_valid_pointer_check";
35
36DynamicCheckerFunctions::DynamicCheckerFunctions ()
37{
38 m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
39 valid_pointer_check_name));
40}
41
42DynamicCheckerFunctions::~DynamicCheckerFunctions ()
43{
44}
45
46bool
47DynamicCheckerFunctions::Install(Stream &error_stream,
48 ExecutionContext &exe_ctx)
49{
50 if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
51 return false;
52
53 return true;
54}
55
Sean Callananf18d91c2010-09-01 00:58:00 +000056static std::string
57PrintValue(llvm::Value *V, bool truncate = false)
58{
59 std::string s;
60 raw_string_ostream rso(s);
61 V->print(rso);
62 rso.flush();
63 if (truncate)
64 s.resize(s.length() - 1);
65 return s;
66}
67
Sean Callanan05262332010-09-02 00:37:32 +000068//----------------------------------------------------------------------
69/// @class Instrumenter IRDynamicChecks.cpp
70/// @brief Finds and instruments individual LLVM IR instructions
71///
72/// When instrumenting LLVM IR, it is frequently desirable to first search
73/// for instructions, and then later modify them. This way iterators
74/// remain intact, and multiple passes can look at the same code base without
75/// treading on each other's toes.
76///
77/// The Instrumenter class implements this functionality. A client first
78/// calls Inspect on a function, which populates a list of instructions to
79/// be instrumented. Then, later, when all passes' Inspect functions have
80/// been called, the client calls Instrument, which adds the desired
81/// instrumentation.
82///
83/// A subclass of Instrumenter must override InstrumentInstruction, which
84/// is responsible for adding whatever instrumentation is necessary.
85///
86/// A subclass of Instrumenter may override:
87///
88/// - InspectInstruction [default: does nothing]
89///
90/// - InspectBasicBlock [default: iterates through the instructions in a
91/// basic block calling InspectInstruction]
92///
93/// - InspectFunction [default: iterates through the basic blocks in a
94/// function calling InspectBasicBlock]
95//----------------------------------------------------------------------
96class Instrumenter {
97public:
98 //------------------------------------------------------------------
99 /// Constructor
100 ///
101 /// @param[in] module
102 /// The module being instrumented.
103 //------------------------------------------------------------------
104 Instrumenter (llvm::Module &module,
105 DynamicCheckerFunctions &checker_functions) :
106 m_module(module),
107 m_checker_functions(checker_functions)
108 {
109 }
110
111 //------------------------------------------------------------------
112 /// Inspect a function to find instructions to instrument
113 ///
114 /// @param[in] function
115 /// The function to inspect.
116 ///
117 /// @return
118 /// True on success; false on error.
119 //------------------------------------------------------------------
120 bool Inspect (llvm::Function &function)
121 {
122 return InspectFunction(function);
123 }
124
125 //------------------------------------------------------------------
126 /// Instrument all the instructions found by Inspect()
127 ///
128 /// @return
129 /// True on success; false on error.
130 //------------------------------------------------------------------
131 bool Instrument ()
132 {
133 for (InstIterator ii = m_to_instrument.begin(), last_ii = m_to_instrument.end();
134 ii != last_ii;
135 ++ii)
136 {
137 if (!InstrumentInstruction(*ii))
138 return false;
139 }
140
141 return true;
142 }
143protected:
144 //------------------------------------------------------------------
145 /// Add instrumentation to a single instruction
146 ///
147 /// @param[in] inst
148 /// The instruction to be instrumented.
149 ///
150 /// @return
151 /// True on success; false otherwise.
152 //------------------------------------------------------------------
153 virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
154
155 //------------------------------------------------------------------
156 /// Register a single instruction to be instrumented
157 ///
158 /// @param[in] inst
159 /// The instruction to be instrumented.
160 //------------------------------------------------------------------
161 void RegisterInstruction(llvm::Instruction &i)
162 {
163 m_to_instrument.push_back(&i);
164 }
165
166 //------------------------------------------------------------------
167 /// Determine whether a single instruction is interesting to
168 /// instrument, and, if so, call RegisterInstruction
169 ///
170 /// @param[in] i
171 /// The instruction to be inspected.
172 ///
173 /// @return
174 /// False if there was an error scanning; true otherwise.
175 //------------------------------------------------------------------
176 virtual bool InspectInstruction(llvm::Instruction &i)
177 {
178 return true;
179 }
180
181 //------------------------------------------------------------------
182 /// Scan a basic block to see if any instructions are interesting
183 ///
184 /// @param[in] bb
185 /// The basic block to be inspected.
186 ///
187 /// @return
188 /// False if there was an error scanning; true otherwise.
189 //------------------------------------------------------------------
190 virtual bool InspectBasicBlock(llvm::BasicBlock &bb)
191 {
192 for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
193 ii != last_ii;
194 ++ii)
195 {
196 if (!InspectInstruction(*ii))
197 return false;
198 }
199
200 return true;
201 }
202
203 //------------------------------------------------------------------
204 /// Scan a function to see if any instructions are interesting
205 ///
206 /// @param[in] f
207 /// The function to be inspected.
208 ///
209 /// @return
210 /// False if there was an error scanning; true otherwise.
211 //------------------------------------------------------------------
212 virtual bool InspectFunction(llvm::Function &f)
213 {
214 for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
215 bbi != last_bbi;
216 ++bbi)
217 {
218 if (!InspectBasicBlock(*bbi))
219 return false;
220 }
221
222 return true;
223 }
224
225 typedef std::vector <llvm::Instruction *> InstVector;
226 typedef InstVector::iterator InstIterator;
227
228 InstVector m_to_instrument; ///< List of instructions the inspector found
229 llvm::Module &m_module; ///< The module which is being instrumented
230 DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process
231};
232
233class ValidPointerChecker : public Instrumenter
234{
235public:
236 ValidPointerChecker(llvm::Module &module,
237 DynamicCheckerFunctions &checker_functions) :
238 Instrumenter(module, checker_functions),
239 m_valid_pointer_check_func(NULL)
240 {
241 }
242private:
243 bool InstrumentInstruction(llvm::Instruction *inst)
244 {
245 lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
246
247 if(log)
248 log->Printf("Instrumenting load/store instruction: %s\n",
249 PrintValue(inst).c_str());
250
251 if (!m_valid_pointer_check_func)
252 {
253 std::vector<const llvm::Type*> params;
254
255 const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
256 (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
257
258 m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
259
260 params.push_back(m_i8ptr_ty);
261
262 FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
263 PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
264 Constant *fun_addr_int = ConstantInt::get(intptr_ty, m_checker_functions.m_valid_pointer_check->StartAddress(), false);
265 m_valid_pointer_check_func = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
266 }
267
268 llvm::Value *dereferenced_ptr;
269
270 if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst> (inst))
271 dereferenced_ptr = li->getPointerOperand();
272 else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst> (inst))
273 dereferenced_ptr = si->getPointerOperand();
274 else
275 return false;
276
277 // Insert an instruction to cast the loaded value to int8_t*
278
279 BitCastInst *bit_cast = new BitCastInst(dereferenced_ptr,
280 m_i8ptr_ty,
281 "",
282 inst);
283
284 // Insert an instruction to call the helper with the result
285
286 SmallVector <llvm::Value*, 1> args;
287 args.push_back(bit_cast);
288
289 CallInst::Create(m_valid_pointer_check_func,
290 args.begin(),
291 args.end(),
292 "",
293 inst);
294
295 return true;
296 }
297
298 bool InspectInstruction(llvm::Instruction &i)
299 {
300 if (dyn_cast<llvm::LoadInst> (&i) ||
301 dyn_cast<llvm::StoreInst> (&i))
302 RegisterInstruction(i);
303
304 return true;
305 }
306
307 llvm::Value *m_valid_pointer_check_func;
308 const PointerType *m_i8ptr_ty;
309};
310
311IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
312 const char *func_name) :
313 ModulePass(&ID),
314 m_checker_functions(checker_functions),
315 m_func_name(func_name)
316{
317}
318
Sean Callananf18d91c2010-09-01 00:58:00 +0000319IRDynamicChecks::~IRDynamicChecks()
320{
321}
322
323bool
324IRDynamicChecks::runOnModule(llvm::Module &M)
325{
326 lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
327
328 llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
329
330 if (!function)
331 {
332 if (log)
333 log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
334
335 return false;
336 }
Sean Callanan05262332010-09-02 00:37:32 +0000337
338 ValidPointerChecker vpc(M, m_checker_functions);
Sean Callananf18d91c2010-09-01 00:58:00 +0000339
Sean Callanan05262332010-09-02 00:37:32 +0000340 if (!vpc.Inspect(*function))
341 return false;
Sean Callananf18d91c2010-09-01 00:58:00 +0000342
Sean Callanan05262332010-09-02 00:37:32 +0000343 if (!vpc.Instrument())
344 return false;
Sean Callananf18d91c2010-09-01 00:58:00 +0000345
346 return true;
347}
348
349void
350IRDynamicChecks::assignPassManager(PMStack &PMS,
351 PassManagerType T)
352{
353}
354
355PassManagerType
356IRDynamicChecks::getPotentialPassManagerType() const
357{
358 return PMT_ModulePassManager;
359}