Home | History | Annotate | Line # | Download | only in src
      1 /* Copyright (C) 2021-2025 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 
     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 
     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 *
    131 Module::openDebugInfo ()
    132 {
    133   setFile ();
    134   objStabs = loadobject->openDebugInfo ();
    135   return objStabs;
    136 }
    137 
    138 void
    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
    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
    164 Module::is_fortran ()
    165 {
    166   return Stabs::is_fortran (lang_code);
    167 }
    168 
    169 SourceFile *
    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 *
    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 *
    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 *
    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
    275 tsIsNewer (time_t t1, time_t t2)
    276 {
    277   return t1 != 0 && t2 != 0 && t1 < t2;
    278 }
    279 
    280 Module::Anno_Errors
    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
    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
    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
    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
    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 *) xmalloc (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 *
    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
    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 = xstrdup (path);
    523 	  disName = xstrdup (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 (xstrdup (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 = xstrdup (stabsTmp);
    557 	      stabsName = xstrdup (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 = xstrdup (path);
    577 	      stabsName = xstrdup (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 = xstrdup (disPath);
    589 	  stabsName = xstrdup (disName);
    590 	  stabsMTime = disMTime;
    591 	}
    592       else if (disPath == NULL)
    593 	{
    594 	  disPath = xstrdup (stabsPath);
    595 	  disName = xstrdup (stabsName);
    596 	  disMTime = stabsMTime;
    597 	}
    598     }
    599   return stabsPath != NULL;
    600 }
    601 
    602 // openStabs -- open mappings from PCs to source lines
    603 bool
    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 *
    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
    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
    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
    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
    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 *
    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> *
   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
   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
   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 = xstrdup (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
   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
   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
   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
   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
   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
   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
   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
   1751 Module::set_name (char *str)
   1752 {
   1753   free (name);
   1754   name = str;
   1755 }
   1756 
   1757 void
   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
   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 *
   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
   1796 Module::readFile ()
   1797 {
   1798   return AE_OK;
   1799 }
   1800 
   1801 Vector<Histable*> *
   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 *
   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