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 <stdlib.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <math.h>
26 #include <assert.h>
27 #include <libintl.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 
34 #include "util.h"
35 #include "Dbe.h"
36 #include "StringBuilder.h"
37 #include "DbeSession.h"
38 #include "DbeView.h"
39 #include "Settings.h"
40 #include "Print.h"
41 #include "DbeView.h"
42 #include "Experiment.h"
43 #include "MetricList.h"
44 #include "Module.h"
45 #include "Function.h"
46 #include "DataSpace.h"
47 #include "DataObject.h"
48 #include "FilterExp.h"
49 #include "LoadObject.h"
50 #include "Emsg.h"
51 #include "Table.h"
52 #include "DbeFile.h"
53 #include "CallStack.h"
54 
55 int
open(Print_params * params)56 er_print_common_display::open (Print_params *params)
57 {
58   pr_params = *params;
59   pr_params.name = dbe_strdup (params->name);
60   if (params->dest == DEST_PRINTER)
61     {
62       tmp_file = dbeSession->get_tmp_file_name (NTXT ("print"), false);
63       dbeSession->tmp_files->append (strdup (tmp_file));
64       out_file = fopen (tmp_file, NTXT ("w"));
65     }
66   else if (params->dest == DEST_OPEN_FILE)
67     out_file = pr_params.openfile;
68   else
69     out_file = fopen (pr_params.name, NTXT ("w"));
70 
71   if (out_file == NULL)
72     // Failure
73     return 1;
74   return 0;
75 }
76 
77 bool
print_output()78 er_print_common_display::print_output ()
79 {
80   char *sys_call;
81   bool ret = true;
82   if (pr_params.dest != DEST_OPEN_FILE)
83     fclose (out_file);
84 
85   if (pr_params.dest == DEST_PRINTER)
86     {
87       if (streq ((char *) pr_params.name, NTXT ("")))
88 	sys_call = dbe_sprintf ("(/usr/bin/lp -c -n%d %s) 2>/dev/null 1>&2",
89 				pr_params.ncopies, tmp_file);
90       else
91 	sys_call = dbe_sprintf ("(/usr/bin/lp -c -d%s -n%d %s) 2>/dev/null 1>&2",
92 				pr_params.name, pr_params.ncopies, tmp_file);
93       if (system (sys_call) != 0)
94 	ret = false;
95       unlink (tmp_file);
96       free (sys_call);
97     }
98 
99   return ret;
100 }
101 
102 // Return the report. If the report size is greater than max, return truncated report
103 // Allocates memory, so the caller should free this memory.
104 
105 char *
get_output(int maxsize)106 er_print_common_display::get_output (int maxsize)
107 {
108   off_t max = (off_t) maxsize;
109   if (out_file != (FILE *) NULL)
110     {
111       fclose (out_file); // close tmp_file
112       out_file = (FILE *) NULL;
113     }
114   struct stat sbuf;
115   int st = stat (tmp_file, &sbuf);
116   if (st == 0)
117     {
118       off_t sz = sbuf.st_size;
119       if (sz > max)
120 	return dbe_sprintf (GTXT ("Error: report is too long.\n"));
121       if (sz <= 0)
122 	return dbe_sprintf (GTXT ("Error: empty temporary file: %s\n"),
123 			    tmp_file);
124       max = sz;
125     }
126 
127   FILE *f = fopen (tmp_file, "r");
128   if (f == NULL)
129     return dbe_sprintf (GTXT ("Error: cannot open temporary file: %s\n"),
130 			tmp_file);
131   char *report = (char *) malloc (max);
132   if (report)
133     {
134       if (1 != fread (report, max - 1, 1, f))
135 	{
136 	  fclose (f);
137 	  free (report);
138 	  return dbe_sprintf (GTXT ("Error: cannot read temporary file: %s\n"),
139 			      tmp_file);
140 	}
141       report[max - 1] = 0;
142     }
143   fclose (f);
144   return report;
145 }
146 
147 void
header_dump(int exp_idx)148 er_print_common_display::header_dump (int exp_idx)
149 {
150   if (load && (exp_idx == exp_idx1))
151     {
152       load = false;
153       print_load_object (out_file);
154     }
155   print_header (dbeSession->get_exp (exp_idx), out_file);
156 }
157 
158 char *
pr_load_objects(Vector<LoadObject * > * loadobjects,char * lead)159 pr_load_objects (Vector<LoadObject*> *loadobjects, char *lead)
160 {
161   int size, i;
162   LoadObject *lo;
163   Emsg *m;
164   char *msg;
165   StringBuilder sb;
166   char *lo_name;
167   size = loadobjects->size ();
168   for (i = 0; i < size; i++)
169     {
170       lo = loadobjects->fetch (i);
171       lo_name = lo->get_name ();
172       if (lo_name != NULL)
173 	{
174 	  size_t len = strlen (lo_name);
175 	  if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
176 	    continue;
177 	}
178 
179       // print the segment name
180       sb.append (lead);
181       sb.append (NTXT (" "));
182       sb.append (lo->get_name ());
183       sb.append (NTXT (" ("));
184       sb.append (lo->get_pathname ());
185       sb.append (NTXT (")\n"));
186 
187       // and any warnings
188       m = lo->fetch_warnings ();
189       if (m != NULL)
190 	{
191 	  msg = pr_mesgs (m, NULL, NTXT ("       "));
192 	  sb.append (msg);
193 	  free (msg);
194 	}
195     }
196   return sb.toString ();
197 }
198 
199 char *
pr_mesgs(Emsg * msg,const char * null_str,const char * lead)200 pr_mesgs (Emsg *msg, const char *null_str, const char *lead)
201 {
202   Emsg *m;
203   StringBuilder sb;
204   if (msg == NULL)
205     return dbe_strdup (null_str);
206   for (m = msg; m; m = m->next)
207     {
208       sb.append (lead);
209       sb.append (m->get_msg ());
210       sb.append (NTXT ("\n"));
211     }
212   return sb.toString ();
213 }
214 
215 void
print_load_object(FILE * out_file)216 print_load_object (FILE *out_file)
217 {
218   Vector<LoadObject*> *loadobjects = dbeSession->get_text_segments ();
219   char *msg = pr_load_objects (loadobjects, NTXT ("\t"));
220   fprintf (out_file, GTXT ("Load Object Coverage:\n"));
221   fprintf (out_file, NTXT ("%s"), msg);
222   fprintf (out_file,
223 	   "----------------------------------------------------------------\n");
224   free (msg);
225   delete loadobjects;
226 }
227 
228 void
print_header(Experiment * exp,FILE * out_file)229 print_header (Experiment *exp, FILE *out_file)
230 {
231   fprintf (out_file, GTXT ("Experiment: %s\n"), exp->get_expt_name ());
232   char *msg = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT (""));
233   fprintf (out_file, NTXT ("%s"), msg);
234   free (msg);
235 
236   msg = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT (""));
237   fprintf (out_file, NTXT ("%s"), msg);
238   free (msg);
239 
240   msg = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT (""));
241   fprintf (out_file, NTXT ("%s"), msg);
242   free (msg);
243 
244   msg = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT (""));
245   fprintf (out_file, NTXT ("%s"), msg);
246   free (msg);
247 
248   msg = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT (""));
249   fprintf (out_file, NTXT ("%s"), msg);
250   free (msg);
251 }
252 
253 static char *
delTrailingBlanks(char * s)254 delTrailingBlanks (char *s)
255 {
256   for (int i = (int) strlen (s) - 1; i >= 0 && s[i] == ' '; i--)
257     s[i] = 0;
258   return s;
259 }
260 
261 /**
262  * Print the 3-line header with column heads for the metrics
263  * Return offset of "Name" column (this is needed to print Callers-Callees)
264  */
265 int
print_label(FILE * out_file,MetricList * metrics_list,Metric::HistMetric * hist_metric,int space)266 print_label (FILE *out_file, MetricList *metrics_list,
267 	     Metric::HistMetric *hist_metric, int space)
268 {
269   char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
270   char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
271   int name_offset = 0;
272   *line0 = *line1 = *line2 = *line3 = '\0';
273   Vector<Metric*> *mlist = metrics_list->get_items ();
274   for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
275     {
276       Metric *mitem = mlist->fetch (index);
277       if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ())
278 	{
279 	  Metric::HistMetric *hitem = hist_metric + index;
280 	  const char *s;
281 	  if (index > 0 && mitem->get_type () == Metric::ONAME)
282 	    {
283 	      s = " ";
284 	      name_offset = strlen (line1);
285 	    }
286 	  else
287 	    s = "";
288 	  int width = (int) hitem->width;
289 	  size_t len = strlen (line1);
290 	  snprintf (line1 + len, sizeof (line1) - len, "%s%-*s", s, width,
291 		    hitem->legend1);
292 	  len = strlen (line2);
293 	  snprintf (line2 + len, sizeof (line2) - len, "%s%-*s", s, width,
294 		    hitem->legend2);
295 	  len = strlen (line3);
296 	  snprintf (line3 + len, sizeof (line3) - len, "%s%-*s", s, width,
297 		    hitem->legend3);
298 	  len = strlen (line0);
299 	  snprintf (line0 + len, sizeof (line0) - len, "%s%-*s", s, width,
300 		    mitem->legend ? mitem->legend : NTXT (""));
301 	}
302     }
303   char *s = delTrailingBlanks (line0);
304   if (*s)
305     fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), s);
306   fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line1));
307   fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line2));
308   fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line3));
309   return name_offset;
310 }
311 
er_print_histogram(DbeView * _dbev,Hist_data * data,MetricList * metrics_list,Print_mode disp_type,int limit,char * sort_name,Histable * sobj,bool show_load,bool show_header)312 er_print_histogram::er_print_histogram (DbeView *_dbev, Hist_data *data,
313 					MetricList *metrics_list,
314 					Print_mode disp_type, int limit,
315 					char *sort_name, Histable *sobj,
316 					bool show_load, bool show_header)
317 {
318   hist_data = data;
319   mlist = metrics_list;
320   type = disp_type;
321   number_entries = limit;
322   sort_metric = sort_name;
323   sel_obj = sobj;
324   dbev = _dbev;
325   exp_idx1 = 0;
326   exp_idx2 = dbeSession->nexps () - 1;
327   load = show_load;
328   header = show_header;
329 }
330 
331 void
dump_list(int limit)332 er_print_histogram::dump_list (int limit)
333 {
334   Histable::NameFormat nfmt = dbev->get_name_format ();
335   StringBuilder sb;
336   char *title = NULL; // No title for some formats
337   enum PrintMode pm = dbev->get_printmode ();
338 
339   // create a header line, except for delimiter-separated list output
340   if (pm != PM_DELIM_SEP_LIST)
341     {
342       if (hist_data->type == Histable::FUNCTION)
343 	sb.append (GTXT ("Functions sorted by metric: "));
344       else if (hist_data->type == Histable::INSTR)
345 	sb.append (GTXT ("PCs sorted by metric: "));
346       else if (hist_data->type == Histable::LINE)
347 	sb.append (GTXT ("Lines sorted by metric: "));
348       else if (hist_data->type == Histable::DOBJECT)
349 	sb.append (GTXT ("Dataobjects sorted by metric: "));
350       else
351 	sb.append (GTXT ("Objects sorted by metric: "));
352       sb.append (sort_metric);
353       title = sb.toString ();
354     }
355 
356   switch (pm)
357     {
358     case PM_TEXT:
359       {
360 	Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
361 	fprintf (out_file, NTXT ("%s\n\n"), title); //print title
362 	hist_data->print_label (out_file, hist_metric, 0);
363 	hist_data->print_content (out_file, hist_metric, limit);
364 	fprintf (out_file, nl);
365 	break;
366       }
367     case PM_HTML:
368       {
369 	print_html_title (out_file, title);
370 	print_html_label (out_file, mlist);
371 	print_html_content (out_file, hist_data, mlist, limit, nfmt);
372 	print_html_trailer (out_file);
373 	break;
374       }
375     case PM_DELIM_SEP_LIST:
376       {
377 	char delim = dbev->get_printdelimiter ();
378 	print_delim_label (out_file, mlist, delim);
379 	print_delim_content (out_file, hist_data, mlist, limit, nfmt, delim);
380 	print_delim_trailer (out_file, delim);
381 	break;
382       }
383     }
384   free (title);
385 }
386 
387 void
dump_annotated_dataobjects(Vector<int> * marks,int ithreshold)388 er_print_histogram::dump_annotated_dataobjects (Vector<int> *marks,
389 						int ithreshold)
390 {
391   if (!dbeSession->is_datamode_available ())
392     fprintf (out_file,
393                     GTXT ("No dataspace information recorded in experiments\n\n"));
394 
395   Hist_data *layout_data = dbev->get_data_space ()->get_layout_data (hist_data, marks, ithreshold);
396   Metric::HistMetric *hist_metric = layout_data->get_histmetrics ();
397 
398 //  snprintf (hist_metric[name_index].legend2, MAX_LEN, GTXT ("* +offset .element"));
399   layout_data->print_label (out_file, hist_metric, 3);
400   fprintf (out_file, nl);
401   StringBuilder sb;
402 
403   for (long i = 0; i < layout_data->size (); i++)
404     {
405       sb.setLength (0);
406       if (marks->find (i) != -1)
407 	sb.append ("## ");
408       else
409 	sb.append ("   ");
410       layout_data->print_row (&sb, i, hist_metric, " ");
411       sb.toFileLn (out_file);
412     }
413   fprintf (out_file, nl);
414   delete layout_data;
415 }
416 
417 static int
max_length(size_t len,size_t str_len)418 max_length(size_t len, size_t str_len)
419 {
420   if (str_len > len)
421     return str_len;
422   return len;
423 }
424 
425 void
dump_detail(int limit)426 er_print_histogram::dump_detail (int limit)
427 {
428   Histable *obj;
429   Hist_data *current_data;
430   Histable::Type htype;
431   TValue *values;
432   double dvalue, percent;
433   MetricList *prop_mlist = new MetricList (mlist);
434   Metric *mitem;
435   int index, i;
436   Module *module;
437   LoadObject *loadobject;
438   char *sname, *oname, *lname, *alias, *mangle;
439 
440   Histable::NameFormat nfmt = dbev->get_name_format ();
441 
442   // Check max. length of metrics names
443   size_t len = 0, slen = 0;
444   Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
445   {
446     mitem->set_vvisible (true);
447     if (mitem->get_vtype () == VT_LABEL)
448       continue;
449 
450     if (mitem->get_subtype () != Metric::STATIC)
451       {
452 	mitem->set_pvisible (true);
453 	len = max_length (len, hist_data->value_maxlen (index));
454 	slen = max_length (slen, strlen (mitem->get_name ()));
455       }
456   }
457 
458   // now get the length of the other (non-performance-data) messages
459   if (hist_data->type == Histable::FUNCTION)
460     {
461       slen = max_length (slen, strlen (GTXT ("Source File")));
462       slen = max_length (slen, strlen (GTXT ("Object File")));
463       slen = max_length (slen, strlen (GTXT ("Load Object")));
464       slen = max_length (slen, strlen (GTXT ("Mangled Name")));
465       slen = max_length (slen, strlen (GTXT ("Aliases")));
466     }
467   else if (hist_data->type == Histable::DOBJECT)
468     {
469       slen = max_length (slen, strlen (GTXT ("Scope")));
470       slen = max_length (slen, strlen (GTXT ("Type")));
471       slen = max_length (slen, strlen (GTXT ("Member of")));
472       slen = max_length (slen, strlen (GTXT ("Offset (bytes)")));
473       slen = max_length (slen, strlen (GTXT ("Size (bytes)")));
474       slen = max_length (slen, strlen (GTXT ("Elements")));
475     }
476   int max_len = (int) len;
477   int smax_len = (int) slen;
478 
479 #define PR_TITLE(t)   fprintf (out_file, "\t%*s:", smax_len, t)
480 #define PR(title, nm) PR_TITLE(title); \
481 		      if (nm) \
482 		        fprintf (out_file, " %s", nm); \
483 		      fprintf (out_file, "\n")
484 
485   // now loop over the objects
486   int num_printed_items = 0;
487   for (i = 0; i < hist_data->size (); i++)
488     {
489       if (hist_data->type == Histable::FUNCTION)
490 	{
491 	  if (num_printed_items >= limit)
492 	    break;
493 	  obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
494 	  htype = obj->get_type ();
495 
496 	  // ask the view for all the data for the object
497 	  // xxxxx may be expensive to rescan all packets via get_hist_data()
498 	  current_data = dbev->get_hist_data (prop_mlist,
499 					      htype, 0, Hist_data::SELF, obj);
500 	  if (current_data->size () == 0)
501 	    continue;
502 	  values = current_data->fetch (0)->value;
503 	}
504       else
505 	{
506 	  obj = hist_data->fetch (i)->obj;
507 	  DataObject *dobj = (DataObject*) obj;
508 	  if (sel_obj)
509 	    {
510 	      // print selected item and its members
511 	      if (sel_obj != obj
512 		  && (DataObject*) sel_obj != dobj->get_parent ())
513 		// not a match, advance to next item
514 		continue;
515 	    }
516 	  else if (num_printed_items >= limit)
517 	    break;
518 	  htype = obj->get_type ();
519 	  values = hist_data->fetch (i)->value;
520 	  current_data = hist_data;
521 	}
522 
523       if (num_printed_items)
524 	// if this isn't the first one, add a blank line
525 	fprintf (out_file, NTXT ("\n"));
526       num_printed_items++;
527 
528       // Print full object name
529       if (htype != Histable::DOBJECT)
530 	fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
531       else
532 	{
533 	  DataObject *dobj = (DataObject*) obj;
534 	  if (!dobj->get_parent ())
535 	    fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
536 	  else
537 	    fprintf (out_file, NTXT ("    %s\n"), obj->get_name (nfmt));
538 	}
539 
540       Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
541       {
542 	if (mitem->get_vtype () == VT_LABEL)
543 	  continue;
544 	if (mitem->get_subtype () == Metric::STATIC
545 	    && htype == Histable::DOBJECT)
546 	  continue;
547 	PR_TITLE (mitem->get_name ());
548 
549 	char buf[128];
550 	char *s = values[index].to_str (buf, sizeof (buf));
551 	if (mitem->get_value_styles () & VAL_PERCENT)
552 	  {
553 	    dvalue = values[index].to_double ();
554 	    percent = 100.0 * current_data->get_percentage (dvalue, index);
555 	    if (!mitem->is_time_val ())
556 	      {
557 		fprintf (out_file, " %*s", max_len, s);
558 		if (dvalue == 0.)
559 		  fprintf (out_file, " (  0. %%)\n");
560 		else
561 		  fprintf (out_file, " (%5.1f%%)\n", percent);
562 		continue;
563 	      }
564 
565 	    TValue v;
566 	    v.tag = VT_DOUBLE;
567 	    v.sign = false;
568 	    v.d = dvalue / (1.e+6 * dbeSession->get_clock (-1));
569 	    char buf1[128];
570 	    char *s1 = v.to_str (buf1, sizeof (buf1));
571 	    fprintf (out_file, " %*s", max_len, s1);
572 	    if (dvalue == 0.)
573 	      fprintf (out_file, " (  0. %%)\n");
574 	    else
575 	      fprintf (out_file, " (%5.1f%%)\n", percent);
576 	    PR_TITLE (GTXT ("Count"));
577 	  }
578 
579 	int max_len1 = max_len;
580 	for (int j = (int) strlen (s) - 1; j >= 0 && s[j] == ' '; j--)
581 	  {
582 	    s[j] = 0;
583 	    max_len1--;
584 	  }
585 	fprintf (out_file, " %*s\n", max_len1, s);
586       }
587 
588       // now add the descriptive information about the object
589       if (htype != Histable::DOBJECT)
590 	{
591 	  Function *func = (Function*) obj->convertto (Histable::FUNCTION);
592 	  if (func && func->get_type () == Histable::FUNCTION)
593 	    {
594 	      // Print the source/object/load-object files & aliases
595 	      oname = lname = alias = NULL;
596 	      sname = func->getDefSrcName ();
597 	      mangle = func->get_mangled_name ();
598 	      if (mangle && streq (func->get_name (), mangle))
599 		mangle = NULL;
600 	      module = func->module;
601 	      if (module)
602 		{
603 		  oname = module->get_name ();
604 		  loadobject = module->loadobject;
605 		  if (loadobject)
606 		    {
607 		      lname = loadobject->get_pathname ();
608 		      alias = loadobject->get_alias (func);
609 		    }
610 		}
611 
612 	      if (htype == Histable::INSTR && dbeSession->is_datamode_available ())
613 		alias = ((DbeInstr*) obj)->get_descriptor ();
614 
615 	      PR (GTXT ("Source File"), sname);
616 	      PR (GTXT ("Object File"), oname);
617 	      PR (GTXT ("Load Object"), lname);
618 	      PR (GTXT ("Mangled Name"), mangle);
619 	      PR (GTXT ("Aliases"), alias);
620 	    }
621 	}
622       else
623 	{
624 	  // Print the dataobject information
625 	  DataObject *dobj = (DataObject*) obj;
626 	  Histable *scope = dobj->get_scope ();
627 
628 	  // print the scope
629 	  PR_TITLE (GTXT ("Scope"));
630 	  if (!scope)
631 	    fprintf (out_file, GTXT ("(Global)\n"));
632 	  else switch (scope->get_type ())
633 	      {
634 	      case Histable::FUNCTION:
635 		fprintf (out_file, NTXT ("%s(%s)\n"),
636 			 ((Function*) scope)->module->get_name (),
637 			 scope->get_name ());
638 		break;
639 	      case Histable::LOADOBJECT:
640 	      case Histable::MODULE:
641 	      default:
642 		fprintf (out_file, NTXT ("%s\n"), scope->get_name ());
643 	      }
644 
645 	  // print the type name
646 	  PR_TITLE (GTXT ("Type"));
647 	  if (dobj->get_typename ())
648 	    fprintf (out_file, NTXT ("%s\n"), dobj->get_typename ());
649 	  else
650 	    fprintf (out_file, GTXT ("(Synthetic)\n"));
651 
652 	  // print the offset
653 	  if (dobj->get_offset () != -1)
654 	    {
655 	      if (dobj->get_parent ())
656 		{
657 		  PR_TITLE (GTXT ("Member of"));
658 		  fprintf (out_file, NTXT ("%s\n"), dobj->get_parent ()->get_name ());
659 		}
660 	      PR_TITLE (GTXT ("Offset (bytes)"));
661 	      fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_offset ());
662 	    }
663 	  // print the size
664 	  if (dobj->get_size ())
665 	    {
666 	      PR_TITLE (GTXT ("Size (bytes)"));
667 	      fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_size ());
668 	    }
669 	}
670       if (hist_data->type == Histable::FUNCTION)
671 	delete current_data;
672     }
673   if (num_printed_items == 0 && sel_obj)
674     fprintf (stderr,
675 	     GTXT ("Error: Specified item `%s' had no recorded metrics.\n"),
676 	     sel_obj->get_name ());
677   delete prop_mlist;
678 }
679 
680 static Metric::HistMetric *
allocateHistMetric(int no_metrics)681 allocateHistMetric (int no_metrics)
682 {
683   Metric::HistMetric *hist_metric = new Metric::HistMetric[no_metrics];
684   for (int i = 0; i < no_metrics; i++)
685     {
686       Metric::HistMetric *hm = &hist_metric[i];
687       hm->init ();
688     }
689   return hist_metric;
690 }
691 
692 void
dump_gprof(int limit)693 er_print_histogram::dump_gprof (int limit)
694 {
695   StringBuilder sb;
696   Histable *obj;
697   Hist_data *callers;
698   Hist_data *callees;
699   Hist_data *center;
700 
701   int no_metrics = mlist->get_items ()->size ();
702   Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
703   for (int i = 0; i < limit; i++)
704     {
705       obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
706       callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
707 				     Hist_data::CALLERS, obj);
708       callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
709 				     Hist_data::CALLEES, obj);
710       center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
711 				    Hist_data::SELF, obj);
712       callers->update_max (hist_metric);
713       callees->update_max (hist_metric);
714       center->update_max (hist_metric);
715       callers->update_legend_width (hist_metric);
716       callers->print_label (out_file, hist_metric, 0);
717       callers->print_content (out_file, hist_metric, callers->size ());
718 
719       if (center->size () > 0)
720 	{
721 	  center->update_total (callers->get_totals ());
722 	  sb.setLength (0);
723 	  center->print_row (&sb, 0, hist_metric, NTXT ("*"));
724 	  sb.toFileLn (out_file);
725 	}
726       callees->print_content (out_file, hist_metric, callees->size ());
727       fprintf (out_file, nl);
728       delete callers;
729       delete callees;
730       delete center;
731     }
732   delete[] hist_metric;
733 }
734 
735 // dump an annotated file
736 void
dump_anno_file(FILE * fp,Histable::Type type,Module * module,DbeView * dbev,MetricList * mlist,TValue * ftotal,const char * srcFile,Function * func,Vector<int> * marks,int threshold,int vis_bits,int src_visible,bool hex_visible,bool src_only)737 dump_anno_file (FILE *fp, Histable::Type type, Module *module, DbeView *dbev,
738 		MetricList *mlist, TValue *ftotal, const char *srcFile,
739 		Function *func, Vector<int> *marks, int threshold, int vis_bits,
740 		int src_visible, bool hex_visible, bool src_only)
741 {
742   int lspace, mspace, tspace, remain, mindex, next_mark, hidx, index;
743   Metric *mitem;
744   char buf[MAX_LEN];
745   Hist_data::HistItem *item;
746 
747   SourceFile *srcContext = NULL;
748   bool func_scope = dbev == NULL ? false : dbev->get_func_scope ();
749   if (srcFile)
750     {
751       srcContext = module->findSource (srcFile, false);
752       if (srcContext == NULL)
753 	{
754 	  Vector<SourceFile*> *includes = module->includes;
755 	  char *bname = get_basename (srcFile);
756 	  for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++)
757 	    {
758 	      SourceFile *sf = includes->fetch (i);
759 	      if (streq (get_basename (sf->get_name ()), bname))
760 		{
761 		  srcContext = sf;
762 		  break;
763 		}
764 	    }
765 	}
766       if (func)
767 	func_scope = true;
768     }
769   else if (func)
770     srcContext = func->getDefSrc ();
771 
772   Hist_data *hdata = module->get_data (dbev, mlist, type, ftotal, srcContext,
773 				       func, marks, threshold, vis_bits,
774 				       src_visible, hex_visible,
775 				       func_scope, src_only);
776 
777   if (hdata == NULL)
778     return;
779 
780   // force the name metric to be invisible
781   MetricList *nmlist = hdata->get_metric_list ();
782   nmlist->find_metric (GTXT ("name"), Metric::STATIC)->clear_all_visbits ();
783   Metric::HistMetric *hist_metric = hdata->get_histmetrics ();
784 
785   // lspace is for max line number that's inserted; use to set width
786   int max_lineno = 0;
787   Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
788   {
789     if (!item->obj)
790       continue;
791     if (item->obj->get_type () == Histable::LINE
792 	&& ((DbeLine*) item->obj)->lineno > max_lineno)
793       max_lineno = ((DbeLine*) item->obj)->lineno;
794     else if (item->obj->get_type () == Histable::INSTR
795 	     && ((DbeInstr*) item->obj)->lineno > max_lineno)
796       max_lineno = ((DbeInstr*) item->obj)->lineno;
797   }
798 
799   lspace = snprintf (buf, sizeof (buf), NTXT ("%d"), max_lineno);
800 
801   // mspace is the space needed for all metrics, and the mark, if any
802   mspace = 0;
803   if (nmlist->get_items ()->size () > 0)
804     {
805       mspace = 3; // mark "## "
806       Vec_loop (Metric*, nmlist->get_items (), index, mitem)
807       {
808 	if (mitem->is_visible () || mitem->is_tvisible ()
809 	    || mitem->is_pvisible ())
810 	  mspace += (int) hist_metric[index].width;
811       }
812     }
813   tspace = 0;
814   remain = (mspace + lspace + 3) % 8; // " " before, ". " after line#
815   if (remain)
816     { // tab alignment
817       tspace = 8 - remain;
818       mspace += tspace;
819     }
820   mindex = 0;
821   next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
822 
823   // Print the header for this list
824   SourceFile *sf = srcContext ? srcContext : module->getMainSrc ();
825   char *src_name = sf->dbeFile->get_location_info ();
826   DbeFile *df = module->dbeFile;
827   if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0)
828     df = module->loadobject->dbeFile;
829   char *lo_name = df->get_location_info ();
830   char *dot_o_name = lo_name;
831   if (module->dot_o_file)
832     dot_o_name = module->dot_o_file->dbeFile->get_location_info ();
833   fprintf (fp, GTXT ("Source file: %s\nObject file: %s\nLoad Object: %s\n\n"),
834 	   src_name, dot_o_name, lo_name);
835 
836   // Print metric labels
837   if (nmlist->get_items ()->size () != 0)
838     print_label (fp, nmlist, hist_metric, 3);
839 
840   // determine the name metric (not printed as a metric, though)
841   int lind = nmlist->get_listorder (GTXT ("name"), Metric::STATIC);
842 
843   // now loop over the data rows -- the lines in the annotated source/disasm,
844   //	including index lines, compiler commentary, etc.
845   StringBuilder sb;
846   Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
847   {
848     sb.setLength (0);
849     if (item->type == Module::AT_DIS || item->type == Module::AT_QUOTE
850 	|| item->type == Module::AT_SRC)
851       {
852 	// does this line get a high-metric mark?
853 	if (hidx == next_mark)
854 	  {
855 	    sb.append (NTXT ("## "));
856 	    mindex++;
857 	    next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
858 	  }
859 	else
860 	  sb.append (NTXT ("   "));
861 
862 	hdata->print_row (&sb, hidx, hist_metric, NTXT (" "));
863 	sb.toFile (fp);
864 	for (int i = sb.length (); i < mspace; i++)
865 	  {
866 	    fputc (' ', fp);
867 	  }
868       }
869     else
870       // this line does not get any metrics; insert blanks in lieu of them
871       for (int i = 0; i < mspace; i++)
872 	fputc (' ', fp);
873 
874     switch (item->type)
875       {
876       case Module::AT_SRC_ONLY:
877 	if (item->obj == NULL)
878 	  fprintf (fp, NTXT ("%*s. "), lspace + 1, "?");
879 	else
880 	  fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
881 	break;
882 
883       case Module::AT_SRC:
884 	fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
885 	break;
886       case Module::AT_FUNC:
887       case Module::AT_QUOTE:
888 	fprintf (fp, NTXT ("%*c"), lspace + 3, ' ');
889 	break;
890       case Module::AT_DIS:
891       case Module::AT_DIS_ONLY:
892 	if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1)
893 	  fprintf (fp, "%*c[%*s] ", lspace + 3, ' ', lspace, "?");
894 	else
895 	  fprintf (fp, "%*c[%*d] ", lspace + 3, ' ', lspace,
896 		   ((DbeInstr*) item->obj)->lineno);
897 	break;
898       case Module::AT_COM:
899       case Module::AT_EMPTY:
900 	break;
901 
902       }
903     if (item->value[lind].l == NULL)
904       item->value[lind].l = dbe_strdup (GTXT ("INTERNAL ERROR: missing line text"));
905     fprintf (fp, NTXT ("%s\n"), item->value[lind].l);
906   }
907   delete hdata;
908 }
909 
910 void
dump_annotated()911 er_print_histogram::dump_annotated ()
912 {
913   Vector<int> *marks = new Vector<int>;
914   Function *anno_func = (Function *) sel_obj;
915   Module *module = anno_func ? anno_func->module : NULL;
916 
917   if (hist_data->type == Histable::DOBJECT)
918     dump_annotated_dataobjects (marks, number_entries); // threshold
919   else if (number_entries == 0)
920       // Annotated source
921     dump_anno_file (out_file, Histable::LINE, module, dbev, mlist,
922 		    hist_data->get_totals ()->value, NULL, anno_func, marks,
923 		    dbev->get_thresh_src (), dbev->get_src_compcom (),
924 		    dbev->get_src_visible (), dbev->get_hex_visible (), true);
925   else
926     // Annotated disassembly
927     dump_anno_file (out_file, Histable::INSTR, module, dbev, mlist,
928 		    hist_data->get_totals ()->value, NULL, anno_func, marks,
929 		    dbev->get_thresh_dis (), dbev->get_dis_compcom (),
930 		    dbev->get_src_visible (), dbev->get_hex_visible (), true);
931 }
932 
933 void
data_dump()934 er_print_histogram::data_dump ()
935 {
936   int limit;
937   if (hist_data->get_status () == Hist_data::SUCCESS)
938     {
939       if (sort_metric[0] == '\n')
940 	{ // csingle Callers-Callees entry
941 	  sort_metric++;
942 	  fprintf (out_file, NTXT ("%s\n\n"), sort_metric);
943 	}
944       else if (!sel_obj && type != MODE_LIST)
945 	{
946 	  if (hist_data->type == Histable::FUNCTION)
947 	    fprintf (out_file,
948 		     GTXT ("Functions sorted by metric: %s\n\n"), sort_metric);
949 	  else if (hist_data->type == Histable::DOBJECT)
950 	    fprintf (out_file, GTXT ("Dataobjects sorted by metric: %s\n\n"),
951 		     sort_metric);
952 	  else
953 	    fprintf (out_file,
954 		     GTXT ("Objects sorted by metric: %s\n\n"), sort_metric);
955 	}
956       limit = hist_data->size ();
957       if ((number_entries > 0) && (number_entries < limit))
958 	limit = number_entries;
959 
960       switch (type)
961 	{
962 	case MODE_LIST:
963 	  dump_list (limit);
964 	  break;
965 	case MODE_DETAIL:
966 	  dump_detail (limit);
967 	  break;
968 	case MODE_GPROF:
969 	  dump_gprof (limit);
970 	  break;
971 	case MODE_ANNOTATED:
972 	  dump_annotated ();
973 	  break;
974 	}
975     }
976   else
977     fprintf (out_file, GTXT ("Get_Hist_data call failed %d\n"),
978 	     (int) hist_data->get_status ());
979 }
980 
981 /*
982  * Class er_print_ctree to print functions call tree
983  */
er_print_ctree(DbeView * _dbev,Vector<Histable * > * _cstack,Histable * _sobj,int _limit)984 er_print_ctree::er_print_ctree (DbeView *_dbev, Vector<Histable*> *_cstack,
985 				Histable *_sobj, int _limit)
986 {
987   dbev = _dbev;
988   cstack = _cstack;
989   sobj = _sobj;
990   limit = _limit;
991   print_row = 0;
992   exp_idx1 = 0;
993   exp_idx2 = dbeSession->nexps () - 1;
994   load = false;
995   header = false;
996 }
997 
998 void
data_dump()999 er_print_ctree::data_dump ()
1000 {
1001   StringBuilder sb;
1002   Hist_data::HistItem *total;
1003   sb.append (GTXT ("Functions Call Tree. Metric: "));
1004   char *s = dbev->getSort (MET_CALL_AGR);
1005   sb.append (s);
1006   free (s);
1007   sb.toFileLn (out_file);
1008   fprintf (out_file, NTXT ("\n"));
1009   mlist = dbev->get_metric_list (MET_CALL_AGR);
1010 
1011   // Change cstack: add sobj to the end of cstack
1012   cstack->append (sobj);
1013   Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1014 					   Hist_data::SELF, cstack);
1015   Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1016 					    Hist_data::CALLERS, cstack);
1017   Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1018 					    Hist_data::CALLEES, cstack);
1019 
1020   // Restore cstack
1021   int last = cstack->size () - 1;
1022   cstack->remove (last);
1023 
1024   // Prepare formats
1025   int no_metrics = mlist->size ();
1026 
1027   // calculate max. width using data from callers, callees, center
1028   hist_metric = allocateHistMetric (no_metrics);
1029   callers->update_max (hist_metric);
1030   callees->update_max (hist_metric);
1031   center->update_max (hist_metric);
1032   callers->update_legend_width (hist_metric);
1033   callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1034 
1035   print_row = 0;
1036   // Pass real total to print_children()
1037   total = center->get_totals ();
1038   print_children (center, 0, sobj, NTXT (" "), total);
1039 
1040   // Free memory
1041   cstack->reset ();
1042   delete callers;
1043   delete callees;
1044   delete center;
1045   delete[] hist_metric;
1046 }
1047 
1048 /*
1049  * Recursive method print_children prints Call Tree elements.
1050  */
1051 void
print_children(Hist_data * data,int index,Histable * my_obj,char * prefix,Hist_data::HistItem * total)1052 er_print_ctree::print_children (Hist_data *data, int index, Histable *my_obj,
1053 				char * prefix, Hist_data::HistItem *total)
1054 {
1055   StringBuilder buf;
1056   const char *P0 = "+-";
1057   const char *P2 = "  |";
1058   const char *P1 = "  ";
1059 
1060   // If limit exceeded - return
1061   ++print_row;
1062   if (limit > 0 && print_row > limit)
1063     return;
1064 
1065   if (my_obj == NULL)
1066     return; // should never happen
1067 
1068   // Prepare prefix
1069   buf.append (prefix);
1070   if (buf.endsWith (P2))
1071     {
1072       int len = buf.length () - 1;
1073       buf.setLength (len);
1074     }
1075   buf.append (P0);
1076 
1077   // Change cstack: add my_obj to the end of cstack
1078   cstack->append (my_obj);
1079 
1080   // Print current node info
1081   char * my_prefix = buf.toString ();
1082 
1083   // Replace parent's total values with real total values
1084   data->update_total (total); // Needed to to calculate percentage only
1085   buf.setLength (0);
1086   data->print_row (&buf, index, hist_metric, my_prefix);
1087   buf.toFileLn (out_file);
1088   free (my_prefix);
1089 
1090   // Get children
1091   Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1092 					    Hist_data::CALLEES, cstack);
1093   int nc = callees->size ();
1094   if (nc > 0)
1095     {
1096       // Print children
1097       Hist_data::HistItem *item;
1098       Histable *ch_obj;
1099       char *ch_prefix;
1100       buf.setLength (0);
1101       buf.append (prefix);
1102       buf.append (P2);
1103       ch_prefix = buf.toString ();
1104       for (int i = 0; i < nc - 1; i++)
1105 	{
1106 	  item = callees->fetch (i);
1107 	  ch_obj = item->obj;
1108 	  print_children (callees, i, ch_obj, ch_prefix, total);
1109 	}
1110       free (ch_prefix);
1111       buf.setLength (0);
1112       buf.append (prefix);
1113       buf.append (P1);
1114       ch_prefix = buf.toString ();
1115       item = callees->fetch (nc - 1);
1116       ch_obj = item->obj;
1117       print_children (callees, nc - 1, ch_obj, ch_prefix, total);
1118       free (ch_prefix);
1119     }
1120 
1121   // Restore cstack
1122   int last = cstack->size () - 1;
1123   cstack->remove (last);
1124   delete callees;
1125   return;
1126 }
1127 
er_print_gprof(DbeView * _dbev,Vector<Histable * > * _cstack)1128 er_print_gprof::er_print_gprof (DbeView *_dbev, Vector<Histable*> *_cstack)
1129 {
1130   dbev = _dbev;
1131   cstack = _cstack;
1132   exp_idx1 = 0;
1133   exp_idx2 = dbeSession->nexps () - 1;
1134   load = false;
1135   header = false;
1136 }
1137 
1138 void
data_dump()1139 er_print_gprof::data_dump ()
1140 {
1141   StringBuilder sb;
1142   sb.append (GTXT ("Callers and callees sorted by metric: "));
1143   char *s = dbev->getSort (MET_CALL);
1144   sb.append (s);
1145   free (s);
1146   sb.toFileLn (out_file);
1147   fprintf (out_file, NTXT ("\n"));
1148 
1149   MetricList *mlist = dbev->get_metric_list (MET_CALL);
1150   Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1151 					   Hist_data::SELF, cstack);
1152   Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1153 					    Hist_data::CALLERS, cstack);
1154   Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1155 					    Hist_data::CALLEES, cstack);
1156 
1157   mlist = center->get_metric_list ();
1158   int no_metrics = mlist->get_items ()->size ();
1159 
1160   // update max. width for callers/callees/center function item
1161   Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
1162   callers->update_max (hist_metric);
1163   callees->update_max (hist_metric);
1164   center->update_max (hist_metric);
1165 
1166   callers->update_legend_width (hist_metric);
1167   int name_offset = callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1168   // Print Callers
1169   sb.setLength (0);
1170   for (int i = 0; i < name_offset; i++)
1171     sb.append (NTXT ("="));
1172   if (name_offset > 0)
1173     sb.append (NTXT (" "));
1174   char *line1 = sb.toString ();
1175   char *line2;
1176   if (callers->size () > 0)
1177     line2 = GTXT ("Callers");
1178   else
1179     line2 = GTXT ("No Callers");
1180   fprintf (out_file, NTXT ("%s%s\n"), line1, line2);
1181   callers->print_content (out_file, hist_metric, callers->size ());
1182 
1183   // Print Stack Fragment
1184   line2 = GTXT ("Stack Fragment");
1185   fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1186 
1187   for (long i = 0, last = cstack->size () - 1; i <= last; ++i)
1188     {
1189       sb.setLength (0);
1190       if (i == last && center->size () > 0)
1191 	{
1192 	  center->update_total (callers->get_totals ()); // Needed to to calculate percentage only
1193 	  center->print_row (&sb, center->size () - 1, hist_metric, NTXT (" "));
1194 	}
1195       else
1196 	{
1197 	  for (int n = name_offset; n > 0; n--)
1198 	    sb.append (NTXT (" "));
1199 	  if (name_offset > 0)
1200 	    sb.append (NTXT (" "));
1201 	  sb.append (cstack->get (i)->get_name ());
1202 	}
1203       sb.toFileLn (out_file);
1204     }
1205 
1206   // Print Callees
1207   if (callees->size () > 0)
1208     line2 = GTXT ("Callees");
1209   else
1210     line2 = GTXT ("No Callees");
1211   fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1212   callees->print_content (out_file, hist_metric, callees->size ());
1213   fprintf (out_file, nl);
1214   free (line1);
1215   delete callers;
1216   delete callees;
1217   delete center;
1218   delete[] hist_metric;
1219 }
1220 
er_print_leaklist(DbeView * _dbev,bool show_leak,bool show_alloca,int _limit)1221 er_print_leaklist::er_print_leaklist (DbeView *_dbev, bool show_leak,
1222 				      bool show_alloca, int _limit)
1223 {
1224   dbev = _dbev;
1225   leak = show_leak;
1226   alloca = show_alloca;
1227   limit = _limit;
1228 }
1229 
1230 // Output routine for leak list only
1231 void
data_dump()1232 er_print_leaklist::data_dump ()
1233 {
1234   CStack_data *lam;
1235   CStack_data::CStack_item *lae;
1236   int index;
1237   if (!dbeSession->is_leaklist_available ())
1238     fprintf (out_file, GTXT ("No leak or allocation information recorded in experiments\n\n"));
1239 
1240   MetricList *origmlist = dbev->get_metric_list (MET_NORMAL);
1241   if (leak)
1242     {
1243       // make a copy of the metric list, and set metrics for leaks
1244       MetricList *nmlist = new MetricList (origmlist);
1245       nmlist->set_metrics ("e.heapleakbytes:e.heapleakcnt:name", true,
1246 			   dbev->get_derived_metrics ());
1247 
1248       // now make a compacted version of it to get the right indices
1249       MetricList *mlist = new MetricList (nmlist);
1250       delete nmlist;
1251 
1252       // fetch the callstack data
1253       lam = dbev->get_cstack_data (mlist);
1254 
1255       // now print it
1256       if (lam && lam->size () != 0)
1257 	{
1258 	  fprintf (out_file, GTXT ("Summary Results: Distinct Leaks = %d, Total Instances = %lld, Total Bytes Leaked = %lld\n\n"),
1259 		   (int) lam->size (), lam->total->value[1].ll,
1260 		   lam->total->value[0].ll);
1261 
1262 	  Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1263 	  {
1264 	    fprintf (out_file,
1265 		     GTXT ("Leak #%d, Instances = %lld, Bytes Leaked = %lld\n"),
1266 		     index + 1, lae->value[1].ll, lae->value[0].ll);
1267 	    if (lae->stack != NULL)
1268 	      for (int i = lae->stack->size () - 1; i >= 0; i--)
1269 		{
1270 		  DbeInstr *instr = lae->stack->fetch (i);
1271 		  fprintf (out_file, NTXT ("  %s\n"), instr->get_name ());
1272 		}
1273 	    fprintf (out_file, NTXT ("\n"));
1274 	    if (index + 1 == limit) break;
1275 	  }
1276 	}
1277       else
1278 	fprintf (out_file, GTXT ("No leak information\n\n"));
1279       delete lam;
1280       delete mlist;
1281     }
1282 
1283   if (alloca)
1284     {
1285       // make a copy of the metric list, and set metrics for leaks
1286       MetricList *nmlist = new MetricList (origmlist);
1287       nmlist->set_metrics ("e.heapallocbytes:e.heapalloccnt:name",
1288 			   true, dbev->get_derived_metrics ());
1289 
1290       // now make a compacted version of it to get the right indices
1291       MetricList *mlist = new MetricList (nmlist);
1292       delete nmlist;
1293 
1294       // fetch the callstack data
1295       lam = dbev->get_cstack_data (mlist);
1296 
1297       // now print it
1298       if (lam && lam->size () != 0)
1299 	{
1300 	  fprintf (out_file, GTXT ("Summary Results: Distinct Allocations = %d, Total Instances = %lld, Total Bytes Allocated = %lld\n\n"),
1301 		   (int) lam->size (), lam->total->value[1].ll,
1302 		   lam->total->value[0].ll);
1303 	  Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1304 	  {
1305 	    fprintf (out_file, GTXT ("Allocation #%d, Instances = %lld, Bytes Allocated = %lld\n"),
1306 		     index + 1, lae->value[1].ll, lae->value[0].ll);
1307 	    if (lae->stack != NULL)
1308 	      for (int i = lae->stack->size () - 1; i >= 0; i--)
1309 		{
1310 		  DbeInstr *instr = lae->stack->fetch (i);
1311 		  fprintf (out_file, NTXT ("  %s\n"), instr->get_name ());
1312 		}
1313 	    fprintf (out_file, NTXT ("\n"));
1314 	    if (index + 1 == limit) break;
1315 	  }
1316 	}
1317       else
1318 	fprintf (out_file, GTXT ("No allocation information\n\n"));
1319       delete lam;
1320       delete mlist;
1321     }
1322 }
1323 
er_print_heapactivity(DbeView * _dbev,Histable::Type _type,bool _printStat,int _limit)1324 er_print_heapactivity::er_print_heapactivity (DbeView *_dbev,
1325 					      Histable::Type _type,
1326 					      bool _printStat, int _limit)
1327 {
1328   dbev = _dbev;
1329   type = _type;
1330   printStat = _printStat;
1331   limit = _limit;
1332 }
1333 
1334 void
printCallStacks(Hist_data * hist_data)1335 er_print_heapactivity::printCallStacks (Hist_data *hist_data)
1336 {
1337   Hist_data::HistItem *hi;
1338   HeapData *hData;
1339   long stackId;
1340   int size = hist_data->size ();
1341   if (limit > 0 && limit < size)
1342     size = limit;
1343 
1344   Histable::NameFormat fmt = dbev->get_name_format ();
1345   for (int i = 0; i < size; i++)
1346     {
1347       hi = hist_data->fetch (i);
1348       hData = (HeapData*) hi->obj;
1349       stackId = hData->id;
1350       if (i != 0)
1351 	fprintf (out_file, NTXT ("\n"));
1352 
1353       fprintf (out_file, NTXT ("%s\n"), hData->get_name (fmt));
1354       if (hData->getAllocCnt () > 0)
1355 	{
1356 	  fprintf (out_file, GTXT ("Instances = %d  "),
1357 		   (int) (hData->getAllocCnt ()));
1358 	  fprintf (out_file, GTXT ("Bytes Allocated = %lld\n"),
1359 		   (long long) hData->getAllocBytes ());
1360 	}
1361 
1362       if (hData->getLeakCnt () > 0)
1363 	{
1364 	  fprintf (out_file, GTXT ("Instances = %d  "),
1365 		   (int) (hData->getLeakCnt ()));
1366 	  fprintf (out_file, GTXT ("Bytes Leaked = %lld\n"),
1367 		   (long long) hData->getLeakBytes ());
1368 	}
1369 
1370       // There is no stack trace for <Total>
1371       if (i == 0)
1372 	continue;
1373 
1374       // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
1375       Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
1376       if (instrs != NULL)
1377 	{
1378 	  int stSize = instrs->size ();
1379 	  for (int j = 0; j < stSize; j++)
1380 	    {
1381 	      Histable *instr = instrs->fetch (j);
1382 	      if (instr != NULL)
1383 		fprintf (out_file, NTXT ("  %s\n"), instr->get_name ());
1384 	    }
1385 	  delete instrs;
1386 	}
1387     }
1388 }
1389 
1390 void
printStatistics(Hist_data * hist_data)1391 er_print_heapactivity::printStatistics (Hist_data *hist_data)
1392 {
1393   Hist_data::HistItem *hi;
1394   HeapData *hDataTotal;
1395   hi = hist_data->fetch (0);
1396   hDataTotal = (HeapData*) hi->obj;
1397   Vector<hrtime_t> *pTimestamps;
1398   if (hDataTotal->getPeakMemUsage () > 0)
1399     {
1400       fprintf (out_file, GTXT ("\nProcess With Highest Peak Memory Usage\n"));
1401       fprintf (out_file,
1402 	       "-------------------------------------------------------\n");
1403       fprintf (out_file, GTXT ("Heap size bytes                   %lld\n"),
1404 	       (long long) hDataTotal->getPeakMemUsage ());
1405       fprintf (out_file, GTXT ("Experiment Id                     %d\n"),
1406 	       (int) (hDataTotal->getUserExpId ()));
1407       fprintf (out_file, GTXT ("Process Id                        %d\n"),
1408 	       (int) (hDataTotal->getPid ()));
1409       pTimestamps = hDataTotal->getPeakTimestamps ();
1410       if (pTimestamps != NULL)
1411 	for (int i = 0; i < pTimestamps->size (); i++)
1412 	  fprintf (out_file,
1413 		   GTXT ("Time of peak                      %.3f (secs.)\n"),
1414 		   (double) (pTimestamps->fetch (i) / (double) NANOSEC));
1415     }
1416 
1417   if (hDataTotal->getAllocCnt () > 0)
1418     {
1419       fprintf (out_file, GTXT ("\nMemory Allocations Statistics\n"));
1420       fprintf (out_file,
1421 	       GTXT ("Allocation Size Range             Allocations          \n"));
1422       fprintf (out_file,
1423 	       "-------------------------------------------------------\n");
1424       if (hDataTotal->getA0KB1KBCnt () > 0)
1425 	fprintf (out_file, NTXT ("  0KB - 1KB                       %d\n"),
1426 		 hDataTotal->getA0KB1KBCnt ());
1427       if (hDataTotal->getA1KB8KBCnt () > 0)
1428 	fprintf (out_file, NTXT ("  1KB - 8KB                       %d\n"),
1429 		 hDataTotal->getA1KB8KBCnt ());
1430       if (hDataTotal->getA8KB32KBCnt () > 0)
1431 	fprintf (out_file, NTXT ("  8KB - 32KB                      %d\n"),
1432 		 hDataTotal->getA8KB32KBCnt ());
1433       if (hDataTotal->getA32KB128KBCnt () > 0)
1434 	fprintf (out_file, NTXT ("  32KB - 128KB                    %d\n"),
1435 		 hDataTotal->getA32KB128KBCnt ());
1436       if (hDataTotal->getA128KB256KBCnt () > 0)
1437 	fprintf (out_file, NTXT ("  128KB - 256KB                   %d\n"),
1438 		 hDataTotal->getA128KB256KBCnt ());
1439       if (hDataTotal->getA256KB512KBCnt () > 0)
1440 	fprintf (out_file, NTXT ("  256KB - 512KB                   %d\n"),
1441 		 hDataTotal->getA256KB512KBCnt ());
1442       if (hDataTotal->getA512KB1000KBCnt () > 0)
1443 	fprintf (out_file, NTXT ("  512KB - 1000KB                  %d\n"),
1444 		 hDataTotal->getA512KB1000KBCnt ());
1445       if (hDataTotal->getA1000KB10MBCnt () > 0)
1446 	fprintf (out_file, NTXT ("  1000KB - 10MB                   %d\n"),
1447 		 hDataTotal->getA1000KB10MBCnt ());
1448       if (hDataTotal->getA10MB100MBCnt () > 0)
1449 	fprintf (out_file, NTXT ("  10MB - 100MB                    %d\n"),
1450 		 hDataTotal->getA10MB100MBCnt ());
1451       if (hDataTotal->getA100MB1GBCnt () > 0)
1452 	fprintf (out_file, NTXT ("  100MB - 1GB                     %d\n"),
1453 		 hDataTotal->getA100MB1GBCnt ());
1454       if (hDataTotal->getA1GB10GBCnt () > 0)
1455 	fprintf (out_file, NTXT ("  1GB - 10GB                      %d\n"),
1456 		 hDataTotal->getA1GB10GBCnt ());
1457       if (hDataTotal->getA10GB100GBCnt () > 0)
1458 	fprintf (out_file, NTXT ("  10GB - 100GB                    %d\n"),
1459 		 hDataTotal->getA10GB100GBCnt ());
1460       if (hDataTotal->getA100GB1TBCnt () > 0)
1461 	fprintf (out_file, NTXT ("  100GB - 1TB                     %d\n"),
1462 		 hDataTotal->getA100GB1TBCnt ());
1463       if (hDataTotal->getA1TB10TBCnt () > 0)
1464 	fprintf (out_file, NTXT ("  1TB - 10TB                      %d\n"),
1465 		 hDataTotal->getA1TB10TBCnt ());
1466       fprintf (out_file, GTXT ("\nSmallest allocation bytes         %lld\n"),
1467 	       (long long) hDataTotal->getASmallestBytes ());
1468       fprintf (out_file, GTXT ("Largest allocation bytes          %lld\n"),
1469 	       (long long) hDataTotal->getALargestBytes ());
1470       fprintf (out_file, GTXT ("Total allocations                 %d\n"),
1471 	       hDataTotal->getAllocCnt ());
1472       fprintf (out_file, GTXT ("Total bytes                       %lld\n"),
1473 	       (long long) hDataTotal->getAllocBytes ());
1474     }
1475 
1476   if (hDataTotal->getLeakCnt () > 0)
1477     {
1478       fprintf (out_file, GTXT ("\nMemory Leaks Statistics\n"));
1479       fprintf (out_file,
1480 	       GTXT ("Leak Size Range                   Leaks              \n"));
1481       fprintf (out_file,
1482 	       "-------------------------------------------------------\n");
1483       if (hDataTotal->getL0KB1KBCnt () > 0)
1484 	fprintf (out_file, NTXT ("  0KB - 1KB                       %d\n"),
1485 		 hDataTotal->getL0KB1KBCnt ());
1486       if (hDataTotal->getL1KB8KBCnt () > 0)
1487 	fprintf (out_file, NTXT ("  1KB - 8KB                       %d\n"),
1488 		 hDataTotal->getL1KB8KBCnt ());
1489       if (hDataTotal->getL8KB32KBCnt () > 0)
1490 	fprintf (out_file, NTXT ("  8KB - 32KB                      %d\n"),
1491 		 hDataTotal->getL8KB32KBCnt ());
1492       if (hDataTotal->getL32KB128KBCnt () > 0)
1493 	fprintf (out_file, NTXT ("  32KB - 128KB                    %d\n"),
1494 		 hDataTotal->getL32KB128KBCnt ());
1495       if (hDataTotal->getL128KB256KBCnt () > 0)
1496 	fprintf (out_file, NTXT ("  128KB - 256KB                   %d\n"),
1497 		 hDataTotal->getL128KB256KBCnt ());
1498       if (hDataTotal->getL256KB512KBCnt () > 0)
1499 	fprintf (out_file, NTXT ("  256KB - 512KB                   %d\n"),
1500 		 hDataTotal->getL256KB512KBCnt ());
1501       if (hDataTotal->getL512KB1000KBCnt () > 0)
1502 	fprintf (out_file, NTXT ("  512KB - 1000KB                  %d\n"),
1503 		 hDataTotal->getL512KB1000KBCnt ());
1504       if (hDataTotal->getL1000KB10MBCnt () > 0)
1505 	fprintf (out_file, NTXT ("  1000KB - 10MB                   %d\n"),
1506 		 hDataTotal->getL1000KB10MBCnt ());
1507       if (hDataTotal->getL10MB100MBCnt () > 0)
1508 	fprintf (out_file, NTXT ("  10MB - 100MB                    %d\n"),
1509 		 hDataTotal->getL10MB100MBCnt ());
1510       if (hDataTotal->getL100MB1GBCnt () > 0)
1511 	fprintf (out_file, NTXT ("  100MB - 1GB                     %d\n"),
1512 		 hDataTotal->getL100MB1GBCnt ());
1513       if (hDataTotal->getL1GB10GBCnt () > 0)
1514 	fprintf (out_file, NTXT ("  1GB - 10GB                      %d\n"),
1515 		 hDataTotal->getL1GB10GBCnt ());
1516       if (hDataTotal->getL10GB100GBCnt () > 0)
1517 	fprintf (out_file, NTXT ("  10GB - 100GB                    %d\n"),
1518 		 hDataTotal->getL10GB100GBCnt ());
1519       if (hDataTotal->getL100GB1TBCnt () > 0)
1520 	fprintf (out_file, NTXT ("  100GB - 1TB                     %d\n"),
1521 		 hDataTotal->getL100GB1TBCnt ());
1522       if (hDataTotal->getL1TB10TBCnt () > 0)
1523 	fprintf (out_file, NTXT ("  1TB - 10TB                      %d\n"),
1524 		 hDataTotal->getL1TB10TBCnt ());
1525       fprintf (out_file, GTXT ("\nSmallest leaked bytes             %lld\n"),
1526 	       (long long) hDataTotal->getLSmallestBytes ());
1527       fprintf (out_file, GTXT ("Largest leaked bytes              %lld\n"),
1528 	       (long long) hDataTotal->getLLargestBytes ());
1529       fprintf (out_file, GTXT ("Total leaked                      %d \n"),
1530 	       hDataTotal->getLeakCnt ());
1531       fprintf (out_file, GTXT ("Total bytes                       %lld\n"),
1532 	       (long long) hDataTotal->getLeakBytes ());
1533     }
1534   fprintf (out_file, NTXT ("\n"));
1535 }
1536 
1537 void
data_dump()1538 er_print_heapactivity::data_dump ()
1539 {
1540   // get the list of heap events from DbeView
1541   int numExps = dbeSession->nexps ();
1542   if (!numExps)
1543     {
1544       fprintf (out_file,
1545 	       GTXT ("There is no heap event information in the experiments\n"));
1546       return;
1547     }
1548   MetricList *mlist = dbev->get_metric_list (MET_HEAP);
1549   Hist_data *hist_data;
1550   hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
1551   if (printStat)
1552     printStatistics (hist_data);
1553   else
1554     printCallStacks (hist_data);
1555 }
1556 
er_print_ioactivity(DbeView * _dbev,Histable::Type _type,bool _printStat,int _limit)1557 er_print_ioactivity::er_print_ioactivity (DbeView *_dbev, Histable::Type _type,
1558 					  bool _printStat, int _limit)
1559 {
1560   dbev = _dbev;
1561   type = _type;
1562   printStat = _printStat;
1563   limit = _limit;
1564 }
1565 
1566 void
printCallStacks(Hist_data * hist_data)1567 er_print_ioactivity::printCallStacks (Hist_data *hist_data)
1568 {
1569   Hist_data::HistItem *hi;
1570   FileData *fData;
1571   long stackId;
1572   int size = hist_data->size ();
1573   if (limit > 0 && limit < size)
1574     size = limit;
1575 
1576   for (int i = 0; i < size; i++)
1577     {
1578       hi = hist_data->fetch (i);
1579       fData = (FileData*) hi->obj;
1580       stackId = fData->id;
1581       if (i != 0)
1582 	fprintf (out_file, NTXT ("\n"));
1583       fprintf (out_file, NTXT ("%s\n"), fData->getFileName ());
1584       if (fData->getWriteCnt () > 0)
1585 	{
1586 	  fprintf (out_file, GTXT ("Write Time=%.6f (secs.)  "),
1587 		   (double) (fData->getWriteTime () / (double) NANOSEC));
1588 	  fprintf (out_file, GTXT ("Write Bytes=%lld  "),
1589 		   (long long) fData->getWriteBytes ());
1590 	  fprintf (out_file, GTXT ("Write Count=%d\n"),
1591 		   (int) (fData->getWriteCnt ()));
1592 	}
1593       if (fData->getReadCnt () > 0)
1594 	{
1595 	  fprintf (out_file, GTXT ("Read Time=%.6f (secs.)  "),
1596 		   (double) (fData->getReadTime () / (double) NANOSEC));
1597 	  fprintf (out_file, GTXT ("Read Bytes=%lld  "),
1598 		   (long long) fData->getReadBytes ());
1599 	  fprintf (out_file, GTXT ("Read Count=%d\n"),
1600 		   (int) fData->getReadCnt ());
1601 	}
1602       if (fData->getOtherCnt () > 0)
1603 	{
1604 	  fprintf (out_file, GTXT ("Other I/O Time=%.6f (secs.)  "),
1605 		   (double) (fData->getOtherTime () / (double) NANOSEC));
1606 	  fprintf (out_file, GTXT ("Other I/O Count=%d\n"),
1607 		   (int) (fData->getOtherCnt ()));
1608 	}
1609       if (fData->getErrorCnt () > 0)
1610 	{
1611 	  fprintf (out_file, GTXT ("I/O Error Time=%.6f (secs.)  "),
1612 		   (double) (fData->getErrorTime () / (double) NANOSEC));
1613 	  fprintf (out_file, GTXT ("I/O Error Count=%d\n"),
1614 		   (int) (fData->getErrorCnt ()));
1615 	}
1616 
1617       // There is no stack trace for <Total>
1618       if (i == 0)
1619 	continue;
1620 
1621       // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
1622       Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
1623       if (instrs != NULL)
1624 	{
1625 	  int stSize = instrs->size ();
1626 	  for (int j = 0; j < stSize; j++)
1627 	    {
1628 	      Histable *instr = instrs->fetch (j);
1629 	      if (instr != NULL)
1630 		fprintf (out_file, "  %s\n", instr->get_name ());
1631 	    }
1632 	  delete instrs;
1633 	}
1634     }
1635 }
1636 
1637 void
printStatistics(Hist_data * hist_data)1638 er_print_ioactivity::printStatistics (Hist_data *hist_data)
1639 {
1640   Hist_data::HistItem *hi;
1641   FileData *fDataTotal;
1642 
1643   hi = hist_data->fetch (0);
1644   fDataTotal = (FileData*) hi->obj;
1645 
1646   if (fDataTotal->getWriteCnt () > 0)
1647     {
1648       fprintf (out_file,
1649 	       GTXT ("\nWrite Statistics\n"));
1650       fprintf (out_file,
1651 	       GTXT ("I/O Size Range                    Write Calls          \n"));
1652       fprintf (out_file,
1653 	       "-------------------------------------------------------\n");
1654       if (fDataTotal->getW0KB1KBCnt () > 0)
1655 	fprintf (out_file, NTXT ("  0KB - 1KB                       %d\n"),
1656 		 fDataTotal->getW0KB1KBCnt ());
1657       if (fDataTotal->getW1KB8KBCnt () > 0)
1658 	fprintf (out_file, NTXT ("  1KB - 8KB                       %d\n"),
1659 		 fDataTotal->getW1KB8KBCnt ());
1660       if (fDataTotal->getW8KB32KBCnt () > 0)
1661 	fprintf (out_file, NTXT ("  8KB - 32KB                      %d\n"),
1662 		 fDataTotal->getW8KB32KBCnt ());
1663       if (fDataTotal->getW32KB128KBCnt () > 0)
1664 	fprintf (out_file, NTXT ("  32KB - 128KB                    %d\n"),
1665 		 fDataTotal->getW32KB128KBCnt ());
1666       if (fDataTotal->getW128KB256KBCnt () > 0)
1667 	fprintf (out_file, NTXT ("  128KB - 256KB                   %d\n"),
1668 		 fDataTotal->getW128KB256KBCnt ());
1669       if (fDataTotal->getW256KB512KBCnt () > 0)
1670 	fprintf (out_file, NTXT ("  256KB - 512KB                   %d\n"),
1671 		 fDataTotal->getW256KB512KBCnt ());
1672       if (fDataTotal->getW512KB1000KBCnt () > 0)
1673 	fprintf (out_file, NTXT ("  512KB - 1000KB                  %d\n"),
1674 		 fDataTotal->getW512KB1000KBCnt ());
1675       if (fDataTotal->getW1000KB10MBCnt () > 0)
1676 	fprintf (out_file, NTXT ("  1000KB - 10MB                   %d\n"),
1677 		 fDataTotal->getW1000KB10MBCnt ());
1678       if (fDataTotal->getW10MB100MBCnt () > 0)
1679 	fprintf (out_file, NTXT ("  10MB - 100MB                    %d\n"),
1680 		 fDataTotal->getW10MB100MBCnt ());
1681       if (fDataTotal->getW100MB1GBCnt () > 0)
1682 	fprintf (out_file, NTXT ("  100MB - 1GB                     %d\n"),
1683 		 fDataTotal->getW100MB1GBCnt ());
1684       if (fDataTotal->getW1GB10GBCnt () > 0)
1685 	fprintf (out_file, NTXT ("  1GB - 10GB                     %d\n"),
1686 		 fDataTotal->getW1GB10GBCnt ());
1687       if (fDataTotal->getW10GB100GBCnt () > 0)
1688 	fprintf (out_file, NTXT ("  10GB - 100GB                   %d\n"),
1689 		 fDataTotal->getW10GB100GBCnt ());
1690       if (fDataTotal->getW100GB1TBCnt () > 0)
1691 	fprintf (out_file, NTXT ("  100GB - 1TB                    %d\n"),
1692 		 fDataTotal->getW100GB1TBCnt ());
1693       if (fDataTotal->getW1TB10TBCnt () > 0)
1694 	fprintf (out_file, NTXT ("  1TB - 10TB                     %d\n"),
1695 		 fDataTotal->getW1TB10TBCnt ());
1696       fprintf (out_file,
1697 	       GTXT ("\nLongest write                     %.6f (secs.)\n"),
1698 	       (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC));
1699       fprintf (out_file, GTXT ("Smallest write bytes              %lld\n"),
1700 	       (long long) fDataTotal->getWSmallestBytes ());
1701       fprintf (out_file, GTXT ("Largest write bytes               %lld\n"),
1702 	       (long long) fDataTotal->getWLargestBytes ());
1703       fprintf (out_file,
1704 	       GTXT ("Total time                        %.6f (secs.)\n"),
1705 	       (double) (fDataTotal->getWriteTime () / (double) NANOSEC));
1706       fprintf (out_file, GTXT ("Total calls                       %d\n"),
1707 	       fDataTotal->getWriteCnt ());
1708       fprintf (out_file, GTXT ("Total bytes                       %lld\n"),
1709 	       (long long) fDataTotal->getWriteBytes ());
1710     }
1711 
1712   if (fDataTotal->getReadCnt () > 0)
1713     {
1714       fprintf (out_file,
1715 	       GTXT ("\nRead Statistics\n"));
1716       fprintf (out_file,
1717 	       GTXT ("I/O Size Range                    Read Calls         \n"));
1718       fprintf (out_file,
1719 	       "------------------------------------------------------\n");
1720       if (fDataTotal->getR0KB1KBCnt () > 0)
1721 	fprintf (out_file, NTXT ("  0KB - 1KB                       %d\n"),
1722 		 fDataTotal->getR0KB1KBCnt ());
1723       if (fDataTotal->getR1KB8KBCnt () > 0)
1724 	fprintf (out_file, NTXT ("  1KB - 8KB                       %d\n"),
1725 		 fDataTotal->getR1KB8KBCnt ());
1726       if (fDataTotal->getR8KB32KBCnt () > 0)
1727 	fprintf (out_file, NTXT ("  8KB - 32KB                      %d\n"),
1728 		 fDataTotal->getR8KB32KBCnt ());
1729       if (fDataTotal->getR32KB128KBCnt () > 0)
1730 	fprintf (out_file, NTXT ("  32KB - 128KB                    %d\n"),
1731 		 fDataTotal->getR32KB128KBCnt ());
1732       if (fDataTotal->getR128KB256KBCnt () > 0)
1733 	fprintf (out_file, NTXT ("  128KB - 256KB                   %d\n"),
1734 		 fDataTotal->getR128KB256KBCnt ());
1735       if (fDataTotal->getR256KB512KBCnt () > 0)
1736 	fprintf (out_file, NTXT ("  256KB - 512KB                   %d\n"),
1737 		 fDataTotal->getR256KB512KBCnt ());
1738       if (fDataTotal->getR512KB1000KBCnt () > 0)
1739 	fprintf (out_file, NTXT ("  512KB - 1000KB                  %d\n"),
1740 		 fDataTotal->getR512KB1000KBCnt ());
1741       if (fDataTotal->getR1000KB10MBCnt () > 0)
1742 	fprintf (out_file, NTXT ("  1000KB - 10MB                   %d\n"),
1743 		 fDataTotal->getR1000KB10MBCnt ());
1744       if (fDataTotal->getR10MB100MBCnt () > 0)
1745 	fprintf (out_file, NTXT ("  10MB - 100MB                    %d\n"),
1746 		 fDataTotal->getR10MB100MBCnt ());
1747       if (fDataTotal->getR100MB1GBCnt () > 0)
1748 	fprintf (out_file, NTXT ("  100MB - 1GB                     %d\n"),
1749 		 fDataTotal->getR100MB1GBCnt ());
1750       if (fDataTotal->getR1GB10GBCnt () > 0)
1751 	fprintf (out_file, NTXT ("  1GB - 10GB                      %d\n"),
1752 		 fDataTotal->getR1GB10GBCnt ());
1753       if (fDataTotal->getR10GB100GBCnt () > 0)
1754 	fprintf (out_file, NTXT ("  10GB - 100GB                    %d\n"),
1755 		 fDataTotal->getR10GB100GBCnt ());
1756       if (fDataTotal->getR100GB1TBCnt () > 0)
1757 	fprintf (out_file, NTXT ("  100GB - 1TB                     %d\n"),
1758 		 fDataTotal->getR100GB1TBCnt ());
1759       if (fDataTotal->getR1TB10TBCnt () > 0)
1760 	fprintf (out_file, NTXT ("  1TB - 10TB                      %d\n"),
1761 		 fDataTotal->getR1TB10TBCnt ());
1762       fprintf (out_file,
1763 	       GTXT ("\nLongest time                      %.6f (secs.)\n"),
1764 	       (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC));
1765       fprintf (out_file, GTXT ("Smallest read bytes               %lld\n"),
1766 	       (long long) fDataTotal->getRSmallestBytes ());
1767       fprintf (out_file, GTXT ("Largest read bytes                %lld\n"),
1768 	       (long long) fDataTotal->getRLargestBytes ());
1769       fprintf (out_file,
1770 	       GTXT ("Total time                        %.6f (secs.)\n"),
1771 	       (double) (fDataTotal->getReadTime () / (double) NANOSEC));
1772       fprintf (out_file, GTXT ("Total calls                       %d\n"),
1773 	       fDataTotal->getReadCnt ());
1774       fprintf (out_file, GTXT ("Total bytes                       %lld\n"),
1775 	       (long long) fDataTotal->getReadBytes ());
1776     }
1777 
1778   if (fDataTotal->getOtherCnt () > 0)
1779     {
1780       fprintf (out_file, GTXT ("\nOther I/O Statistics\n"));
1781       fprintf (out_file,
1782 	       "-----------------------------------------------------\n");
1783       fprintf (out_file,
1784 	       GTXT ("Total time                        %.6f (secs.)\n"),
1785 	       (double) (fDataTotal->getOtherTime () / (double) NANOSEC));
1786       fprintf (out_file, GTXT ("Total calls                       %d \n"),
1787 	       fDataTotal->getOtherCnt ());
1788     }
1789   if (fDataTotal->getErrorCnt () > 0)
1790     {
1791       fprintf (out_file, GTXT ("\nI/O Error Statistics\n"));
1792       fprintf (out_file,
1793 	       "-----------------------------------------------------\n");
1794       fprintf (out_file,
1795 	       GTXT ("Total time                        %.6f (secs.)\n"),
1796 	       (double) (fDataTotal->getErrorTime () / (double) NANOSEC));
1797       fprintf (out_file, GTXT ("Total calls                       %d \n"),
1798 	       fDataTotal->getErrorCnt ());
1799     }
1800   fprintf (out_file, NTXT ("\n"));
1801 }
1802 
1803 void
data_dump()1804 er_print_ioactivity::data_dump ()
1805 {
1806   // get the list of io events from DbeView
1807   int numExps = dbeSession->nexps ();
1808   if (!numExps)
1809     {
1810       fprintf (out_file,
1811 	       GTXT ("There is no IO event information in the experiments\n"));
1812       return;
1813     }
1814 
1815   MetricList *mlist = dbev->get_metric_list (MET_IO);
1816   Hist_data *hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
1817   if (type == Histable::IOCALLSTACK)
1818     printCallStacks (hist_data);
1819   else if (printStat)
1820     printStatistics (hist_data);
1821   else
1822     {
1823       Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
1824       hist_data->print_label (out_file, hist_metric, 0);
1825       hist_data->print_content (out_file, hist_metric, limit);
1826       fprintf (out_file, nl);
1827     }
1828 }
1829 
er_print_experiment(DbeView * _dbev,int bgn_idx,int end_idx,bool show_load,bool show_header,bool show_stat,bool show_over,bool show_odetail)1830 er_print_experiment::er_print_experiment (DbeView *_dbev, int bgn_idx,
1831 					  int end_idx, bool show_load,
1832 					  bool show_header, bool show_stat,
1833 					  bool show_over, bool show_odetail)
1834 {
1835   dbev = _dbev;
1836   exp_idx1 = bgn_idx;
1837   exp_idx2 = end_idx;
1838   load = show_load;
1839   header = show_header;
1840   stat = show_stat;
1841   over = show_over;
1842   odetail = show_odetail;
1843 }
1844 
1845 void
data_dump()1846 er_print_experiment::data_dump ()
1847 {
1848   int index, maxlen;
1849 
1850   maxlen = 0;
1851 
1852   if (stat)
1853     {
1854       max_len1 = 50;
1855       if (exp_idx2 > exp_idx1)
1856 	{
1857 	  statistics_sum (maxlen);
1858 	  fprintf (out_file, nl);
1859 	}
1860 
1861       for (index = exp_idx1; index <= exp_idx2; index++)
1862 	statistics_dump (index, maxlen);
1863     }
1864   else if (over)
1865     {
1866       max_len1 = 50;
1867       if (exp_idx2 > exp_idx1)
1868 	{
1869 	  overview_sum (maxlen);
1870 	  fprintf (out_file, nl);
1871 	}
1872 
1873       for (index = exp_idx1; index <= exp_idx2; index++)
1874 	overview_dump (index, maxlen);
1875     }
1876   else if (header)
1877     for (index = exp_idx1; index <= exp_idx2; index++)
1878       {
1879 	if (index != exp_idx1)
1880 	  fprintf (out_file,
1881 		   "----------------------------------------------------------------\n");
1882        header_dump (index);
1883       }
1884 }
1885 
1886 void
overview_sum(int & maxlen)1887 er_print_experiment::overview_sum (int &maxlen)
1888 {
1889   int index;
1890   Ovw_data *sum_data = new Ovw_data ();
1891   for (index = exp_idx1; index <= exp_idx2; index++)
1892     {
1893       Ovw_data *ovw_data = dbev->get_ovw_data (index);
1894       if (ovw_data == NULL)
1895 	continue;
1896       sum_data->sum (ovw_data);
1897       delete ovw_data;
1898     }
1899 
1900   fprintf (out_file, GTXT ("<Sum across selected experiments>"));
1901   fprintf (out_file, nl);
1902   overview_summary (sum_data, maxlen);
1903   fprintf (out_file, nl);
1904   delete sum_data;
1905 }
1906 
1907 void
overview_dump(int exp_idx,int & maxlen)1908 er_print_experiment::overview_dump (int exp_idx, int &maxlen)
1909 {
1910   Ovw_data *ovw_data;
1911   Ovw_data::Ovw_item ovw_item_labels;
1912   Ovw_data::Ovw_item ovw_item;
1913   int index;
1914   int size;
1915 
1916   ovw_data = dbev->get_ovw_data (exp_idx);
1917   if (ovw_data == NULL)
1918     return;
1919   if (pr_params.header)
1920     header_dump (exp_idx);
1921   else if (odetail)
1922     fprintf (out_file, GTXT ("Experiment: %s\n"),
1923 	     dbeSession->get_exp (exp_idx)->get_expt_name ());
1924 
1925   overview_summary (ovw_data, maxlen);
1926   if (!odetail)
1927     {
1928       delete ovw_data;
1929       return;
1930     }
1931 
1932   //Get the collection params for the sample selection and display them.
1933   fprintf (out_file, "\n\n%*s\n\n", max_len1, GTXT ("Individual samples"));
1934 
1935   size = ovw_data->size ();
1936   ovw_item_labels = ovw_data->get_labels ();
1937 
1938   for (index = 0; index < size; index++)
1939     {
1940       ovw_item = ovw_data->fetch (index);
1941       fprintf (out_file, "%*s: %d\n\n", max_len1, GTXT ("Sample Number"),
1942 	       ovw_item.number);
1943       overview_item (&ovw_item, &ovw_item_labels);
1944       fprintf (out_file, nl);
1945     }
1946 
1947   delete ovw_data;
1948 }
1949 
1950 void
overview_summary(Ovw_data * ovw_data,int & maxlen)1951 er_print_experiment::overview_summary (Ovw_data *ovw_data, int &maxlen)
1952 {
1953   char buf[128];
1954   int len;
1955   Ovw_data::Ovw_item totals;
1956   Ovw_data::Ovw_item ovw_item_labels;
1957   totals = ovw_data->get_totals ();
1958   len = snprintf (buf, sizeof (buf), "%.3lf", tstodouble (totals.total.t));
1959   if (maxlen < len)
1960     maxlen = len;
1961   max_len2 = maxlen;
1962   max_len3 = maxlen;
1963   fprintf (out_file, "%*s\n\n", max_len1,
1964 	   GTXT ("Aggregated statistics for selected samples"));
1965 
1966   ovw_item_labels = ovw_data->get_labels ();
1967   overview_item (&totals, &ovw_item_labels);
1968 }
1969 
1970 void
overview_item(Ovw_data::Ovw_item * ovw_item,Ovw_data::Ovw_item * ovw_item_labels)1971 er_print_experiment::overview_item (Ovw_data::Ovw_item *ovw_item,
1972 				    Ovw_data::Ovw_item *ovw_item_labels)
1973 {
1974   double start, end, total_value;
1975   int index, size;
1976   timestruc_t total_time = {0, 0};
1977 
1978   start = tstodouble (ovw_item->start);
1979   end = tstodouble (ovw_item->end);
1980 
1981   fprintf (out_file, "%*s: %s\n", max_len1, GTXT ("Start Label"),
1982 	   ovw_item->start_label);
1983   fprintf (out_file, "%*s: %s\n", max_len1, GTXT ("End Label"),
1984 	   ovw_item->end_label);
1985 
1986   fprintf (out_file, "%*s: ", max_len1, GTXT ("Start Time (sec.)"));
1987   if (start == -1.0)
1988     fprintf (out_file, GTXT ("N/A"));
1989   else
1990     fprintf (out_file, "%*.3f", max_len2, start);
1991   fprintf (out_file, nl);
1992   fprintf (out_file, "%*s: ", max_len1, GTXT ("End Time (sec.)"));
1993   if (end == -1.0)
1994     fprintf (out_file, GTXT ("N/A"));
1995   else
1996     fprintf (out_file, "%*.3f", max_len2, end);
1997   fprintf (out_file, nl);
1998   fprintf (out_file, "%*s: ", max_len1, GTXT ("Duration (sec.)"));
1999   fprintf (out_file, "%*.3f", max_len2, tstodouble (ovw_item->duration));
2000   fprintf (out_file, NTXT ("\n"));
2001 
2002   size = ovw_item->size;
2003   for (index = 0; index < size; index++)
2004     tsadd (&total_time, &ovw_item->values[index].t);
2005 
2006   total_value = tstodouble (total_time);
2007   fprintf (out_file, "%*s: %*.3f", max_len1, GTXT ("Total Thread Time (sec.)"),
2008 	   max_len2, tstodouble (ovw_item->tlwp));
2009   fprintf (out_file, NTXT ("\n"));
2010   fprintf (out_file, "%*s: ", max_len1, GTXT ("Average number of Threads"));
2011   if (tstodouble (ovw_item->duration) != 0)
2012     fprintf (out_file, "%*.3f", max_len2, ovw_item->nlwp);
2013   else
2014     fprintf (out_file, GTXT ("N/A"));
2015   fprintf (out_file, NTXT ("\n\n"));
2016   fprintf (out_file, "%*s:\n", max_len1, GTXT ("Process Times (sec.)"));
2017   for (index = 1; index < size; index++)
2018     {
2019       overview_value (&ovw_item_labels->values[index], ovw_item_labels->type,
2020 		      total_value);
2021       overview_value (&ovw_item->values[index], ovw_item->type,
2022 		      total_value);
2023       fprintf (out_file, NTXT ("\n"));
2024     }
2025 }
2026 
2027 void
overview_value(Value * value,ValueTag value_tag,double total_value)2028 er_print_experiment::overview_value (Value *value, ValueTag value_tag,
2029 				     double total_value)
2030 {
2031   double dvalue;
2032   switch (value_tag)
2033     {
2034     case VT_LABEL:
2035       fprintf (out_file, "%*s: ", max_len1, value->l);
2036       break;
2037     case VT_HRTIME:
2038       dvalue = tstodouble (value->t);
2039       if (dvalue == 0.0)
2040 	fprintf (out_file, "%*s (  0. %%)", max_len3, "0.   ");
2041       else
2042 	fprintf (out_file, "%*.3f (%5.1f%%)", max_len3, dvalue,
2043 		 100.0 * dvalue / total_value);
2044       break;
2045     case VT_INT:
2046       fprintf (out_file, NTXT ("%d"), value->i);
2047       break;
2048     default:
2049       fprintf (out_file, "%*.3f", max_len3, total_value);
2050     }
2051 }
2052 
2053 void
statistics_sum(int & maxlen)2054 er_print_experiment::statistics_sum (int &maxlen)
2055 {
2056   int index;
2057   int size, len;
2058   Stats_data *sum_data = new Stats_data ();
2059   for (index = exp_idx1; index <= exp_idx2; index++)
2060     {
2061       Stats_data *stats_data = dbev->get_stats_data (index);
2062       if (stats_data == NULL)
2063 	continue;
2064       sum_data->sum (stats_data);
2065       delete stats_data;
2066     }
2067 
2068   // get the maximum width of values
2069   size = sum_data->size ();
2070   for (index = 0; index < size; index++)
2071     {
2072       len = (int) sum_data->fetch (index).value.get_len ();
2073       if (maxlen < len)
2074 	maxlen = len;
2075     }
2076 
2077   // print overview average
2078   overview_sum (maxlen);
2079 
2080   // print statistics data
2081   max_len2 = maxlen;
2082   statistics_item (sum_data);
2083   delete sum_data;
2084 }
2085 
2086 void
statistics_dump(int exp_idx,int & maxlen)2087 er_print_experiment::statistics_dump (int exp_idx, int &maxlen)
2088 {
2089   Stats_data *stats_data;
2090   int index;
2091   int size, len;
2092   stats_data = dbev->get_stats_data (exp_idx);
2093   if (stats_data == NULL)
2094     return;
2095   if (pr_params.header)
2096     {
2097       header_dump (exp_idx);
2098       fprintf (out_file, nl);
2099     }
2100   else
2101     fprintf (out_file, GTXT ("Experiment: %s\n"),
2102 	     dbeSession->get_exp (exp_idx)->get_expt_name ());
2103 
2104   // get the maximum width of values
2105   size = stats_data->size ();
2106   for (index = 0; index < size; index++)
2107     {
2108       len = (int) stats_data->fetch (index).value.get_len ();
2109       if (maxlen < len)
2110 	maxlen = len;
2111     }
2112 
2113   // print overview average
2114   overview_dump (exp_idx, maxlen);
2115   fprintf (out_file, nl);
2116 
2117   // print statistics data
2118   max_len2 = maxlen;
2119   statistics_item (stats_data);
2120   delete stats_data;
2121 }
2122 
2123 void
statistics_item(Stats_data * stats_data)2124 er_print_experiment::statistics_item (Stats_data *stats_data)
2125 {
2126   int size, index;
2127   Stats_data::Stats_item stats_item;
2128   char buf[256];
2129   size = stats_data->size ();
2130   for (index = 0; index < size; index++)
2131     {
2132       stats_item = stats_data->fetch (index);
2133       fprintf (out_file, "%*s: %*s\n", max_len1, stats_item.label,
2134 	       max_len2, stats_item.value.to_str (buf, sizeof (buf)));
2135     }
2136   fprintf (out_file, nl);
2137 }
2138 
2139 // Print annotated source or disassembly -- called by er_print only
2140 void
print_anno_file(char * name,const char * sel,const char * srcFile,bool isDisasm,FILE * dis_file,FILE * inp_file,FILE * out_file,DbeView * dbev,bool xdefault)2141 print_anno_file (char *name, const char *sel, const char *srcFile,
2142 		 bool isDisasm, FILE *dis_file, FILE *inp_file, FILE *out_file,
2143 		 DbeView *dbev, bool xdefault)
2144 {
2145   Histable *obj;
2146   Function *func;
2147   Module *module;
2148   Vector<int> *marks;
2149   Hist_data *hist_data;
2150   char *errstr;
2151   int index;
2152   SourceFile *fitem;
2153   int threshold;
2154   int compcom_bits;
2155   int src_visible;
2156   bool hex_visible;
2157   bool srcmetrics_visible;
2158 
2159   if ((name == NULL) || (strlen (name) == 0))
2160     {
2161       fprintf (stderr, GTXT ("Error: No function or file has been specified.\n"));
2162       return;
2163     }
2164 
2165   // find the function from the name
2166   if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2167 			     Histable::FUNCTION, xdefault))
2168     return;
2169 
2170   if (obj != NULL)
2171     {
2172       // source or disassembly for <Total>, <Unknown>, or @plt
2173       if (obj->get_type () != Histable::FUNCTION)
2174 	{
2175 	  fprintf (stderr,
2176 		   GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2177 		   name);
2178 	  return;
2179 	}
2180 
2181       func = (Function *) obj;
2182       if (func->flags & FUNC_FLAG_SIMULATED)
2183 	{
2184 	  fprintf (stderr,
2185 		   GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2186 		   name);
2187 	  return;
2188 	}
2189       else if (dbev != NULL && isDisasm)
2190 	dbev->set_func_scope (true);
2191 
2192       // function found, set module
2193       module = func->module;
2194       int ix = module->loadobject->seg_idx;
2195       if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2196 	{
2197 	  char *lo_name = module->loadobject->get_name ();
2198 	  fprintf (stderr,
2199 		   GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2200 		   lo_name);
2201 	  return;
2202 	}
2203 
2204       if (srcFile)
2205 	{
2206 	  Vector<SourceFile*> *sources = func->get_sources ();
2207 	  bool found = false;
2208 	  if (sources == NULL)
2209 	    {
2210 	      fitem = func->getDefSrc ();
2211 	      found = (func->line_first > 0)
2212 		      && strcmp (basename (srcFile),
2213 				 basename (fitem->get_name ())) == 0;
2214 	    }
2215 	  else
2216 	    {
2217 	      Vec_loop (SourceFile*, sources, index, fitem)
2218 	      {
2219 		if (strcmp (basename (srcFile), basename (fitem->get_name ())) == 0)
2220 		  {
2221 		    found = true;
2222 		    break;
2223 		  }
2224 	      }
2225 	    }
2226 	  if (!found)
2227 	    {
2228 	      fprintf (stderr, GTXT ("Error: Source file context %s does not contribute to function `%s'.\n"),
2229 		       srcFile, name);
2230 	      return;
2231 	    }
2232 	}
2233     }
2234   else
2235     {
2236       // function not found
2237       if (sel && strrchr (sel, ':'))
2238 	{
2239 	  // 'sel' was "@seg_num:address" or "file_name:address"
2240 	  fprintf (stderr,
2241 		   GTXT ("Error: No function with given name `%s %s' found.\n"),
2242 		   name, sel);
2243 	  return;
2244 	}
2245       // search for a file of that name
2246       if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2247 				 Histable::MODULE, xdefault))
2248 	return;
2249 
2250       if (obj == NULL)
2251 	{ // neither function nor file found
2252 	  fprintf (stderr, GTXT ("Error: No function or file with given name `%s' found.\n"),
2253 		   name);
2254 	  return;
2255 	}
2256 
2257       func = NULL;
2258       module = (Module *) obj;
2259       int ix = module->loadobject->seg_idx;
2260       if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2261 	{
2262 	  char *lo_name = module->loadobject->get_name ();
2263 	  fprintf (stderr, GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2264 		   lo_name);
2265 	  return;
2266 	}
2267       if (name)
2268 	srcFile = name;
2269     }
2270 
2271   if (module == NULL || module->get_name () == NULL)
2272     {
2273       fprintf (stderr, GTXT ("Error: Object name not recorded in experiment\n"));
2274       return;
2275     }
2276   module->read_stabs ();
2277 
2278   if (!isDisasm && (module->file_name == NULL
2279 		    || (module->flags & MOD_FLAG_UNKNOWN) != 0
2280 		    || *module->file_name == 0))
2281     {
2282       fprintf (stderr, GTXT ("Error: Source location not recorded in experiment\n"));
2283       return;
2284     }
2285 
2286   MetricList *metric_list = dbev->get_metric_list (MET_NORMAL);
2287   int sort_ref_index = metric_list->get_sort_ref_index ();
2288   if (isDisasm)
2289     metric_list->set_sort_ref_index (-1);
2290 
2291   // Ask DbeView to generate function-level data
2292   //	MSI: I think this is used only to get totals to compute percentages
2293   hist_data = dbev->get_hist_data (metric_list, Histable::FUNCTION, 0,
2294 				   Hist_data::ALL);
2295   MetricList *nmlist = hist_data->get_metric_list ();
2296   metric_list->set_sort_ref_index (sort_ref_index);
2297   if (nmlist->get_items ()->size () != 0
2298       && hist_data->get_status () != Hist_data::SUCCESS)
2299     {
2300       errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
2301       if (errstr)
2302 	{
2303 	  fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2304 	  free (errstr);
2305 	}
2306       return;
2307     }
2308 
2309   marks = new Vector<int>;
2310   if (isDisasm)
2311     {
2312       threshold = dbev->get_thresh_dis ();
2313       compcom_bits = dbev->get_dis_compcom ();
2314       src_visible = dbev->get_src_visible ();
2315       hex_visible = dbev->get_hex_visible ();
2316       srcmetrics_visible = dbev->get_srcmetric_visible ();
2317     }
2318   else
2319     {
2320       threshold = dbev->get_thresh_src ();
2321       compcom_bits = dbev->get_src_compcom ();
2322       src_visible = SRC_NA;
2323       hex_visible = false;
2324       srcmetrics_visible = false;
2325     }
2326 
2327   dump_anno_file (out_file, isDisasm ? Histable::INSTR : Histable::LINE,
2328 		  module, dbev, nmlist, hist_data->get_totals ()->value,
2329 		  srcFile, func, marks, threshold, compcom_bits,
2330 		  src_visible, hex_visible, srcmetrics_visible);
2331 
2332   delete marks;
2333 
2334   errstr = module->anno_str ();
2335   if (errstr)
2336     {
2337       fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2338       free (errstr);
2339     }
2340   delete hist_data;
2341 }
2342 
2343 void
print_html_title(FILE * out_file,char * title)2344 print_html_title (FILE *out_file, char *title)
2345 {
2346   // This will print a header row for the report
2347   fprintf (out_file, "<html><title>%s</title>\n", title);
2348   fprintf (out_file, "<center><h3>%s</h3></center>\n", title);
2349 }
2350 
2351 void
print_html_label(FILE * out_file,MetricList * metrics_list)2352 print_html_label (FILE *out_file, MetricList *metrics_list)
2353 {
2354   int mlist_sz;
2355 
2356   // This will print  a header row for the metrics
2357   Vector<Metric*> *mlist = metrics_list->get_items ();
2358   mlist_sz = mlist->size ();
2359 
2360   fprintf (out_file, "<style type=\"text/css\">\n");
2361   fprintf (out_file, "<!--\nBODY\n");
2362   fprintf (out_file, ".th_C   { text-align:center; background-color:lightgoldenrodyellow; }\n");
2363   fprintf (out_file, ".th_CG  { text-align:center; background-color:#ffff33; }\n");
2364   fprintf (out_file, ".th_L   { text-align:left; background-color:lightgoldenrodyellow; }\n");
2365   fprintf (out_file, ".th_LG  { text-align:left; background-color:#ffff33; }\n");
2366   fprintf (out_file, ".td_R   { text-align:right;  }\n");
2367   fprintf (out_file, ".td_RG  { text-align:right; background-color:#ffff33; }\n");
2368   fprintf (out_file, ".td_L   { text-align:left; }\n");
2369   fprintf (out_file, ".td_LG  { text-align:left;  background-color:#ffff33; }\n");
2370   fprintf (out_file, "-->\n</style>");
2371   fprintf (out_file, "<center><table border=1 cellspacing=2>\n<tr>");
2372 
2373   for (int index = 0; index < mlist_sz; index++)
2374     {
2375       Metric *mitem = mlist->fetch (index);
2376       int ncols = 0;
2377       if (mitem->is_visible ())
2378 	ncols++;
2379       if (mitem->is_tvisible ())
2380 	ncols++;
2381       if (mitem->is_pvisible ())
2382 	ncols++;
2383       if (ncols == 0)
2384 	continue;
2385       char *name = strdup (mitem->get_name ());
2386       char *name2 = split_metric_name (name);
2387       const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2388 
2389       // start the column, with colspan setting, legend, and sort metric indicator
2390       if (ncols == 1)
2391 	{
2392 	  if (mitem->get_vtype () == VT_LABEL)
2393 	    // left-adjust the name metric
2394 	    fprintf (out_file,
2395 		     "<th class=\"th_L%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2396 		     style, mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2397 		     (index == metrics_list->get_sort_ref_index ()) ? "&nabla;" : "&nbsp;",
2398 		     name, name2 == NULL ? "&nbsp;" : name2);
2399 	  else
2400 	    // but center the others
2401 	    fprintf (out_file,
2402 		     "<th class=\"th_C%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2403 		     style, mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2404 		     (index == metrics_list->get_sort_ref_index ()) ?
2405 			 "&nabla;" : "&nbsp;",
2406 		     name, name2 == NULL ? NTXT ("&nbsp;") : name2);
2407 	}
2408       else
2409 	// name metric can't span columns
2410 	fprintf (out_file,
2411 		 "<th colspan=%d class=\"th_C%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2412 		 ncols, style,
2413 		 mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2414 		 index == metrics_list->get_sort_ref_index () ?
2415 		     "&nabla;" : "&nbsp;",
2416 		 name, name2 == NULL ? "&nbsp;" : name2);
2417 
2418       free (name);
2419     }
2420 
2421   // end this row, start the units row
2422   fprintf (out_file, NTXT ("</tr>\n<tr>"));
2423 
2424   // now do the units row
2425   for (int index = 0; index < mlist_sz; index++)
2426     {
2427       Metric *mitem = mlist->fetch (index);
2428       const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2429 
2430       if (mitem->is_tvisible ())
2431 	fprintf (out_file, "<th class=\"th_C%s\">&nbsp;(%s)</th>", style,
2432 		 GTXT ("sec."));
2433       if (mitem->is_visible ())
2434 	{
2435 	  if (mitem->get_abbr_unit () == NULL)
2436 	    fprintf (out_file, "<th class=\"th_C%s\">&nbsp;</th>", style);
2437 	  else
2438 	    fprintf (out_file, "<th class=\"th_C%s\">(%s)</th>", style,
2439 		     mitem->get_abbr_unit () == NULL ? "&nbsp;"
2440 		     : mitem->get_abbr_unit ());
2441 	}
2442       if (mitem->is_pvisible ())
2443 	fprintf (out_file, "<th class=\"th_C%s\">&nbsp;(%%)</th>", style);
2444     }
2445   fprintf (out_file, NTXT ("</tr>\n"));
2446 }
2447 
2448 void
print_html_content(FILE * out_file,Hist_data * data,MetricList * metrics_list,int limit,Histable::NameFormat nfmt)2449 print_html_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
2450 		    int limit, Histable::NameFormat nfmt)
2451 {
2452   Hist_data::HistItem *item;
2453 
2454   // printing contents.
2455   for (int i = 0; i < limit; i++)
2456     {
2457       item = data->fetch (i);
2458       print_html_one (out_file, data, item, metrics_list, nfmt);
2459     }
2460 }
2461 
2462 void
print_html_one(FILE * out_file,Hist_data * data,Hist_data::HistItem * item,MetricList * metrics_list,Histable::NameFormat nfmt)2463 print_html_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
2464 		MetricList *metrics_list, Histable::NameFormat nfmt)
2465 {
2466   Metric *mitem;
2467   int index;
2468   int visible, tvisible, pvisible;
2469   TValue *value;
2470   double percent;
2471 
2472   fprintf (out_file, NTXT ("<tr>"));
2473   Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
2474   {
2475     visible = mitem->is_visible ();
2476     tvisible = mitem->is_tvisible ();
2477     pvisible = mitem->is_pvisible ();
2478     const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2479 
2480     if (tvisible)
2481       {
2482 	value = &(item->value[index]);
2483 	if (value->ll == 0LL)
2484 	  fprintf (out_file,
2485 		   "<td class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
2486 		   style);
2487 	else
2488 	  fprintf (out_file, "<td class=\"td_R%s\"><tt>%4.3lf</tt></td>",
2489 		   style, 1.e-6 * value->ll / dbeSession->get_clock (-1));
2490       }
2491 
2492     if (visible)
2493       {
2494 	if (mitem->get_vtype () == VT_LABEL)
2495 	  {
2496 	    value = &(item->value[index]);
2497 	    char *r;
2498 	    if (value->tag == VT_OFFSET)
2499 	      r = ((DataObject*) (item->obj))->get_offset_name ();
2500 	    else
2501 	      r = item->obj->get_name (nfmt);
2502 	    char *n = html_ize_name (r);
2503 	    fprintf (out_file, NTXT ("<td class=\"td_L%s\">%s</td>"), style, n);
2504 	    free (n);
2505 	  }
2506 	else
2507 	  {
2508 	    value = &(item->value[index]);
2509 	    switch (value->tag)
2510 	      {
2511 	      case VT_DOUBLE:
2512 		if (value->d == 0.0)
2513 		  fprintf (out_file,
2514 		      "<td class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
2515 			   style);
2516 		else
2517 		  fprintf (out_file,
2518 			   "<td  class=\"td_R%s\"><tt>%4.3lf</tt></td>", style,
2519 			   value->d);
2520 		break;
2521 	      case VT_INT:
2522 		fprintf (out_file, "<td  class=\"td_R%s\"><tt>%d</tt></td>",
2523 			 style, value->i);
2524 		break;
2525 	      case VT_LLONG:
2526 		fprintf (out_file, "<td  class=\"td_R%s\"><tt>%lld</td></tt>",
2527 			 style, value->ll);
2528 		break;
2529 	      case VT_ULLONG:
2530 		fprintf (out_file, "<td  class=\"td_R%s\"><tt>%llu</td></tt>",
2531 			 style, value->ull);
2532 		break;
2533 	      case VT_ADDRESS:
2534 		fprintf (out_file,
2535 			 "<td  class=\"td_R%s\"><tt>%u:0x%08x</tt></td>", style,
2536 			 ADDRESS_SEG (value->ll), ADDRESS_OFF (value->ll));
2537 		break;
2538 	      case VT_FLOAT:
2539 		if (value->f == 0.0)
2540 		  fprintf (out_file,
2541 			   "<td  class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
2542 			   style);
2543 		else
2544 		  fprintf (out_file,
2545 			   "<td  class=\"td_R%s\"><tt>%4.3f</tt></td>",
2546 			   style, value->f);
2547 		break;
2548 	      case VT_SHORT:
2549 		fprintf (out_file, "<td  class=\"td_R%s\"><tt>%d</tt></td>",
2550 			 style, value->s);
2551 		break;
2552 		// ignoring the following cases (why?)
2553 	      case VT_HRTIME:
2554 	      case VT_LABEL:
2555 	      case VT_OFFSET:
2556 		break;
2557 	      }
2558 	  }
2559       }
2560 
2561     if (pvisible)
2562       {
2563 	percent = data->get_percentage (item->value[index].to_double (), index);
2564 	if (percent == 0.0)
2565 	  // adjust to change format from xx.yy%
2566 	  fprintf (out_file, "<td class=\"td_R%s\">0.&nbsp;&nbsp;&nbsp;</td>",
2567 		   style);
2568 	else
2569 	  // adjust format below to change format from xx.yy%
2570 	  fprintf (out_file, "<td class=\"td_R%s\">%3.2f</td>", style,
2571 		   (100.0 * percent));
2572       }
2573   }
2574   fprintf (out_file, NTXT ("</tr>\n"));
2575 }
2576 
2577 void
print_html_trailer(FILE * out_file)2578 print_html_trailer (FILE *out_file)
2579 {
2580   fprintf (out_file, NTXT ("</table></center></html>\n"));
2581 }
2582 
2583 static char *
del_delim(char * s)2584 del_delim (char *s)
2585 {
2586   size_t len = strlen (s);
2587   if (len > 0)
2588     s[len - 1] = 0;
2589   return s;
2590 }
2591 
2592 void
print_delim_label(FILE * out_file,MetricList * metrics_list,char delim)2593 print_delim_label (FILE *out_file, MetricList *metrics_list, char delim)
2594 {
2595   char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
2596   char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
2597   size_t len;
2598 
2599   // This will print four header rows for the metrics
2600   line0[0] = 0;
2601   line1[0] = 0;
2602   line2[0] = 0;
2603   line3[0] = 0;
2604   Vector<Metric*> *mlist = metrics_list->get_items ();
2605   for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
2606     {
2607       Metric *mitem = mlist->fetch (index);
2608       if (!(mitem->is_visible () || mitem->is_tvisible ()
2609 	    || mitem->is_pvisible ()))
2610 	continue;
2611       char *name = strdup (mitem->get_name ());
2612       char *name2 = split_metric_name (name);
2613 
2614       if (mitem->is_tvisible ())
2615 	{
2616 	  len = strlen (line0);
2617 	  snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
2618 		    mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
2619 	  len = strlen (line1);
2620 	  snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
2621 		    name, delim);
2622 	  len = strlen (line2);
2623 	  snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
2624 		    name2 == NULL ? NTXT ("") : name2, delim);
2625 	  len = strlen (line3);
2626 	  if (index == metrics_list->get_sort_ref_index ())
2627 	    snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V  %s\"%c"),
2628 		      GTXT ("(sec.)"), delim);
2629 	  else
2630 	    snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"   %s\"%c"),
2631 		      GTXT ("(sec.)"), delim);
2632 	}
2633       if (mitem->is_visible ())
2634 	{
2635 	  len = strlen (line0);
2636 	  snprintf (line0 + len, sizeof (line0) - len, "\"%s\"%c",
2637 		    mitem->legend == NULL ? "" : mitem->legend, delim);
2638 
2639 	  len = strlen (line1);
2640 	  snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c",
2641 		    name, delim);
2642 
2643 	  len = strlen (line2);
2644 	  snprintf (line2 + len, sizeof (line2) - len, "\"%s\"%c",
2645 		    name2 == NULL ? NTXT ("") : name2, delim);
2646 
2647 	  len = strlen (line3);
2648 	  char *au = mitem->get_abbr_unit ();
2649 
2650 	  if (index == metrics_list->get_sort_ref_index ())
2651 	    {
2652 	      if (au == NULL)
2653 		snprintf (line3 + len, sizeof (line3) - len, "\"V  \"%c", delim);
2654 	      else
2655 		snprintf (line3 + len, sizeof (line3) - len, "\"V  (%s)\"%c",
2656 			    au, delim);
2657 	    }
2658 	  else
2659 	    {
2660 	      if (au == NULL)
2661 		snprintf (line3 + len, sizeof (line3) - len, "\"   \"%c",
2662 			  delim);
2663 	      else
2664 		snprintf (line3 + len, sizeof (line3) - len, "\"   (%s)\"%c",
2665 			  au, delim);
2666 	    }
2667 	}
2668       if (mitem->is_pvisible ())
2669 	{
2670 	  len = strlen (line0);
2671 	  snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
2672 		    mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
2673 
2674 	  len = strlen (line1);
2675 	  snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
2676 		    name, delim);
2677 
2678 	  len = strlen (line2);
2679 	  snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
2680 		    name2 == NULL ? NTXT ("") : name2, delim);
2681 
2682 	  len = strlen (line3);
2683 	  if (index == metrics_list->get_sort_ref_index ())
2684 	    snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V  %s\"%c"),
2685 		      NTXT ("%%"), delim);
2686 	  else
2687 	    snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"   %s\"%c"),
2688 		      NTXT ("%%"), delim);
2689 	}
2690       free (name);
2691     }
2692   // now remove the trailing delimiter, and print the four lines
2693   fprintf (out_file, NTXT ("%s\n"), del_delim (line0));
2694   fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
2695   fprintf (out_file, NTXT ("%s\n"), del_delim (line2));
2696   fprintf (out_file, NTXT ("%s\n"), del_delim (line3));
2697 }
2698 
2699 void
print_delim_content(FILE * out_file,Hist_data * data,MetricList * metrics_list,int limit,Histable::NameFormat nfmt,char delim)2700 print_delim_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
2701 		     int limit, Histable::NameFormat nfmt, char delim)
2702 {
2703   Hist_data::HistItem *item;
2704   int i;
2705 
2706   // printing contents.
2707   for (i = 0; i < limit; i++)
2708     {
2709       item = data->fetch (i);
2710       print_delim_one (out_file, data, item, metrics_list, nfmt, delim);
2711     }
2712 }
2713 
2714 void
print_delim_trailer(FILE *,char)2715 print_delim_trailer (FILE */*out_file*/, char /*delim*/) { }
2716 
2717 // EUGENE does this function work properly when "-compare ratio" is used?
2718 //   how about when the ratio is nonzero-divided-by-zero?
2719 // EUGENE actually, review this entire file
2720 
2721 void
print_delim_one(FILE * out_file,Hist_data * data,Hist_data::HistItem * item,MetricList * metrics_list,Histable::NameFormat nfmt,char delim)2722 print_delim_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
2723 		 MetricList *metrics_list, Histable::NameFormat nfmt,
2724 		 char delim)
2725 {
2726   Metric *mitem;
2727   int index;
2728   int visible, tvisible, pvisible;
2729   TValue *value;
2730   double percent;
2731   size_t len;
2732 
2733   char line1[2 * MAX_LEN];
2734   *line1 = 0;
2735   Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
2736   {
2737     visible = mitem->is_visible ();
2738     tvisible = mitem->is_tvisible ();
2739     pvisible = mitem->is_pvisible ();
2740     if (tvisible)
2741       {
2742 	value = &(item->value[index]);
2743 	len = strlen (line1);
2744 	if (value->ll == 0LL)
2745 	  snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
2746 	else
2747 	  snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
2748 		    1.e-6 * value->ll / dbeSession->get_clock (-1),
2749 		    delim);
2750       }
2751 
2752     if (visible)
2753       {
2754 	len = strlen (line1);
2755 	if (mitem->get_vtype () == VT_LABEL)
2756 	  {
2757 	    value = &(item->value[index]);
2758 	    char *r;
2759 	    if (value->tag == VT_OFFSET)
2760 	      r = ((DataObject*) (item->obj))->get_offset_name ();
2761 	    else
2762 	      r = item->obj->get_name (nfmt);
2763 	    char *p = csv_ize_name (r, delim);
2764 	    snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c", p, delim);
2765 	    free (p);
2766 	  }
2767 	else
2768 	  {
2769 	    value = &(item->value[index]);
2770 	    switch (value->tag)
2771 	      {
2772 	      case VT_DOUBLE:
2773 		if (value->d == 0.0)
2774 		  snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
2775 			    delim);
2776 		else
2777 		  snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
2778 			    value->d, delim);
2779 		break;
2780 	      case VT_INT:
2781 		snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
2782 			  value->i, delim);
2783 		break;
2784 	      case VT_LLONG:
2785 		snprintf (line1 + len, sizeof (line1) - len, "\"%lld\"%c",
2786 			  value->ll, delim);
2787 		break;
2788 	      case VT_ULLONG:
2789 		snprintf (line1 + len, sizeof (line1) - len, "\"%llu\"%c",
2790 			  value->ull, delim);
2791 		break;
2792 	      case VT_ADDRESS:
2793 		snprintf (line1 + len, sizeof (line1) - len, "\"%u:0x%08x\"%c",
2794 			  ADDRESS_SEG (value->ll),
2795 			  ADDRESS_OFF (value->ll), delim);
2796 		break;
2797 	      case VT_FLOAT:
2798 		if (value->f == 0.0)
2799 		  snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
2800 			    delim);
2801 		else
2802 		  snprintf (line1 + len, sizeof (line1) - len, "\"%4.3f\"%c",
2803 			    value->f, delim);
2804 		break;
2805 	      case VT_SHORT:
2806 		snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
2807 			  value->s, delim);
2808 		break;
2809 		// ignoring the following cases (why?)
2810 	      case VT_HRTIME:
2811 	      case VT_LABEL:
2812 	      case VT_OFFSET:
2813 		break;
2814 	      }
2815 	  }
2816       }
2817 
2818     if (pvisible)
2819       {
2820 	len = strlen (line1);
2821 	percent = data->get_percentage (item->value[index].to_double (), index);
2822 	if (percent == 0.0)
2823 	  // adjust to change format from xx.yy%
2824 	  snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
2825 	else
2826 	  // adjust format below to change format from xx.yy%
2827 	  snprintf (line1 + len, sizeof (line1) - len, "\"%3.2f\"%c",
2828 		    (100.0 * percent), delim);
2829       }
2830   }
2831   fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
2832 }
2833 
2834 char *
html_ize_name(char * name)2835 html_ize_name (char *name)
2836 {
2837   StringBuilder sb;
2838   for (size_t i = 0; i < strlen (name); i++)
2839     {
2840       switch (name[i])
2841 	{
2842 	case ' ': sb.append (NTXT ("&nbsp;"));
2843 	  break;
2844 	case '"': sb.append (NTXT ("&quot;"));
2845 	  break;
2846 	case '&': sb.append (NTXT ("&amp;"));
2847 	  break;
2848 	case '<': sb.append (NTXT ("&lt;"));
2849 	  break;
2850 	case '>': sb.append (NTXT ("&gt;"));
2851 	  break;
2852 	default: sb.append (name[i]);
2853 	  break;
2854 	}
2855     }
2856   char *ret = sb.toString ();
2857   return ret;
2858 }
2859 
2860 char *
csv_ize_name(char * name,char)2861 csv_ize_name (char *name, char /*delim*/)
2862 {
2863   StringBuilder sb;
2864   for (size_t i = 0; i < strlen (name); i++)
2865     sb.append (name[i]);
2866   char *ret = sb.toString ();
2867   return ret;
2868 }
2869 
2870 // Split a metric name into two parts, replacing a blank with
2871 //	a zero and returning pointer to the rest of the string, or
2872 //	leaving the string unchanged, and returning NULL;
2873 
2874 char *
split_metric_name(char * name)2875 split_metric_name (char *name)
2876 {
2877   // figure out the most even split of the name
2878   size_t len = strlen (name);
2879   char *middle = &name[len / 2];
2880 
2881   // find the first blank
2882   char *first = strchr (name, (int) ' ');
2883   if (first == NULL)  // no blanks
2884     return NULL;
2885   char *last = first;
2886   char *p = first;
2887   for (;;)
2888     {
2889       p = strchr (p + 1, (int) ' ');
2890       if (p == NULL)
2891 	break;
2892       if (p < middle)
2893 	{
2894 	  first = p;
2895 	  last = p;
2896 	}
2897       else
2898 	{
2899 	  last = p;
2900 	  break;
2901 	}
2902     }
2903   // pick the better of the two
2904   char *ret;
2905   int f = (int) (middle - first);
2906   int l = (int) (last - middle);
2907   if ((first == last) || (f <= l))
2908     {
2909       *first = '\0';
2910       ret = first + 1;
2911     }
2912   else
2913     {
2914       *last = '\0';
2915       ret = last + 1;
2916     }
2917   return ret;
2918 }
2919