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 <unistd.h> 23 #include <ar.h> 24 #include <ctype.h> 25 #include <sys/param.h> 26 27 #include "util.h" 28 #include "DbeSession.h" 29 #include "Experiment.h" 30 #include "DataObject.h" 31 #include "Function.h" 32 #include "DbeView.h" 33 #include "MetricList.h" 34 #include "Module.h" 35 #include "ClassFile.h" 36 #include "LoadObject.h" 37 #include "Disasm.h" 38 #include "CompCom.h" 39 #include "Dwarf.h" 40 #include "DbeFile.h" 41 #include "PathTree.h" 42 #include "Elf.h" 43 44 Module::Module () 45 { 46 lang_code = Sp_lang_unknown; 47 flags = 0; 48 status = AE_NOTREAD; 49 openSourceFlag = AE_NOTREAD; 50 hexVisible = false; 51 disPath = NULL; 52 stabsPath = NULL; 53 stabsTmp = NULL; 54 disName = NULL; 55 stabsName = NULL; 56 indexStabsLink = NULL; 57 file_name = NULL; 58 functions = new Vector<Function*>; 59 loadobject = NULL; 60 dot_o_file = NULL; 61 main_source = dbeSession->get_Unknown_Source (); 62 srcContext = main_source; 63 includes = new Vector<SourceFile*>; 64 includes->append (main_source); 65 curr_inc = NULL; 66 fragmented = 0; 67 hwcprof = 0; 68 hdrOffset = 0; 69 hasDwarf = false; 70 hasStabs = false; 71 readStabs = false; 72 comComs = NULL; 73 infoList = NULL; 74 datatypes = NULL; 75 objStabs = NULL; 76 disasm = NULL; 77 comp_flags = NULL; 78 comp_dir = NULL; 79 linkerStabName = NULL; 80 disMTime = (time_t) 0; 81 stabsMTime = (time_t) 0; 82 real_timestamp = 0; 83 curr_timestamp = 0; 84 src_items = NULL; 85 dis_items = NULL; 86 data_items = NULL; 87 cur_dbev = NULL; 88 maximum = NULL; 89 maximum_inc = NULL; 90 empty = NULL; 91 inlinedSubr = NULL; 92 } 93 94 Module::~Module () 95 { 96 removeStabsTmp (); 97 delete includes; 98 if (comComs != NULL) 99 { 100 comComs->destroy (); 101 delete comComs; 102 } 103 free (comp_flags); 104 free (comp_dir); 105 free (linkerStabName); 106 free (disPath); 107 free (stabsPath); 108 free (disName); 109 free (stabsName); 110 delete functions; 111 free (file_name); 112 if (indexStabsLink) 113 // Remove a link to the current module 114 indexStabsLink->indexStabsLink = NULL; 115 116 if (dot_o_file) 117 { 118 delete dot_o_file->dbeFile; 119 delete dot_o_file; 120 } 121 delete src_items; 122 delete dis_items; 123 delete disasm; 124 free (inlinedSubr); 125 if (lang_code != Sp_lang_java) 126 delete dbeFile; 127 128 } 129 130 Stabs * 131 Module::openDebugInfo () 132 { 133 setFile (); 134 objStabs = loadobject->openDebugInfo (disPath); 135 return objStabs; 136 } 137 138 void 139 Module::removeStabsTmp () 140 { 141 // Remove temporary *.o (got from *.a) after reading Stabs 142 if (stabsTmp != NULL) 143 { 144 unlink (stabsTmp); 145 free (stabsTmp); 146 stabsTmp = NULL; 147 } 148 } 149 150 int64_t 151 Module::get_size () 152 { 153 Function *fp; 154 int index; 155 int64_t result = 0; 156 Vec_loop (Function*, functions, index, fp) 157 { 158 result += fp->size; 159 } 160 return result; 161 } 162 163 bool 164 Module::is_fortran () 165 { 166 return Stabs::is_fortran (lang_code); 167 } 168 169 SourceFile * 170 Module::findSource (const char *fname, bool create) 171 { 172 SourceFile *sf = NULL; 173 if (loadobject && loadobject->firstExp) 174 sf = loadobject->firstExp->get_source (fname); 175 if (sf == NULL) 176 sf = dbeSession->createSourceFile (fname); 177 for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++) 178 { 179 SourceFile *sf1 = includes->fetch (i); 180 if (sf == sf1) 181 return sf; 182 } 183 if (create) 184 { 185 if (includes == NULL) 186 includes = new Vector<SourceFile*>; 187 includes->append (sf); 188 return sf; 189 } 190 return NULL; 191 } 192 193 SourceFile * 194 Module::setIncludeFile (char *includeFile) 195 { 196 curr_inc = NULL; 197 if (includeFile) 198 curr_inc = findSource (includeFile, true); 199 return curr_inc; 200 } 201 202 char * 203 Module::anno_str (char *fnm) 204 { 205 char timebuf1[26], timebuf2[26]; 206 const time_t real_time = (time_t) (unsigned int) real_timestamp; 207 const time_t curr_time = (time_t) (unsigned int) curr_timestamp; 208 209 switch (status) 210 { 211 case AE_OK: 212 case AE_NOTREAD: 213 return NULL; 214 case AE_NOSRC: 215 return dbe_sprintf (GTXT ("Source file `%s' not readable"), 216 fnm ? fnm : file_name); 217 case AE_NOOBJ: 218 if (lang_code == Sp_lang_java) 219 { 220 Emsg *emsg = get_error (); 221 if (emsg) 222 { 223 char *s = dbe_strdup (emsg->get_msg ()); 224 remove_msg (emsg); 225 return s; 226 } 227 return dbe_sprintf (GTXT ("Object file `%s.class' not readable"), 228 name); 229 } 230 return dbe_sprintf (GTXT ("Object file `%s' not readable"), get_name ()); 231 case AE_NOLOBJ: 232 if (lang_code == Sp_lang_java) 233 return dbe_sprintf (GTXT ("Object file `%s' not readable"), 234 dbeFile ? dbeFile->get_name () : name); 235 return dbe_sprintf (GTXT ("Object file `%s' not readable"), loadobject->get_pathname ()); 236 case AE_NOSTABS: 237 return dbe_sprintf (GTXT ("Error reading line-number information in object `%s'; source annotation not available"), 238 stabsPath ? stabsPath : NTXT ("")); 239 case AE_NOSYMTAB: 240 return dbe_sprintf (GTXT ("Error reading symbol table in object `%s'; disassembly annotation not available"), 241 disPath ? disPath : NTXT ("")); 242 case AE_TIMESRC: 243 return dbe_sprintf (GTXT ("Warning! Source file `%s' is newer than the experiment data"), 244 main_source->dbeFile->getResolvedPath ()); 245 case AE_TIMEDIS: 246 return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), 247 disName ? disName : NTXT ("")); 248 case AE_TIMESTABS: 249 return dbe_sprintf (GTXT ("Warning! Object file `%s' is newer than the experiment data"), 250 stabsName ? stabsName : NTXT ("")); 251 case AE_TIMESTABS_DIFF: 252 snprintf (timebuf1, sizeof (timebuf1), NTXT ("%s"), ctime (&curr_time)); 253 snprintf (timebuf2, sizeof (timebuf2), NTXT ("%s"), ctime (&real_time)); 254 timebuf1[24] = timebuf2[24] = '\0'; 255 return dbe_sprintf (GTXT ("Warning! Object file `%s' is not the same one that was linked into executable.\n" 256 "\tObject file: `%s'\n\tcompiled on: %s\n" 257 "\tExecutable contains object file compiled on: %s"), 258 getResolvedObjectPath (), getResolvedObjectPath (), 259 timebuf1, timebuf2); 260 case AE_OTHER: 261 default: 262 return dbe_strdup (GTXT ("Annotation computation error")); 263 } 264 }//anno_str 265 266 LoadObject * 267 Module::createLoadObject (const char *lo_name) 268 { 269 LoadObject *lo = new LoadObject (lo_name); 270 lo->dbeFile->filetype |= DbeFile::F_DOT_O; 271 return lo; 272 } 273 274 static bool 275 tsIsNewer (time_t t1, time_t t2) 276 { 277 return t1 != 0 && t2 != 0 && t1 < t2; 278 } 279 280 Module::Anno_Errors 281 Module::checkTimeStamp (bool chkDis) 282 { 283 /* Check the linked and the real object timestamps due to bug #4796329 */ 284 if (real_timestamp && curr_timestamp && real_timestamp != curr_timestamp) 285 return AE_TIMESTABS_DIFF; 286 287 time_t srctime = main_source->getMTime (); 288 for (int index = 0; index < dbeSession->nexps (); index++) 289 { 290 time_t mtime = dbeSession->get_exp (index)->get_mtime (); 291 if (tsIsNewer (mtime, srctime)) 292 return AE_TIMESRC; 293 if (tsIsNewer (mtime, stabsMTime)) 294 return AE_TIMESTABS; 295 if (chkDis && tsIsNewer (mtime, disMTime)) 296 return AE_TIMEDIS; 297 } 298 return AE_OK; 299 }//checkTimeStamp 300 301 static size_t 302 get_ar_size (char *s, size_t len) 303 { 304 size_t sz = 0; 305 for (size_t i = 0; i < len; i++) 306 { 307 if (s[i] < '0' || s[i] > '9') 308 break; 309 sz = sz * 10 + (s[i] - '0'); 310 } 311 return sz; 312 } 313 314 static void 315 dump_hdr_field (char *nm, char *s, size_t len) 316 { 317 Dprintf (DEBUG_READ_AR, NTXT (" %s "), nm); 318 for (size_t i = 0; i < len; i++) 319 Dprintf (DEBUG_READ_AR, "%c", isprint (s[i]) ? s[i] : '?'); 320 Dprintf (DEBUG_READ_AR, NTXT (" ")); 321 for (size_t i = 0; i < len; i++) 322 Dprintf (DEBUG_READ_AR, NTXT (" %d"), s[i]); 323 Dprintf (DEBUG_READ_AR, NTXT (" \n")); 324 } 325 326 static void 327 dump_ar_hdr (int lineNum, struct ar_hdr *hdr) 328 { 329 if (DEBUG_READ_AR) 330 { 331 Dprintf (DEBUG_READ_AR, NTXT ("Module::read_ar %d\n"), lineNum); 332 dump_hdr_field (NTXT ("ar_name"), hdr->ar_name, sizeof (hdr->ar_name)); 333 dump_hdr_field (NTXT ("ar_date"), hdr->ar_date, sizeof (hdr->ar_date)); 334 dump_hdr_field (NTXT ("ar_uid"), hdr->ar_uid, sizeof (hdr->ar_uid)); 335 dump_hdr_field (NTXT ("ar_gid"), hdr->ar_gid, sizeof (hdr->ar_gid)); 336 dump_hdr_field (NTXT ("ar_mode"), hdr->ar_mode, sizeof (hdr->ar_mode)); 337 dump_hdr_field (NTXT ("ar_size"), hdr->ar_size, sizeof (hdr->ar_size)); 338 dump_hdr_field (NTXT ("ar_fmag"), hdr->ar_fmag, sizeof (hdr->ar_fmag)); 339 } 340 } 341 342 bool 343 Module::read_ar (int ar, int obj, char *obj_base) 344 { 345 struct ar_hdr hdr; // Archive header 346 char magic[SARMAG]; // Magic string from archive 347 Dprintf (DEBUG_READ_AR, "Module::read_ar %d %p %s %s \n", __LINE__, 348 this, STR (obj_base), STR (get_name ())); 349 // Check the magic string 350 if ((read_from_file (ar, magic, SARMAG) != SARMAG) 351 || strncmp (magic, ARMAG, SARMAG)) 352 return false; 353 354 // Read and skip the first file in the archive (index file to ld) 355 if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) 356 return false; 357 DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); 358 if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), SEEK_CUR) 359 == -1) 360 return false; 361 362 // Read the string file where it keeps long file names (if exist) 363 if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) 364 return false; 365 DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); 366 char *longnames = NULL; // Area with names longer than ~13 367 size_t longnames_size = 0; 368 if (!strncmp (hdr.ar_name, NTXT ("//"), 2)) 369 { 370 longnames_size = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); 371 longnames = (char *) malloc (longnames_size + 1); 372 int64_t cnt = read_from_file (ar, longnames, longnames_size); 373 if (cnt != (int64_t) longnames_size) 374 { 375 free (longnames); 376 return false; 377 } 378 longnames[longnames_size] = 0; 379 } 380 else 381 // back out, no long file names 382 lseek (ar, -(sizeof (hdr)), SEEK_CUR); 383 384 // Search the ar for the object file name 385 char ar_buf[sizeof (hdr.ar_name) + 1]; 386 ar_buf[sizeof (hdr.ar_name)] = 0; 387 while (1) 388 { 389 if (read_from_file (ar, &hdr, sizeof (hdr)) != sizeof (hdr)) 390 break; 391 DEBUG_CODE dump_ar_hdr (__LINE__, &hdr); 392 char *ar_name; 393 if (hdr.ar_name[0] != '/') 394 { // Name is in the header 395 for (size_t i = 0; i < sizeof (hdr.ar_name); i++) 396 { 397 if (hdr.ar_name[i] == '/') 398 { 399 ar_buf[i] = 0; 400 break; 401 } 402 ar_buf[i] = hdr.ar_name[i]; 403 } 404 ar_name = ar_buf; 405 } 406 else if (hdr.ar_name[1] == ' ') 407 { // Name is blank 408 ar_buf[0] = 0; 409 ar_name = ar_buf; 410 } 411 else 412 { // Name is in the string table 413 if (longnames == NULL) 414 break; 415 size_t offset = get_ar_size (hdr.ar_name + 1, 416 sizeof (hdr.ar_name) - 1); 417 if (offset >= longnames_size) 418 break; 419 for (size_t i = offset; i < longnames_size; i++) 420 { 421 if (longnames[i] == '/') 422 { 423 longnames[i] = 0; 424 break; 425 } 426 } 427 ar_name = longnames + offset; 428 } 429 Dprintf (DEBUG_READ_AR, "Module::read_ar %d ar_name=%s\n", __LINE__, 430 ar_name); 431 432 if (streq (ar_name, obj_base)) 433 { // create object file 434 free (longnames); 435 for (size_t objsize = get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)); 436 objsize > 0;) 437 { 438 char buf[MAXPATHLEN]; 439 size_t n = objsize < sizeof (buf) ? objsize : sizeof (buf); 440 int64_t cnt = read_from_file (ar, buf, n); 441 if (cnt != (int64_t) n) 442 return false; 443 cnt = write (obj, buf, n); 444 if (cnt != (int64_t) n) 445 return false; 446 objsize -= n; 447 } 448 return true; 449 } 450 if (lseek (ar, get_ar_size (hdr.ar_size, sizeof (hdr.ar_size)), 451 SEEK_CUR) == -1) 452 break; 453 } 454 free (longnames); 455 return false; 456 } 457 458 static char * 459 get_obj_name_from_lib (char *nm) 460 { 461 char *base = strrchr (nm, '('); 462 if (base) 463 { 464 size_t last = strlen (base) - 1; 465 if (base[last] == ')') 466 return base; 467 } 468 return NULL; 469 } 470 471 bool 472 Module::setFile () 473 { 474 if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0) 475 return true; 476 if ((loadobject->dbeFile->filetype & DbeFile::F_FICTION) != 0) 477 return false; 478 if ((flags & MOD_FLAG_UNKNOWN) != 0) 479 return true; 480 481 if (lang_code == Sp_lang_java) 482 { 483 if (dbeFile->get_need_refind ()) 484 { 485 char *fnm = dbeFile->get_location (); 486 stabsPath = dbe_strdup (fnm); 487 stabsName = dbe_strdup (fnm); 488 disPath = dbe_strdup (fnm); 489 disName = dbe_strdup (fnm); 490 stabsMTime = dbeFile->sbuf.st_mtime; 491 } 492 return dbeFile->get_location () != NULL; 493 } 494 495 if (dbeFile == NULL) 496 { 497 char *objname = get_obj_name_from_lib (name); 498 if (objname) 499 { 500 // in the format of libpath(obj) 501 objname = dbe_strdup (objname + 1); 502 size_t last = strlen (objname) - 1; 503 objname[last] = '\0'; 504 } 505 dbeFile = new DbeFile (objname ? objname : name); 506 free (objname); 507 dbeFile->filetype |= DbeFile::F_DOT_O; 508 } 509 if (dbeFile->get_need_refind ()) 510 { 511 disMTime = (time_t) 0; 512 stabsMTime = (time_t) 0; 513 free (disName); 514 free (stabsName); 515 disName = NULL; 516 stabsName = NULL; 517 518 // Find the Executable/Shared-Object file of module 519 char *path = loadobject->dbeFile->get_location (); 520 if (path) 521 { 522 disPath = strdup (path); 523 disName = strdup (path); 524 disMTime = loadobject->dbeFile->sbuf.st_mtime; 525 } 526 527 char *objname = get_obj_name_from_lib (name); 528 if (objname) 529 { 530 // in the format of libpath(obj) 531 char *namebuf = dbe_strdup (name); 532 char *base = namebuf + (objname - name); 533 *base = '\0'; 534 base++; 535 size_t last = strlen (base) - 1; 536 base[last] = '\0'; 537 stabsTmp = dbeSession->get_tmp_file_name (base, false); 538 dbeSession->tmp_files->append (strdup (stabsTmp)); 539 540 DbeFile *dbf = dbeSession->getDbeFile (namebuf, 541 DbeFile::F_DOT_A_LIB | DbeFile::F_FILE); 542 path = dbf->get_location (); 543 int ar = -1, obj = -1; 544 if (path != NULL) 545 { 546 ar = open64 (path, O_RDONLY | O_LARGEFILE); 547 if (ar != -1) 548 obj = open64 (stabsTmp, O_CREAT | O_WRONLY | O_LARGEFILE, 0600); 549 } 550 if (ar != -1 && obj != -1 && read_ar (ar, obj, base)) 551 { 552 dbeFile->set_location (stabsTmp); 553 dbeFile->check_access (stabsTmp); // init 'sbuf' 554 dbeFile->sbuf.st_mtime = 0; // Don't check timestamps 555 dbeFile->container = dbf; 556 stabsPath = strdup (stabsTmp); 557 stabsName = strdup (path); 558 stabsMTime = dbeFile->sbuf.st_mtime; 559 } 560 else 561 { 562 removeStabsTmp (); 563 objname = NULL; 564 } 565 if (ar != -1) 566 close (ar); 567 if (obj != -1) 568 close (obj); 569 free (namebuf); 570 } 571 if (objname == NULL) 572 { 573 path = dbeFile->get_location (); 574 if (path != NULL) 575 { 576 stabsPath = strdup (path); 577 stabsName = strdup (path); 578 stabsMTime = hasDwarf ? 0 : dbeFile->sbuf.st_mtime; 579 } 580 } 581 582 // First, try to access the symbol table of the module itself 583 // If failed, access the symbol table of the executable 584 if (stabsPath == NULL) 585 { 586 if (disPath == NULL) 587 return false; 588 stabsPath = strdup (disPath); 589 stabsName = strdup (disName); 590 stabsMTime = disMTime; 591 } 592 else if (disPath == NULL) 593 { 594 disPath = strdup (stabsPath); 595 disName = strdup (stabsName); 596 disMTime = stabsMTime; 597 } 598 } 599 return stabsPath != NULL; 600 } 601 602 // openStabs -- open mappings from PCs to source lines 603 bool 604 Module::openStabs (bool all) 605 { 606 if ((loadobject->flags & SEG_FLAG_DYNAMIC) != 0 607 || (flags & MOD_FLAG_UNKNOWN) != 0) 608 return true; 609 if (loadobject->platform == Java) 610 { 611 setIncludeFile (NULL); 612 readFile (); 613 return ( status == AE_OK); 614 } 615 if (readStabs) 616 return true; 617 618 // Read Stabs info. 619 int64_t Inode = main_source->getInode (); 620 char *fname = strrchr (file_name, (int) '/'); 621 char *mname = strrchr (main_source->get_name (), (int) '/'); 622 if (fname && mname && !streq (fname, mname)) 623 { 624 SourceFile *sf = findSource (file_name, false); 625 if (sf != NULL) 626 Inode = sf->getInode (); 627 } 628 629 comComs = new Vector<ComC*>; 630 Stabs *stabs = openDebugInfo (); 631 if (stabs == NULL) 632 return false; 633 int st = stabs->read_stabs (Inode, this, comComs, true); 634 if (!hasDwarf && hasStabs && !streq (stabsPath, disPath)) 635 { 636 // Read stabs from .o file 637 if (dot_o_file == NULL) 638 { 639 if (dbeFile->get_location ()) 640 { 641 dot_o_file = createLoadObject (dbeFile->get_name ()); 642 dot_o_file->dbeFile->set_location (dbeFile->get_location ()); 643 dot_o_file->dbeFile->sbuf = dbeFile->sbuf; 644 dot_o_file->dbeFile->container = dbeFile->container; 645 } 646 } 647 if (dot_o_file 648 && dot_o_file->sync_read_stabs () == LoadObject::ARCHIVE_SUCCESS) 649 { 650 Stabs *stabs_o = dot_o_file->objStabs; 651 if (stabs_o) 652 { 653 st = stabs_o->read_stabs (Inode, this, 654 comComs->size () > 0 ? NULL : comComs); 655 Elf *elf_o = stabs_o->openElf (false); 656 if (elf_o->dwarf) 657 stabs->read_dwarf_from_dot_o (this); 658 } 659 } 660 } 661 if (all) 662 read_hwcprof_info (); 663 664 readStabs = true; 665 return st == Stabs::DBGD_ERR_NONE; 666 } 667 668 char * 669 Module::get_disasm (uint64_t inst_address, uint64_t end_address, 670 uint64_t start_address, uint64_t address, int64_t &inst_size) 671 { 672 return disasm->get_disasm (inst_address, end_address, start_address, 673 address, inst_size); 674 } 675 676 void 677 Module::read_stabs (bool all) 678 { 679 if (openSourceFlag == AE_NOTREAD) 680 { 681 openSourceFlag = AE_OK; 682 if (lang_code == Sp_lang_java) 683 { 684 char *clpath = file_name; 685 if (clpath == NULL || strcmp (clpath, "<Unknown>") == 0) 686 clpath = ClassFile::get_java_file_name (name, false); 687 main_source = findSource (clpath, true); 688 main_source->dbeFile->filetype |= DbeFile::F_JAVA_SOURCE; 689 if (clpath != file_name) 690 free (clpath); 691 } 692 else 693 main_source = findSource (file_name, true); 694 if (setFile ()) 695 openStabs (all); 696 } 697 } 698 699 bool 700 Module::openDisPC () 701 { 702 if (disasm == NULL) 703 { 704 if (!(loadobject->flags & SEG_FLAG_DYNAMIC) && loadobject->platform != Java) 705 { 706 // Read Stabs & Symbol tables 707 if (openDebugInfo () == NULL) 708 return false; 709 if (!objStabs->read_symbols (functions)) 710 return false; 711 } 712 disasm = new Disasm (loadobject->platform, objStabs); 713 } 714 return true; 715 } 716 717 static SourceFile *cmpSrcContext; // Use only for func_cmp 718 719 static int 720 func_cmp (const void *a, const void *b) 721 { 722 Function *fp1 = *((Function **) a); 723 Function *fp2 = *((Function **) b); 724 return fp1->func_cmp (fp2, cmpSrcContext); 725 } 726 727 bool 728 Module::computeMetrics (DbeView *dbev, Function *func, MetricList *metrics, 729 Histable::Type type, bool src_metric, 730 bool func_scope, SourceFile *source) 731 { 732 name_idx = metrics->get_listorder (NTXT ("name"), Metric::STATIC); 733 if (name_idx < 0) 734 { 735 metrics->print_metric_list (stderr, 736 GTXT ("Fatal: no name metric in Module::computeMetrics mlist:\n"), 737 1); 738 abort (); 739 } 740 741 // Now find the metrics for size and address, if present 742 size_index = metrics->get_listorder (NTXT ("size"), Metric::STATIC); 743 addr_index = metrics->get_listorder (NTXT ("address"), Metric::STATIC); 744 745 // free the old cached data for both src and disassembly 746 // If it's disassembly with visible source metrics, we use both 747 if (dis_items) 748 { 749 delete dis_items; 750 dis_items = NULL; 751 } 752 if (src_items) 753 { 754 delete src_items; 755 src_items = NULL; 756 } 757 758 // ask the DbeView to generate new data to be cached 759 if (src_metric || type == Histable::LINE) 760 { 761 Histable *obj = (func_scope) ? (Histable*) func : (Histable*)this; 762 if (lang_code == Sp_lang_java) 763 obj = func_scope ? (Histable *) func : 764 (source && source->get_type () == Histable::SOURCEFILE ? 765 (Histable *) source : (Histable *) this); 766 src_items = dbev->get_hist_data (metrics, Histable::LINE, 0, 767 Hist_data::MODL, obj, source); 768 } 769 if (type == Histable::INSTR) 770 dis_items = dbev->get_hist_data (metrics, Histable::INSTR, 0, 771 Hist_data::MODL, 772 func_scope ? (Histable*) func : (Histable*) this, 773 source); 774 775 Hist_data *cur_hist_data; 776 if (type == Histable::INSTR) 777 cur_hist_data = dis_items; 778 else 779 cur_hist_data = src_items; 780 781 Vector<Metric*> *items = cur_hist_data->get_metric_list ()->get_items (); 782 long sz = items->size (); 783 empty = new TValue[sz]; 784 memset (empty, 0, sizeof (TValue) * sz); 785 for (long i = 0; i < sz; i++) 786 empty[i].tag = items->get (i)->get_vtype (); 787 return true; 788 } 789 790 // Method to get annotated source or disassembly for the module 791 // or a function within it 792 Hist_data * 793 Module::get_data (DbeView *dbev, MetricList *mlist, Histable::Type type, 794 TValue *ftotal, SourceFile *srcFile, Function *func, 795 Vector<int> *marks, int threshold, int vis_bits, 796 int src_visible, bool hex_vis, bool func_scope, 797 bool /*src_only*/, Vector<int_pair_t> *marks2d, 798 Vector<int_pair_t> *marks2d_inc) 799 { 800 cur_dbev = dbev; 801 srcContext = srcFile ? srcFile : main_source; 802 read_stabs (); 803 status = AE_OK; 804 dbev->warning_msg = NULL; 805 dbev->error_msg = NULL; 806 if (type == Histable::LINE) 807 { 808 if (!srcContext->readSource ()) 809 { 810 status = AE_NOSRC; 811 dbev->error_msg = anno_str (srcContext->get_name ()); 812 return NULL; 813 } 814 if (!computeMetrics (dbev, func, mlist, type, false, func_scope, srcContext)) 815 { 816 status = AE_OTHER; 817 dbev->error_msg = anno_str (); 818 return NULL; 819 } 820 status = checkTimeStamp (false); 821 } 822 else 823 { // Histable::INSTR 824 Anno_Errors src_status = AE_OK; 825 if (!srcContext->readSource ()) 826 { 827 src_status = AE_NOSRC; 828 dbev->error_msg = anno_str (srcContext->get_name ()); 829 } 830 if (!setFile ()) 831 status = AE_NOLOBJ; 832 else 833 { 834 if (!openStabs ()) 835 src_status = AE_NOSTABS; 836 if (!openDisPC ()) 837 status = AE_NOSYMTAB; 838 } 839 if (status != AE_OK) 840 { 841 dbev->error_msg = anno_str (); 842 return NULL; 843 } 844 if (src_status != AE_OK && func != NULL) 845 { 846 if (loadobject->platform == Java && (func->flags & FUNC_FLAG_NATIVE) != 0) 847 { 848 append_msg (CMSG_ERROR, 849 GTXT ("`%s' is a native method; byte code not available\n"), 850 func->get_name ()); 851 status = AE_NOOBJ; 852 dbev->error_msg = anno_str (); 853 return NULL; 854 } 855 func_scope = true; 856 } 857 // get the disassembly-line metric data 858 if (!computeMetrics (dbev, func, mlist, type, 859 (src_visible & SRC_METRIC) != 0, 860 func_scope, srcContext)) 861 { 862 status = AE_OTHER; 863 dbev->error_msg = anno_str (); 864 return NULL; 865 } 866 status = checkTimeStamp (true); 867 } 868 total = ftotal; 869 870 // initialize line number 871 init_line (); 872 873 // initialize data -- get duplicate metric list for the line texts 874 // pick up the metric list from the computed data 875 MetricList *nmlist = NULL; 876 if (type == Histable::INSTR) 877 { 878 mlist = dis_items->get_metric_list (); 879 nmlist = new MetricList (mlist); 880 data_items = new Hist_data (nmlist, Histable::INSTR, Hist_data::MODL); 881 data_items->set_status (dis_items->get_status ()); 882 set_dis_data (func, vis_bits, dbev->get_cmpline_visible (), 883 src_visible, hex_vis, func_scope, 884 dbev->get_funcline_visible ()); 885 } 886 else 887 { 888 mlist = src_items->get_metric_list (); 889 nmlist = new MetricList (mlist); 890 data_items = new Hist_data (nmlist, Histable::LINE, Hist_data::MODL); 891 data_items->set_status (src_items->get_status ()); 892 set_src_data (func_scope ? func : NULL, vis_bits, 893 dbev->get_cmpline_visible (), 894 dbev->get_funcline_visible ()); 895 } 896 data_items->compute_minmax (); 897 898 Metric *mitem; 899 int index; 900 Hist_data::HistItem *max_item; 901 TValue *value; 902 Hist_data::HistItem *max_item_inc; 903 TValue *value_inc; 904 double dthreshold = threshold / 100.0; 905 906 int sz = data_items->get_metric_list ()->get_items ()->size (); 907 maximum = new TValue[sz]; 908 maximum_inc = new TValue[sz]; 909 memset (maximum, 0, sizeof (TValue) * sz); 910 memset (maximum_inc, 0, sizeof (TValue) * sz); 911 max_item = data_items->get_maximums (); 912 max_item_inc = data_items->get_maximums_inc (); 913 914 Vec_loop (Metric*, data_items->get_metric_list ()->get_items (), index, mitem) 915 { 916 maximum_inc[index].tag = maximum[index].tag = mitem->get_vtype (); 917 918 if (mitem->get_subtype () == Metric::STATIC) 919 continue; 920 if (!mitem->is_visible () && !mitem->is_tvisible () 921 && !mitem->is_pvisible ()) 922 continue; 923 924 value = &max_item->value[index]; 925 value_inc = &max_item_inc->value[index]; 926 927 double dthresh; 928 if (mitem->is_zeroThreshold () == true) 929 dthresh = 0; 930 else 931 dthresh = dthreshold; 932 switch (value->tag) 933 { 934 case VT_INT: 935 maximum[index].i = (int) (dthresh * (double) value->i); 936 maximum_inc[index].i = (int) (dthresh * (double) value_inc->i); 937 break; 938 case VT_DOUBLE: 939 maximum[index].d = dthresh * value->d; 940 maximum_inc[index].d = dthresh * value_inc->d; 941 break; 942 case VT_LLONG: 943 maximum[index].ll = (unsigned long long) (dthresh * (double) value->ll); 944 maximum_inc[index].ll = (unsigned long long) 945 (dthresh * (double) value_inc->ll); 946 break; 947 case VT_ULLONG: 948 maximum[index].ull = (unsigned long long) 949 (dthresh * (double) value->ull); 950 maximum_inc[index].ull = (unsigned long long) 951 (dthresh * (double) value_inc->ull); 952 break; 953 default: 954 // not needed for non-numerical metrics 955 break; 956 } 957 } 958 959 // mark all high values 960 for (int index1 = 0; index1 < data_items->size (); index1++) 961 { 962 Hist_data::HistItem *hi = data_items->fetch (index1); 963 int index2; 964 Vec_loop (Metric*, nmlist->get_items (), index2, mitem) 965 { 966 bool mark = false; 967 if (mitem->get_subtype () == Metric::STATIC) 968 continue; 969 if (!mitem->is_visible () && !mitem->is_tvisible () 970 && !mitem->is_pvisible ()) 971 continue; 972 973 switch (hi->value[index2].tag) 974 { 975 case VT_DOUBLE: 976 if (nmlist->get_type () == MET_SRCDIS 977 && data_items->get_callsite_mark ()->get (hi->obj)) 978 { 979 if (hi->value[index2].d > maximum_inc[index2].d) 980 mark = true; 981 break; 982 } 983 if (hi->value[index2].d > maximum[index2].d) 984 mark = true; 985 break; 986 case VT_INT: 987 if (nmlist->get_type () == MET_SRCDIS 988 && data_items->get_callsite_mark ()->get (hi->obj)) 989 { 990 if (hi->value[index2].i > maximum_inc[index2].i) 991 mark = true; 992 break; 993 } 994 if (hi->value[index2].i > maximum[index2].i) 995 mark = true; 996 break; 997 case VT_LLONG: 998 if (nmlist->get_type () == MET_SRCDIS 999 && data_items->get_callsite_mark ()->get (hi->obj)) 1000 { 1001 if (hi->value[index2].ll > maximum_inc[index2].ll) 1002 mark = true; 1003 break; 1004 } 1005 if (hi->value[index2].ll > maximum[index2].ll) 1006 mark = true; 1007 break; 1008 case VT_ULLONG: 1009 if (nmlist->get_type () == MET_SRCDIS 1010 && data_items->get_callsite_mark ()->get (hi->obj)) 1011 { 1012 if (hi->value[index2].ull > maximum_inc[index2].ull) 1013 mark = true; 1014 break; 1015 } 1016 if (hi->value[index2].ull > maximum[index2].ull) 1017 mark = true; 1018 break; 1019 // ignoring the following cases (why?) 1020 case VT_SHORT: 1021 case VT_FLOAT: 1022 case VT_HRTIME: 1023 case VT_LABEL: 1024 case VT_ADDRESS: 1025 case VT_OFFSET: 1026 break; 1027 } 1028 if (mark) 1029 { 1030 marks->append (index1); 1031 break; 1032 } 1033 } 1034 } 1035 1036 // mark all high values to marks2d 1037 if (marks2d != NULL && marks2d_inc != NULL) 1038 { 1039 for (int index1 = 0; index1 < data_items->size (); index1++) 1040 { 1041 Hist_data::HistItem *hi = data_items->fetch (index1); 1042 int index2; 1043 Vec_loop (Metric*, nmlist->get_items (), index2, mitem) 1044 { 1045 Metric::SubType subType = mitem->get_subtype (); 1046 if (subType == Metric::STATIC) 1047 continue; 1048 if (!mitem->is_visible () && !mitem->is_tvisible () 1049 && !mitem->is_pvisible ()) 1050 continue; 1051 switch (hi->value[index2].tag) 1052 { 1053 case VT_DOUBLE: 1054 if (nmlist->get_type () == MET_SRCDIS 1055 && data_items->get_callsite_mark ()->get (hi->obj)) 1056 { 1057 if (hi->value[index2].d > maximum_inc[index2].d) 1058 { 1059 int_pair_t pair = {index1, index2}; 1060 marks2d_inc->append (pair); 1061 } 1062 break; 1063 } 1064 if (hi->value[index2].d > maximum[index2].d) 1065 { 1066 int_pair_t pair = {index1, index2}; 1067 marks2d->append (pair); 1068 } 1069 break; 1070 case VT_INT: 1071 if (nmlist->get_type () == MET_SRCDIS 1072 && data_items->get_callsite_mark ()->get (hi->obj)) 1073 { 1074 if (hi->value[index2].i > maximum_inc[index2].i) 1075 { 1076 int_pair_t pair = {index1, index2}; 1077 marks2d_inc->append (pair); 1078 } 1079 break; 1080 } 1081 if (hi->value[index2].i > maximum[index2].i) 1082 { 1083 int_pair_t pair = {index1, index2}; 1084 marks2d->append (pair); 1085 } 1086 break; 1087 case VT_LLONG: 1088 if (nmlist->get_type () == MET_SRCDIS 1089 && data_items->get_callsite_mark ()->get (hi->obj)) 1090 { 1091 if (hi->value[index2].ll > maximum_inc[index2].ll) 1092 { 1093 int_pair_t pair = {index1, index2}; 1094 marks2d_inc->append (pair); 1095 } 1096 break; 1097 } 1098 if (hi->value[index2].ll > maximum[index2].ll) 1099 { 1100 int_pair_t pair = {index1, index2}; 1101 marks2d->append (pair); 1102 } 1103 break; 1104 case VT_ULLONG: 1105 if (nmlist->get_type () == MET_SRCDIS 1106 && data_items->get_callsite_mark ()->get (hi->obj)) 1107 { 1108 if (hi->value[index2].ull > maximum_inc[index2].ull) 1109 { 1110 int_pair_t pair = {index1, index2}; 1111 marks2d_inc->append (pair); 1112 } 1113 break; 1114 } 1115 if (hi->value[index2].ull > maximum[index2].ull) 1116 { 1117 int_pair_t pair = {index1, index2}; 1118 marks2d->append (pair); 1119 } 1120 break; 1121 case VT_SHORT: 1122 case VT_FLOAT: 1123 case VT_HRTIME: 1124 case VT_LABEL: 1125 case VT_ADDRESS: 1126 case VT_OFFSET: 1127 break; 1128 } 1129 } 1130 } 1131 } 1132 1133 // free memory used by Computing & Printing metrics 1134 delete[] maximum; 1135 delete[] maximum_inc; 1136 delete[] empty; 1137 maximum = NULL; 1138 maximum_inc = NULL; 1139 empty = NULL; 1140 dbev->warning_msg = anno_str (); 1141 return data_items; 1142 } 1143 1144 Vector<uint64_t> * 1145 Module::getAddrs (Function *func) 1146 { 1147 uint64_t start_address = func->img_offset; 1148 uint64_t end_address = start_address + func->size; 1149 int64_t inst_size = 0; 1150 1151 // initialize "disasm" if necessary 1152 if (!openDisPC ()) 1153 return NULL; 1154 1155 Vector<uint64_t> *addrs = new Vector<uint64_t>; 1156 for (uint64_t inst_address = start_address; inst_address < end_address;) 1157 { 1158 char *s = disasm->get_disasm (inst_address, end_address, start_address, 1159 func->img_offset, inst_size); 1160 free (s); 1161 addrs->append (inst_address - start_address); 1162 inst_address += inst_size; 1163 if (inst_size == 0) 1164 break; 1165 } 1166 return addrs; 1167 } 1168 1169 void 1170 Module::init_line () 1171 { 1172 // initialize the compiler commentary data 1173 cindex = 0; 1174 if (comComs != NULL && comComs->size () > 0) 1175 cline = comComs->fetch (cindex)->line; 1176 else 1177 cline = -1; 1178 1179 sindex = 0; 1180 if (src_items && src_items->size () > 0) 1181 sline = ((DbeLine*) src_items->fetch (0)->obj)->lineno; 1182 else 1183 sline = -1; 1184 1185 dindex = 0; 1186 mindex = 0; 1187 mline = -1; 1188 if (dis_items && dis_items->size () > 0) 1189 { 1190 daddr = (DbeInstr*) dis_items->fetch (0)->obj; 1191 1192 // After sorting all HistItems with PCLineFlag appear 1193 // at the end of the list. Find the first one. 1194 for (mindex = dis_items->size () - 1; mindex >= 0; mindex--) 1195 { 1196 Hist_data::HistItem *item = dis_items->fetch (mindex); 1197 if (!(((DbeInstr*) item->obj)->flags & PCLineFlag)) 1198 break; 1199 mline = (unsigned) (((DbeInstr*) item->obj)->addr); 1200 } 1201 mindex++; 1202 } 1203 else 1204 daddr = NULL; 1205 } 1206 1207 void 1208 Module::set_src_data (Function *func, int vis_bits, int cmpline_visible, 1209 int funcline_visible) 1210 { 1211 Function *curr_func = NULL; 1212 1213 // start at the top of the file, and loop over all lines in the file (source context) 1214 for (curline = 1; curline <= srcContext->getLineCount (); curline++) 1215 { 1216 // Before writing the line, see if there's compiler commentary to insert 1217 if (cline == curline) 1218 set_ComCom (vis_bits); 1219 1220 // Find out if we need to print zero metrics with the line 1221 DbeLine *dbeline = srcContext->find_dbeline (NULL, curline); 1222 Anno_Types type = AT_SRC_ONLY; 1223 if (dbeline->dbeline_func_next) 1224 { 1225 if (func) 1226 for (DbeLine *dl = dbeline->dbeline_func_next; dl; dl = dl->dbeline_func_next) 1227 { 1228 if (dl->func == func) 1229 { 1230 type = AT_SRC; 1231 break; 1232 } 1233 } 1234 else 1235 type = AT_SRC; 1236 } 1237 1238 if (funcline_visible) 1239 { // show red lines 1240 // is there a function index line to insert? 1241 Function *func_next = NULL; 1242 for (DbeLine *dl = dbeline; dl; dl = dl->dbeline_func_next) 1243 { 1244 Function *f = dl->func; 1245 if (f && f->line_first == curline 1246 && f->getDefSrc () == srcContext) 1247 { 1248 if (lang_code == Sp_lang_java 1249 && (f->flags & FUNC_FLAG_DYNAMIC)) 1250 continue; 1251 if (cur_dbev && cur_dbev->get_path_tree ()->get_func_nodeidx (f)) 1252 { 1253 func_next = f; 1254 break; 1255 } 1256 else if (func_next == NULL) 1257 func_next = f; 1258 } 1259 } 1260 if (func_next && curr_func != func_next) 1261 { 1262 curr_func = func_next; 1263 char *func_name = curr_func->get_name (); 1264 if (is_fortran () && streq (func_name, NTXT ("MAIN_"))) 1265 func_name = curr_func->get_match_name (); 1266 Hist_data::HistItem *item = 1267 src_items->new_hist_item (curr_func, AT_FUNC, empty); 1268 item->value[name_idx].l = dbe_sprintf (GTXT ("<Function: %s>"), 1269 func_name); 1270 data_items->append_hist_item (item); 1271 } 1272 } // end of red line 1273 set_src (type, dbeline); // add the source line 1274 } // end of loop over source lines 1275 1276 // See if compiler flags are set; if so, append them 1277 if (cmpline_visible && comp_flags) 1278 { 1279 Hist_data::HistItem *item = src_items->new_hist_item (NULL, AT_EMPTY, 1280 empty); 1281 item->value[name_idx].l = strdup (NTXT ("")); 1282 data_items->append_hist_item (item); 1283 item = src_items->new_hist_item (NULL, AT_COM, empty); 1284 item->value[name_idx].l = dbe_sprintf (GTXT ("Compile flags: %s"), 1285 comp_flags); 1286 data_items->append_hist_item (item); 1287 } 1288 } 1289 1290 void 1291 Module::set_dis_data (Function *func, int vis_bits, int cmpline_visible, 1292 int src_visible, bool hex_vis, bool func_scope, 1293 int funcline_visible) 1294 { 1295 bool nextFile = false; 1296 1297 // initialize the source output, if any 1298 curline = (srcContext->getLineCount () > 0) ? 1 : -1; 1299 if (func) 1300 nextFile = srcContext != func->getDefSrc (); 1301 curr_inc = srcContext; 1302 1303 bool src_code = (src_visible & SRC_CODE); 1304 Anno_Types src_type = (src_visible & SRC_METRIC) ? AT_SRC : AT_SRC_ONLY; 1305 1306 char *img_fname = func ? func->img_fname : NULL; 1307 1308 // Build a new Function list 1309 Vector<Function*> *FuncLst = new Vector<Function*>; 1310 if (func_scope) 1311 { 1312 if (func) 1313 FuncLst->append (func); 1314 } 1315 else 1316 { 1317 for (int i = 0, sz = functions ? functions->size () : 0; i < sz; i++) 1318 { 1319 Function *fitem = functions->fetch (i); 1320 if (fitem != fitem->cardinal ()) 1321 continue; 1322 if (img_fname == NULL) 1323 img_fname = fitem->img_fname; 1324 if (fitem->img_fname == NULL || strcmp (fitem->img_fname, img_fname)) 1325 continue; 1326 FuncLst->append (fitem); 1327 } 1328 } 1329 if (FuncLst->size () == 0) 1330 { // no function is good 1331 delete FuncLst; 1332 return; 1333 } 1334 cmpSrcContext = srcContext; 1335 FuncLst->sort (func_cmp); 1336 1337 disasm->set_hex_visible (hex_vis); 1338 for (int index = 0, sz = FuncLst->size (); index < sz; index++) 1339 { 1340 Function *fitem = FuncLst->fetch (index); 1341 uint64_t start_address, end_address; 1342 int64_t inst_size; 1343 if (fitem->getDefSrc () != srcContext && curline > 0) 1344 { 1345 // now flush the left source line, if available 1346 for (; curline <= srcContext->getLineCount (); curline++) 1347 { 1348 // see if there's a compiler comment line to dump 1349 if (cline == curline) 1350 set_ComCom (vis_bits); 1351 if (src_code) 1352 set_src (src_type, srcContext->find_dbeline (curline)); 1353 } 1354 curline = -1; 1355 } 1356 1357 curr_inc = NULL; 1358 // disassemble one function 1359 start_address = objStabs ? 1360 objStabs->mapOffsetToAddress (fitem->img_offset) : 0; 1361 end_address = start_address + fitem->size; 1362 inst_size = 0; 1363 1364 disasm->set_addr_end (end_address); 1365 if ((loadobject->flags & SEG_FLAG_DYNAMIC) 1366 && loadobject->platform != Java) 1367 disasm->set_img_name (img_fname); 1368 1369 for (uint64_t inst_address = start_address; inst_address < end_address;) 1370 { 1371 uint64_t address = inst_address - start_address; 1372 DbeInstr *instr = fitem->find_dbeinstr (0, address); 1373 DbeLine *dbeline = (DbeLine *) (instr->convertto (Histable::LINE)); 1374 if (instr->lineno == -1 && dbeline && dbeline->lineno > 0) 1375 instr->lineno = dbeline->lineno; 1376 1377 // now write the unannotated source line, if available 1378 if (curline > 0) 1379 { // source is present 1380 int lineno = curline - 1; 1381 if (instr->lineno != -1) 1382 { 1383 if (dbeline && streq (dbeline->sourceFile->get_name (), 1384 srcContext->get_name ())) 1385 lineno = instr->lineno; 1386 } 1387 else if (curr_inc == NULL && srcContext == fitem->def_source 1388 && fitem->line_first > 0) 1389 lineno = fitem->line_first; 1390 1391 for (; curline <= lineno; curline++) 1392 { 1393 // see if there's a compiler comment line to dump 1394 if (cline == curline) 1395 set_ComCom (vis_bits); 1396 if (mline == curline) 1397 set_MPSlave (); 1398 if (src_code) 1399 set_src (src_type, srcContext->find_dbeline (curline)); 1400 if (curline >= srcContext->getLineCount ()) 1401 { 1402 curline = -1; 1403 break; 1404 } 1405 } 1406 } 1407 1408 if (funcline_visible) 1409 { // show red lines 1410 if (!curr_inc || (dbeline && curr_inc != dbeline->sourceFile)) 1411 { 1412 Hist_data::HistItem *item = dis_items->new_hist_item (dbeline, AT_FUNC, empty); 1413 curr_inc = dbeline ? dbeline->sourceFile : srcContext; 1414 char *str; 1415 if (curr_inc != srcContext) 1416 { 1417 char *fileName = curr_inc->dbeFile->getResolvedPath (); 1418 str = dbe_sprintf (GTXT ("<Function: %s, instructions from source file %s>"), 1419 fitem->get_name (), fileName); 1420 } 1421 else 1422 str = dbe_sprintf (GTXT ("<Function: %s>"), 1423 fitem->get_name ()); 1424 item->value[name_idx].l = str; 1425 data_items->append_hist_item (item); 1426 } 1427 } 1428 1429 char *dis_str = get_disasm (inst_address, end_address, start_address, 1430 fitem->img_offset, inst_size); 1431 if (inst_size == 0) 1432 break; 1433 else if (instr->size == 0) 1434 instr->size = (unsigned int) inst_size; 1435 inst_address += inst_size; 1436 1437 // stomp out control characters 1438 for (size_t i = 0, len = strlen (dis_str); i < len; i++) 1439 { 1440 if (dis_str[i] == '\t') 1441 dis_str[i] = ' '; 1442 } 1443 1444 for (int i = 0; i < bTargets.size (); i++) 1445 { 1446 target_info_t *bTarget = bTargets.fetch (i); 1447 if (bTarget->offset == fitem->img_offset + address) 1448 { 1449 // insert a new line for the bTarget 1450 size_t colon = strcspn (dis_str, NTXT (":")); 1451 char *msg = GTXT ("* <branch target>"); 1452 size_t len = colon + strlen (msg); 1453 len = (len < 50) ? (50 - len) : 1; 1454 char *new_dis_str = dbe_sprintf ("%.*s%s%*c <===----<<<", 1455 (int) colon, dis_str, msg, 1456 (int) len, ' '); 1457 DbeInstr *bt = fitem->find_dbeinstr (PCTrgtFlag, address); 1458 bt->lineno = instr->lineno; 1459 bt->size = 0; 1460 set_dis (bt, AT_DIS, nextFile, new_dis_str); 1461 break; 1462 } 1463 } 1464 1465 // AnalyzerInfo/Datatype annotations 1466 if (infoList != NULL) 1467 { 1468 inst_info_t *info = NULL; 1469 int pinfo; 1470 Vec_loop (inst_info_t*, infoList, pinfo, info) 1471 { 1472 if (info->offset == fitem->img_offset + address) break; 1473 } 1474 if (info != NULL) 1475 { // got a matching memop 1476 char typetag[400]; 1477 typetag[0] = '\0'; 1478 long t; 1479 datatype_t *dtype = NULL; 1480 Vec_loop (datatype_t*, datatypes, t, dtype) 1481 { 1482 if (dtype->datatype_id == info->memop->datatype_id) 1483 break; 1484 } 1485 if (datatypes != NULL) 1486 { 1487 size_t len = strlen (typetag); 1488 if (dtype == NULL || t == datatypes->size ()) 1489 snprintf (typetag + len, sizeof (typetag) - len, "%s", 1490 PTXT (DOBJ_UNSPECIFIED)); 1491 else if (dtype->dobj == NULL) 1492 snprintf (typetag + len, sizeof (typetag) - len, "%s", 1493 PTXT (DOBJ_UNDETERMINED)); 1494 else 1495 snprintf (typetag + len, sizeof (typetag) - len, "%s", 1496 dtype->dobj->get_name ()); 1497 } 1498 if (strlen (typetag) > 1) 1499 { 1500 char *new_dis_str; 1501 new_dis_str = dbe_sprintf ("%-50s %s", dis_str, typetag); 1502 free (dis_str); 1503 dis_str = new_dis_str; 1504 } 1505 } 1506 } 1507 set_dis (instr, AT_DIS, nextFile, dis_str); 1508 } 1509 } 1510 1511 // now flush the left source line, if available 1512 if (curline > 0) 1513 { // source is present 1514 for (; curline <= srcContext->getLineCount (); curline++) 1515 { 1516 // see if there's a compiler comment line to dump 1517 if (cline == curline) 1518 set_ComCom (vis_bits); 1519 1520 if (src_code) 1521 set_src (src_type, srcContext->find_dbeline (curline)); 1522 } 1523 } 1524 1525 // See if compiler flags are set; if so, append them 1526 if (cmpline_visible && comp_flags) 1527 { 1528 Hist_data::HistItem *item = dis_items->new_hist_item (NULL, AT_EMPTY, 1529 empty); 1530 item->value[name_idx].l = dbe_strdup (NTXT ("")); 1531 data_items->append_hist_item (item); 1532 item = dis_items->new_hist_item (NULL, AT_COM, empty); 1533 item->value[name_idx].l = dbe_sprintf (GTXT ("Compile flags: %s"), 1534 comp_flags); 1535 data_items->append_hist_item (item); 1536 } 1537 delete FuncLst; 1538 } 1539 1540 // set_src -- inserts one or more lines into the growing data list 1541 void 1542 Module::set_src (Anno_Types type, DbeLine *dbeline) 1543 { 1544 Hist_data::HistItem *item; 1545 1546 // Flush items that are not represented in source 1547 while (sline >= 0 && sline < curline) 1548 { 1549 item = src_items->fetch (sindex); 1550 if (((DbeLine*) item->obj)->lineno > 0) 1551 set_one (item, AT_QUOTE, item->obj->get_name ()); 1552 1553 if (++sindex < src_items->size ()) // get next line with metrics 1554 sline = ((DbeLine*) src_items->fetch (sindex)->obj)->lineno; 1555 else 1556 sline = -1; 1557 } 1558 1559 // write values in the metric fields for the given source line 1560 if (curline == sline) 1561 { // got metrics for this line 1562 item = src_items->fetch (sindex); 1563 if (((DbeLine*) item->obj)->lineno > 0) 1564 set_one (item, AT_SRC, srcContext->getLine (curline)); 1565 1566 if (++sindex < src_items->size ()) // get next line metric index 1567 sline = ((DbeLine*) src_items->fetch (sindex)->obj)->lineno; 1568 else 1569 sline = -1; 1570 } 1571 else 1572 { 1573 item = data_items->new_hist_item (dbeline, type, empty); 1574 if (size_index != -1) 1575 item->value[size_index].ll = dbeline->get_size (); 1576 if (addr_index != -1) 1577 item->value[addr_index].ll = dbeline->get_addr (); 1578 item->value[name_idx].l = dbe_strdup (srcContext->getLine (curline)); 1579 data_items->append_hist_item (item); 1580 } 1581 } 1582 1583 void 1584 Module::set_dis (DbeInstr *instr, Anno_Types type, bool nextFile, char *dis_str) 1585 { 1586 // Flush items that are not represented in disassembly 1587 while (daddr && daddr->pc_cmp (instr) < 0) 1588 { 1589 if (!nextFile) 1590 set_one (dis_items->fetch (dindex), AT_QUOTE, daddr->get_name ()); 1591 if (++dindex < dis_items->size ()) // get next line metric index 1592 daddr = (DbeInstr*) dis_items->fetch (dindex)->obj; 1593 else 1594 daddr = NULL; 1595 } 1596 1597 // Write values in the metric fields for the given pc index value 1598 if (instr->inlinedInd >= 0) 1599 { 1600 StringBuilder sb; 1601 sb.append (dis_str); 1602 instr->add_inlined_info (&sb); 1603 free (dis_str); 1604 dis_str = sb.toString (); 1605 } 1606 if (daddr && daddr->pc_cmp (instr) == 0) 1607 { 1608 Hist_data::HistItem *item = data_items->new_hist_item (instr, type, 1609 dis_items->fetch (dindex)->value); 1610 item->value[name_idx].tag = VT_LABEL; 1611 item->value[name_idx].l = dis_str; 1612 data_items->append_hist_item (item); 1613 if (dis_items->get_callsite_mark ()->get (dis_items->fetch (dindex)->obj)) 1614 data_items->get_callsite_mark ()->put (item->obj, 1); 1615 1616 if (++dindex < dis_items->size ()) // get next line metric index 1617 daddr = (DbeInstr*) dis_items->fetch (dindex)->obj; 1618 else 1619 daddr = NULL; 1620 } 1621 else 1622 { 1623 // create a new item for this PC 1624 Hist_data::HistItem *item = dis_items->new_hist_item (instr, type, empty); 1625 if (size_index != -1) 1626 item->value[size_index].ll = instr->size; 1627 if (addr_index != -1) 1628 item->value[addr_index].ll = instr->get_addr (); 1629 item->value[name_idx].tag = VT_LABEL; 1630 item->value[name_idx].l = dis_str; 1631 data_items->append_hist_item (item); 1632 } 1633 } 1634 1635 void 1636 Module::set_MPSlave () 1637 { 1638 Hist_data::HistItem *item; 1639 Function *fp; 1640 int index; 1641 1642 // write the inclusive metrics for slave threads 1643 while (mline == curline) 1644 { 1645 item = dis_items->fetch (mindex); 1646 DbeInstr *instr = (DbeInstr *) item->obj; 1647 Vec_loop (Function*, functions, index, fp) 1648 { 1649 if (fp->derivedNode == instr) 1650 { 1651 set_one (item, AT_QUOTE, (fp->isOutlineFunction) ? 1652 GTXT ("<inclusive metrics for outlined functions>") : 1653 GTXT ("<inclusive metrics for slave threads>")); 1654 break; 1655 } 1656 } 1657 1658 mindex++; 1659 if (mindex < dis_items->size ()) 1660 mline = (unsigned) ((DbeInstr*) (dis_items->fetch (mindex)->obj))->addr; 1661 else 1662 mline = -1; 1663 } 1664 }//set_MPSlave 1665 1666 void 1667 Module::set_one (Hist_data::HistItem *org_item, Anno_Types type, 1668 const char *text) 1669 { 1670 if (org_item == NULL) 1671 return; 1672 Hist_data::HistItem *item = data_items->new_hist_item (org_item->obj, type, 1673 org_item->value); 1674 item->value[name_idx].tag = VT_LABEL; 1675 item->value[name_idx].l = dbe_strdup (text); 1676 data_items->append_hist_item (item); 1677 if (org_item != NULL && src_items != NULL 1678 && src_items->get_callsite_mark ()->get (org_item->obj)) 1679 data_items->get_callsite_mark ()->put (item->obj, 1); 1680 }//set_one 1681 1682 void 1683 Module::set_ComCom (int vis_bits) 1684 { 1685 Hist_data::HistItem *item; 1686 Function *func = dbeSession->get_Unknown_Function (); 1687 1688 if (vis_bits) 1689 { 1690 // precede the compiler commentary with a blank line 1691 item = data_items->new_hist_item (func, AT_EMPTY, empty); 1692 item->value[name_idx].l = dbe_strdup (NTXT ("")); 1693 data_items->append_hist_item (item); 1694 } 1695 while (cline == curline) 1696 { 1697 ComC *comm = comComs->fetch (cindex); 1698 if (comm->visible & vis_bits) 1699 { 1700 // write the compiler commentary 1701 item = data_items->new_hist_item (func, AT_COM, empty); 1702 item->value[name_idx].l = dbe_strdup (comm->com_str); 1703 data_items->append_hist_item (item); 1704 } 1705 if (++cindex < comComs->size ()) 1706 cline = comComs->fetch (cindex)->line; 1707 else 1708 cline = -1; 1709 } 1710 } 1711 1712 void 1713 Module::dump_dataobjects (FILE *out) 1714 { 1715 int index; 1716 datatype_t *dtype; 1717 Vec_loop (datatype_t*, datatypes, index, dtype) 1718 { 1719 fprintf (out, NTXT ("[0x%08X,%6lld] %4d %6d %s "), dtype->datatype_id, 1720 dtype->dobj ? dtype->dobj->id : 0LL, 1721 dtype->memop_refs, dtype->event_data, 1722 (dtype->dobj != NULL ? (dtype->dobj->get_name () ? 1723 dtype->dobj->get_name () : "<NULL>") : "<no object>")); 1724 #if DEBUG 1725 Histable* scope = dtype->dobj ? dtype->dobj->get_scope () : NULL; 1726 if (scope != NULL) 1727 { 1728 switch (scope->get_type ()) 1729 { 1730 case Histable::LOADOBJECT: 1731 case Histable::FUNCTION: 1732 fprintf (out, NTXT ("%s"), scope->get_name ()); 1733 break; 1734 case Histable::MODULE: 1735 { 1736 char *filename = get_basename (scope->get_name ()); 1737 fprintf (out, NTXT ("%s"), filename); 1738 break; 1739 } 1740 default: 1741 fprintf (out, NTXT ("\tUnexpected scope %d:%s"), 1742 scope->get_type (), scope->get_name ()); 1743 } 1744 } 1745 #endif 1746 fprintf (out, NTXT ("\n")); 1747 } 1748 } 1749 1750 void 1751 Module::set_name (char *str) 1752 { 1753 free (name); 1754 name = str; 1755 } 1756 1757 void 1758 Module::read_hwcprof_info () 1759 { 1760 if (hwcprof == 0) 1761 { 1762 hwcprof = 1; 1763 Stabs *stabs = openDebugInfo (); 1764 if (stabs) 1765 stabs->read_hwcprof_info (this); 1766 } 1767 } 1768 1769 void 1770 Module::reset_datatypes () 1771 { 1772 for (int i = 0, sz = datatypes ? datatypes->size () : -1; i < sz; i++) 1773 { 1774 datatype_t *t = datatypes->fetch (i); 1775 t->event_data = 0; 1776 } 1777 } 1778 1779 DataObject * 1780 Module::get_dobj (uint32_t dtype_id) 1781 { 1782 read_hwcprof_info (); 1783 for (int i = 0, sz = datatypes ? datatypes->size () : -1; i < sz; i++) 1784 { 1785 datatype_t *t = datatypes->fetch (i); 1786 if (t->datatype_id == dtype_id) 1787 { 1788 t->event_data++; 1789 return t->dobj; 1790 } 1791 } 1792 return NULL; 1793 } 1794 1795 int 1796 Module::readFile () 1797 { 1798 return AE_OK; 1799 } 1800 1801 Vector<Histable*> * 1802 Module::get_comparable_objs () 1803 { 1804 update_comparable_objs (); 1805 if (comparable_objs || dbeSession->expGroups->size () <= 1 || loadobject == NULL) 1806 return comparable_objs; 1807 Vector<Histable*> *comparableLoadObjs = loadobject->get_comparable_objs (); 1808 if (comparableLoadObjs == NULL) 1809 return NULL; 1810 comparable_objs = new Vector<Histable*>(comparableLoadObjs->size ()); 1811 for (int i = 0, sz = comparableLoadObjs->size (); i < sz; i++) 1812 { 1813 Module *mod = NULL; 1814 LoadObject *lo = (LoadObject*) comparableLoadObjs->fetch (i); 1815 if (lo) 1816 { 1817 mod = lo->get_comparable_Module (this); 1818 if (mod) 1819 mod->comparable_objs = comparable_objs; 1820 } 1821 comparable_objs->store (i, mod); 1822 } 1823 dump_comparable_objs (); 1824 return comparable_objs; 1825 } 1826 1827 JMethod * 1828 Module::find_jmethod (const char *nm, const char *sig) 1829 { 1830 // Vladimir: Probably we should not use linear search 1831 for (long i = 0, sz = VecSize (functions); i < sz; i++) 1832 { 1833 JMethod *jmthd = (JMethod*) functions->get (i); 1834 char *jmt_name = jmthd->get_name (Histable::SHORT); 1835 if (strcmp (jmt_name, nm) == 0 1836 && strcmp (jmthd->get_signature (), sig) == 0) 1837 return jmthd; 1838 } 1839 return NULL; 1840 } 1841