71 #include <include/hpctoolkit-config.h> 83 #define ARG_ERROR(streamArgs) \ 84 { std::ostringstream WeIrDnAmE; \ 85 WeIrDnAmE << streamArgs ; \ 86 printError(std::cerr, WeIrDnAmE.str()); \ 94 "[options] <binary>\n";
97 Given an application binary or DSO <binary>, hpcstruct recovers the program\n\ 98 structure of its object code. Program structure is a mapping of a program's\n\ 99 static source-level structure to its object code. By default, hpcstruct\n\ 100 writes its results to the file 'basename(<binary>).hpcstruct'. This file\n\ 101 is typically passed to HPCToolkit's correlation tool hpcprof.\n\ 103 hpcstruct is designed primarily for highly optimized binaries created from\n\ 104 C, C++ and Fortran source code. Because hpcstruct's algorithms exploit a\n\ 105 binary's debugging information, for best results, binary should be compiled\n\ 106 with standard debugging information. See the documentation for more\n\ 110 -v [<n>], --verbose [<n>]\n\ 111 Verbose: generate progress messages to stderr at\n\ 112 verbosity level <n>. {1}\n\ 113 -V, --version Print version information.\n\ 114 -h, --help Print this help.\n\ 115 --debug=[<n>] Debug: use debug level <n>. {1}\n\ 116 --debug-proc <glob> Debug structure recovery for procedures matching\n\ 117 the procedure glob <glob>\n\ 118 -j <num>, --jobs <num> Use <num> openmp threads (jobs), default 1.\n\ 119 --jobs-parse <num> Use <num> openmp threads for ParseAPI::parse(),\n\ 120 default is same value for --jobs.\n\ 121 --jobs-symtab <num> Use <num> openmp threads for Symtab methods.\n\ 122 --time Display stats on time and space usage.\n\ 124 Options: Structure recovery\n\ 125 -I <path>, --include <path>\n\ 126 Use <path> when resolving source file names. For a\n\ 127 recursive search, append a '*' after the last slash,\n\ 128 e.g., '/mypath/*' (quote or escape to protect from\n\ 129 the shell.) May pass multiple times.\n" 132 --loop-intvl <yes|no>\n\
133 Should loop recovery heuristics assume an irreducible\n\
134 interval is a loop? {yes}
\n\
135 --loop-fwd-subst <yes|no>\n\
136 Should loop recovery heuristics assume forward\n\
137 substitution may occur? {yes}
\n\
138 -N <all|safe|none>, --normalize <all|safe|none>\n\
139 Specify normalizations to apply to structure. {all}\n\
140 all : apply all normalizations\n\
141 safe: apply only safe normalizations\n\
145 " -R '<old-path>=<new-path>', --replace-path '<old-path>=<new-path>'\n\ 146 Substitute instances of <old-path> with <new-path>;\n\ 147 apply to all paths (profile's load map, source code)\n\ 148 for which <old-path> is a prefix. Use '\\' to escape\n\ 149 instances of '=' within a path. May pass multiple\n\ 151 --use-binutils Use binutils as the default binary instruction decoder\n\ 152 On x86 default is Intel XED library.\n\ 153 --show-gaps Experimental feature to show unclaimed vma ranges (gaps)\n\ 154 in the control-flow graph.\n\ 156 Options: Demangling\n\ 157 --demangle-library <path to demangling library>\n\ 158 Specify the pathname for a dynamically-linked\n\ 159 library whose demangler function should \n\ 160 be used for demangling. By default, the demangler used\n\ 161 is __cxa_demangle in the C++ Standard Library linked into\n\ 164 --demangle-function <name of the demangler>\n\ 165 By default, the demangler used is __cxa_demangle, a function\n\ 166 provided by the C++ Standard Library. This option enables\n\ 167 one to specify an alternate demangler, e.g., cplus_demangle\n\ 168 provided by the BFD library.\n\ 171 -o <file>, --output <file>\n\ 172 Write hpcstruct file to <file>.\n\ 173 Use '--output=-' to write output to stdout.\n\ 174 --compact Generate compact output, eliminating extra white space\n\ 182 #define CLP CmdLineParser 183 #define CLP_SEPARATOR "!!!" 187 { 0 ,
"agent-c++", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
189 { 0 ,
"agent-cilk", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
192 {
'j',
"jobs", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL, NULL },
193 { 0 ,
"jobs-parse", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL, NULL },
194 { 0 ,
"jobs-symtab", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL, NULL },
195 { 0 ,
"time", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL, NULL },
198 { 0 ,
"demangle-library", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL,
202 { 0 ,
"demangle-function", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL,
206 {
'I',
"include", CLP::ARG_REQ, CLP::DUPOPT_CAT,
":",
208 { 0 ,
"loop-intvl", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL,
210 { 0 ,
"loop-fwd-subst", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL,
212 {
'R',
"replace-path", CLP::ARG_REQ, CLP::DUPOPT_CAT,
CLP_SEPARATOR,
214 { 0 ,
"show-gaps", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
218 {
'o',
"output", CLP::ARG_REQ , CLP::DUPOPT_CLOB,
NULL,
220 { 0 ,
"compact", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
224 {
'v',
"verbose", CLP::ARG_OPT, CLP::DUPOPT_CLOB,
NULL,
225 CLP::isOptArg_long },
226 {
'V',
"version", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
228 {
'h',
"help", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
230 { 0 ,
"debug", CLP::ARG_OPT, CLP::DUPOPT_CLOB,
NULL,
231 CLP::isOptArg_long },
232 { 0 ,
"debug-proc", CLP::ARG_REQ, CLP::DUPOPT_CLOB,
NULL,
236 { 0,
"use-binutils", CLP::ARG_NONE, CLP::DUPOPT_CLOB,
NULL,
255 Args::Args(
int argc,
const char*
const argv[])
301 os <<
getCmd() <<
": " << msg << endl
302 <<
"Try '" <<
getCmd() <<
" --help' for more information." << endl;
404 std::vector<std::string> replacePaths;
407 for (
uint i = 0; i < replacePaths.size(); ++i) {
408 int occurancesOfEquals =
411 if (occurancesOfEquals > 1) {
412 ARG_ERROR(
"Too many occurances of \'=\'; make sure to escape any \'=\' in your paths");
414 else if(occurancesOfEquals == 0) {
415 ARG_ERROR(
"The \'=\' between the old path and new path is missing");
447 ARG_ERROR(
"Incorrect number of arguments!");
469 os <<
"Args.cmd= " <<
getCmd() << endl;
470 os <<
"Args.in_filenm= " <<
in_filenm << endl;
489 cerr <<
"Error: Please set your " <<
HPCTOOLKIT <<
" environment variable." 495 int len = strlen(home);
496 if (home[len-1] ==
'/') home[--len] = 0;
498 DIR *fp = opendir(home);
500 cerr <<
"Error: " << home <<
" is not a directory" << endl;
bool isOpt(const char swShort) const
void printUsage(std::ostream &os) const
const std::string & getOptArg(const char swShort) const
std::string demangle_function
const std::string & getCmd() const
int parseReplacePath(const std::string &arg)
virtual const std::string & what() const
bool isIrreducibleIntervalLoop
bool isOptArg(const char swShort) const
void parse(const OptArgDesc *optArgDescs, int argc, const char *const argv[])
unsigned int getNumArgs() const
void printVersion(std::ostream &os) const
void parse(int argc, const char *const argv[])
void tokenize_str(const std::string &tokenstr, const char *delim, std::vector< std::string > &tokenvec)
virtual std::string message() const
std::string searchPathStr() const
#define CmdLineParser_OptArgDesc_NULL_MACRO
bool isForwardSubstitution
void printError(std::ostream &os, const char *msg) const
void Diagnostics_SetDiagnosticFilterLevel(int lvl)
static CmdLineParser::OptArgDesc optArgs[]
const std::string & getArg(unsigned int i) const
static const std::string HPCTOOLKIT
static bool parseArg_bool(const std::string &value, const char *errTag)
string basename(const char *fName)
const std::string & getCmd() const
void dump(std::ostream &os=std::cerr) const
<!-- ********************************************************************--> n<!-- HPCToolkit Experiment DTD --> n<!-- Version 2.1 --> n<!-- ********************************************************************--> n<!ELEMENT HPCToolkitExperiment(Header,(SecCallPathProfile|SecFlatProfile) *)> n<!ATTLIST HPCToolkitExperiment\n version CDATA #REQUIRED > n n<!-- ******************************************************************--> n n<!-- Info/NV:flexible name-value pairs:(n) ame;(t) ype;(v) alue --> n<!ELEMENT Info(NV *)> n<!ATTLIST Info\n n CDATA #IMPLIED > n<!ELEMENT NV EMPTY > n<!ATTLIST NV\n n CDATA #REQUIRED\n t CDATA #IMPLIED\n v CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Header --> n<!-- ******************************************************************--> n<!ELEMENT Header(Info *)> n<!ATTLIST Header\n n CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Section Header --> n<!-- ******************************************************************--> n<!ELEMENT SecHeader(MetricTable?, MetricDBTable?, TraceDBTable?, LoadModuleTable?, FileTable?, ProcedureTable?, Info *)> n n<!-- MetricTable:--> n<!ELEMENT MetricTable(Metric) * > n n<!-- Metric:(i) d;(n) ame --> n<!--(v) alue-type:transient type of values --> n<!--(t) ype:persistent type of metric --> n<!-- fmt:format;show;--> n<!ELEMENT Metric(MetricFormula *, Info?)> n<!ATTLIST Metric\n i CDATA #REQUIRED\n n CDATA #REQUIRED\n es CDATA #IMPLIED\n em CDATA #IMPLIED\n ep CDATA #IMPLIED\n v(raw|final|derived-incr|derived) \"raw\\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ fmt CDATA #IMPLIED\ show (1|0) \1\\ show-percent (1|0) \1> n n<!-- MetricFormula represents derived metrics: (t)ype; (frm): formula --> n<!ELEMENT MetricFormula (Info?)> n<!ATTLIST MetricFormula\ t (combine|finalize) \finalize\\ i CDATA #IMPLIED\ frm CDATA #REQUIRED> n n<!-- Metric data, used in sections: (n)ame [from Metric]; (v)alue --> n<!ELEMENT M EMPTY> n<!ATTLIST M\ n CDATA #REQUIRED\ v CDATA #REQUIRED> n n<!-- MetricDBTable: --> n<!ELEMENT MetricDBTable (MetricDB)*> n n<!-- MetricDB: (i)d; (n)ame --> n<!-- (t)ype: persistent type of metric --> n<!-- db-glob: file glob describing files in metric db --> n<!-- db-id: id within metric db --> n<!-- db-num-metrics: number of metrics in db --> n<!-- db-header-sz: size (in bytes) of a db file header --> n<!ELEMENT MetricDB EMPTY> n<!ATTLIST MetricDB\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ db-glob CDATA #IMPLIED\ db-id CDATA #IMPLIED\ db-num-metrics CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- TraceDBTable: --> n<!ELEMENT TraceDBTable (TraceDB)> n n<!-- TraceDB: (i)d --> n<!-- db-min-time: min beginning time stamp (global) --> n<!-- db-max-time: max ending time stamp (global) --> n<!ELEMENT TraceDB EMPTY> n<!ATTLIST TraceDB\ i CDATA #REQUIRED\ db-glob CDATA #IMPLIED\ db-min-time CDATA #IMPLIED\ db-max-time CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- LoadModuleTable assigns a short name to a load module --> n<!ELEMENT LoadModuleTable (LoadModule)*> n n<!ELEMENT LoadModule (Info?)> n<!ATTLIST LoadModule\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- FileTable assigns a short name to a file --> n<!ELEMENT FileTable (File)*> n n<!ELEMENT File (Info?)> n<!ATTLIST File\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- ProcedureTable assigns a short name to a procedure --> n<!ELEMENT ProcedureTable (Procedure)*> n n<!-- Info/NV: flexible name-value pairs: (n)ame; (t)ype; (v)alue --> n<!-- f: family of the procedure (fake, root, ...)--> n<!ELEMENT Procedure (Info?)> n<!ATTLIST Procedure\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ f CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Call path profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecCallPathProfile (SecHeader, SecCallPathProfileData)> n<!ATTLIST SecCallPathProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecCallPathProfileData (PF|M)*> n<!-- Procedure frame --> n<!-- (i)d: unique identifier for cross referencing --> n<!-- (s)tatic scope id --> n<!-- (n)ame: a string or an id in ProcedureTable --> n<!-- (lm) load module: a string or an id in LoadModuleTable --> n<!-- (f)ile name: a string or an id in LoadModuleTable --> n<!-- (l)ine range: \beg-end\ (inclusive range) --> n<!-- (a)lien: whether frame is alien to enclosing P --> n<!-- (str)uct: hpcstruct node id --> n<!-- (t)ype: hpcrun node type: memory access, variable declaration, ... --> n<!-- (v)ma-range-set: \{[beg-end), [beg-end)...}\ --> n<!ELEMENT PF (PF|Pr|L|C|S|M)*> n<!ATTLIST PF\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Procedure (static): GOAL: replace with 'P' --> n<!ELEMENT Pr (Pr|L|C|S|M)*> n<!ATTLIST Pr\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ a (1|0) \0\\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Callsite (a special StatementRange) --> n<!ELEMENT C (PF|M)*> n<!ATTLIST C\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Flat profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecFlatProfile (SecHeader, SecFlatProfileData)> n<!ATTLIST SecFlatProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecFlatProfileData (LM|M)*> n<!-- Load module: (i)d; (n)ame; (v)ma-range-set --> n<!ELEMENT LM (F|P|M)*> n<!ATTLIST LM\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ v CDATA #IMPLIED> n<!-- File --> n<!ELEMENT F (P|L|S|M)*> n<!ATTLIST F\ i CDATA #IMPLIED\ n CDATA #REQUIRED> n<!-- Procedure (Note 1) --> n<!ELEMENT P (P|A|L|S|C|M)*> n<!ATTLIST P\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Alien (Note 1) --> n<!ELEMENT A (A|L|S|C|M)*> n<!ATTLIST A\ i CDATA #IMPLIED\ f CDATA #IMPLIED\ n CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Loop (Note 1,2) --> n<!ELEMENT L (A|Pr|L|S|C|M)*> n<!ATTLIST L\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ f CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Statement (Note 2) --> n<!-- (it): trace record identifier --> n<!ELEMENT S (S|M)*> n<!ATTLIST S\ i CDATA #IMPLIED\ it CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Note 1: Contained Cs may not contain PFs --> n<!-- Note 2: The 's' attribute is not used for flat profiles --> n
static long toLong(const std::string &str)
std::string demangle_library