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 <errno.h> 23 24#include "util.h" 25#include "StringBuilder.h" 26#include "Application.h" 27#include "DbeSession.h" 28#include "Experiment.h" 29#include "Exp_Layout.h" 30#include "DataObject.h" 31#include "Elf.h" 32#include "Function.h" 33#include "Module.h" 34#include "ClassFile.h" 35#include "Stabs.h" 36#include "LoadObject.h" 37#include "dbe_types.h" 38#include "DbeFile.h" 39#include "ExpGroup.h" 40 41enum 42{ 43 LO_InstHTableSize = 4096, 44 HTableSize = 1024 45}; 46 47LoadObject * 48LoadObject::create_item (const char *nm, int64_t chksum) 49{ 50 LoadObject *lo = new LoadObject (nm); 51 lo->checksum = chksum; 52 dbeSession->append (lo); 53 return lo; 54} 55 56LoadObject * 57LoadObject::create_item (const char *nm, const char *_runTimePath, DbeFile *df) 58{ 59 LoadObject *lo = new LoadObject (nm); 60 lo->runTimePath = dbe_strdup (_runTimePath); 61 lo->dbeFile->orig_location = dbe_strdup (_runTimePath); 62 if (df) 63 { 64 if ((df->filetype & DbeFile::F_JAR_FILE) != 0) 65 { 66 if (lo->dbeFile->find_in_jar_file (nm, df->get_jar_file ())) 67 { 68 lo->dbeFile->inArchive = df->inArchive; 69 lo->dbeFile->container = df; 70 } 71 } 72 else 73 { 74 lo->dbeFile->set_location (df->get_location ()); 75 lo->dbeFile->sbuf = df->sbuf; 76 lo->dbeFile->inArchive = df->inArchive; 77 } 78 } 79 dbeSession->append (lo); 80 return lo; 81} 82 83LoadObject::LoadObject (const char *loname) 84{ 85 flags = 0; 86 size = 0; 87 type = SEG_UNKNOWN; 88 isReadStabs = false; 89 need_swap_endian = false; 90 instHTable = new DbeInstr*[LO_InstHTableSize]; 91 for (int i = 0; i < LO_InstHTableSize; i++) 92 instHTable[i] = NULL; 93 94 functions = new Vector<Function*>; 95 funcHTable = new Function*[HTableSize]; 96 for (int i = 0; i < HTableSize; i++) 97 funcHTable[i] = NULL; 98 99 seg_modules = new Vector<Module*>; 100 modules = new HashMap<char*, Module*>; 101 platform = Unknown; 102 noname = dbeSession->createUnknownModule (this); 103 modules->put (noname->get_name (), noname); 104 pathname = NULL; 105 arch_name = NULL; 106 runTimePath = NULL; 107 objStabs = NULL; 108 firstExp = NULL; 109 seg_modules_map = NULL; 110 comp_funcs = NULL; 111 warnq = new Emsgqueue (NTXT ("lo_warnq")); 112 commentq = new Emsgqueue (NTXT ("lo_commentq")); 113 elf_lo = NULL; 114 elf_inited = false; 115 checksum = 0; 116 isUsed = false; 117 h_function = NULL; 118 h_instr = NULL; 119 120 char *nm = (char *) loname; 121 if (strncmp (nm, NTXT ("./"), 2) == 0) 122 nm += 2; 123 set_name (nm); 124 dbeFile = new DbeFile (nm); 125 dbeFile->filetype |= DbeFile::F_LOADOBJ | DbeFile::F_FILE; 126} 127 128LoadObject::~LoadObject () 129{ 130 delete seg_modules_map; 131 delete functions; 132 delete[] instHTable; 133 delete[] funcHTable; 134 delete seg_modules; 135 delete modules; 136 delete elf_lo; 137 free (pathname); 138 free (arch_name); 139 free (runTimePath); 140 delete objStabs; 141 delete warnq; 142 delete commentq; 143 delete h_instr; 144} 145 146Elf * 147LoadObject::get_elf () 148{ 149 if (elf_lo == NULL) 150 { 151 if (dbeFile->get_need_refind ()) 152 elf_inited = false; 153 if (elf_inited) 154 return NULL; 155 elf_inited = true; 156 char *fnm = dbeFile->get_location (); 157 if (fnm == NULL) 158 { 159 append_msg (CMSG_ERROR, GTXT ("Cannot find file: `%s'"), 160 dbeFile->get_name ()); 161 return NULL; 162 } 163 Elf::Elf_status st = Elf::ELF_ERR_CANT_OPEN_FILE; 164 elf_lo = Elf::elf_begin (fnm, &st); 165 if (elf_lo == NULL) 166 switch (st) 167 { 168 case Elf::ELF_ERR_CANT_OPEN_FILE: 169 append_msg (CMSG_ERROR, GTXT ("Cannot open ELF file `%s'"), fnm); 170 break; 171 case Elf::ELF_ERR_BAD_ELF_FORMAT: 172 default: 173 append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"), 174 fnm); 175 break; 176 } 177 } 178 return elf_lo; 179} 180 181Stabs * 182LoadObject::openDebugInfo (char *fname, Stabs::Stab_status *stp) 183{ 184 if (objStabs == NULL) 185 { 186 if (fname == NULL) 187 return NULL; 188 objStabs = new Stabs (fname, get_pathname ()); 189 Stabs::Stab_status st = objStabs->get_status (); 190 if ((st == Stabs::DBGD_ERR_NONE) && (checksum != 0)) 191 { 192 Elf *elf = get_elf (); 193 if (elf && (checksum != elf->elf_checksum ())) 194 { 195 char *buf = dbe_sprintf (GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"), 196 fname); 197 commentq->append (new Emsg (CMSG_ERROR, buf)); 198 delete buf; 199 st = Stabs::DBGD_ERR_CHK_SUM; 200 } 201 } 202 if (stp) 203 *stp = st; 204 if (st != Stabs::DBGD_ERR_NONE) 205 { 206 delete objStabs; 207 objStabs = NULL; 208 } 209 } 210 return objStabs; 211} 212 213uint64_t 214LoadObject::get_addr () 215{ 216 return MAKE_ADDRESS (seg_idx, 0); 217} 218 219bool 220LoadObject::compare (const char *_path, int64_t _checksum) 221{ 222 return _checksum == checksum && dbe_strcmp (_path, get_pathname ()) == 0; 223} 224 225int 226LoadObject::compare (const char *_path, const char *_runTimePath, DbeFile *df) 227{ 228 int ret = 0; 229 if (dbe_strcmp (_path, get_pathname ()) != 0) 230 return ret; 231 ret |= CMP_PATH; 232 if (_runTimePath) 233 { 234 if (dbe_strcmp (_runTimePath, runTimePath) != 0) 235 return ret; 236 ret |= CMP_RUNTIMEPATH; 237 } 238 if (df && dbeFile->compare (df)) 239 ret |= CMP_CHKSUM; 240 return ret; 241} 242 243void 244LoadObject::set_platform (Platform_t pltf, int wsz) 245{ 246 switch (pltf) 247 { 248 case Sparc: 249 case Sparcv9: 250 case Sparcv8plus: 251 platform = (wsz == W64) ? Sparcv9 : Sparc; 252 break; 253 case Intel: 254 case Amd64: 255 platform = (wsz == W64) ? Amd64 : Intel; 256 break; 257 default: 258 platform = pltf; 259 break; 260 } 261}; 262 263void 264LoadObject::set_name (char *string) 265{ 266 char *p; 267 pathname = dbe_strdup (string); 268 269 p = get_basename (pathname); 270 if (p[0] == '<') 271 name = dbe_strdup (p); 272 else // set a short name to "<basename>" 273 name = dbe_sprintf (NTXT ("<%s>"), p); 274} 275 276void 277LoadObject::dump_functions (FILE *out) 278{ 279 int index; 280 Function *fitem; 281 char *sname, *mname; 282 if (platform == Java) 283 { 284 JMethod *jmthd; 285 Vector<JMethod*> *jmethods = (Vector<JMethod*>*)functions; 286 Vec_loop (JMethod*, jmethods, index, jmthd) 287 { 288 fprintf (out, "id %6llu, @0x%llx sz-%lld %s (module = %s)\n", 289 (unsigned long long) jmthd->id, (long long) jmthd->get_mid (), 290 (long long) jmthd->size, jmthd->get_name (), 291 jmthd->module ? jmthd->module->file_name : noname->file_name); 292 } 293 } 294 else 295 { 296 Vec_loop (Function*, functions, index, fitem) 297 { 298 if (fitem->alias && fitem->alias != fitem) 299 fprintf (out, "id %6llu, @0x%llx - %s == alias of '%s'\n", 300 (ull_t) fitem->id, (ull_t) fitem->img_offset, 301 fitem->get_name (), fitem->alias->get_name ()); 302 else 303 { 304 mname = fitem->module ? fitem->module->file_name : noname->file_name; 305 sname = fitem->getDefSrcName (); 306 fprintf (out, 307 "id %6llu, @0x%llx - 0x%llx [save 0x%llx] o-%lld sz-%lld %s (module = %s)", 308 (ull_t) fitem->id, (ull_t) fitem->img_offset, 309 (ull_t) (fitem->img_offset + fitem->size), 310 (ull_t) fitem->save_addr, (ull_t) fitem->img_offset, 311 (ll_t) fitem->size, fitem->get_name (), mname); 312 if (sname && !streq (sname, mname)) 313 fprintf (out, " (Source = %s)", sname); 314 fprintf (out, "\n"); 315 } 316 } 317 } 318} 319 320int 321LoadObject::get_index (Function *func) 322{ 323 Function *fp; 324 uint64_t offset; 325 int x; 326 int left = 0; 327 int right = functions->size () - 1; 328 offset = func->img_offset; 329 while (left <= right) 330 { 331 x = (left + right) / 2; 332 fp = functions->fetch (x); 333 334 if (left == right) 335 { 336 if (offset >= fp->img_offset + fp->size) 337 return -1; 338 if (offset >= fp->img_offset) 339 return x; 340 return -1; 341 } 342 if (offset < fp->img_offset) 343 right = x - 1; 344 else if (offset >= fp->img_offset + fp->size) 345 left = x + 1; 346 else 347 return x; 348 } 349 return -1; 350} 351 352char * 353LoadObject::get_alias (Function *func) 354{ 355 Function *fp, *alias; 356 int index, nsize; 357 static char buf[1024]; 358 if (func->img_offset == 0 || func->alias == NULL) 359 return NULL; 360 int fid = get_index (func); 361 if (fid == -1) 362 return NULL; 363 364 nsize = functions->size (); 365 alias = func->alias; 366 for (index = fid; index < nsize; index++) 367 { 368 fp = functions->fetch (index); 369 if (fp->alias != alias) 370 { 371 fid = index; 372 break; 373 } 374 } 375 376 *buf = '\0'; 377 for (index--; index >= 0; index--) 378 { 379 fp = functions->fetch (index); 380 if (fp->alias != alias) 381 break; 382 if (fp != alias) 383 { 384 size_t len = strlen (buf); 385 if (*buf != '\0') 386 { 387 snprintf (buf + len, sizeof (buf) - len, NTXT (", ")); 388 len = strlen (buf); 389 } 390 snprintf (buf + len, sizeof (buf) - len, "%s", fp->get_name ()); 391 } 392 } 393 return buf; 394} 395 396DbeInstr* 397LoadObject::find_dbeinstr (uint64_t file_off) 398{ 399 int hash = (((int) file_off) >> 2) & (LO_InstHTableSize - 1); 400 DbeInstr *instr = instHTable[hash]; 401 if (instr && instr->img_offset == file_off) 402 return instr; 403 Function *fp = find_function (file_off); 404 if (fp == NULL) 405 fp = dbeSession->get_Unknown_Function (); 406 uint64_t func_off = file_off - fp->img_offset; 407 instr = fp->find_dbeinstr (0, func_off); 408 instHTable[hash] = instr; 409 return instr; 410} 411 412Function * 413LoadObject::find_function (uint64_t foff) 414{ 415 // Look up in the hash table 416 int hash = (((int) foff) >> 6) & (HTableSize - 1); 417 Function *func = funcHTable[hash]; 418 if (func && foff >= func->img_offset && foff < func->img_offset + func->size) 419 return func->alias ? func->alias : func; 420 421 // Use binary search 422 func = NULL; 423 int left = 0; 424 int right = functions->size () - 1; 425 while (left <= right) 426 { 427 int x = (left + right) / 2; 428 Function *fp = functions->fetch (x); 429 assert (fp != NULL); 430 431 if (foff < fp->img_offset) 432 right = x - 1; 433 else if (foff >= fp->img_offset + fp->size) 434 left = x + 1; 435 else 436 { 437 func = fp; 438 break; 439 } 440 } 441 442 // Plug the hole with a static function 443 char *func_name = NULL; 444 Size low_bound = 0, high_bound = 0; 445 if (func == NULL) 446 { 447 int last = functions->size () - 1; 448 uint64_t usize = (uint64_t) size; 449 if (foff >= usize) 450 { 451 // Cannot map to this LoadObject. Probably LoadObject was changed. 452 if (last >= 0 && functions->fetch (last)->img_offset == usize) 453 { 454 // Function is already created 455 func = functions->fetch (last); 456 if (func->size < 0 || (uint64_t) func->size < foff - usize) 457 func->size = foff - usize; 458 } 459 else 460 { 461 low_bound = size; 462 high_bound = foff; 463 func_name = dbe_sprintf (GTXT ("<static>@0x%llx (%s) -- no functions found"), 464 low_bound, name); 465 } 466 } 467 else if (last < 0) 468 { 469 low_bound = 0; 470 high_bound = size; 471 func_name = dbe_sprintf (GTXT ("<static>@0x%llx (%s) -- no functions found"), 472 low_bound, name); 473 } 474 else if (foff < functions->fetch (0)->img_offset) 475 { 476 low_bound = 0; 477 high_bound = functions->fetch (0)->img_offset; 478 } 479 else 480 { 481 Function *fp = functions->fetch (last); 482 if (foff >= fp->img_offset + fp->size) 483 { 484 low_bound = fp->img_offset + fp->size; 485 high_bound = size; 486 } 487 else 488 { 489 fp = functions->fetch (left); 490 if (foff >= fp->img_offset + fp->size) 491 { 492 low_bound = fp->img_offset + fp->size; 493 high_bound = functions->fetch (left + 1)->img_offset; 494 } 495 else 496 { 497 Function *fp1 = functions->fetch (left - 1); 498 low_bound = fp1->img_offset + fp1->size; 499 high_bound = fp->img_offset; 500 } 501 } 502 } 503 } 504 505 if (func == NULL) 506 { 507 func = dbeSession->createFunction (); 508 func->size = (unsigned) (high_bound - low_bound); 509 func->module = noname; 510 func->img_fname = get_pathname (); 511 func->img_offset = (off_t) low_bound; 512 noname->functions->append (func); // unordered 513 if (func_name == NULL) 514 func_name = dbe_sprintf (GTXT ("<static>@0x%llx (%s)"), low_bound, 515 name); 516 func->set_name (func_name); 517 free (func_name); 518 519 // now insert the function 520 functions->insert (left, func); 521 } 522 523 // Update the hash table 524 funcHTable[hash] = func; 525 return func->alias ? func->alias : func; 526} 527 528static void 529fixFuncAlias (Vector<Function*> *SymLst) 530{ 531 int ind, i, k; 532 int64_t len, bestLen, maxSize; 533 Function *sym, *bestAlias; 534 535 // XXXX it is a clone of Stabs::fixSymtabAlias() 536 ind = SymLst->size () - 1; 537 for (i = 0; i < ind; i++) 538 { 539 bestAlias = SymLst->fetch (i); 540 if (bestAlias->img_offset == 0) // Ignore this bad symbol 541 continue; 542 sym = SymLst->fetch (i + 1); 543 if (bestAlias->img_offset != sym->img_offset) 544 { 545 if (bestAlias->size == 0 546 || sym->img_offset < bestAlias->img_offset + bestAlias->size) 547 bestAlias->size = (int) (sym->img_offset - bestAlias->img_offset); 548 continue; 549 } 550 551 // Find a "best" alias 552 bestLen = strlen (bestAlias->get_name ()); 553 maxSize = bestAlias->size; 554 for (k = i + 1; k <= ind; k++) 555 { 556 sym = SymLst->fetch (k); 557 if (bestAlias->img_offset != sym->img_offset) 558 { // no more aliases 559 if ((maxSize == 0) || 560 (sym->img_offset < bestAlias->img_offset + maxSize)) 561 maxSize = sym->img_offset - bestAlias->img_offset; 562 break; 563 } 564 if (maxSize < sym->size) 565 maxSize = sym->size; 566 len = strlen (sym->get_name ()); 567 if (len < bestLen) 568 { 569 bestAlias = sym; 570 bestLen = len; 571 } 572 } 573 for (; i < k; i++) 574 { 575 sym = SymLst->fetch (i); 576 sym->alias = bestAlias; 577 sym->size = maxSize; 578 } 579 i--; 580 } 581} 582 583void 584LoadObject::post_process_functions () 585{ 586 if (flags & SEG_FLAG_DYNAMIC || platform == Java) 587 return; 588 589 char *msg = GTXT ("Processing Load Object Data"); 590 if (dbeSession->is_interactive ()) 591 theApplication->set_progress (1, msg); 592 593 // First sort the functions 594 functions->sort (func_compare); 595 fixFuncAlias (functions); 596 597 Module *mitem; 598 int index; 599 Vec_loop (Module*, seg_modules, index, mitem) 600 { 601 mitem->functions->sort (func_compare); 602 } 603 604 // Find any derived functions, and set their derivedNode 605 Function *fitem; 606 Vec_loop (Function*, functions, index, fitem) 607 { 608 if (dbeSession->is_interactive () && index % 5000 == 0) 609 { 610 int percent = (int) (100.0 * index / functions->size ()); 611 theApplication->set_progress (percent, (percent != 0) ? NULL : msg); 612 } 613 fitem->findDerivedFunctions (); 614 } 615 616 // 4987698: get the alias name for MAIN_ 617 fitem = find_function (NTXT ("MAIN_")); 618 if (fitem) 619 fitem->module->read_stabs (); 620 fitem = find_function (NTXT ("@plt")); 621 if (fitem) 622 fitem->flags |= FUNC_FLAG_PLT; 623 if (dbeSession->is_interactive ()) 624 theApplication->set_progress (0, NTXT ("")); 625} 626 627int 628LoadObject::func_compare (const void *p1, const void *p2) 629{ 630 Function *f1 = *(Function **) p1; 631 Function *f2 = *(Function **) p2; 632 if (f1->img_offset != f2->img_offset) 633 return f1->img_offset > f2->img_offset ? 1 : -1; 634 635 // annotated source not available for weak symbols. 636 if ((f1->module->flags & MOD_FLAG_UNKNOWN) != 0) 637 { 638 if ((f2->module->flags & MOD_FLAG_UNKNOWN) == 0) 639 return -1; 640 } 641 else if ((f2->module->flags & MOD_FLAG_UNKNOWN) != 0) 642 return 1; 643 return strcoll (f1->get_name (), f2->get_name ()); 644} 645 646Function * 647LoadObject::find_function (char *fname) 648{ 649 Function *fitem; 650 int index; 651 Vec_loop (Function*, functions, index, fitem) 652 { 653 if (strcmp (fitem->get_name (), fname) == 0) 654 return fitem; 655 } 656 return (Function *) NULL; 657} 658 659Function * 660LoadObject::find_function (char *fname, unsigned int chksum) 661{ 662 Function *fitem; 663 int index; 664 Vec_loop (Function*, functions, index, fitem) 665 { 666 if (fitem->chksum == chksum && strcmp (fitem->get_name (), fname) == 0) 667 return fitem; 668 } 669 return (Function *) NULL; 670} 671 672Module * 673LoadObject::find_module (char *mname) 674{ 675 for (int i = 0, sz = seg_modules ? seg_modules->size () : 0; i < sz; i++) 676 { 677 Module *module = seg_modules->fetch (i); 678 if (strcmp (module->get_name (), mname) == 0) 679 return module; 680 } 681 return (Module *) NULL; 682} 683 684LoadObject::Arch_status 685LoadObject::sync_read_stabs () 686{ 687 Arch_status st = ARCHIVE_SUCCESS; 688 if (!isReadStabs) 689 { 690 aquireLock (); 691 if (!isReadStabs) 692 { 693 st = read_stabs (); 694 post_process_functions (); 695 isReadStabs = true; 696 } 697 releaseLock (); 698 } 699 return st; 700} 701 702LoadObject::Arch_status 703LoadObject::read_stabs () 704{ 705 if ((dbeFile->filetype & DbeFile::F_FICTION) != 0) 706 return ARCHIVE_SUCCESS; 707 Arch_status stabs_status = ARCHIVE_ERR_OPEN; 708 if (platform == Java) 709 { 710 Module *cf = NULL; 711 for (int i = 0, sz = seg_modules ? seg_modules->size () : 0; i < sz; i++) 712 { 713 Module *mod = seg_modules->fetch (i); 714 if (mod->dbeFile 715 && (mod->dbeFile->filetype & DbeFile::F_JAVACLASS) != 0) 716 { 717 cf = mod; 718 break; 719 } 720 } 721 if (cf) 722 { 723 int status = cf->readFile (); 724 switch (status) 725 { 726 case Module::AE_OK: 727 stabs_status = ARCHIVE_SUCCESS; 728 break; 729 case Module::AE_NOSTABS: 730 stabs_status = ARCHIVE_NO_STABS; 731 break; 732 case Module::AE_NOTREAD: 733 default: 734 stabs_status = ARCHIVE_ERR_OPEN; 735 break; 736 } 737 } 738 } 739 else if (strchr (pathname, '`')) 740 return ARCHIVE_SUCCESS; 741 else 742 { 743 Arch_status st = ARCHIVE_WRONG_ARCH; 744 Elf *elf = get_elf (); 745 if (elf == NULL) 746 { 747 if (read_archive () == 0) 748 st = ARCHIVE_SUCCESS; 749 else 750 { 751 char *msg = dbe_sprintf (GTXT ("*** Warning: Can't open file: %s"), 752 dbeFile->get_name ()); 753 warnq->append (new Emsg (CMSG_ERROR, msg)); 754 delete msg; 755 } 756 } 757 else if (checksum != 0 && checksum != elf->elf_checksum ()) 758 { 759 if (read_archive () == 0) 760 st = ARCHIVE_SUCCESS; 761 else 762 { 763 char *msg = dbe_sprintf ( 764 GTXT ("*** Note: '%s' has an unexpected checksum value; perhaps it was rebuilt. File ignored"), 765 dbeFile->get_location ()); 766 commentq->append (new Emsg (CMSG_ERROR, msg)); 767 delete msg; 768 } 769 } 770 if (st == ARCHIVE_SUCCESS) // An old archive is used 771 return st; 772 773 Stabs::Stab_status status = Stabs::DBGD_ERR_CANT_OPEN_FILE; 774 char *location = dbeFile->get_location (true); 775 if (location == NULL) 776 return ARCHIVE_ERR_OPEN; 777 778 if (openDebugInfo (location, &status)) 779 { 780 status = objStabs->read_archive (this); 781 isRelocatable = objStabs->is_relocatable (); 782 size = objStabs->get_textsz (); 783 platform = objStabs->get_platform (); 784 wsize = objStabs->get_class (); 785 } 786 787 switch (status) 788 { 789 case Stabs::DBGD_ERR_NONE: 790 stabs_status = ARCHIVE_SUCCESS; 791 break; 792 case Stabs::DBGD_ERR_CANT_OPEN_FILE: 793 stabs_status = ARCHIVE_ERR_OPEN; 794 break; 795 case Stabs::DBGD_ERR_BAD_ELF_LIB: 796 case Stabs::DBGD_ERR_BAD_ELF_FORMAT: 797 stabs_status = ARCHIVE_BAD_STABS; 798 break; 799 case Stabs::DBGD_ERR_NO_STABS: 800 stabs_status = ARCHIVE_NO_STABS; 801 break; 802 case Stabs::DBGD_ERR_NO_DWARF: 803 stabs_status = ARCHIVE_NO_DWARF; 804 break; 805 default: 806 stabs_status = ARCHIVE_BAD_STABS; 807 break; 808 } 809 } 810 return stabs_status; 811} 812 813#define ARCH_STRLEN(s) ((strlen(s) + 4) & ~0x3 ) 814 815static int 816offsetCmp (const void *a, const void *b) 817{ 818 uint32_t o1 = ((inst_info_t *) a)->offset; 819 uint32_t o2 = ((inst_info_t *) b)->offset; 820 return o1 == o2 ? 0 : (o1 < o2 ? -1 : 1); 821} 822 823int 824LoadObject::read_archive () 825{ 826 if (arch_name == NULL) 827 return 1; 828 Module *mod = NULL; 829 Function *func = NULL; 830 char *buf; 831 Data_window *dwin = new Data_window (arch_name); 832 if (dwin->not_opened ()) 833 { 834 delete dwin; 835 buf = dbe_sprintf (GTXT ("*** Warning: Error opening file for reading: %s: %s"), 836 arch_name, strerror (errno)); 837 warnq->append (new Emsg (CMSG_ERROR, buf)); 838 delete buf; 839 return 1; 840 } 841 dwin->need_swap_endian = need_swap_endian; 842 843 // Prevent reading earlier archive files, which didn't support versioning. 844 int64_t offset = 0; 845 ARCH_common *cpkt = (ARCH_common*) dwin->bind (offset, sizeof (ARCH_common)); 846 uint16_t v16; 847 if (cpkt) 848 { 849 v16 = (uint16_t) cpkt->type; 850 if (dwin->decode (v16) != ARCH_SEGMENT) 851 cpkt = NULL; 852 } 853 if (cpkt == NULL) 854 { 855 buf = dbe_sprintf (GTXT ("archive file malformed %s"), arch_name); 856 warnq->append (new Emsg (CMSG_WARN, buf)); 857 delete buf; 858 return 1; 859 } 860 861 char *msg = NULL; 862 unsigned long long pointer_invalid = 0; 863 for (int64_t last_offset = -5000;;) 864 { 865 cpkt = (ARCH_common*) dwin->bind (offset, sizeof (ARCH_common)); 866 if (cpkt == NULL) 867 break; 868 v16 = (uint16_t) cpkt->size; 869 uint32_t cpktsize = dwin->decode (v16); 870 cpkt = (ARCH_common*) dwin->bind (offset, cpktsize); 871 if ((cpkt == NULL) || (cpktsize == 0)) 872 { 873 buf = dbe_sprintf (GTXT ("archive file malformed %s"), arch_name); 874 warnq->append (new Emsg (CMSG_WARN, buf)); 875 delete buf; 876 break; 877 } 878 879 // Update the progress bar 880 if (dbeSession->is_interactive () && ((offset - last_offset) >= 5000)) 881 { 882 last_offset = offset; 883 int percent = (int) (100.0 * offset / dwin->get_fsize ()); 884 if (msg == NULL) 885 msg = dbe_sprintf (GTXT ("Reading Load Object Data: %s"), name); 886 theApplication->set_progress (percent, (percent != 0) ? NULL : msg); 887 } 888 char *ptr = (char *) cpkt; 889 v16 = (uint16_t) cpkt->type; 890 switch (dwin->decode (v16)) 891 { 892 case ARCH_SEGMENT: 893 { 894 ARCH_segment *aseg = (ARCH_segment*) cpkt; 895 if (dwin->decode (aseg->version) != ARCH_VERSION) 896 { 897 buf = dbe_sprintf (GTXT ("Archive file version mismatch for %s"), arch_name); 898 warnq->append (new Emsg (CMSG_ERROR, buf)); 899 delete buf; 900 if (dbeSession->is_interactive ()) 901 theApplication->set_progress (0, ""); 902 return 1; 903 } 904 if (size == 0) 905 size = dwin->decode (aseg->textsz); 906 Platform_t pltf = (Platform_t) dwin->decode (aseg->platform); 907 if (pltf != Unknown) 908 { 909 platform = pltf; // override if known 910 wsize = (platform == Sparcv9 || platform == Amd64) ? W64 : W32; 911 } 912 break; 913 } 914 case ARCH_MSG: 915 { 916 ARCH_message *amsg = (ARCH_message*) cpkt; 917 buf = status_str ((Arch_status) dwin->decode (amsg->errcode)); 918 commentq->append (new Emsg (CMSG_ARCHIVE, buf)); 919 free (buf); 920 break; 921 } 922 case ARCH_INF: 923 { 924 ARCH_info *ainf = (ARCH_info*) cpkt; 925 Emsg *m = new Emsg (CMSG_ARCHIVE, (char*) (ainf + 1)); 926 commentq->append (m); 927 break; 928 } 929 case ARCH_MODULE: 930 { 931 ARCH_module *amod = (ARCH_module*) cpkt; 932 char *str = ((char*) amod) + sizeof (ARCH_module); 933 if (streq (str, SP_UNKNOWN_NAME) && 934 streq (str + ARCH_STRLEN (str), SP_UNKNOWN_NAME)) 935 { 936 mod = noname; 937 break; 938 } 939 mod = dbeSession->createModule (this, str); 940 mod->lang_code = (Sp_lang_code) dwin->decode (amod->lang_code); 941 mod->fragmented = dwin->decode (amod->fragmented); 942 str += ARCH_STRLEN (str); 943 mod->set_file_name (dbe_strdup (str)); 944 modules->put (get_basename (str), mod); 945 break; 946 } 947 case ARCH_FUNCTION: 948 { 949 if (mod == NULL) 950 break; 951 ARCH_function *afnc = (ARCH_function*) cpkt; 952 func = dbeSession->createFunction (); 953 func->img_offset = dwin->decode (afnc->offset); 954 func->size = dwin->decode (afnc->size); 955 func->save_addr = dwin->decode (afnc->save_addr) 956 - dwin->decode (afnc->offset); 957 func->module = mod; 958 func->set_name (((char*) afnc) + sizeof (ARCH_function)); 959 mod->functions->append (func); 960 functions->append (func); 961 break; 962 } 963 case ARCH_LDINSTR: 964 if (mod == NULL) 965 break; 966 Dprintf (DEBUG_LOADOBJ, "LDINSTR list for %s\n", mod->get_name ()); 967 if (mod->infoList == NULL) 968 mod->infoList = new Vector<inst_info_t*>; 969 for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); 970 (char*) mp < ptr + cpktsize; mp++) 971 { 972 memop_info_t *memop = new memop_info_t; 973 memop->offset = dwin->decode (mp->offset); 974 memop->id = dwin->decode (mp->id); 975 memop->signature = dwin->decode (mp->signature); 976 memop->datatype_id = dwin->decode (mp->datatype_id); 977 mod->ldMemops.append (memop); 978 979 inst_info_t *instop = new inst_info_t; 980 instop->type = CPF_INSTR_TYPE_LD; 981 instop->offset = memop->offset; 982 instop->memop = memop; 983 mod->infoList->incorporate (instop, offsetCmp); 984 Dprintf (DEBUG_LOADOBJ, 985 "ld: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", 986 memop->offset, memop->id, memop->signature, 987 memop->datatype_id); 988 } 989 Dprintf (DEBUG_LOADOBJ, "LDINSTR list of %lld for %s\n", 990 (long long) mod->ldMemops.size (), mod->get_name ()); 991 break; 992 case ARCH_STINSTR: 993 if (mod == NULL) 994 break; 995 Dprintf (DEBUG_LOADOBJ, NTXT ("STINSTR list for %s\n"), mod->get_name ()); 996 if (mod->infoList == NULL) 997 mod->infoList = new Vector<inst_info_t*>; 998 for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); 999 ((char *) mp) < ptr + cpktsize; mp++) 1000 { 1001 memop_info_t *memop = new memop_info_t; 1002 memop->offset = dwin->decode (mp->offset); 1003 memop->id = dwin->decode (mp->id); 1004 memop->signature = dwin->decode (mp->signature); 1005 memop->datatype_id = dwin->decode (mp->datatype_id); 1006 mod->stMemops.append (memop); 1007 1008 inst_info_t *instop = new inst_info_t; 1009 instop->type = CPF_INSTR_TYPE_ST; 1010 instop->offset = memop->offset; 1011 instop->memop = memop; 1012 mod->infoList->incorporate (instop, offsetCmp); 1013 Dprintf (DEBUG_LOADOBJ, 1014 "st: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", 1015 memop->offset, memop->id, memop->signature, 1016 memop->datatype_id); 1017 } 1018 Dprintf (DEBUG_LOADOBJ, "STINSTR list of %lld for %s\n", 1019 (long long) mod->stMemops.size (), mod->get_name ()); 1020 break; 1021 case ARCH_PREFETCH: 1022 if (mod == NULL) 1023 break; 1024 Dprintf (DEBUG_LOADOBJ, "PFINSTR list for %s\n", mod->get_name ()); 1025 if (mod->infoList == NULL) 1026 mod->infoList = new Vector<inst_info_t*>; 1027 for (memop_info_t *mp = (memop_info_t*) (ptr + sizeof (ARCH_aninfo)); 1028 ((char*) mp) < ptr + cpkt->size; mp++) 1029 { 1030 memop_info_t *memop = new memop_info_t; 1031 memop->offset = dwin->decode (mp->offset); 1032 memop->id = dwin->decode (mp->id); 1033 memop->signature = dwin->decode (mp->signature); 1034 memop->datatype_id = dwin->decode (mp->datatype_id); 1035 mod->pfMemops.append (memop); 1036 1037 inst_info_t *instop = new inst_info_t; 1038 instop->type = CPF_INSTR_TYPE_PREFETCH; 1039 instop->offset = memop->offset; 1040 instop->memop = memop; 1041 mod->infoList->incorporate (instop, offsetCmp); 1042 Dprintf (DEBUG_LOADOBJ, 1043 "pf: offset=0x%04x id=0x%08x sig=0x%08x dtid=0x%08x\n", 1044 memop->offset, memop->id, memop->signature, 1045 memop->datatype_id); 1046 } 1047 Dprintf (DEBUG_LOADOBJ, "PFINSTR list of %lld for %s\n", 1048 (long long) mod->pfMemops.size (), mod->get_name ()); 1049 break; 1050 case ARCH_BRTARGET: 1051 if (mod == NULL) 1052 break; 1053 for (target_info_t *tp = (target_info_t*) (ptr + sizeof (ARCH_aninfo)); 1054 ((char*) tp) < ptr + cpkt->size; tp++) 1055 { 1056 target_info_t *bTarget = new target_info_t; 1057 bTarget->offset = dwin->decode (tp->offset); 1058 mod->bTargets.append (bTarget); 1059 } 1060 Dprintf (DEBUG_LOADOBJ, "BRTARGET list of %lld for %s\n", 1061 (long long) mod->infoList->size (), mod->get_name ()); 1062 break; 1063 default: 1064 /* Check if the prointer is valid - should be even. */ 1065 pointer_invalid = (unsigned long long) (offset + cpktsize) & 1; 1066 break; // ignore unknown packets 1067 } 1068 if (pointer_invalid) 1069 break; 1070 offset += cpktsize; 1071 } 1072 delete msg; 1073 delete dwin; 1074 1075 if (dbeSession->is_interactive ()) 1076 theApplication->set_progress (0, NTXT ("")); 1077 return 0; 1078} 1079 1080char * 1081LoadObject::status_str (Arch_status rv, char */*arg*/) 1082{ 1083 switch (rv) 1084 { 1085 case ARCHIVE_SUCCESS: 1086 case ARCHIVE_EXIST: 1087 return NULL; 1088 case ARCHIVE_BAD_STABS: 1089 return dbe_sprintf (GTXT ("Error: unable to read symbol table of %s"), 1090 name); 1091 case ARCHIVE_ERR_SEG: 1092 return dbe_sprintf (GTXT ("Error: unable to read load object file %s"), 1093 pathname); 1094 case ARCHIVE_ERR_OPEN: 1095 return dbe_sprintf (GTXT ("Error: unable to open file %s"), 1096 pathname); 1097 case ARCHIVE_ERR_MAP: 1098 return dbe_sprintf (GTXT ("Error: unable to map file %s"), 1099 pathname); 1100 case ARCHIVE_WARN_CHECKSUM: 1101 return dbe_sprintf (GTXT ("Note: checksum differs from that recorded in experiment for %s"), 1102 name); 1103 case ARCHIVE_WARN_MTIME: 1104 return dbe_sprintf (GTXT ("Warning: last-modified time differs from that recorded in experiment for %s"), 1105 name); 1106 case ARCHIVE_WARN_HOST: 1107 return dbe_sprintf (GTXT ("Try running er_archive -F on the experiment, on the host where it was recorded")); 1108 case ARCHIVE_ERR_VERSION: 1109 return dbe_sprintf (GTXT ("Error: Wrong version of archive for %s"), 1110 pathname); 1111 case ARCHIVE_NO_STABS: 1112 return dbe_sprintf (GTXT ("Note: no stabs or dwarf information in %s"), 1113 name); 1114 case ARCHIVE_WRONG_ARCH: 1115#if ARCH(SPARC) 1116 return dbe_sprintf (GTXT ("Error: file %s is built for Intel, and can't be read on SPARC"), 1117 name); 1118#else 1119 return dbe_sprintf (GTXT ("Error: file %s is built for SPARC, and can't be read on Intel"), 1120 name); 1121#endif 1122 case ARCHIVE_NO_LIBDWARF: 1123 return dbe_strdup (GTXT ("Warning: no libdwarf found to read DWARF symbol tables")); 1124 case ARCHIVE_NO_DWARF: 1125 return dbe_sprintf (GTXT ("Note: no DWARF symbol table in %s"), name); 1126 default: 1127 return dbe_sprintf (GTXT ("Warning: unexpected archive error %d"), 1128 (int) rv); 1129 } 1130} 1131 1132uint32_t 1133LoadObject::get_checksum () 1134{ 1135 char *errmsg = NULL; 1136 uint32_t crcval = get_cksum (pathname, &errmsg); 1137 if (0 == crcval && errmsg) 1138 { 1139 warnq->append (new Emsg (CMSG_ERROR, errmsg)); 1140 free (errmsg); 1141 } 1142 return crcval; 1143} 1144 1145static char* 1146get_module_map_key (Module *mod) 1147{ 1148 return mod->lang_code == Sp_lang_java ? mod->get_name () : mod->file_name; 1149} 1150 1151Module * 1152LoadObject::get_comparable_Module (Module *mod) 1153{ 1154 if (mod->loadobject == this) 1155 return mod; 1156 if (get_module_map_key (mod) == NULL) 1157 return NULL; 1158 if (seg_modules_map == NULL) 1159 { 1160 seg_modules_map = new HashMap<char*, Module*>; 1161 for (int i = 0; i < seg_modules->size (); i++) 1162 { 1163 Module *m = seg_modules->fetch (i); 1164 char *key = get_module_map_key (m); 1165 if (key) 1166 { 1167 seg_modules_map->put (m->file_name, m); 1168 char *bname = get_basename (key); 1169 if (bname != key) 1170 seg_modules_map->put (bname, m); 1171 } 1172 } 1173 } 1174 1175 char *key = get_module_map_key (mod); 1176 Module *cmpMod = seg_modules_map->get (key); 1177 if (cmpMod && cmpMod->comparable_objs == NULL) 1178 return cmpMod; 1179 char *bname = get_basename (key); 1180 if (bname != key) 1181 { 1182 cmpMod = seg_modules_map->get (bname); 1183 if (cmpMod && cmpMod->comparable_objs == NULL) 1184 return cmpMod; 1185 } 1186 return NULL; 1187} 1188 1189Vector<Histable*> * 1190LoadObject::get_comparable_objs () 1191{ 1192 update_comparable_objs (); 1193 if (comparable_objs || dbeSession->expGroups->size () <= 1) 1194 return comparable_objs; 1195 comparable_objs = new Vector<Histable*>(dbeSession->expGroups->size ()); 1196 for (int i = 0, sz = dbeSession->expGroups->size (); i < sz; i++) 1197 { 1198 ExpGroup *gr = dbeSession->expGroups->fetch (i); 1199 Histable *h = gr->get_comparable_loadObject (this); 1200 comparable_objs->append (h); 1201 if (h) 1202 h->comparable_objs = comparable_objs; 1203 } 1204 dump_comparable_objs (); 1205 return comparable_objs; 1206} 1207 1208void 1209LoadObject::append_module (Module *mod) 1210{ 1211 seg_modules->append (mod); 1212 if (seg_modules_map == NULL) 1213 seg_modules_map = new HashMap<char*, Module*>; 1214 char *key = get_module_map_key (mod); 1215 if (key) 1216 { 1217 seg_modules_map->put (key, mod); 1218 char *bname = get_basename (key); 1219 if (bname != key) 1220 seg_modules_map->put (bname, mod); 1221 } 1222} 1223 1224// LIBRARY_VISIBILITY 1225Function * 1226LoadObject::get_hide_function () 1227{ 1228 if (h_function == NULL) 1229 h_function = dbeSession->create_hide_function (this); 1230 return h_function; 1231} 1232 1233DbeInstr * 1234LoadObject::get_hide_instr (DbeInstr *instr) 1235{ 1236 if (h_instr == NULL) 1237 { 1238 Function *hf = get_hide_function (); 1239 h_instr = hf->create_hide_instr (instr); 1240 } 1241 return h_instr; 1242} 1243