HPCToolkit
Struct-Inline.hpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 // This file defines the API between symtabAPI and the banal code for
48 // the static inline support. Now with support for building a tree of
49 // inlined call sites.
50 //
51 // For each VM address that came from inlined code, symtab provides a
52 // C++ list representing the sequence of inlining steps. (The list
53 // front is outermost, back is innermost.) An empty list means not
54 // inlined code (or else missing dwarf info).
55 //
56 // Each node in the list contains: (1) the file name and (2) line
57 // number in the source code, and (3) the procedure name at the call
58 // site.
59 //
60 // The inline TreeNode represents several InlineNode paths combined
61 // into a single tree. Edges in the tree represent one (file, line,
62 // proc) call site and nodes contain a map of subtrees and a list of
63 // terminal statements.
64 
65 //***************************************************************************
66 
67 #ifndef Banal_Struct_Inline_hpp
68 #define Banal_Struct_Inline_hpp
69 
70 #include <list>
71 #include <map>
72 
73 #include <lib/isa/ISATypes.hpp>
74 #include <lib/support/FileUtil.hpp>
76 #include <lib/support/SrcFile.hpp>
78 
79 #include <Symtab.h>
80 #include <Function.h>
81 
82 class ElfFile;
83 
84 using namespace Dyninst;
85 using namespace SymtabAPI;
86 using namespace std;
87 
88 namespace Inline {
89 
90 class InlineNode;
91 class FLPIndex;
92 class FLPCompare;
93 class StmtInfo;
94 class StmtMap;
95 class LoopInfo;
96 class TreeNode;
97 
98 typedef list <InlineNode> InlineSeqn;
99 typedef list <FLPIndex> FLPSeqn;
100 typedef list <LoopInfo *> LoopList;
101 typedef map <FLPIndex, TreeNode *, FLPCompare> NodeMap;
102 
103 
104 // File, proc, line we get from Symtab inline call sites.
105 class InlineNode {
106 private:
107  std::string m_filenm;
108  std::string m_procnm;
109  std::string m_prettynm;
111 
112 public:
113  InlineNode(std::string &file, std::string &proc, std::string &pretty,
114  SrcFile::ln line)
115  {
116  m_filenm = file;
117  m_procnm = proc;
118  m_prettynm = pretty;
119  m_lineno = line;
120  }
121 
122  std::string & getFileName() { return m_filenm; }
123  std::string & getProcName() { return m_procnm; }
124  std::string & getPrettyName() { return m_prettynm; }
125  SrcFile::ln getLineNum() { return m_lineno; }
126 };
127 
128 
129 // 3-tuple of indices for file, line, proc.
130 class FLPIndex {
131 public:
134  long line_num;
137 
138  // constructor by index
139  FLPIndex(long file, long base, long line, long proc, long pretty)
140  {
141  file_index = file;
142  base_index = base;
143  line_num = line;
144  proc_index = proc;
145  pretty_index = pretty;
146  }
147 
148  // constructor by InlineNode strings
150  {
151  string & fname = node.getFileName();
152 
153  file_index = strTab.str2index(fname);
154  base_index = strTab.str2index(FileUtil::basename(fname.c_str()));
155  line_num = (long) node.getLineNum();
156  proc_index = strTab.str2index(node.getProcName());
157  pretty_index = strTab.str2index(node.getPrettyName());
158  }
159 
160  bool operator == (const FLPIndex rhs)
161  {
162  return file_index == rhs.file_index
163  && line_num == rhs.line_num
164  && proc_index == rhs.proc_index;
165  }
166 
167  bool operator != (const FLPIndex rhs)
168  {
169  return ! (*this == rhs);
170  }
171 };
172 
173 
174 // Compare (file, line, proc) indices lexigraphically.
175 class FLPCompare {
176 public:
177  bool operator() (const FLPIndex t1, const FLPIndex t2)
178  {
179  if (t1.file_index < t2.file_index) { return true; }
180  if (t1.file_index > t2.file_index) { return false; }
181  if (t1.line_num < t2.line_num) { return true; }
182  if (t1.line_num > t2.line_num) { return false; }
183  if (t1.proc_index < t2.proc_index) { return true; }
184  return false;
185  }
186 };
187 
188 
189 // Info for one terminal statement (vma) in the inline tree. Now used
190 // for multiple, consecutive instructions, all with the same file and
191 // line info.
192 //
193 class StmtInfo {
194 public:
196  int len;
199  long line_num;
200 
201  // constructor by index
202  StmtInfo(VMA vm, int ln, long file, long base, long line)
203  {
204  vma = vm;
205  len = ln;
206  file_index = file;
207  base_index = base;
208  line_num = line;
209  }
210 
211  // constructor by string name
212  StmtInfo(HPC::StringTable & strTab, VMA vm, int ln,
213  const std::string & filenm, long line)
214  {
215  vma = vm;
216  len = ln;
217  file_index = strTab.str2index(filenm);
218  base_index = strTab.str2index(FileUtil::basename(filenm.c_str()));
219  line_num = line;
220  }
221 
222  // returns: true if vma is contained within this range
223  bool member(VMA x)
224  {
225  return vma <= x && x < vma + len;
226  }
227 };
228 
229 
230 // Map of vma ranges and their file and line info.
231 //
232 // The intervals are disjoint, semi-open [...), the map key is by left
233 // endpoint, the addresses within a single range share a common file
234 // and line and may contain multiple instructions, and we compact
235 // adjacent ranges with identical attributes into one interval.
236 //
237 class StmtMap : public std::map <VMA, StmtInfo *> {
238 public:
239 
240  // returns: pointer to StmtInfo that contains vma, else NULL
242  {
243  auto it = this->upper_bound(vma);
244 
245  if (it == this->begin()) {
246  return NULL;
247  }
248  --it;
249  StmtInfo * sinfo = it->second;
250 
251  return (sinfo->member(vma)) ? sinfo : NULL;
252  }
253 
254  // returns: true if vma is contained within some range in the map
255  bool member(VMA vma)
256  {
257  return findStmt(vma) != NULL;
258  }
259 
260  // insert one statement range into the map
261  void insert(StmtInfo *);
262 };
263 
264 
265 // Info for one loop scope in the inline tree. Note: 'node' is the
266 // TreeNode containing the loop vma without the FLP path above it.
267 class LoopInfo {
268 public:
270  FLPSeqn path;
271  std::string name;
275  long line_num;
276  bool irred;
277 
278  LoopInfo(TreeNode *nd, FLPSeqn &pth, const std::string &nm, VMA vma,
279  long file, long base, long line, bool ir = false)
280  {
281  node = nd;
282  path = pth;
283  name = nm;
284  entry_vma = vma;
285  file_index = file;
286  base_index = base;
287  line_num = line;
288  irred = ir;
289  }
290 
291  // delete the subtree 'node' in ~TreeNode(), not here.
293  }
294 };
295 
296 
297 // One node in the inline tree.
298 class TreeNode {
299 public:
300  NodeMap nodeMap;
302  LoopList loopList;
304 
305  TreeNode(long file = 0)
306  {
307  nodeMap.clear();
308  stmtMap.clear();
309  loopList.clear();
310  file_index = file;
311  }
312 
313  // shallow delete: erase the maps, but don't delete their contents.
314  // we use this when the elements are copies from other trees.
315  void
317  {
318  nodeMap.clear();
319  stmtMap.clear();
320  loopList.clear();
321  }
322 
323  // recursively delete the stmts and subtrees
325  {
326  for (StmtMap::iterator sit = stmtMap.begin(); sit != stmtMap.end(); ++sit) {
327  delete sit->second;
328  }
329  stmtMap.clear();
330 
331  for (LoopList::iterator lit = loopList.begin(); lit != loopList.end(); ++lit) {
332  delete (*lit)->node;
333  }
334  loopList.clear();
335 
336  for (NodeMap::iterator nit = nodeMap.begin(); nit != nodeMap.end(); ++nit) {
337  delete nit->second;
338  }
339  nodeMap.clear();
340  }
341 };
342 
343 //***************************************************************************
344 
345 Symtab * openSymtab(ElfFile *elfFile);
346 bool closeSymtab();
347 
348 bool analyzeAddr(InlineSeqn & nodelist, VMA addr, RealPathMgr *);
349 
350 void
352  VMA vma, int len, string & filenm, SrcFile::ln line);
353 
354 void
355 mergeInlineStmts(TreeNode * dest, TreeNode * src);
356 
357 void
358 mergeInlineEdge(TreeNode * dest, FLPIndex flp, TreeNode * src);
359 
360 void
361 mergeInlineTree(TreeNode * dest, TreeNode * src);
362 
363 void
364 mergeInlineLoop(TreeNode * dest, FLPSeqn & path, LoopInfo * info);
365 
366 } // namespace Inline
367 
368 #endif
std::string m_prettynm
list< InlineNode > InlineSeqn
unsigned int ln
Definition: SrcFile.hpp:66
long str2index(const std::string &str)
bfd_vma VMA
Definition: ISATypes.hpp:79
list< LoopInfo * > LoopList
map< FLPIndex, TreeNode *, FLPCompare > NodeMap
bool operator==(const VMAInterval &x, const VMAInterval &y)
cct_node_t * node
Definition: cct.c:128
Symtab * openSymtab(ElfFile *elfFile)
bool operator!=(const VMAInterval &x, const VMAInterval &y)
void mergeInlineLoop(TreeNode *dest, FLPSeqn &path, LoopInfo *info)
list< FLPIndex > FLPSeqn
SrcFile::ln getLineNum()
std::string & getProcName()
bool closeSymtab()
void addStmtToTree(TreeNode *root, HPC::StringTable &strTab, RealPathMgr *realPath, VMA vma, int len, string &filenm, SrcFile::ln line)
void mergeInlineStmts(TreeNode *dest, TreeNode *src)
FLPIndex(HPC::StringTable &strTab, InlineNode &node)
StmtInfo(HPC::StringTable &strTab, VMA vm, int ln, const std::string &filenm, long line)
bool member(VMA x)
FLPIndex(long file, long base, long line, long proc, long pretty)
void mergeInlineEdge(TreeNode *dest, FLPIndex flp, TreeNode *src)
TreeNode(long file=0)
void mergeInlineTree(TreeNode *dest, TreeNode *src)
bool member(VMA vma)
std::string & getFileName()
#define NULL
Definition: ElfHelper.cpp:85
StmtInfo(VMA vm, int ln, long file, long base, long line)
std::string & getPrettyName()
LoopInfo(TreeNode *nd, FLPSeqn &pth, const std::string &nm, VMA vma, long file, long base, long line, bool ir=false)
string basename(const char *fName)
Definition: FileUtil.cpp:90
cct_addr_t * addr
Definition: cct.c:130
StmtInfo * findStmt(VMA vma)
bool analyzeAddr(InlineSeqn &nodelist, VMA addr, RealPathMgr *realPath)
InlineNode(std::string &file, std::string &proc, std::string &pretty, SrcFile::ln line)