klee
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InstructionInfoTable.cpp
Go to the documentation of this file.
1 //===-- InstructionInfoTable.cpp ------------------------------------------===//
2 //
3 // The KLEE Symbolic Virtual Machine
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "klee/Config/Version.h"
12 
13 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/Instructions.h"
16 #include "llvm/IR/IntrinsicInst.h"
17 #include "llvm/IR/Module.h"
18 #else
19 #include "llvm/Function.h"
20 #include "llvm/Instructions.h"
21 #include "llvm/IntrinsicInst.h"
22 #include "llvm/Module.h"
23 #endif
24 #include "llvm/Linker.h"
25 #include "llvm/Assembly/AssemblyAnnotationWriter.h"
26 #include "llvm/Support/FormattedStream.h"
27 #include "llvm/Support/CFG.h"
28 #include "llvm/Support/InstIterator.h"
29 #include "llvm/Support/raw_ostream.h"
30 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2)
31 #include "llvm/DebugInfo.h"
32 #else
33 #include "llvm/Analysis/DebugInfo.h"
34 #endif
35 #include "llvm/Analysis/ValueTracking.h"
36 #include "llvm/Support/Debug.h"
37 
38 #include <map>
39 #include <string>
40 
41 using namespace llvm;
42 using namespace klee;
43 
44 class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter {
45 public:
46  void emitInstructionAnnot(const Instruction *i,
47  llvm::formatted_raw_ostream &os) {
48  os << "%%%";
49  os << (uintptr_t) i;
50  }
51 };
52 
53 static void buildInstructionToLineMap(Module *m,
54  std::map<const Instruction*, unsigned> &out) {
56  std::string str;
57  llvm::raw_string_ostream os(str);
58  m->print(os, &a);
59  os.flush();
60  const char *s;
61 
62  unsigned line = 1;
63  for (s=str.c_str(); *s; s++) {
64  if (*s=='\n') {
65  line++;
66  if (s[1]=='%' && s[2]=='%' && s[3]=='%') {
67  s += 4;
68  char *end;
69  unsigned long long value = strtoull(s, &end, 10);
70  if (end!=s) {
71  out.insert(std::make_pair((const Instruction*) value, line));
72  }
73  s = end;
74  }
75  }
76  }
77 }
78 
79 static std::string getDSPIPath(DILocation Loc) {
80  std::string dir = Loc.getDirectory();
81  std::string file = Loc.getFilename();
82  if (dir.empty() || file[0] == '/') {
83  return file;
84  } else if (*dir.rbegin() == '/') {
85  return dir + file;
86  } else {
87  return dir + "/" + file;
88  }
89 }
90 
91 bool InstructionInfoTable::getInstructionDebugInfo(const llvm::Instruction *I,
92  const std::string *&File,
93  unsigned &Line) {
94  if (MDNode *N = I->getMetadata("dbg")) {
95  DILocation Loc(N);
96  File = internString(getDSPIPath(Loc));
97  Line = Loc.getLineNumber();
98  return true;
99  }
100 
101  return false;
102 }
103 
104 InstructionInfoTable::InstructionInfoTable(Module *m)
105  : dummyString(""), dummyInfo(0, dummyString, 0, 0) {
106  unsigned id = 0;
107  std::map<const Instruction*, unsigned> lineTable;
108  buildInstructionToLineMap(m, lineTable);
109 
110  for (Module::iterator fnIt = m->begin(), fn_ie = m->end();
111  fnIt != fn_ie; ++fnIt) {
112 
113  for (inst_iterator it = inst_begin(fnIt), ie = inst_end(fnIt); it != ie;
114  ++it) {
115  const std::string *initialFile = &dummyString;
116  unsigned initialLine = 0;
117  Instruction *instr = &*it;
118  unsigned assemblyLine = 0;
119 
120  std::map<const Instruction*, unsigned>::const_iterator ltit =
121  lineTable.find(instr);
122  if (ltit!=lineTable.end())
123  assemblyLine = ltit->second;
124  if (getInstructionDebugInfo(instr, initialFile, initialLine))
125  {
126  infos.insert(std::make_pair(instr,
127  InstructionInfo(id++,
128  *initialFile,
129  initialLine,
130  assemblyLine)));
131  DEBUG_WITH_TYPE("klee_obtained_debug", dbgs() <<
132  "Instruction: \"" << *instr << "\" (assembly line " << assemblyLine <<
133  ") has debug location " << *initialFile << ":" << initialLine << "\n");
134  }
135  else
136  {
137  DEBUG_WITH_TYPE("klee_missing_debug", dbgs() <<
138  "Instruction: \"" << *instr << "\" (assembly line " << assemblyLine <<
139  ") is missing debug info.\n");
140  }
141  }
142  }
143 }
144 
146  for (std::set<const std::string *, ltstr>::iterator
147  it = internedStrings.begin(), ie = internedStrings.end();
148  it != ie; ++it)
149  delete *it;
150 }
151 
152 const std::string *InstructionInfoTable::internString(std::string s) {
153  std::set<const std::string *, ltstr>::iterator it = internedStrings.find(&s);
154  if (it==internedStrings.end()) {
155  std::string *interned = new std::string(s);
156  internedStrings.insert(interned);
157  return interned;
158  } else {
159  return *it;
160  }
161 }
162 
164  return infos.size();
165 }
166 
167 const InstructionInfo &
168 InstructionInfoTable::getInfo(const Instruction *inst) const {
169  std::map<const llvm::Instruction*, InstructionInfo>::const_iterator it =
170  infos.find(inst);
171  if (it==infos.end()) {
172  return dummyInfo;
173  } else {
174  return it->second;
175  }
176 }
177 
178 const InstructionInfo &
179 InstructionInfoTable::getFunctionInfo(const Function *f) const {
180  if (f->isDeclaration()) {
181  return dummyInfo;
182  } else {
183  return getInfo(f->begin()->begin());
184  }
185 }
const std::string * internString(std::string s)
static std::string getDSPIPath(DILocation Loc)
const InstructionInfo & getFunctionInfo(const llvm::Function *) const
static void buildInstructionToLineMap(Module *m, std::map< const Instruction *, unsigned > &out)
bool getInstructionDebugInfo(const llvm::Instruction *I, const std::string *&File, unsigned &Line)
std::set< const std::string *, ltstr > internedStrings
const InstructionInfo & getInfo(const llvm::Instruction *) const
int line
Definition: klee.h:68
std::map< const llvm::Instruction *, InstructionInfo > infos
void emitInstructionAnnot(const Instruction *i, llvm::formatted_raw_ostream &os)