HPCToolkit
main.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 // This file is the main program for hpcstruct. This side just
48 // handles the argument list. The real work is in makeStructure() in
49 // lib/banal/Struct.cpp.
50 
51 //****************************** Include Files ******************************
52 
53 #include <iostream>
54 using std::cerr;
55 using std::endl;
56 
57 #include <dlfcn.h>
58 #include <stdio.h>
59 #include <fstream>
60 #include <string>
61 #include <streambuf>
62 #include <new>
63 
64 #include "Args.hpp"
65 
66 #include <lib/banal/Struct.hpp>
68 #include <lib/prof-lean/hpcio.h>
69 
71 #include <lib/support/realpath.h>
72 #include <lib/support/FileUtil.hpp>
73 #include <lib/support/IOUtil.hpp>
75 
76 #include <include/hpctoolkit-config.h>
77 
78 #ifdef ENABLE_OPENMP
79 #include <omp.h>
80 #endif
81 
82 
83 //**************************** Support Functions ****************************
84 
85 #define CXX_DEMANGLER_FN_NAME "__cxa_demangle"
86 
87 static int
88 realmain(int argc, char* argv[]);
89 
90 
91 static void
92 hpctoolkit_demangler_error(char *error_string, const char *demangler_library_filename)
93 {
94  std::cerr << "WARNING: Unable to open user-specified C++ demangler library '"
95  << demangler_library_filename << "'" << std::endl;
96 
97  std::cerr << " Dynamic library error: '" << error_string << "'"
98  << std::endl;
99 
100  std::cerr << " Using default demangler instead." << std::endl;
101 }
102 
103 
104 static void
105 hpctoolkit_demangler_init(const char *demangler_library_filename, const char *demangler_function)
106 {
107  if (demangler_library_filename) {
108  static void *demangler_library_handle =
109  dlopen(demangler_library_filename, RTLD_LAZY | RTLD_LOCAL);
110 
111  if (demangler_library_handle) {
112  dlerror(); // clear error condition before calling dlsym
113 
115  dlsym(demangler_library_handle, demangler_function);
116  if (demangle_fn) {
117  hpctoolkit_demangler_set(demangle_fn);
118  return;
119  }
120  }
121  hpctoolkit_demangler_error(dlerror(), demangler_library_filename);
122  }
123 }
124 
125 //****************************** Main Program *******************************
126 
127 int
128 main(int argc, char* argv[])
129 {
130  try {
131  return realmain(argc, argv);
132  }
133  catch (const Diagnostics::Exception& x) {
134  DIAG_EMsg(x.message());
135  exit(1);
136  }
137  catch (const std::bad_alloc& x) {
138  DIAG_EMsg("[std::bad_alloc] " << x.what());
139  exit(1);
140  }
141  catch (const std::exception& x) {
142  DIAG_EMsg("[std::exception] " << x.what());
143  exit(1);
144  }
145  catch (...) {
146  DIAG_EMsg("Unknown exception encountered!");
147  exit(2);
148  }
149 }
150 
151 
152 static int
153 realmain(int argc, char* argv[])
154 {
155  Args args(argc, argv);
157 
160 
161  // ------------------------------------------------------------
162  // Parameters on how to run hpcstruct
163  // ------------------------------------------------------------
164 
165 #ifdef ENABLE_OPENMP
166  opts.jobs = args.jobs;
167  opts.jobs_parse = args.jobs_parse;
168  opts.jobs_symtab = args.jobs_symtab;
169 
170  // default is to run serial (for correctness), unless --jobs is
171  // specified.
172  if (opts.jobs < 1) {
173  opts.jobs = 1;
174  }
175  if (opts.jobs_parse < 1) {
176  opts.jobs_parse = opts.jobs;
177  }
178 
179  // libdw is not yet thread-safe, so run symtab serial unless
180  // specifically requested.
181  if (opts.jobs_symtab < 1) {
182  opts.jobs_symtab = 1;
183  }
184  omp_set_num_threads(1);
185 #else
186  opts.jobs = 1;
187  opts.jobs_parse = 1;
188  opts.jobs_symtab = 1;
189 #endif
190 
191  opts.show_time = args.show_time;
192 
193  // ------------------------------------------------------------
194  // Set the demangler before reading the executable
195  // ------------------------------------------------------------
196  if (!args.demangle_library.empty()) {
197  const char* demangle_library = args.demangle_library.c_str();
198  const char* demangle_function = CXX_DEMANGLER_FN_NAME;
199  if (!args.demangle_function.empty()) {
200  demangle_function = args.demangle_function.c_str();
201  }
202  hpctoolkit_demangler_init(demangle_library, demangle_function);
203  opts.ourDemangle = true;
204  }
205 
206  // ------------------------------------------------------------
207  // Build and print the program structure tree
208  // ------------------------------------------------------------
209 
210  const char* osnm = (args.out_filenm == "-") ? NULL : args.out_filenm.c_str();
211  std::ostream* outFile = IOUtil::OpenOStream(osnm);
212  char* outBuf = new char[HPCIO_RWBufferSz];
213 
214  std::streambuf* os_buf = outFile->rdbuf();
215  os_buf->pubsetbuf(outBuf, HPCIO_RWBufferSz);
216 
217  std::string gapsName = "";
218  std::ostream* gapsFile = NULL;
219  char* gapsBuf = NULL;
220  std::streambuf* gaps_rdbuf = NULL;
221 
222  if (args.show_gaps) {
223  // fixme: may want to add --gaps-name option
224  if (args.out_filenm == "-") {
225  DIAG_EMsg("Cannot make gaps file when hpcstruct file is stdout.");
226  exit(1);
227  }
228 
229  gapsName = RealPath(osnm) + std::string(".gaps");
230  gapsFile = IOUtil::OpenOStream(gapsName.c_str());
231  gapsBuf = new char[HPCIO_RWBufferSz];
232  gaps_rdbuf = gapsFile->rdbuf();
233  gaps_rdbuf->pubsetbuf(gapsBuf, HPCIO_RWBufferSz);
234  }
235 
236 #if 0
237  ProcNameMgr* procNameMgr = NULL;
238  if (args.lush_agent == "agent-c++") {
239  procNameMgr = new CppNameMgr;
240  }
241  else if (args.lush_agent == "agent-cilk") {
242  procNameMgr = new CilkNameMgr;
243  }
244 #endif
245 
246  BAnal::Struct::makeStructure(args.in_filenm, outFile, gapsFile, gapsName,
247  args.searchPathStr, opts);
248 
249  IOUtil::CloseStream(outFile);
250  delete[] outBuf;
251 
252  if (gapsFile != NULL) {
253  IOUtil::CloseStream(gapsFile);
254  delete[] gapsBuf;
255  }
256 
257  return (0);
258 }
Definition: Args.hpp:79
#define CXX_DEMANGLER_FN_NAME
Definition: main.cpp:85
void CloseStream(std::istream *s)
Definition: IOUtil.cpp:127
static demangler_t demangle_fn
Definition: Demangler.cpp:85
std::string demangle_function
Definition: Args.hpp:121
#define DIAG_EMsg(...)
Definition: diagnostics.h:251
bool show_gaps
Definition: Args.hpp:129
static int realmain(int argc, char *argv[])
Definition: main.cpp:153
int jobs_parse
Definition: Args.hpp:113
int jobs
Definition: Args.hpp:112
std::string lush_agent
Definition: Args.hpp:118
static RealPathMgr & singleton()
std::string searchPathStr
Definition: Args.hpp:119
std::ostream * OpenOStream(const char *filenm)
Definition: IOUtil.cpp:106
std::string in_filenm
Definition: Args.hpp:132
virtual std::string message() const
Definition: Exception.hpp:134
bool realpath(std::string &pathNm) const
exit
Definition: names.cpp:1
void makeStructure(string filename, ostream *outFile, ostream *gapsFile, string gaps_filenm, string search_path, Struct::Options &structOpts)
Definition: Struct.cpp:552
std::string out_filenm
Definition: Args.hpp:126
int main(int argc, char *argv[])
Definition: main.cpp:125
static BAnal::Struct::Options opts
Definition: Struct.cpp:160
const std::string & searchPaths() const
void hpctoolkit_demangler_set(demangler_t _demangle_fn)
Definition: Demangler.cpp:93
const char * RealPath(const char *nm)
Definition: realpath.c:69
bool show_time
Definition: Args.hpp:115
#define NULL
Definition: ElfHelper.cpp:85
int jobs_symtab
Definition: Args.hpp:114
char *(* demangler_t)(const char *mangled_name, char *output_buffer, size_t *length, int *status)
Definition: Demangler.hpp:71
static void hpctoolkit_demangler_init(const char *demangler_library_filename, const char *demangler_function)
Definition: main.cpp:105
#define HPCIO_RWBufferSz
Definition: hpcio.h:86
std::string demangle_library
Definition: Args.hpp:120
static void hpctoolkit_demangler_error(char *error_string, const char *demangler_library_filename)
Definition: main.cpp:92