HPCToolkit
ProfileWriter.cpp
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 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 //************************* System Include Files ****************************
61 
62 #include <iostream>
63 using std::ostream;
64 using std::cerr;
65 using std::endl;
66 using std::hex;
67 using std::dec;
68 
69 #include <fstream>
70 #include <map>
71 
72 #include <string>
73 using std::string;
74 
75 #ifdef NO_STD_CHEADERS
76 # include <string.h>
77 #else
78 # include <cstring>
79 using namespace std; // For compatibility with non-std C headers
80 #endif
81 
82 //*************************** User Include Files ****************************
83 
84 #include <include/uint.h>
85 
86 #include "ProfileWriter.hpp"
87 #include "PCProfile.hpp"
88 #include "DerivedProfile.hpp"
89 
90 #include <lib/binutils/LM.hpp>
92 
93 #include <lib/xml/xml.hpp>
94 using namespace xml;
95 
96 #include <lib/support/SrcFile.hpp>
97 
98 //*************************** Forward Declarations ***************************
99 
100 const char* UNKNOWN = "<unknown>";
101 
102 //*************************** Forward Declarations ***************************
103 
104 // LineToPCProfileVecMap
105 typedef std::map<SrcFile::ln, PCProfileVec*> LineToPCProfileVecMap;
106 typedef LineToPCProfileVecMap::iterator LineToPCProfileVecMapIt;
107 typedef LineToPCProfileVecMap::value_type LineToPCProfileVecMapVal;
108 
109 void
110 DumpFuncLineMap(ostream& os, LineToPCProfileVecMap& map,
111  DerivedProfile* profData,
112  const string& func, const string& file);
113 void
115 
116 //****************************************************************************
117 //
118 //****************************************************************************
119 
120 void
121 ProfileWriter::WriteProfile(std::ostream& os, DerivedProfile* profData,
122  binutils::LM* lm)
123 {
124  // Sanity check
125  if (profData->GetNumMetrics() == 0) {
126  return; // We must have at least one metric
127  }
128 
129  const PCProfile* rawprofData = profData->GetPCProfile();
130  ISA* isa = rawprofData->GetISA();
131  isa->attach(); // ensure longevity
132 
133  // ------------------------------------------------------------------------
134  // Dump header info
135  // ------------------------------------------------------------------------
137 
138  const string& profiledFile = rawprofData->GetProfiledFile();
139 
140  os << "<PROFILE version=\"3.0\">\n";
141  os << "<PROFILEHDR>\n" << rawprofData->GetHdrInfo() << "</PROFILEHDR>\n";
142  os << "<PROFILEPARAMS>\n";
143  {
144  os << "<TARGET name"; WriteAttrStr(os, profiledFile); os << "/>\n";
145  os << "<METRICS>\n";
146 
147  DerivedProfile_MetricIterator it(*profData);
148  for (uint i = 0; it.IsValid(); ++it, ++i) {
149  DerivedProfileMetric* m = it.Current();
150  os << "<METRIC shortName"; WriteAttrNum(os, i);
151  os << " displayName"; WriteAttrStr(os, m->GetName());
152  os << " nativeName"; WriteAttrStr(os, m->GetNativeName());
153  os << " period"; WriteAttrNum(os, m->GetPeriod());
154  // os << " count_total"; WriteAttrNum(os, m->GetTotalCount());
155  os << "/>\n";
156  }
157  os << "</METRICS>\n";
158  os << "</PROFILEPARAMS>\n";
159  }
160 
161  // ------------------------------------------------------------------------
162  // Iterate through the PC values in the profile, collect symbolic
163  // information on a source line basis, and output the results
164  // ------------------------------------------------------------------------
165 
166  os << "<PROFILESCOPETREE>\n";
167  os << "<PGM n"; WriteAttrStr(os, profiledFile); os << ">\n";
168 
169  // 'funcLineMap' maps a line number to a 'PCProfileVec'. It should
170  // contain information only for the current function, 'theFunc'.
171  string theFunc, theFile;
172  LineToPCProfileVecMap funcLineMap;
173 
174  // Iterate over PC values in the profile
175  for (PCProfile_PCIterator it(*rawprofData); it.IsValid(); ++it) {
176 
177  VMA oppc = it.Current(); // an 'operation pc'
178  ushort opIndex;
179  VMA pc = isa->convertOpVMAToVMA(oppc, opIndex);
180 
181  // --------------------------------------------------
182  // 1. Attempt to find symbolic information
183  // --------------------------------------------------
184  string func, file;
185  SrcFile::ln line;
186  lm->findSrcCodeInfo(pc, opIndex, func, file, line);
187  func = GetBestFuncName(func);
188 
189  // Bad line info: cannot fix and cannot report; advance iteration
190  if (!SrcFile::isValid(line)) {
191  continue;
192  }
193 
194  // Bad function name: cannot fix
195  if (func.empty()) { func = UNKNOWN; }
196 
197  // Bad file name: try to fix
198  if (file.empty()) {
199  if (!theFile.empty() && func == theFunc && func != UNKNOWN) {
200  file = theFile; // valid replacement
201  } else {
202  file = UNKNOWN;
203  }
204  }
205 
206  // --------------------------------------------------
207  // 2. If we are starting a new function, dump 'funcLineMap'
208  // --------------------------------------------------
209  if (func != theFunc) {
210  DumpFuncLineMap(os, funcLineMap, profData, theFunc, theFile);
211  ClearFuncLineMap(funcLineMap); // clears map and memory
212  }
213 
214  // --------------------------------------------------
215  // 3. Update 'funcLineMap' for each derived metric
216  // --------------------------------------------------
217  PCProfileVec* vec = NULL;
218  LineToPCProfileVecMapIt it1 = funcLineMap.find(line);
219  if (it1 == funcLineMap.end()) {
220  // Initialize the vector and insert into the map
221  vec = new PCProfileVec(profData->GetNumMetrics());
222  funcLineMap.insert(LineToPCProfileVecMapVal(line, vec));
223  } else {
224  vec = (*it1).second;
225  }
226 
227  // Update vector counts for each derived metric. Note that we
228  // only update when the current pc applies to the derived metric.
229  DerivedProfile_MetricIterator dmIt(*profData);
230  for (uint i = 0; dmIt.IsValid(); ++dmIt, ++i) {
231  DerivedProfileMetric* dm = dmIt.Current();
232  if (dm->FindPC(pc, opIndex)) {
234  for ( ; mIt.IsValid(); ++mIt) {
235  PCProfileMetric* m = mIt.Current();
236  (*vec)[i] += m->Find(pc, opIndex);
237  }
238  }
239  }
240 
241  if (theFunc != func) { theFunc = func; }
242  if (theFile != file) { theFile = file; }
243  }
244 
245  // --------------------------------------------------
246  // 4. Dump 'funcLineMap', if it contains info for the last function
247  // --------------------------------------------------
248  if (funcLineMap.size() > 0) {
249  DumpFuncLineMap(os, funcLineMap, profData, theFunc, theFile);
250  ClearFuncLineMap(funcLineMap); // clears map and memory
251  }
252 
253  os << "</PGM>\n";
254  os << "</PROFILESCOPETREE>\n";
255 
256  // ------------------------------------------------------------------------
257  // Dump footer
258  // ------------------------------------------------------------------------
259  os << "</PROFILE>\n";
261 
262  isa->detach();
263 }
264 
265 //****************************************************************************
266 //
267 //****************************************************************************
268 
269 const char *PROFILEdtd =
270 #include <lib/xml/PROFILE.dtd.h>
271 
272 void
274 {
275  os << "<?xml version=\"1.0\"?>" << endl;
276  os << "<!DOCTYPE PROFILE [\n" << PROFILEdtd << "]>" << endl;
277  os.flush();
278 }
279 
280 void
282 {
283  /* nothing to do */
284 }
285 
286 // Output should be in increasing order by line number.
287 void
288 DumpFuncLineMap(ostream& os, LineToPCProfileVecMap& map,
289  DerivedProfile* profData,
290  const string& func, const string& file)
291 {
292  static const char* I[] = { "", // Indent levels (0 - 5)
293  " ",
294  " ",
295  " ",
296  " ",
297  " " };
298 
299  if (map.size() == 0) { return; }
300 
301  os << I[1] << "<F n"; WriteAttrStr(os, file); os << ">\n";
302  os << I[2] << "<P n"; WriteAttrStr(os, func); os << ">\n";
303 
305  for (it = map.begin(); it != map.end(); ++it) {
306  SrcFile::ln srcLn = (*it).first;
307  PCProfileVec* vec = (*it).second;
308 
309  os << I[3] << "<S b"; WriteAttrNum(os, srcLn);
310  os << " id"; WriteAttrNum(os, 0); // was: SrcLineX.id
311  os << ">\n";
312  for (unsigned int i = 0; i < vec->GetSz(); ++i) {
313  if ( (*vec)[i] != 0 ) {
314  const DerivedProfileMetric* dm = profData->GetMetric(i);
315  double v = (double)(*vec)[i] * (double)dm->GetPeriod();
316 
317  os << I[4] << "<M n"; WriteAttrNum(os, i);
318  os << " v"; WriteAttrNum(os, v);
319  os << "/>\n";
320  }
321  }
322  os << I[3] << "</S>" << endl;
323  }
324 
325  os << I[2] << "</P>" << endl;
326  os << I[1] << "</F>\n";
327 }
328 
330 {
332  for (it = map.begin(); it != map.end(); ++it) {
333  delete (*it).second;
334  }
335  map.clear();
336 }
337 
338 //***************************************************************************
unsigned int GetNumMetrics() const
void detach()
Definition: ISA.hpp:388
PCProfileDatum Find(VMA pc, ushort opIndex) const
unsigned int GetSz() const
Definition: PCProfile.hpp:329
unsigned int ln
Definition: SrcFile.hpp:66
bfd_vma VMA
Definition: ISATypes.hpp:79
const std::string & GetNativeName() const
void ClearFuncLineMap(LineToPCProfileVecMap &map)
const std::string & GetName() const
bool isValid(SrcFile::ln line)
Definition: SrcFile.hpp:70
const PCProfileMetricSet * GetMetricSet() const
void DumpFuncLineMap(ostream &os, LineToPCProfileVecMap &map, DerivedProfile *profData, const string &func, const string &file)
bool IsValid() const
Definition: PCProfile.hpp:293
const std::string & GetHdrInfo() const
Definition: PCProfile.hpp:233
bool WriteAttrStr(std::ostream &os, const char *s, int flags=ESC_TRUE)
Definition: xml.cpp:112
DerivedProfileMetric * Current() const
static void WriteProfile(std::ostream &os, DerivedProfile *profData, binutils::LM *lm)
void attach()
Definition: ISA.hpp:384
const PCProfile * GetPCProfile() const
std::map< SrcFile::ln, PCProfileVec * > LineToPCProfileVecMap
Definition: xml.cpp:127
LineToPCProfileVecMap::iterator LineToPCProfileVecMapIt
unsigned short int ushort
Definition: uint.h:120
unsigned int uint
Definition: uint.h:124
bool WriteAttrNum(std::ostream &os, T n)
Definition: xml.hpp:205
const DerivedProfileMetric * GetMetric(unsigned int i) const
static void DumpProfileFooter(std::ostream &os)
Definition: ISA.hpp:106
PCProfileMetric * Current() const
Definition: PCProfile.hpp:182
bool FindPC(VMA pc, ushort opIndex)
static void DumpProfileHeader(std::ostream &os)
ISA * GetISA() const
Definition: PCProfile.hpp:136
#define NULL
Definition: ElfHelper.cpp:85
virtual VMA convertOpVMAToVMA(VMA opvma, ushort &opIndex) const
Definition: ISA.hpp:475
LineToPCProfileVecMap::value_type LineToPCProfileVecMapVal
const char * UNKNOWN
const std::string & GetProfiledFile() const
Definition: PCProfile.hpp:232