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