]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gprofng/src/LoadObject.cc
Update year range in gprofng copyright notices
[thirdparty/binutils-gdb.git] / gprofng / src / LoadObject.cc
CommitLineData
76bdc726 1/* Copyright (C) 2021-2023 Free Software Foundation, Inc.
bb368aad
VM
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}