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