66 #include <sys/types.h> 67 #include <sys/resource.h> 90 #include <CodeObject.h> 91 #include <CodeSource.h> 93 #include <Instruction.h> 98 #include <include/hpctoolkit-config.h> 123 #ifdef DYNINST_USE_CUDA 124 #define SYMTAB_ARCH_CUDA(symtab) \ 125 ((symtab)->getArchitecture() == Dyninst::Arch_cuda) 127 #define SYMTAB_ARCH_CUDA(symtab) 0 130 #define DEBUG_CFG_SOURCE 0 131 #define DEBUG_MAKE_SKEL 0 132 #define DEBUG_SHOW_GAPS 0 133 #define DEBUG_SKEL_SUMMARY 0 135 #if DEBUG_CFG_SOURCE || DEBUG_MAKE_SKEL || DEBUG_SHOW_GAPS 136 #define DEBUG_ANY_ON 1 138 #define DEBUG_ANY_ON 0 141 #define WORK_LIST_PCT 0.05 143 #define MIN_BYTES_GLOBAL_VARIABLE 1024 172 typedef map <Block *, bool>
BlockSet;
198 BlockSet &, LoopTreeNode *);
202 BlockSet &, Loop *,
const string &);
218 getStatement(StatementVector &, Offset, SymtabAPI::Function *);
222 TreeNode *, Loop *,
const string &);
237 #define DEBUG_ANY(expr) std::cout << expr 240 debugPrettyName(
const string &);
252 debugEdges(Block * block);
255 debugLoop(
GroupInfo *, ParseAPI::Function *, Loop *,
const string &,
261 #else // ! DEBUG_ANY_ON 263 #define DEBUG_ANY(expr) 268 #define DEBUG_CFG(expr) std::cout << expr 270 #define DEBUG_CFG(expr) 274 #define DEBUG_SKEL(expr) std::cout << expr 276 #define DEBUG_SKEL(expr) 280 #define DEBUG_GAPS(expr) std::cout << expr 282 #define DEBUG_GAPS(expr) 380 if (start <= vma && vma < end) {
381 filenm = cache_filenm;
387 StatementVector svec;
390 if (! svec.empty()) {
391 filenm = svec[0]->getFile();
392 line = svec[0]->getLine();
395 cache_filenm = filenm;
397 start = svec[0]->startAddr();
398 end = svec[0]->endAddr();
419 return b1->start() < b2->start();
427 return (e1->trg()->start() < e2->trg()->start())
428 || (e1->trg()->start() == e2->trg()->start()
429 && e1->src()->last() < e2->src()->last());
450 vector <Block *> entBlocks;
451 int num_ents = loop->getLoopEntries(entBlocks);
458 for (
int i = 0; i < num_ents; i++) {
459 ans = std::min(ans, entBlocks[i]->start());
486 getStatement(StatementVector & svec, Offset vma, SymtabAPI::Function * sym_func)
491 if (sym_func !=
NULL) {
492 Module * mod = sym_func->getModule();
495 mod->getSourceLines(svec, vma);
501 set <Module *> modSet;
504 for (
auto mit = modSet.begin(); mit != modSet.end(); ++mit) {
505 (*mit)->getSourceLines(svec, vma);
506 if (! svec.empty()) {
514 if (! svec.empty() && svec[0]->getFile() ==
"") {
525 printTime(
const char *label,
struct timeval *tv_prev,
struct rusage *ru_prev,
526 struct timeval *tv_now,
struct rusage *ru_now)
528 gettimeofday(tv_now,
NULL);
529 getrusage(RUSAGE_SELF, ru_now);
531 float delta = (float)(tv_now->tv_sec - tv_prev->tv_sec)
532 + ((float)(tv_now->tv_usec - tv_prev->tv_usec))/1000000.0;
534 printf(
"%s %8.1f sec %8ld meg %8ld meg", label, delta,
535 (ru_now->ru_maxrss - ru_prev->ru_maxrss)/1024,
536 ru_now->ru_maxrss/1024);
559 struct timeval tv_init, tv_symtab, tv_parse, tv_fini;
560 struct rusage ru_init, ru_symtab, ru_parse, ru_fini;
565 omp_set_num_threads(opts.jobs_symtab);
569 if (! inputFile.
openFile(filename)) {
575 string & sfilename = inputFile.
fileName();
576 const char * cfilename = inputFile.
CfileName();
578 if (elfFileVector ==
NULL || elfFileVector->empty()) {
584 for (
uint i = 0; i < elfFileVector->size(); i++) {
585 ElfFile *elfFile = (*elfFileVector)[i];
587 if (opts.show_time) {
589 <<
"symtab threads: " << opts.jobs_symtab
590 <<
" parse: " << opts.jobs_parse
591 <<
" struct: " << opts.jobs <<
"\n\n";
592 printTime(
"init: ", &tv_init, &ru_init, &tv_init, &ru_init);
596 debugElfHeader(elfFile);
600 omp_set_num_threads(opts.jobs_symtab);
604 if (symtab ==
NULL) {
611 vector <Module *> modVec;
614 #pragma omp parallel shared(modVec) 616 #pragma omp for schedule(dynamic, 1) 617 for (
uint i = 0; i < modVec.size(); i++) {
618 Module * mod = modVec[i];
619 mod->parseLineInformation();
623 if (opts.show_time) {
624 printTime(
"symtab:", &tv_init, &ru_init, &tv_symtab, &ru_symtab);
628 omp_set_num_threads(opts.jobs_parse);
631 SymtabCodeSource * code_src =
new SymtabCodeSource(symtab);
632 CodeObject * code_obj =
new CodeObject(code_src);
639 if (opts.show_time) {
640 printTime(
"parse: ", &tv_symtab, &ru_symtab, &tv_parse, &ru_parse);
644 omp_set_num_threads(opts.jobs);
669 #pragma omp parallel default(none) \ 670 shared(wlPrint, wlLaunch, num_done, output_mtx) \ 671 firstprivate(outFile, gapsFile, search_path, gaps_filenm, cuda_file) 673 #pragma omp for schedule(dynamic, 1) 674 for (
uint i = 0; i < wlLaunch.size(); i++) {
675 doWorkItem(wlLaunch[i], search_path, cuda_file, gapsFile !=
NULL);
678 if (output_mtx.try_lock()) {
679 printWorkList(wlPrint, num_done, outFile, gapsFile, gaps_filenm);
687 printWorkList(wlPrint, num_done, outFile, gapsFile, gaps_filenm);
691 if (opts.show_time) {
692 printTime(
"struct:", &tv_parse, &ru_parse, &tv_fini, &ru_fini);
693 printTime(
"total: ", &tv_init, &ru_init, &tv_fini, &ru_fini);
694 cout <<
"\nnum funcs: " << wlPrint.size() <<
"\n" << endl;
699 if (i + 1 < elfFileVector->size()) {
700 for (
uint i = 0; i < wlPrint.size(); i++) {
764 double total_cost = 0.0;
771 for (
auto fit = fileMap->begin(); fit != fileMap->end(); ++fit) {
773 auto group_begin = finfo->
groupMap.begin();
774 auto group_end = finfo->
groupMap.end();
776 for (
auto git = group_begin; git != group_end; ++git) {
778 auto next_git = git; ++next_git;
781 double cost = ginfo->
end - ginfo->
start;
786 new WorkItem(finfo, ginfo, (git == group_begin), (next_git == group_end), cost);
788 wlPrint.push_back(witem);
793 if (opts.
jobs == 1) {
804 for (
auto wit = wlPrint.begin(); wit != wlPrint.end(); ++wit) {
807 if (witem->
cost > threshold) {
808 wlLaunch.push_back(witem);
815 for (
auto wit = wlPrint.begin(); wit != wlPrint.end(); ++wit) {
819 wlLaunch.push_back(witem);
836 ostream * gapsFile,
string & gaps_filenm)
838 while (num_done < workList.size() && workList[num_done]->is_done) {
839 WorkItem * witem = workList[num_done];
848 for (
auto pit = ginfo->
procMap.begin(); pit != ginfo->
procMap.end(); ++pit) {
883 vector <Region *> regVec;
888 for (
auto it = regVec.begin(); it != regVec.end(); ++it) {
890 VMA start = reg->getMemOffset();
892 codeMap[start] = reg;
895 <<
"--0x" << (start + reg->getMemSize()) << dec
896 <<
" " << reg->getRegionName() <<
"\n");
901 vector <Module *> modVec;
905 for (
auto mit = modVec.begin(); mit != modVec.end(); ++mit) {
909 cout <<
"module: 0x" << hex << mod->addr() << dec
910 <<
" (lang " << mod->language() <<
")" 911 <<
" " << mod->fullName() <<
"\n";
925 auto it = codeMap.upper_bound(vma);
928 while (it != codeMap.begin()) {
931 Region * reg = it->second;
932 VMA start = reg->getMemOffset();
933 VMA end = start + reg->getMemSize();
935 if (start <= vma && vma < end) {
955 SymtabAPI::Function * sym_func)
961 if (! svec.empty()) {
966 if (sym_func ==
NULL) {
969 Module * mod = sym_func->getModule();
977 const int init_step = 2;
978 const int max_tries = 8;
979 int step = init_step;
981 end = std::min(end, vma + 800);
985 Offset next = vma + step;
990 mod->getSourceLines(svec, next);
993 if (! svec.empty()) {
995 if (step <= init_step) {
1005 if (num_tries >= max_tries) {
1018 SymtabAPI::Function * sym_func,
VMA start,
VMA end,
bool alt_file =
false)
1023 auto fit = fileMap->find(filenm);
1024 if (fit != fileMap->end()) {
1025 finfo = fit->second;
1029 (*fileMap)[filenm] = finfo;
1035 auto git = finfo->
groupMap.find(start);
1036 if (git != finfo->
groupMap.end()) {
1037 ginfo = git->second;
1040 ginfo =
new GroupInfo(sym_func, start, end, alt_file);
1047 cout <<
"link: " << pinfo->
linkName <<
"\n" 1049 << (alt_file ?
"alt-file: " :
"file: ") << finfo->
fileName <<
"\n" 1050 <<
"group: 0x" << hex << ginfo->
start <<
"--0x" << ginfo->
end << dec <<
"\n";
1062 std::vector<Symbol*> symvec;
1064 the_symtab->getAllSymbolsByType(symvec, Symbol::ST_OBJECT);
1066 for (
auto i=0; i<symvec.size(); i++) {
1067 Symbol *s = symvec[i];
1099 string & linknm,
bool ourDemangle)
1101 auto pretty_begin = sym_func->pretty_names_begin();
1102 auto pretty_end = sym_func->pretty_names_end();
1103 auto mangled_end = sym_func->mangled_names_end();
1105 auto pretty_it = pretty_begin;
1106 auto mangled_it = sym_func->mangled_names_begin();
1108 while (pretty_it != pretty_end && mangled_it != mangled_end) {
1109 string new_mangled = *mangled_it;
1113 if (pretty_it == pretty_begin || new_pretty.compare(prettynm) < 0) {
1114 prettynm = new_pretty;
1115 linknm = new_mangled;
1137 string unknown_base =
unknown_file +
" [" + basename +
"]";
1145 const CodeObject::funclist & funcList = code_obj->funcs();
1146 map <VMA, ParseAPI::Function *> funcMap;
1148 for (
auto flit = funcList.begin(); flit != funcList.end(); ++flit) {
1149 ParseAPI::Function * func = *flit;
1150 funcMap[func->addr()] = func;
1153 for (
auto fmit = funcMap.begin(); fmit != funcMap.end(); ++fmit) {
1154 ParseAPI::Function * func = fmit->second;
1155 SymtabAPI::Function * sym_func =
NULL;
1156 VMA vma = func->addr();
1158 auto next_it = fmit; ++next_it;
1159 VMA next_vma = (next_it != funcMap.end()) ? next_it->second->addr() : 0;
1162 buf <<
"0x" << hex << vma << dec;
1163 string vma_str = buf.str();
1165 DEBUG_SKEL(
"\nskel: " << vma_str <<
" " << func->name() <<
"\n");
1172 Region * region =
NULL;
1176 if (found && sym_func !=
NULL) {
1177 sym_start = sym_func->getOffset();
1178 sym_end = sym_start + sym_func->getSize();
1180 region = sym_func->getRegion();
1181 if (region !=
NULL) {
1182 reg_start = region->getMemOffset();
1183 reg_end = reg_start + region->getMemSize();
1187 DEBUG_SKEL(
"symbol: 0x" << hex << sym_start <<
"--0x" << sym_end
1188 <<
" next: 0x" << next_vma
1189 <<
" region: 0x" << reg_start <<
"--0x" << reg_end << dec <<
"\n");
1194 if (found && sym_func !=
NULL && region !=
NULL 1195 && reg_start <= vma && vma < reg_end)
1197 string filenm = unknown_base;
1199 string prettynm =
unknown_proc +
" " + vma_str +
" [" + basename +
"]";
1203 if (sym_start < reg_end && reg_end < sym_end) {
1208 vector <Statement::Ptr> svec;
1211 if (! svec.empty()) {
1212 filenm = svec[0]->getFile();
1213 line = svec[0]->getLine();
1217 if (vma == sym_start) {
1227 prettynm +=
" (" + basename +
")";
1231 sym_func->getFirstSymbol()->getIndex());
1232 addProc(fileMap, pinfo, filenm, sym_func, sym_start, sym_end);
1236 string parse_filenm = unknown_base;
1240 vector <Statement::Ptr> pvec;
1243 if (! pvec.empty()) {
1244 parse_filenm = pvec[0]->getFile();
1245 parse_line = pvec[0]->getLine();
1251 buf <<
"outline " << parse_base <<
":" << parse_line <<
" (" << vma_str <<
")";
1253 buf <<
" (" << basename <<
")";
1256 linknm = func->name();
1257 prettynm = buf.str();
1259 if (filenm == parse_filenm) {
1267 addProc(fileMap, pinfo, filenm, sym_func, sym_start, sym_end);
1278 addProc(fileMap, pinfo, parse_filenm, sym_func, sym_start, sym_end,
true);
1281 addProc(fileMap, pinfo, filenm, sym_func, sym_start, sym_end);
1291 string linknm = func->name();
1296 if (linknm != prettynm
1297 && prettynm.find_first_of(
"()<>") == string::npos) {
1302 reg_start = (region !=
NULL) ? region->getMemOffset() : 0;
1303 reg_end = (region !=
NULL) ? (reg_start + region->getMemSize()) : 0;
1305 DEBUG_SKEL(
"region: 0x" << hex << reg_start <<
"--0x" << reg_end << dec <<
"\n");
1308 if (next_it != funcMap.end()) {
1310 if (region !=
NULL && vma < reg_end && reg_end < end) {
1314 else if (region !=
NULL && vma < reg_end) {
1324 if (end - vma <= 32) {
1325 int len = linknm.length();
1326 const char *str = linknm.c_str();
1328 if (len < 5 || strncasecmp(&str[len-4],
"@plt", 4) != 0) {
1334 prettynm +=
" (" + basename +
")";
1338 addProc(fileMap, pinfo, unknown_base,
NULL, vma, end);
1342 #if DEBUG_SKEL_SUMMARY 1344 cout <<
"\n------------------------------------------------------------\n";
1346 for (
auto fit = fileMap->begin(); fit != fileMap->end(); ++fit) {
1347 auto finfo = fit->second;
1349 for (
auto git = finfo->groupMap.begin(); git != finfo->groupMap.end(); ++git) {
1350 auto ginfo = git->second;
1351 long size = ginfo->procMap.size();
1354 for (
auto pit = ginfo->procMap.begin(); pit != ginfo->procMap.end(); ++pit) {
1355 auto pinfo = pit->second;
1358 cout <<
"\nentry: 0x" << hex << pinfo->entry_vma << dec
1359 <<
" (" << num <<
"/" << size <<
")\n" 1360 <<
"group: 0x" << hex << ginfo->start
1361 <<
"--0x" << ginfo->end << dec <<
"\n" 1362 <<
"file: " << finfo->fileName <<
"\n" 1363 <<
"link: " << pinfo->linkName <<
"\n" 1364 <<
"pretty: " << pinfo->prettyName <<
"\n" 1365 <<
"parse: " << pinfo->func->name() <<
"\n" 1366 <<
"line: " << pinfo->line_num <<
"\n";
1413 long num_funcs = ginfo->
procMap.size();
1414 set <Address> coveredFuncs;
1421 map <VMA, VMA> callMap;
1424 for (
auto pit = ginfo->
procMap.begin(); pit != ginfo->
procMap.end(); ++pit) {
1425 ParseAPI::Function * func = pit->second->func;
1426 const ParseAPI::Function::edgelist & elist = func->callEdges();
1428 for (
auto eit = elist.begin(); eit != elist.end(); ++eit) {
1429 VMA src = (*eit)->src()->last();
1430 VMA targ = (*eit)->trg()->start();
1431 callMap[targ] = src;
1438 for (
auto pit = ginfo->
procMap.begin(); pit != ginfo->
procMap.end(); ++pit) {
1440 ParseAPI::Function * func = pinfo->
func;
1441 Address entry_addr = func->addr();
1450 auto call_it = callMap.find(entry_addr);
1452 if (call_it != callMap.end()) {
1456 #if DEBUG_CFG_SOURCE 1457 debugFuncHeader(finfo, pinfo, num, num_funcs);
1459 if (call_it != callMap.end()) {
1460 cout <<
"\ncall site prefix: 0x" << hex << call_it->second
1461 <<
" -> 0x" << call_it->first << dec <<
"\n";
1462 for (
auto pit = prefix.begin(); pit != prefix.end(); ++pit) {
1463 cout <<
"inline: l=" << pit->getLineNum()
1464 <<
" f='" << pit->getFileName()
1465 <<
"' p='" << debugPrettyName(pit->getPrettyName()) <<
"'\n";
1475 int num_contain = func->entry()->containingFuncs();
1476 bool add_blocks =
true;
1478 if (num_contain > 1) {
1479 vector <ParseAPI::Function *> funcVec;
1480 func->entry()->getFuncs(funcVec);
1483 for (
auto fit = funcVec.begin(); fit != funcVec.end(); ++fit) {
1484 Address entry = (*fit)->addr();
1486 if (coveredFuncs.find(entry) != coveredFuncs.end()) {
1495 DEBUG_CFG(
"\nskipping duplicated function: '" << func->name() <<
"'\n");
1501 vector <Block *> bvec;
1504 const ParseAPI::Function::blocklist & blist = func->blocks();
1506 for (
auto bit = blist.begin(); bit != blist.end(); ++bit) {
1507 Block * block = *bit;
1508 bvec.push_back(block);
1509 visited[block] =
false;
1516 for (
auto bit = bvec.begin(); bit != bvec.end(); ++bit) {
1517 Block * block = *bit;
1518 covered.
insert(block->start(), block->end());
1520 coveredFuncs.insert(entry_addr);
1524 if (num_contain > 1) {
1525 DEBUG_CFG(
"\nskipping duplicated function: '" << func->name() <<
"'\n");
1533 DEBUG_CFG(
"\nskipping full parse (gap only) for function: '" 1534 << func->name() <<
"'\n");
1542 doLoopTree(env, finfo, ginfo, func, visited, func->getLoopTree());
1547 for (
auto bit = bvec.begin(); bit != bvec.end(); ++bit) {
1548 Block * block = *bit;
1549 if (! visited[block]) {
1550 doBlock(env, ginfo, func, visited, block, root);
1557 for (
auto it = llist->begin(); it != llist->end(); ++it) {
1562 if (! prefix.empty()) {
1569 #if DEBUG_CFG_SOURCE 1570 cout <<
"\nfinal inline tree: (" << num <<
"/" << num_funcs <<
")" 1571 <<
" link='" << pinfo->
linkName <<
"'\n" 1572 <<
"parse: '" << func->name() <<
"'\n";
1574 if (call_it != callMap.end()) {
1575 cout <<
"\ncall site prefix: 0x" << hex << call_it->second
1576 <<
" -> 0x" << call_it->first << dec <<
"\n";
1577 for (
auto pit = prefix.begin(); pit != prefix.end(); ++pit) {
1578 cout <<
"inline: l=" << pit->getLineNum()
1579 <<
" f='" << pit->getFileName()
1580 <<
"' p='" << debugPrettyName(pit->getPrettyName()) <<
"'\n";
1584 debugInlineTree(root,
NULL, *(env.
strTab), 0,
true);
1585 cout <<
"\nend proc: (" << num <<
"/" << num_funcs <<
")" 1586 <<
" link='" << pinfo->
linkName <<
"'\n" 1587 <<
"parse: '" << func->name() <<
"'\n";
1602 auto pit = ginfo->
procMap.begin();
1605 cout <<
"\nfunc: 0x" << hex << pinfo->
entry_vma << dec
1606 <<
" (1/" << num_funcs <<
")\n" 1607 <<
"link: " << pinfo->
linkName <<
"\n" 1608 <<
"parse: " << pinfo->
func->name() <<
"\n" 1609 <<
"0x" << hex << ginfo->
start 1610 <<
"--0x" << ginfo->
end << dec <<
"\n";
1613 cout <<
"\ncovered:\n" 1619 cout <<
"\ngaps: alt-file\n";
1634 ParseAPI::Function * func, BlockSet & visited, LoopTreeNode * ltnode)
1638 if (ltnode ==
NULL) {
1641 Loop *loop = ltnode->loop;
1644 vector <LoopTreeNode *> clist = ltnode->children;
1648 for (
uint i = 0; i < clist.size(); i++) {
1650 doLoopTree(env, finfo, ginfo, func, visited, clist[i]);
1652 for (
auto sit = subList->begin(); sit != subList->end(); ++sit) {
1653 myList->push_back(*sit);
1666 string loopName = ltnode->name();
1670 doLoopLate(env, ginfo, func, visited, loop, loopName);
1672 for (
auto it = myList->begin(); it != myList->end(); ++it) {
1685 myList->push_back(myInfo);
1701 BlockSet & visited, Loop * loop,
const string & loopName)
1705 DEBUG_CFG(
"\nbegin loop: " << loopName <<
" '" << func->name() <<
"'\n");
1708 vector <Block *> bvec;
1709 loop->getLoopBasicBlocks(bvec);
1713 for (
uint i = 0; i < bvec.size(); i++) {
1714 if (! visited[bvec[i]]) {
1715 doBlock(env, ginfo, func, visited, bvec[i], root);
1728 BlockSet & visited, Block * block,
TreeNode * root)
1730 if (block ==
NULL || visited[block]) {
1733 visited[block] =
true;
1740 #ifdef DYNINST_INSTRUCTION_PTR 1741 map <Offset, Instruction::Ptr> imap;
1743 map <Offset, Instruction> imap;
1745 block->getInsns(imap);
1747 for (
auto iit = imap.begin(); iit != imap.end(); ++iit) {
1748 Offset vma = iit->first;
1752 #ifdef DYNINST_INSTRUCTION_PTR 1753 int len = iit->second->size();
1755 int len = iit->second.size();
1760 #if DEBUG_CFG_SOURCE 1761 debugStmt(vma, len, filenm, line, env.
realPath);
1767 #if DEBUG_CFG_SOURCE 1782 for (
auto pit = ginfo->
procMap.begin(); pit != ginfo->
procMap.end(); ++pit) {
1784 ParseAPI::Function * func = pinfo->
func;
1787 #if DEBUG_CFG_SOURCE 1788 long num_funcs = ginfo->
procMap.size();
1789 debugFuncHeader(finfo, pinfo, num, num_funcs,
"cuda");
1798 #if DEBUG_CFG_SOURCE 1799 cout <<
"\nfinal cuda tree: '" << pinfo->
linkName <<
"'\n\n";
1800 debugInlineTree(root,
NULL, *(env.
strTab), 0,
true);
1821 for (Offset vma = ginfo->
start; vma < ginfo->end; vma += len) {
1827 #if DEBUG_CFG_SOURCE 1828 debugStmt(vma, len, filenm, line, env.
realPath);
1860 for (
auto git = ginfo->
gapSet.begin(); git != ginfo->
gapSet.end(); ++git) {
1861 VMA vma = git->beg();
1862 VMA end_gap = git->end();
1864 while (vma < end_gap) {
1865 StatementVector svec;
1868 if (! svec.empty()) {
1869 string filenm = svec[0]->getFile();
1871 VMA end = std::min(((
VMA) svec[0]->endAddr()), end_gap);
1878 VMA end = std::min(vma + 4, end_gap);
1905 ParseAPI::Function * func,
TreeNode * root, Loop * loop,
1906 const string & loopName)
1909 long empty_index = strTab->
str2index(
"");
1915 vector <Block *> inclBlocks;
1919 loop->getLoopBasicBlocks(inclBlocks);
1920 for (
auto bit = inclBlocks.begin(); bit != inclBlocks.end(); ++bit) {
1929 for (
auto bit = inclBlocks.begin(); bit != inclBlocks.end(); ++bit) {
1930 Block * block = *bit;
1931 const Block::edgelist & outEdges = block->targets();
1932 VMA src_vma = block->last();
1933 bool in_loop =
false, out_loop =
false;
1935 for (
auto eit = outEdges.begin(); eit != outEdges.end(); ++eit) {
1936 Block *dest = (*eit)->trg();
1937 int type = (*eit)->type();
1939 if (type != ParseAPI::CALL && type != ParseAPI::CALL_FT) {
1940 if (bset.find(dest) != bset.end()) { in_loop =
true; }
1941 else { out_loop =
true; }
1945 if (in_loop && out_loop) {
1949 StatementVector svec;
1952 if (! svec.empty()) {
1953 filenm = svec[0]->getFile();
1954 line = svec[0]->getLine();
1962 clist[src_vma].is_excl = loop->hasBlockExclusive(block);
1963 clist[src_vma].depth = seqn.size();
1964 clist[src_vma].file_index = strTab->
str2index(filenm);
1966 clist[src_vma].line_num = line;
1972 vector <Edge *> backEdges;
1973 loop->getBackEdges(backEdges);
1975 std::sort(backEdges.begin(), backEdges.end(),
EdgeLessThan);
1977 for (
auto eit = backEdges.begin(); eit != backEdges.end(); ++eit) {
1978 VMA src_vma = (*eit)->src()->last();
1980 auto it = clist.find(src_vma);
1981 if (it != clist.end()) {
1982 it->second.is_src =
true;
1986 #if DEBUG_CFG_SOURCE 1987 cout <<
"\nraw inline tree: " << loopName
1988 <<
" '" << func->name() <<
"'\n" 1989 <<
"file: '" << finfo->
fileName <<
"'\n\n";
1990 debugInlineTree(root,
NULL, *strTab, 0,
false);
1991 debugLoop(ginfo, func, loop, loopName, backEdges, clist, env.
realPath);
1992 cout <<
"\nsearching inline tree:\n";
2014 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2015 VMA vma = cit->first;
2029 for (
auto sit = root->
stmtMap.begin(); sit != root->
stmtMap.end(); ++sit) {
2030 stmts.
insert(sit->second);
2038 path.push_back(flp);
2048 #if DEBUG_CFG_SOURCE 2049 if (root->
nodeMap.size() > 0) {
2050 cout <<
"\nremaining inline subtrees:\n";
2052 for (
auto nit = root->
nodeMap.begin(); nit != root->
nodeMap.end(); ++nit) {
2054 cout <<
"inline: l=" << flp.
line_num 2068 for (
auto sit = stmts.begin(); sit != stmts.end(); ++sit) {
2084 long file_ans = empty_index;
2085 long base_ans = empty_index;
2090 if (depth_root == 0) {
2091 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2096 file_ans = proc_file;
2097 base_ans = proc_base;
2104 for (
auto nit = root->
nodeMap.begin(); nit != root->
nodeMap.end(); ++nit) {
2107 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2121 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2132 if (depth_root == 0 && proc_file != empty_index) {
2133 file_ans = proc_file;
2134 base_ans = proc_base;
2139 for (
auto nit = root->
nodeMap.begin(); nit != root->
nodeMap.end(); ++nit) {
2150 for (
auto lit = root->
loopList.begin(); lit != root->
loopList.end(); ++lit) {
2161 for (
auto sit = root->
stmtMap.begin(); sit != root->
stmtMap.end(); ++sit) {
2176 for (
auto nit = root->
nodeMap.begin(); nit != root->
nodeMap.end(); ++nit) {
2187 for (
auto lit = root->
loopList.begin(); lit != root->
loopList.end(); ++lit) {
2191 && (line_ans == 0 || (linfo->
line_num > 0 && linfo->
line_num < line_ans))) {
2197 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2200 if (info->
depth == depth_root
2206 DEBUG_CFG(
"\nheader: l=" << line_ans <<
" f='" 2207 << strTab->
index2str(file_ans) <<
"'\n");
2209 vector <Block *> entryBlocks;
2210 loop->getLoopEntries(entryBlocks);
2213 for (
auto bit = entryBlocks.begin(); bit != entryBlocks.end(); ++bit) {
2214 entry_vma = std::min(entry_vma, (*bit)->start());
2218 file_ans, base_ans, line_ans,
2219 entryBlocks.size() > 1);
2221 #if DEBUG_CFG_SOURCE 2222 cout <<
"\nreparented inline tree: " << loopName
2223 <<
" '" << func->
name() <<
"'\n\n";
2224 debugInlineTree(root, info, *strTab, 0,
false);
2246 for (
auto pit = prefix.begin(); pit != prefix.end(); ++pit)
2249 auto nit = root->
nodeMap.find(flp);
2251 if (nit != root->
nodeMap.end()) {
2255 for (
auto sit = root->
stmtMap.begin(); sit != root->
stmtMap.end(); ++sit) {
2256 stmts.
insert(sit->second);
2261 for (
auto lit = root->
loopList.begin(); lit != root->
loopList.end(); ++lit) {
2262 loops.push_back(*lit);
2267 for (
auto it = root->
nodeMap.begin(); it != root->
nodeMap.end(); ++it) {
2269 if (node != subtree) {
2281 for (
auto sit = stmts.begin(); sit != stmts.end(); ++sit) {
2286 for (
auto lit = loops.begin(); lit != loops.end(); ++lit) {
2316 bool has_irred =
false;
2317 for (
auto it = list1.begin(); it != list1.end(); ++it) {
2319 if (L2->
irred) { has_irred =
true;
break; }
2332 vector <LoopInfo *> newList;
2334 for (
auto it1 = list1.begin(); it1 != list1.end(); ++it1) {
2344 for (
auto it2 = list2.begin(); it2 != list2.end(); ++it2) {
2345 newList.push_back(*it2);
2353 newList.push_back(L2);
2361 for (
auto nit = newList.begin(); nit != newList.end(); ++nit) {
2362 list1.push_back(*nit);
2366 #if DEBUG_CFG_SOURCE 2368 debugInlineTree(node1, L1, *(env.
strTab), 0,
false);
2382 auto it = vset.begin();
2386 if (it == vset.end()) {
2390 else if (it->end() <= start) {
2394 else if (it->beg() <= start) {
2401 VMA gap_end = std::min(it->beg(), end);
2402 gaps.
insert(start, gap_end);
2429 debugPrettyName(
const string & procnm)
2431 string str = procnm;
2433 size_t str_len = str.size();
2436 while (pos < str_len) {
2437 size_t next = str.find_first_of(
"<(", pos);
2440 if (next == string::npos) {
2441 ans += str.substr(pos);
2444 if (str[next] ==
'<') { open =
'<'; close =
'>'; }
2445 else { open =
'('; close =
')'; }
2447 ans += str.substr(pos, next - pos) + open + close;
2450 for (pos = next + 1; pos < str_len && depth > 0; pos++) {
2451 if (str[pos] == open) { depth++; }
2452 else if (str[pos] == close) { depth--; }
2462 debugElfHeader(
ElfFile * elfFile)
2466 cout <<
"\n============================================================\n" 2468 <<
"length: 0x" << hex << len << dec <<
" (" << len <<
")\n" 2469 <<
"============================================================\n";
2475 debugFuncHeader(
FileInfo * finfo,
ProcInfo * pinfo,
long num,
long num_funcs,
2478 ParseAPI::Function * func = pinfo->
func;
2479 Address entry_addr = func->addr();
2481 cout <<
"\n------------------------------------------------------------\n";
2483 if (label !=
"") { cout << label <<
" "; }
2485 cout <<
"func: 0x" << hex << entry_addr << dec
2486 <<
" (" << num <<
"/" << num_funcs <<
")" 2487 <<
" link='" << pinfo->
linkName <<
"'\n" 2488 <<
"parse: '" << func->name() <<
"'\n" 2489 <<
"file: '" << finfo->
fileName <<
"'\n";
2499 cout <<
"stmt: 0x" << hex << vma << dec <<
" (" << len <<
")" 2500 <<
" l=" << line <<
" f='" << filenm <<
"'\n";
2506 for (
auto nit = nodeList.begin(); nit != nodeList.end(); ++nit) {
2507 cout <<
INDENT <<
"inline: l=" << nit->getLineNum()
2508 <<
" f='" << nit->getFileName()
2509 <<
"' p='" << debugPrettyName(nit->getPrettyName()) <<
"'\n";
2518 if (type == ParseAPI::CALL) {
return "call"; }
2519 if (type == ParseAPI::COND_TAKEN) {
return "cond-take"; }
2520 if (type == ParseAPI::COND_NOT_TAKEN) {
return "cond-not"; }
2521 if (type == ParseAPI::INDIRECT) {
return "indirect"; }
2522 if (type == ParseAPI::DIRECT) {
return "direct"; }
2523 if (type == ParseAPI::FALLTHROUGH) {
return "fallthr"; }
2524 if (type == ParseAPI::CATCH) {
return "catch"; }
2525 if (type == ParseAPI::CALL_FT) {
return "call-ft"; }
2531 debugEdges(Block * block)
2533 const Block::edgelist & outEdges = block->targets();
2534 vector <Edge *> edgeVec;
2536 for (
auto eit = outEdges.begin(); eit != outEdges.end(); ++eit) {
2537 edgeVec.push_back(*eit);
2539 std::sort(edgeVec.begin(), edgeVec.end(),
EdgeLessThan);
2541 cout <<
"out edges:" << hex;
2543 for (
auto eit = edgeVec.begin(); eit != edgeVec.end(); ++eit) {
2546 cout <<
" 0x" << edge->trg()->start()
2547 <<
" (" << edgeType(edge->type());
2549 if (edge->interproc()) {
2550 cout <<
", interproc";
2555 cout << dec <<
"\n";
2563 StatementVector svec;
2569 if (! svec.empty()) {
2570 filenm = svec[0]->getFile();
2571 line = svec[0]->getLine();
2575 cout <<
"0x" << hex << vma << dec
2576 <<
" l=" << line <<
" f='" << filenm <<
"'\n";
2582 debugLoop(
GroupInfo * ginfo, ParseAPI::Function * func,
2583 Loop * loop,
const string & loopName,
2584 vector <Edge *> & backEdges, HeaderList & clist,
2587 vector <Block *> entBlocks;
2588 int num_ents = loop->getLoopEntries(entBlocks);
2590 std::sort(entBlocks.begin(), entBlocks.end(),
BlockLessThan);
2592 cout <<
"\nheader info: " << loopName
2593 << ((num_ents == 1) ?
" (reducible)" :
" (irreducible)")
2594 <<
" '" << func->name() <<
"'\n";
2596 cout <<
"\nfunc header:\n";
2597 debugAddr(ginfo, func->addr(), realPath);
2599 cout <<
"\nentry blocks:" << hex;
2600 for (
auto bit = entBlocks.begin(); bit != entBlocks.end(); ++bit) {
2601 cout <<
" 0x" << (*bit)->start();
2604 cout <<
"\nback edge sources:";
2605 for (
auto eit = backEdges.begin(); eit != backEdges.end(); ++eit) {
2606 cout <<
" 0x" << (*eit)->src()->last();
2609 cout <<
"\nback edge targets:";
2610 for (
auto eit = backEdges.begin(); eit != backEdges.end(); ++eit) {
2611 cout <<
" 0x" << (*eit)->trg()->start();
2615 cout <<
"\n\nexit conditions:\n";
2616 for (
auto cit = clist.begin(); cit != clist.end(); ++cit) {
2617 VMA vma = cit->first;
2625 StatementVector svec;
2628 if (! svec.empty()) {
2629 filenm = svec[0]->getFile();
2630 line = svec[0]->getLine();
2634 cout <<
"0x" << hex << vma << dec
2635 <<
" " << (info->
is_src ?
"src " :
"cond")
2637 <<
" depth: " << info->
depth 2639 <<
" f='" << filenm <<
"'\n";
2651 int depth,
bool expand_loops)
2656 for (
auto pit = info->
path.begin(); pit != info->
path.end(); ++pit) {
2657 for (
int i = 1; i <= depth; i++) {
2662 cout <<
"inline: l=" << flp.
line_num 2669 for (
int i = 1; i <= depth; i++) {
2672 cout <<
"loop: " << info->
name 2673 << (info->
irred ?
" (irred)" :
"")
2680 for (
auto sit = node->
stmtMap.begin(); sit != node->
stmtMap.end(); ++sit) {
2683 for (
int i = 1; i <= depth; i++) {
2686 cout <<
"stmt: 0x" << hex << sinfo->
vma << dec <<
" (" << sinfo->
len <<
")" 2692 for (
auto nit = node->
nodeMap.begin(); nit != node->
nodeMap.end(); ++nit) {
2695 for (
int i = 1; i <= depth; i++) {
2698 cout <<
"inline: l=" << flp.
line_num 2703 debugInlineTree(nit->second,
NULL, strTab, depth + 1, expand_loops);
2707 for (
auto lit = node->
loopList.begin(); lit != node->
loopList.end(); ++lit) {
2710 for (
int i = 1; i <= depth; i++) {
2714 cout <<
"loop: " << info->
name 2715 << (info->
irred ?
" (irred)" :
"")
2720 debugInlineTree(info->
node,
NULL, strTab, depth + 1, expand_loops);
2725 #endif // DEBUG_CFG_SOURCE
HPC::StringTable * strTab
static void doWorkItem(WorkItem *, string &, bool, bool)
static void getProcLineMap(StatementVector &svec, Offset vma, Offset end, SymtabAPI::Function *sym_func)
list< InlineNode > InlineSeqn
LineMapCache(SymtabAPI::Function *sf, RealPathMgr *rp)
void printProc(ostream *os, ostream *gaps, string gaps_file, FileInfo *finfo, GroupInfo *ginfo, ProcInfo *pinfo, HPC::StringTable &strTab)
void printStructFileEnd(ostream *os, ostream *gaps)
static const string & unknown_proc
long str2index(const std::string &str)
static TreeNode * doLoopLate(WorkEnv &, GroupInfo *, ParseAPI::Function *, BlockSet &, Loop *, const string &)
list< LoopInfo * > LoopList
void printLoadModuleBegin(ostream *os, string lmName)
vector< Statement::Ptr > StatementVector
SymtabAPI::Function * sym_func
static LoopList * doLoopTree(WorkEnv &, FileInfo *, GroupInfo *, ParseAPI::Function *, BlockSet &, LoopTreeNode *)
static void addProc(FileMap *fileMap, ProcInfo *pinfo, string &filenm, SymtabAPI::Function *sym_func, VMA start, VMA end, bool alt_file=false)
static void printTime(const char *label, struct timeval *tv_prev, struct rusage *ru_prev, struct timeval *tv_now, struct rusage *ru_now)
static void addGaps(WorkEnv &env, FileInfo *, GroupInfo *)
static void getStatement(StatementVector &, Offset, SymtabAPI::Function *)
static void getFuncNames(SymtabAPI::Function *sym_func, string &prettynm, string &linknm, bool ourDemangle)
static const string & unknown_file
WorkItem(FileInfo *fi, GroupInfo *gi, bool first, bool last, double cst)
static void doCudaList(WorkEnv &, FileInfo *, GroupInfo *)
Symtab * openSymtab(ElfFile *elfFile)
static RealPathMgr & singleton()
static void makeWorkList(FileMap *, WorkList &, WorkList &)
void mergeInlineLoop(TreeNode *dest, FLPSeqn &path, LoopInfo *info)
static int merge_irred_loops
static void doFunctionList(WorkEnv &, FileInfo *, GroupInfo *, bool)
static bool BlockLessThan(Block *b1, Block *b2)
void printVariable(ostream *os, FileInfo *finfo, VariableInfo vinfo)
static Region * findCodeRegion(RegionMap &codeMap, VMA vma)
map< Block *, bool > BlockSet
bool realpath(std::string &pathNm) const
void printLoadModuleEnd(ostream *os)
void printFileBegin(ostream *os, FileInfo *finfo)
static bool LoopInfoLessThan(LoopInfo *l1, LoopInfo *l2)
void makeStructure(string filename, ostream *outFile, ostream *gapsFile, string gaps_filenm, string search_path, Struct::Options &structOpts)
void addStmtToTree(TreeNode *root, HPC::StringTable &strTab, RealPathMgr *realPath, VMA vma, int len, string &filenm, SrcFile::ln line)
static bool LoopTreeLessThan(LoopTreeNode *n1, LoopTreeNode *n2)
const std::string & index2str(long index)
static const string & unknown_link
static void mergeIrredLoops(WorkEnv &, LoopInfo *)
map< VMA, Region * > RegionMap
std::string getFileName()
static BAnal::Struct::Options opts
std::pair< iterator, bool > insert(const VMA beg, const VMA end)
std::string toString() const
void printFileEnd(ostream *os, FileInfo *finfo)
void mergeInlineEdge(TreeNode *dest, FLPIndex flp, TreeNode *src)
map< string, FileInfo * > FileMap
ParseAPI::Function * func
const std::string & searchPaths() const
void mergeInlineTree(TreeNode *dest, TreeNode *src)
static bool WorkItemGreaterThan(WorkItem *w1, WorkItem *w2)
#define SYMTAB_ARCH_CUDA(symtab)
static void computeGaps(VMAIntervalSet &, VMAIntervalSet &, VMA, VMA)
static void makeCodeMap(RegionMap &codeMap)
static void doBlock(WorkEnv &, GroupInfo *, ParseAPI::Function *, BlockSet &, Block *, TreeNode *)
SymtabAPI::Function * sym_func
static void makeVariables(ostream *outFile)
bool getLineInfo(VMA vma, string &filenm, uint &line)
static Symtab * the_symtab
void printStructFileBegin(ostream *os, ostream *gaps, string filenm)
map< VMA, HeaderInfo > HeaderList
static bool EdgeLessThan(Edge *e1, Edge *e2)
string basename(const char *fName)
static int const threshold
static TreeNode * deleteInlinePrefix(WorkEnv &, TreeNode *, Inline::InlineSeqn)
static void doCudaFunction(WorkEnv &, GroupInfo *, ParseAPI::Function *, TreeNode *)
static FileMap * makeSkeleton(CodeObject *, const string &)
vector< WorkItem * > WorkList
StmtInfo * findStmt(VMA vma)
static LoopInfo * findLoopHeader(WorkEnv &env, FileInfo *, GroupInfo *, ParseAPI::Function *, TreeNode *, Loop *, const string &)
#define MIN_BYTES_GLOBAL_VARIABLE
static void printWorkList(WorkList &, uint &, ostream *, ostream *, string &)
bool analyzeAddr(InlineSeqn &nodelist, VMA addr, RealPathMgr *realPath)
string demangleProcName(const std::string &name)
static VMA LoopMinEntryAddr(Loop *loop)