58 #define __STDC_FORMAT_MACROS 61 #include <sys/types.h> 91 #define PATHSCALE_EXCEPTION_HANDLER_PREFIX "Handler." 92 #define USE_PATHSCALE_SYMBOL_FILTER 93 #define USE_SYMTABAPI_EXCEPTION_BLOCKS 95 #define STRLEN(s) (sizeof(s) - 1) 101 static void usage(
char *command,
int status);
131 for (n = 1; n < argc; n++) {
132 if (strcmp(argv[n],
"-c") == 0) {
135 else if (strcmp(argv[n],
"-d") == 0) {
138 else if (strcmp(argv[n],
"-h") == 0 || strcmp(argv[n],
"--help") == 0) {
141 else if (strcmp(argv[n],
"-m") == 0) {
145 else if (strcmp(argv[n],
"-s") == 0) {
147 if (argc < n + 3 || sscanf(argv[n+1],
"%d", &fdin) < 1
148 || sscanf(argv[n+2],
"%d", &fdout) < 1) {
149 fprintf(stderr,
"%s: missing file descriptors for server mode\n",
155 else if (strcmp(argv[n],
"-t") == 0) {
158 else if (strcmp(argv[n],
"-v") == 0) {
161 else if (strcmp(argv[n],
"--") == 0) {
165 else if (strncmp(argv[n],
"-", 1) == 0) {
166 fprintf(stderr,
"%s: unknown option: %s\n", argv[0], argv[n]);
184 object_file = argv[
n];
192 "!!! INTERNAL hpcfnbounds-bin error !!!\n" 193 "argument string = ");
194 for (
int i = 0; i < argc; i++)
195 fprintf(stderr,
"%s ", argv[i]);
196 fprintf(stderr,
"\n");
242 "Usage: hpcfnbounds [options] object-file\n\n" 243 "\t-c\twrite output in C source code\n" 244 "\t-d\tdon't perform function discovery on stripped code\n" 245 "\t-h\tprint this help message and exit\n" 246 "\t-s fdin fdout\trun in server mode\n" 247 "\t-t\twrite output in text format (default)\n" 248 "\t-v\tturn on verbose output in hpcfnbounds script\n\n" 249 "If no format is specified, then text mode is used.\n");
264 const struct sigaction segv_action= {
269 struct sigaction segv_action;
271 segv_action.sa_flags = 0;
272 sigemptyset(&segv_action.sa_mask);
274 sigaction(SIGSEGV, &segv_action,
NULL);
281 const char *sc = s.c_str();
282 return strncmp(sc, pre, n) == 0;
287 matches_contains(
string s,
const char *substring)
289 const char *sc = s.c_str();
290 return strstr(sc, substring) != 0;
310 #ifdef USE_PATHSCALE_SYMBOL_FILTER 321 name = name +
" " + section +
" section";
329 char *start = (
char *) s->getDiskOffset();
330 char *end = start + s->getDiskSize();
342 long memaddr = (long) syms->mem_image();
344 if (syms->findRegion(s, sname) && s)
375 for (
unsigned int i = 0; i < symvec.size(); i++) {
376 Symbol *s = symvec[i];
377 Symbol::SymbolLinkage sl = s->getLinkage();
379 string mname = s->getMangledName();
380 bool invisible = (sl & Symbol::SL_GLOBAL) || (sl & Symbol::SL_WEAK);
402 for (
unsigned int i = 0; i < symvec.size(); i++) {
403 Symbol *s = symvec[i];
404 if (s->getOffset() != 0) {
406 void *
addr = (
void*)s->getOffset();
407 long size = s->getSize();
408 string comment = s->getMangledName();
425 printf(
"unsigned long hpcrun_nm_addrs[] = {\n");
454 printf(
"unsigned long hpcrun_nm_addrs_len = " 455 "sizeof(hpcrun_nm_addrs) / sizeof(hpcrun_nm_addrs[0]);\n" 456 "unsigned long hpcrun_reference_offset = 0x%" PRIxPTR
";\n" 457 "int hpcrun_is_relocatable = %d;\n",
458 ref_offset, is_relocatable);
463 printf(
"num symbols = %ld, reference offset = 0x%" PRIxPTR
", " 464 "relocatable = %d\n",
473 int ret = stat(filename, &sbuf);
474 if (ret != 0 || !S_ISREG(sbuf.st_mode)) {
475 fprintf(stderr,
"hpcfnbounds: unable to open file: %s\n", filename);
485 string sfile(filename);
486 vector<Symbol *> symvec;
487 uintptr_t image_offset = 0;
491 if ( ! Symtab::openFile(syms, sfile) ) {
493 "!!! INTERNAL hpcfnbounds-bin error !!!\n" 494 " -- file %s is readable, but Symtab::openFile fails !\n",
500 #ifdef USE_SYMTABAPI_EXCEPTION_BLOCKS 505 vector<ExceptionBlock *> exvec;
506 syms->getAllExceptions(exvec);
508 for (
unsigned int i = 0; i < exvec.size(); i++) {
509 ExceptionBlock *e = exvec[i];
511 #ifdef DUMP_EXCEPTION_BLOCK_INFO 512 printf(
"tryStart = %p tryEnd = %p, catchStart = %p\n", e->tryStart(),
513 e->tryEnd(), e->catchStart());
514 #endif // DUMP_EXCEPTION_BLOCK_INFO 524 long cs = e->catchStart();
527 #endif // USE_SYMTABAPI_EXCEPTION_BLOCKS 531 syms->getAllSymbolsByType(symvec, Symbol::ST_FUNCTION);
534 syms->getAllSymbolsByType(symvec, Symbol::ST_OBJECT);
537 syms->getAllSymbolsByType(symvec, Symbol::ST_UNKNOWN);
548 vector<Symbol *> vec;
549 syms->getAllSymbolsByType(vec, Symbol::ST_NOTYPE);
550 for (
unsigned int i = 0; i < vec.size(); i++) {
552 string mname = s->getMangledName();
553 if (matches_contains(mname,
"long_branch") && s->getOffset() != 0) {
560 if (syms->getObjectType() != obj_Unknown) {
561 int dwarf_fd = open(filename, O_RDONLY);
564 fprintf(stderr,
"hpcfnbounds: unable to open: %s", filename);
570 relocatable = syms->isExec() ? 0 : 1;
571 image_offset = syms->imageOffset();
void system_server(DiscoverFnTy fn_discovery, int fd1, int fd2)
#define PATHSCALE_EXCEPTION_HANDLER_PREFIX
static void note_code_ranges(Symtab *syms, DiscoverFnTy fn_discovery)
const char * SECTION_INIT
static void note_code_range(const char *sname, Region *s, long memaddr, DiscoverFnTy discover)
long num_function_entries(void)
void dump_reachable_functions()
void new_code_range(const char *sname, void *start, void *end, long offset, DiscoverFnTy discover)
static bool pathscale_filter(Symbol *sym)
void process_code_ranges()
const char * SECTION_FINI
static void usage(char *command, int status)
const char * SECTION_TEXT
static void note_section(Symtab *syms, const char *sname, DiscoverFnTy discover)
static void assert_file_is_readable(const char *filename)
void add_variable_entry(void *addr, long size, const string *comment, bool isvisible)
static bool matches_prefix(string s, const char *pre, int n)
static jmp_buf segv_recover
static void dump_file_symbols(int dwarf_fd, Symtab *syms, vector< Symbol *> &symvec, DiscoverFnTy fn_discovery, int query)
void add_function_entry(void *addr, const string *comment, bool isvisible, int call_count)
static void setup_segv_handler(void)
void add_frame_addr(void *addr)
static bool report_symbol(Symbol *sym)
int main(int argc, char *argv[])
static BAnal::Struct::Options opts
void dump_file_info(const char *filename, DiscoverFnTy fn_discovery, int query)
void dwarf_eh_frame_info(int fd)
static void dump_header_info(int is_relocatable, uintptr_t ref_offset)
static void segv_handler(int sig)
static void dump_symbols_var(int dwarf_fd, Symtab *syms, vector< Symbol *> &symvec, DiscoverFnTy fn_discovery)
<!-- ********************************************************************--> 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
void add_protected_range(void *start, void *end)
static string * code_range_comment(string &name, string section, const char *which)
void syserv_add_header(int is_relocatable, uintptr_t ref_offset)
char * cplus_demangle(char *s, int opts)
static void dump_symbols(int dwarf_fd, Symtab *syms, vector< Symbol *> &symvec, DiscoverFnTy fn_discovery)