]> Git Repo - binutils.git/blob - gprofng/src/LoadObject.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / LoadObject.cc
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
41 enum
42 {
43   LO_InstHTableSize     = 4096,
44   HTableSize            = 1024
45 };
46
47 LoadObject *
48 LoadObject::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
56 LoadObject *
57 LoadObject::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
83 LoadObject::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
128 LoadObject::~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
146 Elf *
147 LoadObject::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
181 Stabs *
182 LoadObject::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
213 uint64_t
214 LoadObject::get_addr ()
215 {
216   return MAKE_ADDRESS (seg_idx, 0);
217 }
218
219 bool
220 LoadObject::compare (const char *_path, int64_t _checksum)
221 {
222   return _checksum == checksum && dbe_strcmp (_path, get_pathname ()) == 0;
223 }
224
225 int
226 LoadObject::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
243 void
244 LoadObject::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
263 void
264 LoadObject::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
276 void
277 LoadObject::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
320 int
321 LoadObject::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
352 char *
353 LoadObject::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
396 DbeInstr*
397 LoadObject::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
412 Function *
413 LoadObject::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
528 static void
529 fixFuncAlias (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
583 void
584 LoadObject::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
627 int
628 LoadObject::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
646 Function *
647 LoadObject::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
659 Function *
660 LoadObject::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
672 Module *
673 LoadObject::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
684 LoadObject::Arch_status
685 LoadObject::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
702 LoadObject::Arch_status
703 LoadObject::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
815 static int
816 offsetCmp (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
823 int
824 LoadObject::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
1080 char *
1081 LoadObject::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
1132 uint32_t
1133 LoadObject::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
1145 static char*
1146 get_module_map_key (Module *mod)
1147 {
1148   return mod->lang_code == Sp_lang_java ? mod->get_name () : mod->file_name;
1149 }
1150
1151 Module *
1152 LoadObject::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
1189 Vector<Histable*> *
1190 LoadObject::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
1208 void
1209 LoadObject::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
1225 Function *
1226 LoadObject::get_hide_function ()
1227 {
1228   if (h_function == NULL)
1229     h_function = dbeSession->create_hide_function (this);
1230   return h_function;
1231 }
1232
1233 DbeInstr *
1234 LoadObject::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 }
This page took 0.094253 seconds and 4 git commands to generate.