]> Git Repo - binutils.git/blob - gprofng/src/Module.cc
Automatic date update in version.in
[binutils.git] / gprofng / src / Module.cc
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #include "config.h"
22 #include <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 (disPath);
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 *) 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 *
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 = 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
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 = 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
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 }
This page took 0.129726 seconds and 4 git commands to generate.