1 /* Copyright (C) 2021-2024 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 36 struct SrcInfo 37 { 38 DbeLine *src_line; 39 SrcInfo *included_from; 40 SrcInfo *next; 41 }; 42 43 struct PCInfo 44 { 45 int64_t offset; 46 int64_t size; 47 SrcInfo *src_info; 48 }; 49 50 Function::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 91 Function::~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 115 char * 116 Function::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 157 uint64_t 158 Function::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 165 Histable * 166 Function::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 193 void 194 Function::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 226 void 227 Function::set_mangled_name (const char *string) 228 { 229 if (string) 230 { 231 free (mangled_name); 232 mangled_name = dbe_strdup (string); 233 } 234 } 235 236 void 237 Function::set_match_name (const char *string) 238 { 239 if (string) 240 { 241 free (match_name); 242 match_name = dbe_strdup (string); 243 } 244 } 245 246 void 247 Function::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 276 void 277 Function::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 415 SrcInfo * 416 Function::new_srcInfo () 417 { 418 SrcInfo *t = new SrcInfo (); 419 t->src_line = NULL; 420 t->included_from = NULL; 421 t->next = srcinfo_list; 422 srcinfo_list = t; 423 return t; 424 } 425 426 void 427 Function::pushSrcFile (SourceFile* source, int /*lineno*/) 428 { 429 // create new file stack 430 if (curr_srcfile == NULL) 431 { 432 curr_srcfile = source; 433 return; 434 } 435 436 SrcInfo *src_info = new_srcInfo (); 437 // In the ideal world, we need a DbeLine(III) here, 438 // but right now it would make us later believe that there are 439 // instructions generated for #include lines. To avoid that, 440 // we ask for a DbeLine(II). 441 src_info->src_line = curr_srcfile->find_dbeline (this, 0 /*lineno*/); 442 if (src_info->src_line) 443 { 444 src_info->included_from = curr_srcinfo; 445 curr_srcinfo = src_info; 446 } 447 curr_srcfile = source; 448 setSource (); 449 } 450 451 SourceFile * 452 Function::popSrcFile () 453 { 454 if (curr_srcinfo != NULL) 455 { 456 curr_srcfile = curr_srcinfo->src_line->sourceFile; 457 curr_srcinfo = curr_srcinfo->included_from; 458 } 459 else 460 curr_srcfile = NULL; 461 return curr_srcfile; 462 } 463 464 void 465 Function::copy_PCInfo (Function *from) 466 { 467 if (line_first <= 0) 468 line_first = from->line_first; 469 if (line_last <= 0) 470 line_last = from->line_last; 471 if (def_source == NULL) 472 def_source = from->def_source; 473 for (int i = 0, sz = from->linetab ? from->linetab->size () : 0; i < sz; i++) 474 { 475 PCInfo *pcinf = from->linetab->fetch (i); 476 DbeLine *dbeLine = pcinf->src_info->src_line; 477 add_PC_info (pcinf->offset, dbeLine->lineno, dbeLine->sourceFile); 478 } 479 } 480 481 void 482 Function::add_PC_info (uint64_t offset, int lineno, SourceFile *cur_src) 483 { 484 if (lineno <= 0 || size < 0 || offset >= (uint64_t) size) 485 return; 486 if (cur_src == NULL) 487 cur_src = curr_srcfile ? curr_srcfile : def_source; 488 if (linetab == NULL) 489 linetab = new Vector<PCInfo*>; 490 491 int left = 0; 492 int right = linetab->size () - 1; 493 DbeLine *dbeline; 494 while (left <= right) 495 { 496 int x = (left + right) / 2; 497 PCInfo *pcinf = linetab->fetch (x); 498 uint64_t pcinf_offset = ((uint64_t) pcinf->offset); 499 if (offset == pcinf_offset) 500 { 501 dbeline = cur_src->find_dbeline (this, lineno); 502 dbeline->init_Offset (offset); 503 pcinf->src_info->src_line = dbeline; 504 // Ignore duplicate offset 505 return; 506 } 507 else if (offset > pcinf_offset) 508 left = x + 1; 509 else 510 right = x - 1; 511 } 512 PCInfo *pcinfo = new PCInfo; 513 pcinfo->offset = offset; 514 515 // Form new SrcInfo 516 SrcInfo *srcInfo = new_srcInfo (); 517 dbeline = cur_src->find_dbeline (this, lineno); 518 dbeline->init_Offset (offset); 519 srcInfo->src_line = dbeline; 520 // For now don't build included_from list. 521 // We need better compiler support for that. 522 //srcInfo->included_from = curr_srcinfo; 523 srcInfo->included_from = NULL; 524 pcinfo->src_info = srcInfo; 525 526 // Update the size of the current line in both structures: 527 // current PCInfo and corresponding DbeLine. 528 if (left < linetab->size ()) 529 pcinfo->size = linetab->fetch (left)->offset - offset; 530 else 531 pcinfo->size = size - offset; 532 pcinfo->src_info->src_line->size += pcinfo->size; 533 534 // If not the first line, update the size of the previous line 535 if (left > 0) 536 { 537 PCInfo *pcinfo_prev = linetab->fetch (left - 1); 538 int64_t delta = (offset - pcinfo_prev->offset) - pcinfo_prev->size; 539 pcinfo_prev->size += delta; 540 pcinfo_prev->src_info->src_line->size += delta; 541 } 542 543 linetab->insert (left, pcinfo); 544 if (cur_src == def_source) 545 { 546 if (line_first <= 0) 547 setLineFirst (lineno); 548 if (line_last <= 0 || lineno > line_last) 549 line_last = lineno; 550 } 551 } 552 553 PCInfo * 554 Function::lookup_PCInfo (uint64_t offset) 555 { 556 module->read_stabs (); 557 if (linetab == NULL) 558 linetab = new Vector<PCInfo*>; 559 560 int left = 0; 561 int right = linetab->size () - 1; 562 while (left <= right) 563 { 564 int x = (left + right) / 2; 565 PCInfo *pcinfo = linetab->fetch (x); 566 if (offset >= ((uint64_t) pcinfo->offset)) 567 { 568 if (offset < (uint64_t) (pcinfo->offset + pcinfo->size)) 569 return pcinfo; 570 left = x + 1; 571 } 572 else 573 right = x - 1; 574 } 575 return NULL; 576 } 577 578 DbeInstr* 579 Function::mapLineToPc (DbeLine *dbeLine) 580 { 581 if (dbeLine && linetab) 582 { 583 DbeLine *dbl = dbeLine->dbeline_base; 584 for (int i = 0, sz = linetab->size (); i < sz; i++) 585 { 586 PCInfo *pcinfo = linetab->get (i); 587 if (pcinfo->src_info 588 && (pcinfo->src_info->src_line->dbeline_base == dbl)) 589 { 590 DbeInstr *dbeInstr = find_dbeinstr (PCLineFlag, pcinfo->offset); 591 if (dbeInstr) 592 { 593 dbeInstr->lineno = dbeLine->lineno; 594 return dbeInstr; 595 } 596 } 597 } 598 } 599 return NULL; 600 } 601 602 DbeLine* 603 Function::mapPCtoLine (uint64_t addr, SourceFile *src) 604 { 605 PCInfo *pcinfo = lookup_PCInfo (addr); 606 if (pcinfo == NULL) 607 { 608 if (defaultDbeLine == NULL) 609 defaultDbeLine = getDefSrc ()->find_dbeline (this, 0); 610 return defaultDbeLine; 611 } 612 DbeLine *dbeline = pcinfo->src_info->src_line; 613 614 // If source-context is not specified return the line 615 // from which this pc has been generated. 616 if (src == NULL) 617 return dbeline; 618 if (dbeline->sourceFile == src) 619 return dbeline->dbeline_base; 620 return src->find_dbeline (this, 0); 621 } 622 623 DbeInstr * 624 Function::find_dbeinstr (int flag, uint64_t addr) 625 { 626 DbeInstr *instr; 627 628 enum 629 { 630 FuncInstHTableSize = 128 631 }; 632 633 int hash = (((int) addr) >> 2) & (FuncInstHTableSize - 1); 634 if (instHTable == NULL) 635 { 636 if (size > 2048) 637 { 638 instHTable = new DbeInstr*[FuncInstHTableSize]; 639 for (int i = 0; i < FuncInstHTableSize; i++) 640 instHTable[i] = NULL; 641 } 642 } 643 else 644 { 645 instr = instHTable[hash]; 646 if (instr && instr->addr == addr && instr->flags == flag) 647 return instr; 648 } 649 650 int left = 0; 651 int right = instrs->size () - 1; 652 while (left <= right) 653 { 654 int index = (left + right) / 2; 655 instr = instrs->fetch (index); 656 if (addr < instr->addr) 657 right = index - 1; 658 else if (addr > instr->addr) 659 left = index + 1; 660 else 661 { 662 if (flag == instr->flags) 663 { 664 if (instHTable) 665 instHTable[hash] = instr; 666 return instr; 667 } 668 else if (flag < instr->flags) 669 right = index - 1; 670 else 671 left = index + 1; 672 } 673 } 674 675 // None found, create a new one 676 instr = new DbeInstr (instr_id++, flag, this, addr); 677 instrs->insert (left, instr); 678 if (instHTable) 679 instHTable[hash] = instr; 680 return instr; 681 } 682 683 // LIBRARY_VISIBILITY 684 DbeInstr * 685 Function::create_hide_instr (DbeInstr *instr) 686 { 687 DbeInstr *new_instr = new DbeInstr (instr_id++, 0, this, instr->addr); 688 return new_instr; 689 } 690 691 uint64_t 692 Function::find_previous_addr (uint64_t addr) 693 { 694 if (addrs == NULL) 695 { 696 addrs = module->getAddrs (this); 697 if (addrs == NULL) 698 return addr; 699 } 700 701 int index = -1, not_found = 1; 702 703 enum 704 { 705 FuncAddrIndexHTableSize = 128 706 }; 707 int hash = (((int) addr) >> 2) & (FuncAddrIndexHTableSize - 1); 708 if (addrIndexHTable == NULL) 709 { 710 if (size > 2048) 711 { 712 addrIndexHTable = new int[FuncAddrIndexHTableSize]; 713 for (int i = 0; i < FuncAddrIndexHTableSize; i++) 714 addrIndexHTable[i] = -1; 715 } 716 } 717 else 718 { 719 index = addrIndexHTable[hash]; 720 if (index >= 0 && addrs->fetch (index) == addr) 721 not_found = 0; 722 } 723 724 int left = 0; 725 int right = addrs->size () - 1; 726 while (not_found && left <= right) 727 { 728 index = (left + right) / 2; 729 uint64_t addr_test = addrs->fetch (index); 730 if (addr < addr_test) 731 right = index - 1; 732 else if (addr > addr_test) 733 left = index + 1; 734 else 735 { 736 if (addrIndexHTable) 737 addrIndexHTable[hash] = index; 738 not_found = 0; 739 } 740 } 741 if (not_found) 742 return addr; 743 if (index > 0) 744 index--; 745 return addrs->fetch (index); 746 } 747 748 void 749 Function::setSource () 750 { 751 SourceFile *sf = module->getIncludeFile (); 752 if (sf == NULL) 753 sf = getDefSrc (); 754 if (def_source == NULL) 755 setDefSrc (sf); 756 if (sf == def_source) 757 return; 758 if (sources == NULL) 759 { 760 sources = new Vector<SourceFile*>; 761 sources->append (def_source); 762 sources->append (sf); 763 } 764 else if (sources->find (sf) < 0) 765 sources->append (sf); 766 } 767 768 void 769 Function::setDefSrc (SourceFile *sf) 770 { 771 if (sf) 772 { 773 def_source = sf; 774 if (line_first > 0) 775 add_PC_info (0, line_first, def_source); 776 } 777 } 778 779 void 780 Function::setLineFirst (int lineno) 781 { 782 if (lineno > 0) 783 { 784 line_first = lineno; 785 if (line_last <= 0) 786 line_last = lineno; 787 if (def_source) 788 add_PC_info (0, line_first, def_source); 789 } 790 } 791 792 Vector<SourceFile*> * 793 Function::get_sources () 794 { 795 if (module) 796 module->read_stabs (); 797 if (sources == NULL) 798 { 799 sources = new Vector<SourceFile*>; 800 sources->append (getDefSrc ()); 801 } 802 return sources; 803 } 804 805 SourceFile* 806 Function::getDefSrc () 807 { 808 if (module) 809 module->read_stabs (); 810 if (def_source == NULL) 811 setDefSrc (module->getMainSrc ()); 812 return def_source; 813 } 814 815 char * 816 Function::getDefSrcName () 817 { 818 SourceFile *sf = getDefSrc (); 819 if (sf) 820 return sf->dbeFile->getResolvedPath (); 821 if (module) 822 return module->file_name; 823 sf = dbeSession->get_Unknown_Source (); 824 return sf->get_name (); 825 } 826 827 #define cmpValue(a, b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1) 828 829 int 830 Function::func_cmp (Function *func, SourceFile *srcContext) 831 { 832 if (def_source != func->def_source) 833 { 834 if (srcContext == NULL) 835 srcContext = getDefSrc (); 836 if (def_source == srcContext) 837 return -1; 838 if (func->def_source == srcContext) 839 return 1; 840 return cmpValue (img_offset, func->img_offset); 841 } 842 843 if (line_first == func->line_first) 844 return cmpValue (img_offset, func->img_offset); 845 if (line_first <= 0) 846 { 847 if (func->line_first > 0) 848 return 1; 849 return cmpValue (img_offset, func->img_offset); 850 } 851 if (func->line_first <= 0) 852 return -1; 853 return cmpValue (line_first, func->line_first); 854 } 855 856 Vector<Histable*> * 857 Function::get_comparable_objs () 858 { 859 update_comparable_objs (); 860 if (comparable_objs || dbeSession->expGroups->size () <= 1 || module == NULL) 861 return comparable_objs; 862 if (module == NULL || module->loadobject == NULL) 863 return NULL; 864 Vector<Histable*> *comparableModules = module->get_comparable_objs (); 865 if (comparableModules == NULL) 866 { 867 return NULL; 868 } 869 comparable_objs = new Vector<Histable*>(comparableModules->size ()); 870 for (long i = 0, sz = comparableModules->size (); i < sz; i++) 871 { 872 Function *func = NULL; 873 comparable_objs->store (i, func); 874 Module *mod = (Module*) comparableModules->fetch (i); 875 if (mod == NULL) 876 continue; 877 if (mod == module) 878 func = this; 879 else 880 { 881 for (long i1 = 0, sz1 = VecSize (mod->functions); i1 < sz1; i1++) 882 { 883 Function *f = mod->functions->get (i1); 884 if ((f->comparable_objs == NULL) 885 && (strcmp (f->comparable_name, comparable_name) == 0)) 886 { 887 func = f; 888 func->comparable_objs = comparable_objs; 889 break; 890 } 891 } 892 } 893 comparable_objs->store (i, func); 894 } 895 Vector<Histable*> *comparableLoadObjs = 896 module->loadobject->get_comparable_objs (); 897 if (VecSize (comparableLoadObjs) == VecSize (comparable_objs)) 898 { 899 for (long i = 0, sz = VecSize (comparableLoadObjs); i < sz; i++) 900 { 901 LoadObject *lo = (LoadObject *) comparableLoadObjs->get (i); 902 Function *func = (Function *) comparable_objs->get (i); 903 if (func || (lo == NULL)) 904 continue; 905 if (module->loadobject == lo) 906 func = this; 907 else 908 { 909 for (long i1 = 0, sz1 = VecSize (lo->functions); i1 < sz1; i1++) 910 { 911 Function *f = lo->functions->fetch (i1); 912 if ((f->comparable_objs == NULL) 913 && (strcmp (f->comparable_name, comparable_name) == 0)) 914 { 915 func = f; 916 func->comparable_objs = comparable_objs; 917 break; 918 } 919 } 920 } 921 comparable_objs->store (i, func); 922 } 923 } 924 dump_comparable_objs (); 925 return comparable_objs; 926 } 927 928 JMethod::JMethod (uint64_t _id) : Function (_id) 929 { 930 mid = 0LL; 931 addr = (Vaddr) 0; 932 signature = NULL; 933 jni_function = NULL; 934 } 935 936 JMethod::~JMethod () 937 { 938 free (signature); 939 } 940 941 uint64_t 942 JMethod::get_addr () 943 { 944 if (addr != (Vaddr) 0) 945 return addr; 946 else 947 return Function::get_addr (); 948 } 949 950 typedef struct 951 { 952 size_t used_in; 953 size_t used_out; 954 } MethodField; 955 956 static void 957 write_buf (char* buf, char* str) 958 { 959 while ((*buf++ = *str++)); 960 } 961 962 /** Translate one field from the nane buffer. 963 * return how many chars were read from name and how many bytes were used in buf. 964 */ 965 static MethodField 966 translate_method_field (const char* name, char* buf) 967 { 968 MethodField out, t; 969 switch (*name) 970 { 971 case 'L': 972 name++; 973 out.used_in = 1; 974 out.used_out = 0; 975 while (*name != ';') 976 { 977 *buf = *name++; 978 if (*buf == '/') 979 *buf = '.'; 980 buf++; 981 out.used_in++; 982 out.used_out++; 983 } 984 out.used_in++; /* the ';' is also used. */ 985 break; 986 case 'Z': 987 write_buf (buf, NTXT ("boolean")); 988 out.used_out = 7; 989 out.used_in = 1; 990 break; 991 case 'B': 992 write_buf (buf, NTXT ("byte")); 993 out.used_out = 4; 994 out.used_in = 1; 995 break; 996 case 'C': 997 write_buf (buf, NTXT ("char")); 998 out.used_out = 4; 999 out.used_in = 1; 1000 break; 1001 case 'S': 1002 write_buf (buf, NTXT ("short")); 1003 out.used_out = 5; 1004 out.used_in = 1; 1005 break; 1006 case 'I': 1007 write_buf (buf, NTXT ("int")); 1008 out.used_out = 3; 1009 out.used_in = 1; 1010 break; 1011 case 'J': 1012 write_buf (buf, NTXT ("long")); 1013 out.used_out = 4; 1014 out.used_in = 1; 1015 break; 1016 case 'F': 1017 write_buf (buf, NTXT ("float")); 1018 out.used_out = 5; 1019 out.used_in = 1; 1020 break; 1021 case 'D': 1022 write_buf (buf, NTXT ("double")); 1023 out.used_out = 6; 1024 out.used_in = 1; 1025 break; 1026 case 'V': 1027 write_buf (buf, NTXT ("void")); 1028 out.used_out = 4; 1029 out.used_in = 1; 1030 break; 1031 case '[': 1032 t = translate_method_field (name + 1, buf); 1033 write_buf (buf + t.used_out, NTXT ("[]")); 1034 out.used_out = t.used_out + 2; 1035 out.used_in = t.used_in + 1; 1036 break; 1037 default: 1038 out.used_out = 0; 1039 out.used_in = 0; 1040 } 1041 return out; 1042 } 1043 1044 /** 1045 * translate method name to full method signature 1046 * into the output buffer (buf). 1047 * ret_type - true for printing result type 1048 */ 1049 static bool 1050 translate_method (char* mname, char *signature, bool ret_type, char* buf) 1051 { 1052 MethodField p; 1053 size_t l; 1054 int first = 1; 1055 if (signature == NULL) 1056 return false; 1057 1058 const char *c = strchr (signature, ')'); 1059 if (c == NULL) 1060 return false; 1061 if (ret_type) 1062 { 1063 p = translate_method_field (++c, buf); 1064 buf += p.used_out; 1065 *buf++ = ' '; 1066 } 1067 1068 l = strlen (mname); 1069 memcpy (buf, mname, l + 1); 1070 buf += l; 1071 // *buf++ = ' '; // space before () 1072 *buf++ = '('; 1073 1074 c = signature + 1; 1075 while (*c != ')') 1076 { 1077 if (!first) 1078 { 1079 *buf++ = ','; 1080 *buf++ = ' '; 1081 } 1082 first = 0; 1083 p = translate_method_field (c, buf); 1084 c += p.used_in; 1085 buf += p.used_out; 1086 } 1087 1088 *buf++ = ')'; 1089 *buf = '\0'; 1090 return true; 1091 } 1092 1093 void 1094 JMethod::set_name (char *string) 1095 { 1096 if (string == NULL) 1097 return; 1098 set_mangled_name (string); 1099 1100 char buf[MAXDBUF]; 1101 *buf = '\0'; 1102 if (translate_method (string, signature, false, buf)) 1103 { 1104 name = dbe_strdup (buf); // got translated string 1105 Dprintf (DUMP_JCLASS_READER, 1106 "JMethod::set_name: true name=%s string=%s signature=%s\n", 1107 STR (name), STR (string), STR (signature)); 1108 } 1109 else 1110 { 1111 name = dbe_strdup (string); 1112 Dprintf (DUMP_JCLASS_READER, 1113 "JMethod::set_name: false name=%s signature=%s\n", 1114 STR (name), STR (signature)); 1115 } 1116 set_match_name (name); 1117 set_comparable_name (name); 1118 } 1119 1120 bool 1121 JMethod::jni_match (Function *func) 1122 { 1123 if (func == NULL || (func->flags & FUNC_NOT_JNI) != 0) 1124 return false; 1125 if (jni_function == func) 1126 return true; 1127 1128 char *fname = func->get_name (); 1129 if ((func->flags & FUNC_JNI_CHECKED) == 0) 1130 { 1131 func->flags |= FUNC_JNI_CHECKED; 1132 if (strncmp (func->get_name (), NTXT ("Java_"), 5) != 0) 1133 { 1134 func->flags |= FUNC_NOT_JNI; 1135 return false; 1136 } 1137 } 1138 1139 char *d = name; 1140 char *s = fname + 5; 1141 while (*d && *d != '(' && *d != ' ') 1142 { 1143 if (*d == '.') 1144 { 1145 if (*s++ != '_') 1146 return false; 1147 d++; 1148 } 1149 else if (*d == '_') 1150 { 1151 if (*s++ != '_') 1152 return false; 1153 if (*s++ != '1') 1154 return false; 1155 d++; 1156 } 1157 else if (*d++ != *s++) 1158 return false; 1159 } 1160 jni_function = func; 1161 return true; 1162 } 1163