1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <assert.h> 23#include <string.h> 24#include <ctype.h> 25 26#include "demangle.h" 27#include "util.h" 28#include "DbeSession.h" 29#include "Function.h" 30#include "Module.h" 31#include "LoadObject.h" 32#include "Settings.h" 33#include "DbeFile.h" 34#include "DbeView.h" 35 36struct SrcInfo 37{ 38 DbeLine *src_line; 39 SrcInfo *included_from; 40 SrcInfo *next; 41}; 42 43struct PCInfo 44{ 45 int64_t offset; 46 int64_t size; 47 SrcInfo *src_info; 48}; 49 50Function::Function (uint64_t _id) 51{ 52 id = _id; 53 instr_id = id << 32; 54 derivedNode = NULL; 55 module = NULL; 56 line_first = line_last = -1; 57 isOutlineFunction = false; 58 name = NULL; 59 mangled_name = NULL; 60 match_name = NULL; 61 comparable_name = NULL; 62 img_fname = NULL; 63 img_offset = 0; 64 chksum = 0; 65 flags = 0; 66 size = 0; 67 save_addr = FUNC_NO_SAVE; 68 linetab = NULL; 69 def_source = NULL; 70 indexStabsLink = NULL; 71 elfSym = NULL; 72 sources = NULL; 73 instrs = new Vector<DbeInstr*>; 74 addrs = NULL; 75 name_buf = NULL; 76 current_name_format = Histable::NA; 77 curr_srcinfo = NULL; 78 curr_srcfile = NULL; 79 srcinfo_list = NULL; 80 defaultDbeLine = NULL; 81 usrfunc = NULL; 82 alias = NULL; 83 instHTable = NULL; 84 addrIndexHTable = NULL; 85 isUsed = false; 86 isHideFunc = false; 87 inlinedSubr = NULL; 88 inlinedSubrCnt = 0; 89} 90 91Function::~Function () 92{ 93 free (mangled_name); 94 free (match_name); 95 free (comparable_name); 96 free (name_buf); 97 Destroy (linetab); 98 Destroy (instrs); 99 100 while (srcinfo_list) 101 { 102 SrcInfo *t = srcinfo_list; 103 srcinfo_list = t->next; 104 delete t; 105 } 106 delete sources; 107 delete addrs; 108 delete[] instHTable; 109 delete[] addrIndexHTable; 110 if (indexStabsLink) 111 // Remove a link to the current function 112 indexStabsLink->indexStabsLink = NULL; 113} 114 115char * 116Function::get_name (NameFormat nfmt) 117{ 118 if (nfmt == Histable::NA) 119 { 120 DbeView *dbeView = dbeSession->getView (0); 121 if (dbeView) 122 nfmt = dbeView->get_name_format (); 123 } 124 if (name_buf && (nfmt == current_name_format || nfmt == Histable::NA)) 125 return name_buf; 126 free (name_buf); 127 current_name_format = nfmt; 128 129 bool soname_fmt = Histable::soname_fmt (nfmt); 130 int fname_fmt = Histable::fname_fmt (nfmt); 131 if (fname_fmt == Histable::MANGLED) 132 name_buf = strdup (mangled_name); 133 else 134 { 135 if (module && module->is_fortran () 136 && (streq (name, "MAIN") || streq (name, "MAIN_"))) 137 name_buf = strdup (match_name); 138 else 139 name_buf = strdup (name); 140 141 if (fname_fmt == Histable::SHORT) 142 { 143 int i = get_paren (name_buf); 144 if (i != -1) 145 name_buf[i] = (char) 0; 146 } 147 } 148 if (soname_fmt) 149 { 150 char *fname = dbe_sprintf (NTXT ("%s [%s]"), name_buf, module->loadobject->get_name ()); 151 free (name_buf); 152 name_buf = fname; 153 } 154 return name_buf; 155} 156 157uint64_t 158Function::get_addr () 159{ 160 LoadObject *lo = module ? module->loadobject : NULL; 161 int seg_idx = lo ? lo->seg_idx : -1; 162 return MAKE_ADDRESS (seg_idx, img_offset); 163} 164 165Histable * 166Function::convertto (Histable_type type, Histable *obj) 167{ 168 Histable *res = NULL; 169 SourceFile *source = (SourceFile*) obj; 170 switch (type) 171 { 172 case INSTR: 173 res = find_dbeinstr (0, 0); 174 break; 175 case LINE: 176 { 177 // mapPCtoLine will implicitly read line info if necessary 178 res = mapPCtoLine (0, source); 179 break; 180 } 181 case FUNCTION: 182 res = this; 183 break; 184 case SOURCEFILE: 185 res = def_source; 186 break; 187 default: 188 assert (0); 189 } 190 return res; 191} 192 193void 194Function::set_name (char *string) 195{ 196 if (string == NULL) 197 return; 198 set_mangled_name (string); 199 200 // strip away any globalization prefix, and save result for matching 201 char *mname = string; 202 if (strncmp (string, "$X", 2) == 0 || strncmp (string, ".X", 2) == 0) 203 { 204 // name was globalized 205 char *n = strchr (string + 2, (int) '.'); 206 if (n != NULL) 207 mname = n + 1; 208 } 209 set_match_name (mname); 210 name = NULL; 211 if (module) 212 { 213 if (name == NULL && *match_name == '_') 214 { 215 int flag = DMGL_PARAMS; 216 if (module->lang_code == Sp_lang_java) 217 flag |= DMGL_JAVA; 218 name = cplus_demangle (match_name, flag); 219 } 220 } 221 if (name == NULL) // got demangled string 222 name = dbe_strdup (match_name); 223 set_comparable_name (name); 224} 225 226void 227Function::set_mangled_name (const char *string) 228{ 229 if (string) 230 { 231 free (mangled_name); 232 mangled_name = dbe_strdup (string); 233 } 234} 235 236void 237Function::set_match_name (const char *string) 238{ 239 if (string) 240 { 241 free (match_name); 242 match_name = dbe_strdup (string); 243 } 244} 245 246void 247Function::set_comparable_name (const char *string) 248{ 249 if (string) 250 { 251 free (comparable_name); 252 comparable_name = dbe_strdup (string); 253 254 // remove blanks from comparable_name 255 for (char *s = comparable_name, *s1 = comparable_name;;) 256 { 257 if (*s == 0) 258 { 259 *s1 = 0; 260 break; 261 } 262 else if (*s != ' ') 263 { 264 *s1 = *s; 265 s1++; 266 } 267 s++; 268 } 269 } 270} 271 272// This function looks at the name of a function, and determines whether 273// or not it may be a derived function -- outline, mtask, or clone -- 274// If it is, it writes the function name as demangled, 275// and sets a pointer to the function from which it was derived 276void 277Function::findDerivedFunctions () 278 279{ 280 MPFuncTypes ftype; 281 int index; 282 Function *fitem; 283 unsigned long long line_no; 284 char *namefmt; 285 char *subname = mangled_name; 286 char *demname; 287 288 // see if we've already done this 289 if ((flags & FUNC_FLAG_RESDER) != 0) 290 return; 291 292 // set flag for future 293 flags = flags | FUNC_FLAG_RESDER; 294 if (module == NULL) 295 return; 296 if (*subname != '_' || subname[1] != '$') // Not a specially named function 297 return; 298 299 // look for the current versions of naming 300 if (strncmp (subname + 2, NTXT ("d1"), 2) == 0) // doall function 301 ftype = MPF_DOALL; 302 else if (strncmp (subname + 2, "p1", 2) == 0) // parallel region function 303 ftype = MPF_PAR; 304 else if (strncmp (subname + 2, "l1", 2) == 0) // single thread loop setup 305 ftype = MPF_DOALL; 306 else if (strncmp (subname + 2, "s1", 2) == 0) // parallel section function 307 ftype = MPF_SECT; 308 else if (strncmp (subname + 2, "t1", 2) == 0) // task function 309 ftype = MPF_TASK; 310 else if (strncmp (subname + 2, "o1", 2) == 0) // outline function 311 { 312 ftype = MPF_OUTL; 313 isOutlineFunction = true; 314 } 315 else if (strncmp (subname + 2, "c1", 2) == 0) // clone function 316 ftype = MPF_CLONE; 317 else // Not an encoded name, just return 318 return; 319 320 // we know it's one of the above prefixes 321 char *sub = dbe_strdup (name + 4); // starting with base-26 number 322 char *p = sub; 323 324 // skip the base-26 number, and extract the line number 325 while (isalpha ((int) (*p)) != 0 && *p != 0) 326 p++; 327 line_no = atoll (p); 328 329 // skip past the number to to the . 330 while (*p != '.' && *p != 0) 331 p++; 332 if (*p == 0) 333 { 334 // can't be right 335 free (sub); 336 return; 337 } 338 // skip the trailing . 339 p++; 340 subname = p; 341 bool foundmatch = false; 342 343 // Find the function from which it is derived -- the one that matched subname 344 Vec_loop (Function*, module->functions, index, fitem) 345 { 346 if (streq (subname, fitem->mangled_name)) 347 { // found it 348 foundmatch = true; 349 usrfunc = fitem; 350 351 // set the derived node 352 if ((fitem->flags & FUNC_FLAG_RESDER) == 0) 353 // ensure that it, too, is resolved if derived 354 fitem->findDerivedFunctions (); 355 356 // Build a demangled name 357 switch (ftype) 358 { 359 case MPF_OUTL: 360 isOutlineFunction = true; 361 namefmt = GTXT ("%s -- outline code from line %lld [%s]"); 362 derivedNode = fitem->find_dbeinstr (PCLineFlag, line_no); 363 break; 364 case MPF_PAR: 365 namefmt = GTXT ("%s -- OMP parallel region from line %lld [%s]"); 366 break; 367 case MPF_DOALL: 368 namefmt = GTXT ("%s -- Parallel loop from line %lld [%s]"); 369 break; 370 case MPF_SECT: 371 namefmt = GTXT ("%s -- OMP sections from line %lld [%s]"); 372 break; 373 case MPF_CLONE: 374 // Note that clones are handled differently -- no line number and 375 // clones are NOT shown as called from the original 376 // so after constructing the name, just return 377 // later, establish link from clone to parent 378 demname = dbe_sprintf (GTXT ("%s -- cloned version [%s]"), 379 fitem->get_name (), name); 380 free (name); 381 // set the name to the demangled version 382 name = demname; 383 free (sub); 384 derivedNode = fitem->find_dbeinstr (PCLineFlag, line_no); 385 return; 386 case MPF_TASK: 387 namefmt = GTXT ("%s -- OMP task from line %lld [%s]"); 388 break; 389 default: 390 free (sub); 391 return; 392 393 } 394 395 // Finally, construct the demangled name 396 demname = dbe_sprintf (namefmt, fitem->get_name (), line_no, name); 397 free (name); 398 name = demname; 399 setLineFirst ((int) line_no); 400 break; 401 } 402 } 403 404 if (foundmatch == false && ftype == MPF_OUTL) 405 { 406 // Even if derived node was not found, we can demangle 407 demname = dbe_sprintf (GTXT ("%s -- outline code [%s]"), subname, 408 mangled_name); 409 free (name); 410 name = demname; 411 } 412 free (sub); 413} 414 415SrcInfo * 416Function::new_srcInfo () 417{ 418 SrcInfo *t = new SrcInfo (); 419 t->next = srcinfo_list; 420 srcinfo_list = t; 421 return t; 422} 423 424void 425Function::pushSrcFile (SourceFile* source, int /*lineno*/) 426{ 427 // create new file stack 428 if (curr_srcfile == NULL) 429 { 430 curr_srcfile = source; 431 return; 432 } 433 434 SrcInfo *src_info = new_srcInfo (); 435 // In the ideal world, we need a DbeLine(III) here, 436 // but right now it would make us later believe that there are 437 // instructions generated for #include lines. To avoid that, 438 // we ask for a DbeLine(II). 439 src_info->src_line = curr_srcfile->find_dbeline (this, 0 /*lineno*/); 440 if (src_info->src_line) 441 { 442 src_info->included_from = curr_srcinfo; 443 curr_srcinfo = src_info; 444 } 445 curr_srcfile = source; 446 setSource (); 447} 448 449SourceFile * 450Function::popSrcFile () 451{ 452 if (curr_srcinfo != NULL) 453 { 454 curr_srcfile = curr_srcinfo->src_line->sourceFile; 455 curr_srcinfo = curr_srcinfo->included_from; 456 } 457 else 458 curr_srcfile = NULL; 459 return curr_srcfile; 460} 461 462void 463Function::copy_PCInfo (Function *from) 464{ 465 if (line_first <= 0) 466 line_first = from->line_first; 467 if (line_last <= 0) 468 line_last = from->line_last; 469 if (def_source == NULL) 470 def_source = from->def_source; 471 for (int i = 0, sz = from->linetab ? from->linetab->size () : 0; i < sz; i++) 472 { 473 PCInfo *pcinf = from->linetab->fetch (i); 474 DbeLine *dbeLine = pcinf->src_info->src_line; 475 add_PC_info (pcinf->offset, dbeLine->lineno, dbeLine->sourceFile); 476 } 477} 478 479void 480Function::add_PC_info (uint64_t offset, int lineno, SourceFile *cur_src) 481{ 482 if (lineno <= 0 || size < 0 || offset >= (uint64_t) size) 483 return; 484 if (cur_src == NULL) 485 cur_src = curr_srcfile ? curr_srcfile : def_source; 486 if (linetab == NULL) 487 linetab = new Vector<PCInfo*>; 488 489 int left = 0; 490 int right = linetab->size () - 1; 491 DbeLine *dbeline; 492 while (left <= right) 493 { 494 int x = (left + right) / 2; 495 PCInfo *pcinf = linetab->fetch (x); 496 uint64_t pcinf_offset = ((uint64_t) pcinf->offset); 497 if (offset == pcinf_offset) 498 { 499 dbeline = cur_src->find_dbeline (this, lineno); 500 dbeline->init_Offset (offset); 501 pcinf->src_info->src_line = dbeline; 502 // Ignore duplicate offset 503 return; 504 } 505 else if (offset > pcinf_offset) 506 left = x + 1; 507 else 508 right = x - 1; 509 } 510 PCInfo *pcinfo = new PCInfo; 511 pcinfo->offset = offset; 512 513 // Form new SrcInfo 514 SrcInfo *srcInfo = new_srcInfo (); 515 dbeline = cur_src->find_dbeline (this, lineno); 516 dbeline->init_Offset (offset); 517 srcInfo->src_line = dbeline; 518 // For now don't build included_from list. 519 // We need better compiler support for that. 520 //srcInfo->included_from = curr_srcinfo; 521 srcInfo->included_from = NULL; 522 pcinfo->src_info = srcInfo; 523 524 // Update the size of the current line in both structures: 525 // current PCInfo and corresponding DbeLine. 526 if (left < linetab->size ()) 527 pcinfo->size = linetab->fetch (left)->offset - offset; 528 else 529 pcinfo->size = size - offset; 530 pcinfo->src_info->src_line->size += pcinfo->size; 531 532 // If not the first line, update the size of the previous line 533 if (left > 0) 534 { 535 PCInfo *pcinfo_prev = linetab->fetch (left - 1); 536 int64_t delta = (offset - pcinfo_prev->offset) - pcinfo_prev->size; 537 pcinfo_prev->size += delta; 538 pcinfo_prev->src_info->src_line->size += delta; 539 } 540 541 linetab->insert (left, pcinfo); 542 if (cur_src == def_source) 543 { 544 if (line_first <= 0) 545 setLineFirst (lineno); 546 if (line_last <= 0 || lineno > line_last) 547 line_last = lineno; 548 } 549} 550 551PCInfo * 552Function::lookup_PCInfo (uint64_t offset) 553{ 554 module->read_stabs (); 555 if (linetab == NULL) 556 linetab = new Vector<PCInfo*>; 557 558 int left = 0; 559 int right = linetab->size () - 1; 560 while (left <= right) 561 { 562 int x = (left + right) / 2; 563 PCInfo *pcinfo = linetab->fetch (x); 564 if (offset >= ((uint64_t) pcinfo->offset)) 565 { 566 if (offset < (uint64_t) (pcinfo->offset + pcinfo->size)) 567 return pcinfo; 568 left = x + 1; 569 } 570 else 571 right = x - 1; 572 } 573 return NULL; 574} 575 576DbeInstr* 577Function::mapLineToPc (DbeLine *dbeLine) 578{ 579 if (dbeLine && linetab) 580 { 581 DbeLine *dbl = dbeLine->dbeline_base; 582 for (int i = 0, sz = linetab->size (); i < sz; i++) 583 { 584 PCInfo *pcinfo = linetab->get (i); 585 if (pcinfo->src_info 586 && (pcinfo->src_info->src_line->dbeline_base == dbl)) 587 { 588 DbeInstr *dbeInstr = find_dbeinstr (PCLineFlag, pcinfo->offset); 589 if (dbeInstr) 590 { 591 dbeInstr->lineno = dbeLine->lineno; 592 return dbeInstr; 593 } 594 } 595 } 596 } 597 return NULL; 598} 599 600DbeLine* 601Function::mapPCtoLine (uint64_t addr, SourceFile *src) 602{ 603 PCInfo *pcinfo = lookup_PCInfo (addr); 604 if (pcinfo == NULL) 605 { 606 if (defaultDbeLine == NULL) 607 defaultDbeLine = getDefSrc ()->find_dbeline (this, 0); 608 return defaultDbeLine; 609 } 610 DbeLine *dbeline = pcinfo->src_info->src_line; 611 612 // If source-context is not specified return the line 613 // from which this pc has been generated. 614 if (src == NULL) 615 return dbeline; 616 if (dbeline->sourceFile == src) 617 return dbeline->dbeline_base; 618 return src->find_dbeline (this, 0); 619} 620 621DbeInstr * 622Function::find_dbeinstr (int flag, uint64_t addr) 623{ 624 DbeInstr *instr; 625 626 enum 627 { 628 FuncInstHTableSize = 128 629 }; 630 631 int hash = (((int) addr) >> 2) & (FuncInstHTableSize - 1); 632 if (instHTable == NULL) 633 { 634 if (size > 2048) 635 { 636 instHTable = new DbeInstr*[FuncInstHTableSize]; 637 for (int i = 0; i < FuncInstHTableSize; i++) 638 instHTable[i] = NULL; 639 } 640 } 641 else 642 { 643 instr = instHTable[hash]; 644 if (instr && instr->addr == addr && instr->flags == flag) 645 return instr; 646 } 647 648 int left = 0; 649 int right = instrs->size () - 1; 650 while (left <= right) 651 { 652 int index = (left + right) / 2; 653 instr = instrs->fetch (index); 654 if (addr < instr->addr) 655 right = index - 1; 656 else if (addr > instr->addr) 657 left = index + 1; 658 else 659 { 660 if (flag == instr->flags) 661 { 662 if (instHTable) 663 instHTable[hash] = instr; 664 return instr; 665 } 666 else if (flag < instr->flags) 667 right = index - 1; 668 else 669 left = index + 1; 670 } 671 } 672 673 // None found, create a new one 674 instr = new DbeInstr (instr_id++, flag, this, addr); 675 instrs->insert (left, instr); 676 if (instHTable) 677 instHTable[hash] = instr; 678 return instr; 679} 680 681// LIBRARY_VISIBILITY 682DbeInstr * 683Function::create_hide_instr (DbeInstr *instr) 684{ 685 DbeInstr *new_instr = new DbeInstr (instr_id++, 0, this, instr->addr); 686 return new_instr; 687} 688 689uint64_t 690Function::find_previous_addr (uint64_t addr) 691{ 692 if (addrs == NULL) 693 { 694 addrs = module->getAddrs (this); 695 if (addrs == NULL) 696 return addr; 697 } 698 699 int index = -1, not_found = 1; 700 701 enum 702 { 703 FuncAddrIndexHTableSize = 128 704 }; 705 int hash = (((int) addr) >> 2) & (FuncAddrIndexHTableSize - 1); 706 if (addrIndexHTable == NULL) 707 { 708 if (size > 2048) 709 { 710 addrIndexHTable = new int[FuncAddrIndexHTableSize]; 711 for (int i = 0; i < FuncAddrIndexHTableSize; i++) 712 addrIndexHTable[i] = -1; 713 } 714 } 715 else 716 { 717 index = addrIndexHTable[hash]; 718 if (index >= 0 && addrs->fetch (index) == addr) 719 not_found = 0; 720 } 721 722 int left = 0; 723 int right = addrs->size () - 1; 724 while (not_found && left <= right) 725 { 726 index = (left + right) / 2; 727 uint64_t addr_test = addrs->fetch (index); 728 if (addr < addr_test) 729 right = index - 1; 730 else if (addr > addr_test) 731 left = index + 1; 732 else 733 { 734 if (addrIndexHTable) 735 addrIndexHTable[hash] = index; 736 not_found = 0; 737 } 738 } 739 if (not_found) 740 return addr; 741 if (index > 0) 742 index--; 743 return addrs->fetch (index); 744} 745 746void 747Function::setSource () 748{ 749 SourceFile *sf = module->getIncludeFile (); 750 if (sf == NULL) 751 sf = getDefSrc (); 752 if (def_source == NULL) 753 setDefSrc (sf); 754 if (sf == def_source) 755 return; 756 if (sources == NULL) 757 { 758 sources = new Vector<SourceFile*>; 759 sources->append (def_source); 760 sources->append (sf); 761 } 762 else if (sources->find (sf) < 0) 763 sources->append (sf); 764} 765 766void 767Function::setDefSrc (SourceFile *sf) 768{ 769 if (sf) 770 { 771 def_source = sf; 772 if (line_first > 0) 773 add_PC_info (0, line_first, def_source); 774 } 775} 776 777void 778Function::setLineFirst (int lineno) 779{ 780 if (lineno > 0) 781 { 782 line_first = lineno; 783 if (line_last <= 0) 784 line_last = lineno; 785 if (def_source) 786 add_PC_info (0, line_first, def_source); 787 } 788} 789 790Vector<SourceFile*> * 791Function::get_sources () 792{ 793 if (module) 794 module->read_stabs (); 795 if (sources == NULL) 796 { 797 sources = new Vector<SourceFile*>; 798 sources->append (getDefSrc ()); 799 } 800 return sources; 801} 802 803SourceFile* 804Function::getDefSrc () 805{ 806 if (module) 807 module->read_stabs (); 808 if (def_source == NULL) 809 setDefSrc (module->getMainSrc ()); 810 return def_source; 811} 812 813char * 814Function::getDefSrcName () 815{ 816 SourceFile *sf = getDefSrc (); 817 if (sf) 818 return sf->dbeFile->getResolvedPath (); 819 if (module) 820 return module->file_name; 821 sf = dbeSession->get_Unknown_Source (); 822 return sf->get_name (); 823} 824 825#define cmpValue(a, b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1) 826 827int 828Function::func_cmp (Function *func, SourceFile *srcContext) 829{ 830 if (def_source != func->def_source) 831 { 832 if (srcContext == NULL) 833 srcContext = getDefSrc (); 834 if (def_source == srcContext) 835 return -1; 836 if (func->def_source == srcContext) 837 return 1; 838 return cmpValue (img_offset, func->img_offset); 839 } 840 841 if (line_first == func->line_first) 842 return cmpValue (img_offset, func->img_offset); 843 if (line_first <= 0) 844 { 845 if (func->line_first > 0) 846 return 1; 847 return cmpValue (img_offset, func->img_offset); 848 } 849 if (func->line_first <= 0) 850 return -1; 851 return cmpValue (line_first, func->line_first); 852} 853 854Vector<Histable*> * 855Function::get_comparable_objs () 856{ 857 update_comparable_objs (); 858 if (comparable_objs || dbeSession->expGroups->size () <= 1 || module == NULL) 859 return comparable_objs; 860 if (module == NULL || module->loadobject == NULL) 861 return NULL; 862 Vector<Histable*> *comparableModules = module->get_comparable_objs (); 863 if (comparableModules == NULL) 864 { 865 return NULL; 866 } 867 comparable_objs = new Vector<Histable*>(comparableModules->size ()); 868 for (long i = 0, sz = comparableModules->size (); i < sz; i++) 869 { 870 Function *func = NULL; 871 comparable_objs->store (i, func); 872 Module *mod = (Module*) comparableModules->fetch (i); 873 if (mod == NULL) 874 continue; 875 if (mod == module) 876 func = this; 877 else 878 { 879 for (long i1 = 0, sz1 = VecSize (mod->functions); i1 < sz1; i1++) 880 { 881 Function *f = mod->functions->get (i1); 882 if ((f->comparable_objs == NULL) 883 && (strcmp (f->comparable_name, comparable_name) == 0)) 884 { 885 func = f; 886 func->comparable_objs = comparable_objs; 887 break; 888 } 889 } 890 } 891 comparable_objs->store (i, func); 892 } 893 Vector<Histable*> *comparableLoadObjs = 894 module->loadobject->get_comparable_objs (); 895 if (VecSize (comparableLoadObjs) == VecSize (comparable_objs)) 896 { 897 for (long i = 0, sz = VecSize (comparableLoadObjs); i < sz; i++) 898 { 899 LoadObject *lo = (LoadObject *) comparableLoadObjs->get (i); 900 Function *func = (Function *) comparable_objs->get (i); 901 if (func || (lo == NULL)) 902 continue; 903 if (module->loadobject == lo) 904 func = this; 905 else 906 { 907 for (long i1 = 0, sz1 = VecSize (lo->functions); i1 < sz1; i1++) 908 { 909 Function *f = lo->functions->fetch (i1); 910 if ((f->comparable_objs == NULL) 911 && (strcmp (f->comparable_name, comparable_name) == 0)) 912 { 913 func = f; 914 func->comparable_objs = comparable_objs; 915 break; 916 } 917 } 918 } 919 comparable_objs->store (i, func); 920 } 921 } 922 dump_comparable_objs (); 923 return comparable_objs; 924} 925 926JMethod::JMethod (uint64_t _id) : Function (_id) 927{ 928 mid = 0LL; 929 addr = (Vaddr) 0; 930 signature = NULL; 931 jni_function = NULL; 932} 933 934JMethod::~JMethod () 935{ 936 free (signature); 937} 938 939uint64_t 940JMethod::get_addr () 941{ 942 if (addr != (Vaddr) 0) 943 return addr; 944 else 945 return Function::get_addr (); 946} 947 948typedef struct 949{ 950 size_t used_in; 951 size_t used_out; 952} MethodField; 953 954static void 955write_buf (char* buf, char* str) 956{ 957 while ((*buf++ = *str++)); 958} 959 960/** Translate one field from the nane buffer. 961 * return how many chars were read from name and how many bytes were used in buf. 962 */ 963static MethodField 964translate_method_field (const char* name, char* buf) 965{ 966 MethodField out, t; 967 switch (*name) 968 { 969 case 'L': 970 name++; 971 out.used_in = 1; 972 out.used_out = 0; 973 while (*name != ';') 974 { 975 *buf = *name++; 976 if (*buf == '/') 977 *buf = '.'; 978 buf++; 979 out.used_in++; 980 out.used_out++; 981 } 982 out.used_in++; /* the ';' is also used. */ 983 break; 984 case 'Z': 985 write_buf (buf, NTXT ("boolean")); 986 out.used_out = 7; 987 out.used_in = 1; 988 break; 989 case 'B': 990 write_buf (buf, NTXT ("byte")); 991 out.used_out = 4; 992 out.used_in = 1; 993 break; 994 case 'C': 995 write_buf (buf, NTXT ("char")); 996 out.used_out = 4; 997 out.used_in = 1; 998 break; 999 case 'S': 1000 write_buf (buf, NTXT ("short")); 1001 out.used_out = 5; 1002 out.used_in = 1; 1003 break; 1004 case 'I': 1005 write_buf (buf, NTXT ("int")); 1006 out.used_out = 3; 1007 out.used_in = 1; 1008 break; 1009 case 'J': 1010 write_buf (buf, NTXT ("long")); 1011 out.used_out = 4; 1012 out.used_in = 1; 1013 break; 1014 case 'F': 1015 write_buf (buf, NTXT ("float")); 1016 out.used_out = 5; 1017 out.used_in = 1; 1018 break; 1019 case 'D': 1020 write_buf (buf, NTXT ("double")); 1021 out.used_out = 6; 1022 out.used_in = 1; 1023 break; 1024 case 'V': 1025 write_buf (buf, NTXT ("void")); 1026 out.used_out = 4; 1027 out.used_in = 1; 1028 break; 1029 case '[': 1030 t = translate_method_field (name + 1, buf); 1031 write_buf (buf + t.used_out, NTXT ("[]")); 1032 out.used_out = t.used_out + 2; 1033 out.used_in = t.used_in + 1; 1034 break; 1035 default: 1036 out.used_out = 0; 1037 out.used_in = 0; 1038 } 1039 return out; 1040} 1041 1042/** 1043 * translate method name to full method signature 1044 * into the output buffer (buf). 1045 * ret_type - true for printing result type 1046 */ 1047static bool 1048translate_method (char* mname, char *signature, bool ret_type, char* buf) 1049{ 1050 MethodField p; 1051 size_t l; 1052 int first = 1; 1053 if (signature == NULL) 1054 return false; 1055 1056 const char *c = strchr (signature, ')'); 1057 if (c == NULL) 1058 return false; 1059 if (ret_type) 1060 { 1061 p = translate_method_field (++c, buf); 1062 buf += p.used_out; 1063 *buf++ = ' '; 1064 } 1065 1066 l = strlen (mname); 1067 memcpy (buf, mname, l + 1); 1068 buf += l; 1069 // *buf++ = ' '; // space before () 1070 *buf++ = '('; 1071 1072 c = signature + 1; 1073 while (*c != ')') 1074 { 1075 if (!first) 1076 { 1077 *buf++ = ','; 1078 *buf++ = ' '; 1079 } 1080 first = 0; 1081 p = translate_method_field (c, buf); 1082 c += p.used_in; 1083 buf += p.used_out; 1084 } 1085 1086 *buf++ = ')'; 1087 *buf = '\0'; 1088 return true; 1089} 1090 1091void 1092JMethod::set_name (char *string) 1093{ 1094 if (string == NULL) 1095 return; 1096 set_mangled_name (string); 1097 1098 char buf[MAXDBUF]; 1099 *buf = '\0'; 1100 if (translate_method (string, signature, false, buf)) 1101 { 1102 name = dbe_strdup (buf); // got translated string 1103 Dprintf (DUMP_JCLASS_READER, 1104 "JMethod::set_name: true name=%s string=%s signature=%s\n", 1105 STR (name), STR (string), STR (signature)); 1106 } 1107 else 1108 { 1109 name = dbe_strdup (string); 1110 Dprintf (DUMP_JCLASS_READER, 1111 "JMethod::set_name: false name=%s signature=%s\n", 1112 STR (name), STR (signature)); 1113 } 1114 set_match_name (name); 1115 set_comparable_name (name); 1116} 1117 1118bool 1119JMethod::jni_match (Function *func) 1120{ 1121 if (func == NULL || (func->flags & FUNC_NOT_JNI) != 0) 1122 return false; 1123 if (jni_function == func) 1124 return true; 1125 1126 char *fname = func->get_name (); 1127 if ((func->flags & FUNC_JNI_CHECKED) == 0) 1128 { 1129 func->flags |= FUNC_JNI_CHECKED; 1130 if (strncmp (func->get_name (), NTXT ("Java_"), 5) != 0) 1131 { 1132 func->flags |= FUNC_NOT_JNI; 1133 return false; 1134 } 1135 } 1136 1137 char *d = name; 1138 char *s = fname + 5; 1139 while (*d && *d != '(' && *d != ' ') 1140 { 1141 if (*d == '.') 1142 { 1143 if (*s++ != '_') 1144 return false; 1145 d++; 1146 } 1147 else if (*d == '_') 1148 { 1149 if (*s++ != '_') 1150 return false; 1151 if (*s++ != '1') 1152 return false; 1153 d++; 1154 } 1155 else if (*d++ != *s++) 1156 return false; 1157 } 1158 jni_function = func; 1159 return true; 1160} 1161