ff4ff35918
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
2840 lines
78 KiB
C++
2840 lines
78 KiB
C++
/* Copyright (C) 2021-2024 Free Software Foundation, Inc.
|
|
Contributed by Oracle.
|
|
|
|
This file is part of GNU Binutils.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "config.h"
|
|
#include <unistd.h> // isatty
|
|
#include <errno.h>
|
|
|
|
#include "gp-print.h"
|
|
#include "ipcio.h"
|
|
#include "Command.h"
|
|
#include "Dbe.h"
|
|
#include "DbeApplication.h"
|
|
#include "DbeSession.h"
|
|
#include "Experiment.h"
|
|
#include "Emsg.h"
|
|
#include "DbeView.h"
|
|
#include "DataObject.h"
|
|
#include "Function.h"
|
|
#include "Hist_data.h"
|
|
#include "PathTree.h"
|
|
#include "LoadObject.h"
|
|
#include "Function.h"
|
|
#include "FilterSet.h"
|
|
#include "Filter.h"
|
|
#include "MetricList.h"
|
|
#include "MemorySpace.h"
|
|
#include "Module.h"
|
|
#include "util.h"
|
|
#include "i18n.h"
|
|
#include "StringBuilder.h"
|
|
#include "debug.h"
|
|
#include "UserLabel.h"
|
|
|
|
static char *exe_name;
|
|
static char **new_argv;
|
|
|
|
void
|
|
reexec ()
|
|
{
|
|
if (dbeSession != NULL)
|
|
dbeSession->unlink_tmp_files ();
|
|
execvp (exe_name, new_argv);
|
|
fprintf (stderr, GTXT ("Error: reexec() failed (%d: %s)\n"), errno,
|
|
STR(strerror (errno)));
|
|
fflush (stderr);
|
|
exit (1);
|
|
}
|
|
|
|
/**
|
|
* Run application under enhance if the following requirements are satisfied:
|
|
* 1. Environment variable GPROFNG_ENHANCE is not set to "no"
|
|
* 2. Standard input is terminal
|
|
* 3. Standard output is terminal
|
|
* 4. /bin/enhance exists and can work on this system
|
|
*/
|
|
static void
|
|
reexec_enhance (int argc, char *argv[])
|
|
{
|
|
char *gp_enhance = getenv ("GPROFNG_ENHANCE");
|
|
if (NULL != gp_enhance && 0 == strcasecmp (gp_enhance, "no"))
|
|
return; // Do not enhance
|
|
// Verify that input and output are tty
|
|
if (!isatty (fileno (stdin))) // stdin is not a terminal
|
|
return; // Do not enhance
|
|
if (!isatty (fileno (stdout))) // stdout is not a terminal
|
|
return; // Do not enhance
|
|
char *enhance_name = NTXT ("/bin/enhance");
|
|
struct stat sbuf;
|
|
int res = stat (enhance_name, &sbuf); // Check if enhance exists
|
|
if (res == 0)
|
|
res = system (NTXT ("/bin/enhance /bin/true")); // Check if enhance can work
|
|
if (res != 0)
|
|
{
|
|
fflush (stdout);
|
|
printf (GTXT ("Warning: History and command editing is not supported on this system.\n"));
|
|
fflush (stdout);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
printf (GTXT ("Note: History and command editing is supported on this system.\n"));
|
|
fflush (stdout);
|
|
}
|
|
char **nargv = new char*[argc + 2];
|
|
for (int i = 0; i < argc; i++)
|
|
nargv[i + 1] = argv[i];
|
|
nargv[0] = enhance_name;
|
|
nargv[argc + 1] = NULL;
|
|
putenv (NTXT ("GPROFNG_ENHANCE=no")); // prevent recursion
|
|
execv (enhance_name, nargv);
|
|
// execv failed. Continue to run the program
|
|
delete[] nargv;
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
er_print *erprint;
|
|
int ind = 1;
|
|
if (argc > ind && *argv[ind] == '-')
|
|
{
|
|
int arg_count, cparam;
|
|
if (Command::get_command (argv[ind] + 1, arg_count, cparam) == WHOAMI)
|
|
ind = ind + 1 + arg_count;
|
|
}
|
|
if (argc > ind && argv[ind] != NULL && *argv[ind] != '-')
|
|
reexec_enhance (argc, argv);
|
|
|
|
// Save argv for reexec())
|
|
exe_name = argv[0];
|
|
new_argv = argv;
|
|
|
|
if (argc > ind && argv[ind] != NULL && strcmp (argv[ind], "-IPC") == 0)
|
|
{
|
|
putenv (NTXT ("LC_NUMERIC=C")); // Use non-localized numeric data in IPC packets
|
|
erprint = new er_print (argc, argv);
|
|
theDbeApplication->rdtMode = false;
|
|
ipc_mainLoop (argc, argv);
|
|
}
|
|
else
|
|
{
|
|
erprint = new er_print (argc, argv);
|
|
erprint->start (argc, argv);
|
|
}
|
|
|
|
dbeSession->unlink_tmp_files ();
|
|
if (DUMP_CALL_STACK)
|
|
{
|
|
extern long total_calls_add_stack, total_stacks, total_nodes, call_stack_size[201];
|
|
fprintf (stderr, NTXT ("total_calls_add_stack=%lld\ntotal_stacks=%lld\ntotal_nodes=%lld\n"),
|
|
(long long) total_calls_add_stack, (long long) total_stacks, (long long) total_nodes);
|
|
for (int i = 0; i < 201; i++)
|
|
if (call_stack_size[i] != 0)
|
|
fprintf (stderr, NTXT (" call_stack_size[%d] = %6lld\n"), i,
|
|
(long long) call_stack_size[i]);
|
|
}
|
|
#if defined(DEBUG)
|
|
delete erprint;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
er_print::er_print (int argc, char *argv[])
|
|
: DbeApplication (argc, argv)
|
|
{
|
|
out_fname = GTXT ("<stdout>");
|
|
inp_file = stdin;
|
|
out_file = stdout;
|
|
dis_file = stdout;
|
|
cov_string = NULL;
|
|
limit = 0;
|
|
cstack = new Vector<Histable*>();
|
|
was_QQUIT = false;
|
|
}
|
|
|
|
er_print::~er_print ()
|
|
{
|
|
free (cov_string);
|
|
delete cstack;
|
|
if (inp_file != stdin)
|
|
fclose (inp_file);
|
|
}
|
|
|
|
void
|
|
er_print::start (int argc, char *argv[])
|
|
{
|
|
Vector<String> *res = theDbeApplication->initApplication (NULL, NULL, NULL);
|
|
res->destroy ();
|
|
delete res;
|
|
|
|
// Create a view on the session
|
|
dbevindex = dbeSession->createView (0, -1);
|
|
dbev = dbeSession->getView (dbevindex);
|
|
limit = dbev->get_limit ();
|
|
(void) check_args (argc, argv);
|
|
int ngood = dbeSession->ngoodexps ();
|
|
if (ngood == 0)
|
|
{
|
|
fprintf (stderr, GTXT ("No valid experiments loaded; exiting\n"));
|
|
return;
|
|
}
|
|
dbeDetectLoadMachineModel (dbevindex);
|
|
run (argc, argv);
|
|
}
|
|
|
|
bool
|
|
er_print::free_memory_before_exit ()
|
|
{
|
|
return was_QQUIT;
|
|
}
|
|
|
|
void
|
|
er_print::usage ()
|
|
{
|
|
|
|
/*
|
|
Ruud - Isolate this line because it has an argument. Otherwise it would be at the
|
|
end of the long option list.
|
|
*/
|
|
printf ( GTXT (
|
|
"Usage: gprofng display text [OPTION(S)] [COMMAND(S)] [-script <script_file>] EXPERIMENT(S)\n"));
|
|
|
|
printf ( GTXT (
|
|
"\n"
|
|
"Print a plain text version of the various displays supported by gprofng.\n"
|
|
"\n"
|
|
"Options:\n"
|
|
"\n"
|
|
" --version print the version number and exit.\n"
|
|
" --help print usage information and exit.\n"
|
|
" --verbose {on|off} enable (on) or disable (off) verbose mode; the default is \"off\".\n"
|
|
"\n"
|
|
" -script <script-file> execute the commands stored in the script file;\n"
|
|
" this feature may be combined with commands specified\n"
|
|
" at the command line.\n"
|
|
"\n"
|
|
"Commands:\n"
|
|
"\n"
|
|
"This tool supports a rich set of commands to control the display of the\n"
|
|
"data; instead of, or in addition to, including these commands in a script\n"
|
|
"file, it is also allowed to include such commands at the command line;\n"
|
|
"in this case, the commands need to be prepended with the \"-\" symbol; the\n"
|
|
"commands are processed and interpreted left from right, so the order matters;\n"
|
|
"The gprofng manual documents the commands that are supported.\n"
|
|
"\n"
|
|
"If this tool is invoked without options, commands, or a script file, it starts\n"
|
|
"in interpreter mode. The user can then issue the commands interactively; the\n"
|
|
"session is terminated with the \"exit\" command in the interpreter.\n"
|
|
"\n"
|
|
"Documentation:\n"
|
|
"\n"
|
|
"A getting started guide for gprofng is maintained as a Texinfo manual. If the info and\n"
|
|
"gprofng programs are properly installed at your site, the command \"info gprofng\"\n"
|
|
"should give you access to this document.\n"
|
|
"\n"
|
|
"See also:\n"
|
|
"\n"
|
|
"gprofng(1), gp-archive(1), gp-collect-app(1), gp-display-html(1), gp-display-src(1)\n"));
|
|
}
|
|
|
|
int // returns count of experiments read
|
|
er_print::check_args (int argc, char *argv[])
|
|
{
|
|
CmdType cmd_type;
|
|
int arg_count;
|
|
int cparam;
|
|
int exp_no;
|
|
error_msg = NULL;
|
|
|
|
Emsg *rcmsg = fetch_comments ();
|
|
while (rcmsg != NULL)
|
|
{
|
|
fprintf (stderr, NTXT ("%s: %s\n"), prog_name, rcmsg->get_msg ());
|
|
rcmsg = rcmsg->next;
|
|
}
|
|
delete_comments ();
|
|
|
|
// Set up the list of experiments to add after checking the args
|
|
Vector<Vector<char*>*> *exp_list = new Vector<Vector<char*>*>();
|
|
|
|
// Prescan the command line arguments, processing only a few
|
|
for (int i = 1; i < argc; i++)
|
|
{
|
|
if (*argv[i] != '-')
|
|
{
|
|
// we're at the end -- get the list of experiments
|
|
// Build the list of experiments, and set the searchpath
|
|
Vector<char*> *list = dbeSession->get_group_or_expt (argv[i]);
|
|
if (list->size () > 0)
|
|
{
|
|
for (int j = 0, list_sz = list->size (); j < list_sz; j++)
|
|
{
|
|
char *path = list->fetch (j);
|
|
if (strlen (path) == 0 || strcmp (path, NTXT ("\\")) == 0)
|
|
continue;
|
|
char *p = strrchr (path, '/');
|
|
if (p)
|
|
{
|
|
// there's a directory in front of the name; add it to search path
|
|
*p = '\0';
|
|
dbeSession->set_search_path (path, false);
|
|
}
|
|
}
|
|
list->destroy ();
|
|
list->append (dbe_strdup (argv[i]));
|
|
exp_list->append (list);
|
|
}
|
|
else
|
|
delete list;
|
|
continue;
|
|
}
|
|
|
|
// Not at the end yet, treat the next argument as a command
|
|
switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam))
|
|
{
|
|
case WHOAMI:
|
|
whoami = argv[i] + 1 + cparam;
|
|
break;
|
|
case HELP:
|
|
if (i + 1 + arg_count == argc)
|
|
{
|
|
usage();
|
|
exit (0);
|
|
}
|
|
break;
|
|
case HHELP:
|
|
Command::print_help (whoami, true, false, stdout);
|
|
fprintf (stdout, "\n");
|
|
indxo_list (false, stdout);
|
|
fprintf (stdout, "\n");
|
|
mo_list (false, stdout);
|
|
if (!getenv ("_BUILDING_MANPAGE"))
|
|
fprintf (stdout, GTXT ("\nSee gprofng(1) for more details\n"));
|
|
exit (0);
|
|
case ADD_EXP:
|
|
case DROP_EXP:
|
|
case OPEN_EXP:
|
|
printf (GTXT ("Error: command %s can not appear on the command line\n"), argv[i]);
|
|
exit (2);
|
|
case VERSION_cmd:
|
|
Application::print_version_info ();
|
|
exit (0);
|
|
case AMBIGUOUS_CMD:
|
|
fprintf (stderr, GTXT ("Error: Ambiguous command: %s\n"), argv[i]);
|
|
exit (2);
|
|
case UNKNOWN_CMD:
|
|
fprintf (stderr, GTXT ("Error: Invalid command: %s\n"), argv[i]);
|
|
exit (2);
|
|
// it's a plausible argument; see if we process now or later
|
|
case SOURCE:
|
|
case DISASM:
|
|
case CSINGLE:
|
|
case CPREPEND:
|
|
case CAPPEND:
|
|
case FSINGLE:
|
|
case SAMPLE_DETAIL:
|
|
case STATISTICS:
|
|
case HEADER:
|
|
//skip the arguments to that command
|
|
i += arg_count;
|
|
if (i >= argc || end_command (argv[i]))
|
|
i--;
|
|
break;
|
|
case PRINTMODE:
|
|
case INDXOBJDEF:
|
|
case ADDPATH:
|
|
case SETPATH:
|
|
case PATHMAP:
|
|
case OBJECT_SHOW:
|
|
case OBJECT_HIDE:
|
|
case OBJECT_API:
|
|
case OBJECTS_DEFAULT:
|
|
case EN_DESC:
|
|
// these are processed in the initial pass over the arguments
|
|
proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL,
|
|
(arg_count > 1) ? argv[i + 2] : NULL,
|
|
(arg_count > 2) ? argv[i + 3] : NULL,
|
|
(arg_count > 3) ? argv[i + 4] : NULL);
|
|
i += arg_count;
|
|
break;
|
|
default:
|
|
// any others, we skip for now
|
|
i += arg_count;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Make sure some experiments were specified
|
|
exp_no = exp_list->size ();
|
|
if (exp_no == 0)
|
|
{ // no experiment name
|
|
fprintf (stderr, GTXT ("%s: Missing experiment directory (use the --help option to get a usage overview)\n"), whoami);
|
|
exit (1);
|
|
}
|
|
|
|
// add the experiments to the session
|
|
char *errstr = dbeOpenExperimentList (0, exp_list, false);
|
|
for (long i = 0; i < exp_list->size (); i++)
|
|
{
|
|
Vector<char*>* p = exp_list->get (i);
|
|
Destroy (p);
|
|
}
|
|
delete exp_list;
|
|
if (errstr != NULL)
|
|
{
|
|
fprintf (stderr, NTXT ("%s"), errstr);
|
|
free (errstr);
|
|
}
|
|
|
|
return exp_no;
|
|
}
|
|
|
|
int
|
|
er_print::is_valid_seg_name (char *lo_name, int prev)
|
|
{
|
|
// prev is the loadobject segment index that was last returned
|
|
// search starts following that loadobject
|
|
int index;
|
|
LoadObject *lo;
|
|
char *p_lo_name = lo_name;
|
|
char *name = NULL;
|
|
|
|
// strip angle brackets from all but <Unknown> and <Total>
|
|
if (strcmp (lo_name, "<Unknown>") && strcmp (lo_name, "<Total>"))
|
|
{
|
|
if (*lo_name == '<')
|
|
{
|
|
name = dbe_strdup (lo_name + 1);
|
|
p_lo_name = name;
|
|
char *p = strchr (name, '>');
|
|
if (p)
|
|
*p = '\0';
|
|
}
|
|
}
|
|
|
|
// get the load object list from the session
|
|
Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
|
|
Vec_loop (LoadObject*, lobjs, index, lo)
|
|
{
|
|
if (prev > 0)
|
|
{
|
|
if (lo->seg_idx == prev) // this is where we left off
|
|
prev = -1;
|
|
continue;
|
|
}
|
|
|
|
// does this one match?
|
|
if (cmp_seg_name (lo->get_pathname (), p_lo_name))
|
|
{
|
|
delete lobjs;
|
|
free (name);
|
|
size_t len = strlen (lo_name);
|
|
if ((len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) ||
|
|
(len > 6 && streq (lo_name + len - 6, NTXT (".class"))))
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Java class `%s' is not selectable\n"), lo_name);
|
|
return -1;
|
|
}
|
|
return lo->seg_idx;
|
|
}
|
|
}
|
|
delete lobjs;
|
|
free (name);
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
er_print::cmp_seg_name (char *full_name, char *lo_name)
|
|
{
|
|
char *cmp_name;
|
|
if (!strchr (lo_name, '/') && (cmp_name = strrchr (full_name, '/')))
|
|
cmp_name++; // basename
|
|
else
|
|
cmp_name = full_name; // full path name
|
|
return !strcmp (lo_name, cmp_name);
|
|
}
|
|
|
|
// processing object_select
|
|
// Note that this does not affect the strings in Settings,
|
|
// unlike object_show, object_hide, and object_api
|
|
int
|
|
er_print::process_object_select (char *names)
|
|
{
|
|
int index;
|
|
LoadObject *lo;
|
|
int no_lobj = 0;
|
|
bool got_err = false;
|
|
Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
|
|
if ((names == NULL) || !strcasecmp (names, Command::ALL_CMD))
|
|
{ // full coverage
|
|
Vec_loop (LoadObject*, lobjs, index, lo)
|
|
{
|
|
dbev->set_lo_expand (lo->seg_idx, LIBEX_SHOW);
|
|
}
|
|
}
|
|
else
|
|
{ // parsing coverage
|
|
// first, hide functions from all loadobjects
|
|
// except the java ones
|
|
Vec_loop (LoadObject*, lobjs, index, lo)
|
|
{
|
|
char *lo_name = lo->get_name ();
|
|
if (lo_name != NULL)
|
|
{
|
|
size_t len = strlen (lo_name);
|
|
if ((len > 7 && streq (lo_name + len - 7, NTXT (".class>"))) ||
|
|
(len > 6 && streq (lo_name + len - 6, NTXT (".class"))))
|
|
continue;
|
|
}
|
|
dbev->set_lo_expand (lo->seg_idx, LIBEX_HIDE);
|
|
}
|
|
|
|
Vector <char *> *tokens = split_str (names, ',');
|
|
for (long j = 0, sz = VecSize (tokens); j < sz; j++)
|
|
{
|
|
// loop over the provided names
|
|
char *lo_name = tokens->get (j);
|
|
int seg_idx = -1;
|
|
seg_idx = is_valid_seg_name (lo_name, seg_idx);
|
|
while (seg_idx != -1)
|
|
{
|
|
dbev->set_lo_expand (seg_idx, LIBEX_SHOW);
|
|
no_lobj++;
|
|
seg_idx = is_valid_seg_name (lo_name, seg_idx);
|
|
}
|
|
if (no_lobj == 0)
|
|
{
|
|
got_err = true;
|
|
fprintf (stderr, GTXT ("Error: Unknown load object: `%s'\n"), lo_name);
|
|
}
|
|
free (lo_name);
|
|
}
|
|
delete tokens;
|
|
}
|
|
|
|
if (!got_err)
|
|
{ // good coverage string
|
|
free (cov_string);
|
|
cov_string = strdup (names);
|
|
}
|
|
else
|
|
{ // bad, restore original coverage
|
|
no_lobj = -1;
|
|
process_object_select (cov_string);
|
|
}
|
|
delete lobjs;
|
|
return no_lobj;
|
|
}
|
|
|
|
int
|
|
er_print::set_libexpand (char *cov, enum LibExpand expand)
|
|
{
|
|
bool changed = dbev->set_libexpand (cov, expand);
|
|
if (changed == true)
|
|
dbev->update_lo_expands ();
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
er_print::set_libdefaults ()
|
|
{
|
|
dbev->set_libdefaults ();
|
|
return 0;
|
|
}
|
|
|
|
bool
|
|
er_print::end_command (char *cmd)
|
|
{
|
|
if (cmd == NULL || *cmd == '-')
|
|
return true;
|
|
size_t len = strlen (cmd);
|
|
if (cmd[len - 1] == '/')
|
|
len--;
|
|
if ((len > 3 && !strncmp (&cmd[len - 3], NTXT (".er"), 3)) ||
|
|
(len > 4 && !strncmp (&cmd[len - 4], NTXT (".erg"), 4)))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// Now actually start processing the arguments
|
|
void
|
|
er_print::run (int argc, char *argv[])
|
|
{
|
|
CmdType cmd_type;
|
|
int arg_count, cparam, i;
|
|
bool got = false;
|
|
char *arg1, *arg2;
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (*argv[i] != '-') // open experiment pointer files
|
|
continue;
|
|
switch (cmd_type = Command::get_command (argv[i] + 1, arg_count, cparam))
|
|
{
|
|
case WHOAMI:
|
|
whoami = argv[i] + 1 + cparam;
|
|
break;
|
|
case SCRIPT:
|
|
got = true;
|
|
inp_file = fopen (argv[++i], "r");
|
|
if (inp_file == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Script file cannot be opened: %s\n"), argv[i]);
|
|
exit (3);
|
|
}
|
|
proc_script ();
|
|
break;
|
|
case STDIN:
|
|
got = true;
|
|
inp_file = stdin;
|
|
proc_script ();
|
|
break;
|
|
case SOURCE: // with option arg_count == 2
|
|
case DISASM:
|
|
got = true;
|
|
i += arg_count;
|
|
if ((i >= argc) || end_command (argv[i]))
|
|
{
|
|
i--;
|
|
arg1 = argv[i];
|
|
arg2 = NTXT ("");
|
|
}
|
|
else
|
|
{
|
|
arg1 = argv[i - 1];
|
|
arg2 = argv[i];
|
|
}
|
|
proc_cmd (cmd_type, cparam, arg1, arg2, NULL, NULL, true);
|
|
break;
|
|
case CSINGLE:
|
|
case CPREPEND:
|
|
case CAPPEND:
|
|
case FSINGLE:
|
|
got = true;
|
|
i += arg_count;
|
|
if ((i >= argc) || end_command (argv[i]))
|
|
{
|
|
i--;
|
|
proc_cmd (cmd_type, cparam, argv[i], NTXT ("1"));
|
|
}
|
|
else
|
|
proc_cmd (cmd_type, cparam, argv[i - 1], argv[i]);
|
|
break;
|
|
case SAMPLE_DETAIL: // with option arg_count == 1
|
|
case STATISTICS:
|
|
case HEADER:
|
|
got = true;
|
|
// now fall through to process the command
|
|
case COMPARE:
|
|
got = true;
|
|
i += arg_count;
|
|
if ((i >= argc) || end_command (argv[i]))
|
|
{
|
|
i--;
|
|
proc_cmd (cmd_type, cparam, NULL, NULL);
|
|
}
|
|
else
|
|
proc_cmd (cmd_type, cparam, argv[i], NULL);
|
|
break;
|
|
case PRINTMODE:
|
|
case INDXOBJDEF:
|
|
case ADDPATH:
|
|
case SETPATH:
|
|
case PATHMAP:
|
|
case OBJECT_SHOW:
|
|
case OBJECT_HIDE:
|
|
case OBJECT_API:
|
|
case OBJECTS_DEFAULT:
|
|
case EN_DESC:
|
|
got = true;
|
|
// these have been processed already
|
|
i += arg_count;
|
|
break;
|
|
case LIMIT:
|
|
got = true;
|
|
proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL,
|
|
(arg_count > 1) ? argv[i + 2] : NULL);
|
|
i += arg_count;
|
|
break;
|
|
default:
|
|
got = true;
|
|
proc_cmd (cmd_type, cparam, (arg_count > 0) ? argv[i + 1] : NULL,
|
|
(arg_count > 1) ? argv[i + 2] : NULL);
|
|
i += arg_count;
|
|
break;
|
|
}
|
|
}
|
|
if (!got) // no command has been specified
|
|
proc_script ();
|
|
}
|
|
|
|
#define MAXARGS 20
|
|
|
|
void
|
|
er_print::proc_script ()
|
|
{
|
|
CmdType cmd_type;
|
|
int arg_count, cparam;
|
|
char *cmd, *end_cmd;
|
|
char *script = NULL;
|
|
char *arglist[MAXARGS];
|
|
char *line = NULL;
|
|
int lineno = 0;
|
|
while (!feof (inp_file))
|
|
{
|
|
if (inp_file == stdin)
|
|
printf (NTXT ("(%s) "), get_basename (prog_name));
|
|
free (script);
|
|
script = read_line (inp_file);
|
|
if (script == NULL)
|
|
continue;
|
|
free (line);
|
|
line = dbe_strdup (script);
|
|
lineno++;
|
|
for (int i = 0; i < MAXARGS; i++)
|
|
arglist[i] = NULL;
|
|
|
|
// ensure it's terminated by a \n, and remove that character
|
|
strtok (script, NTXT ("\n"));
|
|
|
|
// extract the command
|
|
cmd = strtok (script, NTXT (" \t"));
|
|
if (cmd == NULL)
|
|
continue;
|
|
if (*cmd == '#')
|
|
{
|
|
fprintf (stderr, NTXT ("%s"), line);
|
|
continue;
|
|
}
|
|
if (*cmd == '\n')
|
|
continue;
|
|
|
|
char *remainder = strtok (NULL, NTXT ("\n"));
|
|
// now extract the arguments
|
|
int nargs = 0;
|
|
for (;;)
|
|
{
|
|
end_cmd = NULL;
|
|
if (nargs >= MAXARGS)
|
|
fprintf (stderr, GTXT ("Warning: more than %d arguments to %s command, line %d\n"),
|
|
MAXARGS, cmd, lineno);
|
|
char *nextarg = strtok (remainder, NTXT ("\n"));
|
|
if ((nextarg == NULL) || (*nextarg == '#'))
|
|
// either the end of the line, or a comment indicator
|
|
break;
|
|
if (nargs >= MAXARGS)
|
|
{
|
|
parse_qstring (nextarg, &end_cmd);
|
|
nargs++;
|
|
}
|
|
else
|
|
arglist[nargs++] = parse_qstring (nextarg, &end_cmd);
|
|
remainder = end_cmd;
|
|
if (remainder == NULL)
|
|
break;
|
|
// skip any blanks or tabs to get to next argument
|
|
while (*remainder == ' ' || *remainder == '\t')
|
|
remainder++;
|
|
}
|
|
|
|
cmd_type = Command::get_command (cmd, arg_count, cparam);
|
|
|
|
// check for extra arguments
|
|
if (cmd_type != UNKNOWN_CMD && cmd_type != INDXOBJDEF && nargs > arg_count)
|
|
fprintf (stderr, GTXT ("Warning: extra arguments to %s command, line %d\n"),
|
|
cmd, lineno);
|
|
switch (cmd_type)
|
|
{
|
|
case SOURCE:
|
|
case DISASM:
|
|
// ignore any third parameter
|
|
// if there was, we have written a warning
|
|
proc_cmd (cmd_type, cparam, arglist[0], arglist[1], NULL, NULL,
|
|
(inp_file != stdin));
|
|
break;
|
|
case QUIT:
|
|
free (script);
|
|
free (line);
|
|
exit (0);
|
|
case QQUIT:
|
|
was_QQUIT = true;
|
|
free (script);
|
|
free (line);
|
|
return;
|
|
case STDIN:
|
|
break;
|
|
case COMMENT:
|
|
fprintf (dis_file, NTXT ("%s"), line);
|
|
break;
|
|
case AMBIGUOUS_CMD:
|
|
fprintf (stderr, GTXT ("Error: Ambiguous command: %s\n"), cmd);
|
|
break;
|
|
case UNKNOWN_CMD:
|
|
if (*cmd != '\n')
|
|
fprintf (stderr, GTXT ("Error: Invalid command: %s\n"), cmd);
|
|
break;
|
|
default:
|
|
proc_cmd (cmd_type, cparam, arglist[0], arglist[1]);
|
|
break;
|
|
}
|
|
}
|
|
// free up the input line
|
|
free (script);
|
|
free (line);
|
|
}
|
|
|
|
void
|
|
er_print::proc_cmd (CmdType cmd_type, int cparam,
|
|
char *arg1, char *arg2, char *arg3, char *arg4, bool xdefault)
|
|
{
|
|
er_print_common_display *cd;
|
|
FILE *ck_file, *save_file;
|
|
char *name;
|
|
int bgn_index, end_index, index;
|
|
Cmd_status status;
|
|
char *scratch, *scratch1;
|
|
switch (cmd_type)
|
|
{
|
|
case FUNCS:
|
|
print_func (Histable::FUNCTION, MODE_LIST,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL));
|
|
break;
|
|
case FDETAIL:
|
|
print_func (Histable::FUNCTION, MODE_DETAIL,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL));
|
|
break;
|
|
case FSINGLE:
|
|
print_func (Histable::FUNCTION, MODE_DETAIL,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL),
|
|
arg1, arg2);
|
|
break;
|
|
case HOTPCS:
|
|
print_func (Histable::INSTR, MODE_LIST,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL));
|
|
break;
|
|
case PDETAIL:
|
|
print_func (Histable::INSTR, MODE_DETAIL,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL));
|
|
break;
|
|
case HOTLINES:
|
|
print_func (Histable::LINE, MODE_LIST,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_list (MET_NORMAL));
|
|
break;
|
|
case LDETAIL:
|
|
print_func (Histable::LINE, MODE_DETAIL,
|
|
dbev->get_metric_list (MET_NORMAL), dbev->get_metric_ref (MET_NORMAL));
|
|
break;
|
|
case OBJECTS:
|
|
print_objects ();
|
|
break;
|
|
case OVERVIEW_NEW:
|
|
print_overview ();
|
|
break;
|
|
case LOADOBJECT:
|
|
print_segments ();
|
|
break;
|
|
case GPROF:
|
|
print_func (Histable::FUNCTION, MODE_GPROF,
|
|
dbev->get_metric_list (MET_CALL), dbev->get_metric_list (MET_NORMAL));
|
|
break;
|
|
case CALLTREE:
|
|
if (dbev->comparingExperiments ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
|
|
break;
|
|
}
|
|
print_ctree (cmd_type);
|
|
break;
|
|
case CSINGLE:
|
|
case CPREPEND:
|
|
case CAPPEND:
|
|
case CRMFIRST:
|
|
case CRMLAST:
|
|
print_gprof (cmd_type, arg1, arg2);
|
|
break;
|
|
case EXP_LIST:
|
|
exp_list ();
|
|
break;
|
|
case DESCRIBE:
|
|
describe ();
|
|
break;
|
|
case SCOMPCOM:
|
|
status = dbev->proc_compcom (arg1, true, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
break;
|
|
case STHRESH:
|
|
status = dbev->proc_thresh (arg1, true, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
break;
|
|
case DCOMPCOM:
|
|
status = dbev->proc_compcom (arg1, false, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
break;
|
|
case COMPCOM:
|
|
status = dbev->proc_compcom (arg1, true, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
status = dbev->proc_compcom (arg1, false, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
break;
|
|
case DTHRESH:
|
|
status = dbev->proc_thresh (arg1, false, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
break;
|
|
case SOURCE:
|
|
case DISASM:
|
|
{
|
|
if (arg3 != NULL)
|
|
abort ();
|
|
if (arg1 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Invalid function/file setting: \n"));
|
|
break;
|
|
}
|
|
char *fcontext = NULL;
|
|
char *arg = parse_fname (arg1, &fcontext);
|
|
if (arg == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Invalid function/file setting: %s\n"), arg1);
|
|
free (fcontext);
|
|
break;
|
|
}
|
|
if (arg2 && (strlen (arg2) == 0))
|
|
arg2 = NULL;
|
|
print_anno_file (arg, arg2, fcontext, cmd_type == DISASM,
|
|
dis_file, inp_file, out_file, dbev, xdefault);
|
|
free (arg);
|
|
free (fcontext);
|
|
break;
|
|
}
|
|
case METRIC_LIST:
|
|
proc_cmd (METRICS, cparam, NULL, NULL);
|
|
dbev->get_metric_ref (MET_NORMAL)->print_metric_list (dis_file,
|
|
GTXT ("Available metrics:\n"), false);
|
|
break;
|
|
case METRICS:
|
|
if (arg1)
|
|
{
|
|
char *ret = dbev->setMetrics (arg1, false);
|
|
if (ret != NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: %s\n"), ret);
|
|
proc_cmd (METRIC_LIST, cparam, NULL, NULL);
|
|
break;
|
|
}
|
|
}
|
|
scratch = dbev->get_metric_list (MET_NORMAL)->get_metrics ();
|
|
fprintf (dis_file, GTXT ("Current metrics: %s\n"), scratch);
|
|
free (scratch);
|
|
proc_cmd (SORT, cparam, NULL, NULL);
|
|
break;
|
|
case GMETRIC_LIST:
|
|
scratch = dbev->get_metric_list (MET_CALL)->get_metrics ();
|
|
fprintf (dis_file, GTXT ("Current caller-callee metrics: %s\n"), scratch);
|
|
free (scratch);
|
|
fprintf (dis_file, GTXT ("Current caller-callee sort Metric: %s\n"),
|
|
dbev->getSort (MET_DATA));
|
|
break;
|
|
case INDX_METRIC_LIST:
|
|
scratch = dbev->get_metric_list (MET_INDX)->get_metrics ();
|
|
fprintf (dis_file, GTXT ("Current index-object metrics: %s\n"), scratch);
|
|
free (scratch);
|
|
scratch = dbev->getSort (MET_INDX);
|
|
fprintf (dis_file, GTXT ("Current index-object sort Metric: %s\n"), scratch);
|
|
free (scratch);
|
|
break;
|
|
case SORT:
|
|
if (arg1)
|
|
{
|
|
char *ret = dbev->setSort (arg1, MET_NORMAL, false);
|
|
if (ret != NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: %s\n"), ret);
|
|
proc_cmd (METRICS, cparam, NULL, NULL);
|
|
break;
|
|
}
|
|
dbev->setSort (arg1, MET_SRCDIS, false);
|
|
dbev->setSort (arg1, MET_CALL, false);
|
|
dbev->setSort (arg1, MET_DATA, false);
|
|
dbev->setSort (arg1, MET_INDX, false);
|
|
dbev->setSort (arg1, MET_CALL_AGR, false);
|
|
dbev->setSort (arg1, MET_IO, false);
|
|
dbev->setSort (arg1, MET_HEAP, false);
|
|
}
|
|
scratch = dbev->getSort (MET_NORMAL);
|
|
scratch1 = dbev->getSortCmd (MET_NORMAL);
|
|
fprintf (dis_file,
|
|
GTXT ("Current Sort Metric: %s ( %s )\n"), scratch, scratch1);
|
|
free (scratch1);
|
|
free (scratch);
|
|
break;
|
|
case OBJECT_SHOW:
|
|
if (arg1)
|
|
set_libexpand (arg1, LIBEX_SHOW);
|
|
obj_list ();
|
|
break;
|
|
case OBJECT_HIDE:
|
|
if (arg1)
|
|
set_libexpand (arg1, LIBEX_HIDE);
|
|
obj_list ();
|
|
break;
|
|
case OBJECT_API:
|
|
if (arg1)
|
|
set_libexpand (arg1, LIBEX_API);
|
|
obj_list ();
|
|
break;
|
|
case OBJECTS_DEFAULT:
|
|
set_libdefaults ();
|
|
obj_list ();
|
|
break;
|
|
case OBJECT_LIST:
|
|
obj_list ();
|
|
break;
|
|
case OBJECT_SELECT:
|
|
if (arg1)
|
|
{
|
|
if (process_object_select (arg1) != -1)
|
|
proc_cmd (OBJECT_LIST, cparam, NULL, NULL);
|
|
else
|
|
fprintf (stderr, GTXT ("Error: Type \"object_list\" for a list of all load objects.\n"));
|
|
}
|
|
else
|
|
fprintf (stderr, GTXT ("Error: No load object has been specified.\n"));
|
|
break;
|
|
case LOADOBJECT_LIST:
|
|
seg_list ();
|
|
break;
|
|
case LOADOBJECT_SELECT:
|
|
if (arg1)
|
|
{
|
|
if (process_object_select (arg1) != -1)
|
|
proc_cmd (LOADOBJECT_LIST, cparam, NULL, NULL);
|
|
else
|
|
fprintf (stderr, GTXT ("Error: Type \"segment_list\" for a list of all segments.\n"));
|
|
}
|
|
else
|
|
fprintf (stderr, GTXT ("Error: No segment has been specified.\n"));
|
|
break;
|
|
case SAMPLE_LIST:
|
|
filter_list (SAMPLE_LIST);
|
|
break;
|
|
case SAMPLE_SELECT:
|
|
if (arg1 && !dbev->set_pattern (SAMPLE_FILTER_IDX, arg1))
|
|
fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1);
|
|
proc_cmd (SAMPLE_LIST, cparam, NULL, NULL);
|
|
break;
|
|
case THREAD_LIST:
|
|
filter_list (THREAD_LIST);
|
|
break;
|
|
case THREAD_SELECT:
|
|
if (arg1 && !dbev->set_pattern (THREAD_FILTER_IDX, arg1))
|
|
fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1);
|
|
proc_cmd (THREAD_LIST, cparam, NULL, NULL);
|
|
break;
|
|
case LWP_LIST:
|
|
filter_list (LWP_LIST);
|
|
break;
|
|
case LWP_SELECT:
|
|
if (arg1 && !dbev->set_pattern (LWP_FILTER_IDX, arg1))
|
|
fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1);
|
|
proc_cmd (LWP_LIST, cparam, NULL, NULL);
|
|
break;
|
|
case CPU_LIST:
|
|
filter_list (CPU_LIST);
|
|
break;
|
|
case CPU_SELECT:
|
|
if (arg1 && !dbev->set_pattern (CPU_FILTER_IDX, arg1))
|
|
fprintf (stderr, GTXT ("Error: Invalid filter pattern specification %s\n"), arg1);
|
|
proc_cmd (CPU_LIST, cparam, NULL, NULL);
|
|
break;
|
|
case FILTERS:
|
|
if (arg1 != NULL)
|
|
{
|
|
if (strcmp (arg1, NTXT ("True")) == 0)
|
|
scratch = dbev->set_filter (NULL);
|
|
else
|
|
scratch = dbev->set_filter (arg1);
|
|
if (scratch != NULL)
|
|
fprintf (stderr, GTXT ("Error: %s\n"), scratch);
|
|
}
|
|
scratch = dbev->get_filter ();
|
|
fprintf (dis_file, GTXT ("current filter setting: \"%s\"\n"),
|
|
scratch == NULL ? GTXT ("<none>") : scratch);
|
|
break;
|
|
case OUTFILE:
|
|
if (arg1)
|
|
{
|
|
set_outfile (arg1, out_file, false);
|
|
if (inp_file != stdin)
|
|
dis_file = out_file;
|
|
}
|
|
break;
|
|
case APPENDFILE:
|
|
if (arg1)
|
|
{
|
|
set_outfile (arg1, out_file, true);
|
|
if (inp_file != stdin)
|
|
dis_file = out_file;
|
|
}
|
|
break;
|
|
case LIMIT:
|
|
if (arg1)
|
|
{
|
|
limit = (int) strtol (arg1, (char **) NULL, 10);
|
|
char *res = dbeSetPrintLimit (dbevindex, limit);
|
|
if (res != NULL)
|
|
fprintf (stderr, NTXT ("%s\n"), res);
|
|
}
|
|
|
|
limit = dbeGetPrintLimit (dbevindex);
|
|
fprintf (stderr, GTXT ("Print limit set to %d\n"), limit);
|
|
break;
|
|
case NAMEFMT:
|
|
if (arg1)
|
|
{
|
|
status = dbev->set_name_format (arg1);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
}
|
|
else
|
|
fprintf (stderr, GTXT ("Error: No format has been specified.\n"));
|
|
break;
|
|
case VIEWMODE:
|
|
{
|
|
if (arg1)
|
|
{
|
|
status = dbev->set_view_mode (arg1, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
}
|
|
const char *vname = "unknown";
|
|
int vm = dbev->get_view_mode ();
|
|
switch (vm)
|
|
{
|
|
case VMODE_USER:
|
|
vname = "user";
|
|
break;
|
|
case VMODE_EXPERT:
|
|
vname = "expert";
|
|
break;
|
|
case VMODE_MACHINE:
|
|
vname = "machine";
|
|
break;
|
|
}
|
|
fprintf (stderr, GTXT ("Viewmode set to %s\n"), vname);
|
|
}
|
|
break;
|
|
|
|
// EN_DESC does not make sense after experiments are read, but it does make sense on the command line,
|
|
// processed before the experiments are read.
|
|
case EN_DESC:
|
|
if (arg1)
|
|
{
|
|
status = dbev->set_en_desc (arg1, false);
|
|
if (status != CMD_OK)
|
|
fprintf (stderr, GTXT ("Error: %s: %s\n"), Command::get_err_string (status), arg1);
|
|
}
|
|
else
|
|
fprintf (stderr, GTXT ("Error: No descendant processing has been specified.\n"));
|
|
break;
|
|
case SETPATH:
|
|
case ADDPATH:
|
|
if (arg1)
|
|
dbeSession->set_search_path (arg1, (cmd_type == SETPATH));
|
|
fprintf (dis_file, GTXT ("search path:\n"));
|
|
Vec_loop (char*, dbeSession->get_search_path (), index, name)
|
|
{
|
|
fprintf (dis_file, NTXT ("\t%s\n"), name);
|
|
}
|
|
break;
|
|
case PATHMAP:
|
|
{
|
|
Vector<pathmap_t*> *pathMaps = dbeSession->get_pathmaps ();
|
|
if (arg1 != NULL)
|
|
{
|
|
if (arg2 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No replacement path prefix has been specified.\n"));
|
|
break;
|
|
}
|
|
// add this mapping to the session
|
|
char *err = Settings::add_pathmap (pathMaps, arg1, arg2);
|
|
if (err != NULL)
|
|
{
|
|
fprintf (stderr, NTXT ("%s"), err);
|
|
free (err);
|
|
}
|
|
}
|
|
fprintf (dis_file, GTXT ("Path mappings: from -> to\n"));
|
|
for (int i = 0, sz = pathMaps->size (); i < sz; i++)
|
|
{
|
|
pathmap_t *thismap = pathMaps->get (i);
|
|
fprintf (dis_file, NTXT ("\t`%s' -> `%s'\n"), thismap->old_prefix, thismap->new_prefix);
|
|
}
|
|
}
|
|
break;
|
|
case SAMPLE_DETAIL:
|
|
if (get_exp_id (arg1, bgn_index, end_index) != -1)
|
|
{
|
|
cd = new er_print_experiment (dbev, bgn_index, end_index, false,
|
|
false, false, true, true);
|
|
print_cmd (cd);
|
|
delete cd;
|
|
}
|
|
break;
|
|
case STATISTICS:
|
|
if (get_exp_id (arg1, bgn_index, end_index) != -1)
|
|
{
|
|
cd = new er_print_experiment (dbev, bgn_index, end_index, false,
|
|
false, true, true, false);
|
|
print_cmd (cd);
|
|
delete cd;
|
|
}
|
|
break;
|
|
case PRINTMODE:
|
|
{
|
|
if (arg1 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex));
|
|
break;
|
|
}
|
|
char *s = dbeSetPrintMode (dbevindex, arg1);
|
|
if (s != NULL)
|
|
{
|
|
fprintf (stderr, NTXT ("%s\n"), s);
|
|
break;
|
|
}
|
|
fprintf (stderr, GTXT ("printmode is set to `%s'\n\n"), dbeGetPrintModeString (dbevindex));
|
|
}
|
|
break;
|
|
case HEADER:
|
|
if (get_exp_id (arg1, bgn_index, end_index) != -1)
|
|
{
|
|
cd = new er_print_experiment (dbev, bgn_index, end_index, false,
|
|
true, false, false, false);
|
|
print_cmd (cd);
|
|
delete cd;
|
|
}
|
|
break;
|
|
case COMPARE:
|
|
if (arg1 == NULL)
|
|
{
|
|
fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n"));
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
int cmp;
|
|
if (strcasecmp (arg1, NTXT ("OFF")) == 0 || strcmp (arg1, NTXT ("0")) == 0)
|
|
cmp = CMP_DISABLE;
|
|
else if (strcasecmp (arg1, NTXT ("ON")) == 0 || strcmp (arg1, NTXT ("1")) == 0)
|
|
cmp = CMP_ENABLE;
|
|
else if (strcasecmp (arg1, NTXT ("DELTA")) == 0)
|
|
cmp = CMP_DELTA;
|
|
else if (strcasecmp (arg1, NTXT ("RATIO")) == 0)
|
|
cmp = CMP_RATIO;
|
|
else
|
|
{
|
|
fprintf (out_file, GTXT ("The argument to `compare' must be `on', `off', `delta', or `ratio'\n\n"));
|
|
break;
|
|
}
|
|
int oldMode = dbev->get_compare_mode ();
|
|
dbev->set_compare_mode (cmp);
|
|
if (oldMode != cmp)
|
|
{
|
|
dbev->reset_data (false);
|
|
dbeSession->reset_data ();
|
|
}
|
|
}
|
|
break;
|
|
case LEAKS:
|
|
if (!dbeSession->is_leaklist_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
if (dbev->comparingExperiments ())
|
|
{ // XXXX show warning for compare
|
|
fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_leaklist (dbev, true, false, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case ALLOCS:
|
|
if (!dbeSession->is_leaklist_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_leaklist (dbev, false, true, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case HEAP:
|
|
if (!dbeSession->is_heapdata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, false, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case HEAPSTAT:
|
|
if (!dbeSession->is_heapdata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("Heap trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_heapactivity (dbev, Histable::HEAPCALLSTACK, true, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case IOACTIVITY:
|
|
if (!dbeSession->is_iodata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
if (dbev->comparingExperiments ())
|
|
{ // XXXX show warning for compare
|
|
fprintf (out_file, GTXT ("\nNot available when comparing experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_ioactivity (dbev, Histable::IOACTFILE, false, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case IOVFD:
|
|
if (!dbeSession->is_iodata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, false, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case IOCALLSTACK:
|
|
if (!dbeSession->is_iodata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_ioactivity (dbev, Histable::IOCALLSTACK, false, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case IOSTAT:
|
|
if (!dbeSession->is_iodata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("I/O trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
cd = new er_print_ioactivity (dbev, Histable::IOACTVFD, true, dbev->get_limit ());
|
|
print_cmd (cd);
|
|
delete cd;
|
|
break;
|
|
case HELP:
|
|
Command::print_help(whoami, false, true, out_file);
|
|
break;
|
|
case VERSION_cmd:
|
|
Application::print_version_info ();
|
|
break;
|
|
case SCRIPT:
|
|
if (arg1)
|
|
{
|
|
ck_file = fopen (arg1, NTXT ("r"));
|
|
if (ck_file == NULL)
|
|
fprintf (stderr, GTXT ("Error: Script file cannot be opened: %s\n"), arg1);
|
|
else
|
|
{
|
|
save_file = inp_file;
|
|
inp_file = ck_file;
|
|
proc_script ();
|
|
inp_file = save_file;
|
|
}
|
|
}
|
|
else
|
|
fprintf (stderr, GTXT ("Error: No filename has been specified.\n"));
|
|
break;
|
|
case QUIT:
|
|
exit (0);
|
|
break;
|
|
|
|
// commands relating to index Objects
|
|
case INDXOBJ:
|
|
if ((cparam == -1) && (arg1 == NULL))
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No index object name has been specified.\n"));
|
|
break;
|
|
}
|
|
// automatically load machine model if applicable
|
|
dbeDetectLoadMachineModel (dbevindex);
|
|
indxobj (arg1, cparam);
|
|
break;
|
|
case INDXOBJLIST:
|
|
// automatically load machine model if applicable
|
|
dbeDetectLoadMachineModel (dbevindex);
|
|
indxo_list (false, out_file);
|
|
break;
|
|
|
|
// define a new IndexObject type
|
|
case INDXOBJDEF:
|
|
if (arg1 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No index object name has been specified.\n"));
|
|
break;
|
|
}
|
|
if (arg2 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No index-expr has been specified.\n"));
|
|
break;
|
|
}
|
|
indxo_define (arg1, arg2, arg3, arg4);
|
|
break;
|
|
|
|
// the commands following this are unsupported/hidden
|
|
case IFREQ:
|
|
if (!dbeSession->is_ifreq_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nInstruction frequency data was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
ifreq ();
|
|
break;
|
|
case DUMPNODES:
|
|
dump_nodes ();
|
|
break;
|
|
case DUMPSTACKS:
|
|
dump_stacks ();
|
|
break;
|
|
case DUMPUNK:
|
|
dump_unk_pcs ();
|
|
break;
|
|
case DUMPFUNC:
|
|
dump_funcs (arg1);
|
|
break;
|
|
case DUMPDOBJS:
|
|
dump_dataobjects (arg1);
|
|
break;
|
|
case DUMPMAP:
|
|
dump_map ();
|
|
break;
|
|
case DUMPENTITIES:
|
|
dump_entities ();
|
|
break;
|
|
case DUMP_PROFILE:
|
|
dbev->dump_profile (out_file);
|
|
break;
|
|
case DUMP_SYNC:
|
|
dbev->dump_sync (out_file);
|
|
break;
|
|
case DUMP_HWC:
|
|
dbev->dump_hwc (out_file);
|
|
break;
|
|
case DUMP_HEAP:
|
|
if (!dbeSession->is_leaklist_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nHeap trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
dbev->dump_heap (out_file);
|
|
break;
|
|
case DUMP_IOTRACE:
|
|
if (!dbeSession->is_iodata_available ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nI/O trace information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
dbev->dump_iotrace (out_file);
|
|
break;
|
|
case DMEM:
|
|
if (arg1 == NULL)
|
|
fprintf (stderr, GTXT ("Error: No sample has been specified.\n"));
|
|
else
|
|
{
|
|
Experiment *exp = dbeSession->get_exp (0);
|
|
if (exp != NULL)
|
|
exp->DBG_memuse (arg1);
|
|
}
|
|
break;
|
|
case DUMP_GC:
|
|
if (!dbeSession->has_java ())
|
|
{
|
|
fprintf (out_file, GTXT ("\nJava garbage collection information was not requested when recording experiments\n\n"));
|
|
break;
|
|
}
|
|
dbev->dump_gc_events (out_file);
|
|
break;
|
|
case DKILL:
|
|
{
|
|
if (arg1 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No process has been specified.\n"));
|
|
break;
|
|
}
|
|
if (arg2 == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No signal has been specified.\n"));
|
|
break;
|
|
}
|
|
pid_t p = (pid_t) atoi (arg1);
|
|
int signum = atoi (arg2);
|
|
char *ret = dbeSendSignal (p, signum);
|
|
if (ret != NULL)
|
|
fprintf (stderr, GTXT ("Error: %s"), ret);
|
|
}
|
|
break;
|
|
case PROCSTATS:
|
|
dump_stats ();
|
|
break;
|
|
case ADD_EXP:
|
|
case OPEN_EXP:
|
|
if (arg1 == NULL)
|
|
fprintf (stderr, GTXT ("Error: No experiment name has been specified.\n"));
|
|
else
|
|
{
|
|
Vector<Vector<char*>*> *groups = new Vector<Vector<char*>*>(1);
|
|
Vector<char*> *list = new Vector<char*>(1);
|
|
list->append (arg1);
|
|
groups->append (list);
|
|
char *res = dbeOpenExperimentList (dbevindex, groups, cmd_type == OPEN_EXP);
|
|
if (cmd_type == OPEN_EXP)
|
|
fprintf (stderr, GTXT ("Previously loaded experiment have been dropped.\n"));
|
|
if (res != NULL)
|
|
fprintf (stderr, NTXT ("%s"), res);
|
|
else
|
|
fprintf (stderr, GTXT ("Experiment %s has been loaded\n"), arg1);
|
|
free (res);
|
|
delete list;
|
|
delete groups;
|
|
}
|
|
break;
|
|
case DROP_EXP:
|
|
{
|
|
if (arg1 == NULL)
|
|
fprintf (stderr, GTXT ("Error: No experiment name has been specified.\n"));
|
|
else
|
|
{
|
|
int exp_index = dbeSession->find_experiment (arg1);
|
|
if (exp_index < 0)
|
|
fprintf (stderr, GTXT ("Error: experiment %s has not been opened.\n"), arg1);
|
|
else
|
|
{
|
|
Vector<int> *expid = new Vector<int> (1);
|
|
expid->append (exp_index);
|
|
char *res = dbeDropExperiment (dbevindex, expid);
|
|
if (res != NULL)
|
|
fprintf (stderr, NTXT ("%s"), res);
|
|
else
|
|
fprintf (stderr, GTXT ("Experiment %s has been dropped\n"), arg1);
|
|
delete expid;
|
|
free (res);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case HHELP:
|
|
// automatically load machine model if applicable
|
|
dbeDetectLoadMachineModel (dbevindex);
|
|
Command::print_help (whoami, false, false, out_file);
|
|
fprintf (out_file, NTXT ("\n"));
|
|
indxo_list (false, out_file);
|
|
fprintf (out_file, NTXT ("\n"));
|
|
mo_list (false, out_file);
|
|
if (!getenv ("_BUILDING_MANPAGE"))
|
|
fprintf (out_file, GTXT ("\nSee gprofng(1) for more details\n"));
|
|
break;
|
|
case QQUIT:
|
|
was_QQUIT = true;
|
|
return;
|
|
default:
|
|
fprintf (stderr, GTXT ("Error: Invalid option\n"));
|
|
break;
|
|
}
|
|
|
|
// check for any processing error messages
|
|
dump_proc_warnings ();
|
|
fflush (out_file);
|
|
}
|
|
|
|
#define MAX_NUM_HEADER 4
|
|
|
|
void
|
|
er_print::disp_list (int num_header, int size, int align[], char *header[],
|
|
char **lists[])
|
|
{
|
|
size_t maxlen[MAX_NUM_HEADER];
|
|
char fmt[MAX_NUM_HEADER][64];
|
|
if (num_header > MAX_NUM_HEADER)
|
|
abort ();
|
|
for (int i = 0; i < num_header; i++)
|
|
{
|
|
maxlen[i] = strlen (header[i]);
|
|
for (int j = 0; j < size; j++)
|
|
{
|
|
size_t len = strlen (lists[i][j]);
|
|
if (maxlen[i] < len)
|
|
maxlen[i] = len;
|
|
}
|
|
|
|
// get format string
|
|
if ((align[i] == -1) && (i == num_header - 1))
|
|
snprintf (fmt[i], sizeof (fmt[i]), NTXT ("%%s "));
|
|
else
|
|
snprintf (fmt[i], sizeof (fmt[i]), NTXT ("%%%ds "), (int) (align[i] * maxlen[i]));
|
|
|
|
// write header
|
|
fprintf (out_file, fmt[i], header[i]);
|
|
}
|
|
putc ('\n', out_file);
|
|
|
|
// write separator "==="
|
|
size_t np = 0;
|
|
for (int i = 0; (i < num_header) && (np < 132); i++)
|
|
{
|
|
size_t nc = maxlen[i];
|
|
if (nc + np > 132)
|
|
nc = 132 - np;
|
|
for (size_t j = 0; j < nc; j++)
|
|
putc ('=', out_file);
|
|
putc (' ', out_file);
|
|
np += nc + 1;
|
|
}
|
|
putc ('\n', out_file);
|
|
|
|
// write lists
|
|
for (int j = 0; j < size; j++)
|
|
{
|
|
for (int i = 0; i < num_header; i++)
|
|
fprintf (out_file, fmt[i], lists[i][j]);
|
|
putc ('\n', out_file);
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::exp_list ()
|
|
{
|
|
int size, index;
|
|
int align[MAX_NUM_HEADER];
|
|
char *header[MAX_NUM_HEADER];
|
|
char **lists[MAX_NUM_HEADER];
|
|
|
|
align[0] = 1; // right-justify
|
|
align[1] = 1; // right-justify
|
|
align[2] = 1; // right-justify
|
|
align[3] = -1; // left-justify
|
|
header[0] = GTXT ("ID");
|
|
header[1] = GTXT ("Sel");
|
|
header[2] = GTXT ("PID");
|
|
header[3] = GTXT ("Experiment");
|
|
|
|
size = dbeSession->nexps ();
|
|
lists[0] = new char*[size];
|
|
lists[1] = new char*[size];
|
|
lists[2] = new char*[size];
|
|
lists[3] = new char*[size];
|
|
for (index = 0; index < size; index++)
|
|
{
|
|
lists[0][index] = dbe_sprintf (NTXT ("%d"), index + 1);
|
|
lists[1][index] = strdup (dbev->get_exp_enable (index) ? GTXT ("yes") : GTXT ("no"));
|
|
lists[2][index] = dbe_sprintf (NTXT ("%d"), dbeSession->get_exp (index)->getPID ());
|
|
lists[3][index] = strdup (dbeSession->get_exp (index)->get_expt_name ());
|
|
}
|
|
disp_list (4, size, align, header, lists);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j < size; j++)
|
|
free (lists[i][j]);
|
|
delete[] lists[i];
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::describe ()
|
|
{
|
|
Vector<void*> *res = dbeGetFilterKeywords (dbev->vindex);
|
|
if (res == NULL)
|
|
return;
|
|
Vector <char*> *kwCategoryI18N = (Vector<char*>*) res->fetch (1);
|
|
Vector <char*> *kwKeyword = (Vector<char*>*) res->fetch (3);
|
|
Vector <char*> *kwFormula = (Vector<char*>*) res->fetch (4);
|
|
Vector <char*> *kwDescrip = (Vector<char*>*) res->fetch (5);
|
|
Vector <void*> *kwEnumDescs = (Vector<void*>*) res->fetch (6);
|
|
String sectionFormat = NTXT ("\n------ %s ------\n");
|
|
String categoryFormat = NTXT ("\n%s\n");
|
|
String keywordFormat = NTXT (" %-20s %s\n");
|
|
String empty = NTXT ("");
|
|
String previousCategory = empty;
|
|
|
|
for (int i = 0; i < kwKeyword->size (); i++)
|
|
{
|
|
if (kwKeyword->fetch (i) == NULL)
|
|
{
|
|
fprintf (dis_file, sectionFormat, kwCategoryI18N->fetch (i));
|
|
continue;
|
|
}
|
|
String cat = kwCategoryI18N->fetch (i);
|
|
if (dbe_strcmp (previousCategory, cat) != 0)
|
|
fprintf (dis_file, categoryFormat, cat);
|
|
previousCategory = cat;
|
|
Vector <String> *enumDescs = (Vector <String> *) kwEnumDescs->fetch (i);
|
|
String keyword = kwKeyword->fetch (i);
|
|
if (kwDescrip->fetch (i) != NULL)
|
|
{
|
|
fprintf (dis_file, keywordFormat, keyword, kwDescrip->fetch (i));
|
|
keyword = empty;
|
|
}
|
|
if (kwFormula->fetch (i) != NULL)
|
|
{
|
|
fprintf (dis_file, keywordFormat, keyword, kwFormula->fetch (i));
|
|
keyword = empty;
|
|
continue;
|
|
}
|
|
int numEnums = enumDescs != NULL ? enumDescs->size () : 0;
|
|
for (int jj = 0; jj < numEnums; jj++)
|
|
{
|
|
fprintf (dis_file, keywordFormat, keyword, enumDescs->fetch (jj));
|
|
keyword = empty;
|
|
}
|
|
}
|
|
destroy (res);
|
|
}
|
|
|
|
void
|
|
er_print::obj_list ()
|
|
{
|
|
LoadObject *lo;
|
|
int index;
|
|
int align[MAX_NUM_HEADER];
|
|
char *header[MAX_NUM_HEADER];
|
|
char **lists[MAX_NUM_HEADER];
|
|
Vector<LoadObject*> *text_segments = dbeSession->get_text_segments ();
|
|
if (text_segments->size () == 0)
|
|
{
|
|
fprintf (dis_file, GTXT ("There are no load objects in this experiment\n"));
|
|
return;
|
|
}
|
|
align[0] = -1; // left-justify
|
|
align[1] = -1; // left-justify
|
|
align[2] = -1; // left-justify
|
|
align[3] = -1; // left-justify
|
|
header[0] = GTXT ("Sel");
|
|
header[1] = GTXT ("Load Object");
|
|
header[2] = GTXT ("Index");
|
|
header[3] = GTXT ("Path");
|
|
|
|
int size = text_segments->size ();
|
|
lists[0] = new char*[size];
|
|
lists[1] = new char*[size];
|
|
lists[2] = new char*[size];
|
|
lists[3] = new char*[size];
|
|
|
|
char *lo_name;
|
|
int new_index = 0;
|
|
Vec_loop (LoadObject*, text_segments, index, lo)
|
|
{
|
|
lo_name = lo->get_name ();
|
|
if (lo_name != NULL)
|
|
{
|
|
size_t len = strlen (lo_name);
|
|
if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
|
|
continue;
|
|
}
|
|
LibExpand expand = dbev->get_lo_expand (lo->seg_idx);
|
|
switch (expand)
|
|
{
|
|
case LIBEX_SHOW:
|
|
lists[0][new_index] = dbe_strdup (GTXT ("show"));
|
|
break;
|
|
case LIBEX_HIDE:
|
|
lists[0][new_index] = dbe_strdup (GTXT ("hide"));
|
|
break;
|
|
case LIBEX_API:
|
|
lists[0][new_index] = dbe_strdup (GTXT ("API-only"));
|
|
break;
|
|
}
|
|
lists[1][new_index] = dbe_strdup (lo_name);
|
|
lists[2][new_index] = dbe_sprintf (NTXT ("%d"), lo->seg_idx);
|
|
lists[3][new_index] = dbe_strdup (lo->get_pathname ());
|
|
new_index++;
|
|
}
|
|
disp_list (4, new_index, align, header, lists);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j < new_index; j++)
|
|
free (lists[i][j]);
|
|
delete[] lists[i];
|
|
}
|
|
delete text_segments;
|
|
}
|
|
|
|
void
|
|
er_print::seg_list ()
|
|
{
|
|
LoadObject *lo;
|
|
int index;
|
|
int align[MAX_NUM_HEADER];
|
|
char *header[MAX_NUM_HEADER];
|
|
char **lists[MAX_NUM_HEADER];
|
|
|
|
// XXX seg_list only prints text segments; should extend to all
|
|
Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
|
|
if (lobjs->size () == 0)
|
|
{
|
|
fprintf (dis_file, GTXT ("There are no segments in this experiment\n"));
|
|
return;
|
|
}
|
|
align[0] = -1; // left-justify
|
|
align[1] = 1; // right-justify
|
|
align[2] = -1; // left-justify
|
|
header[0] = GTXT ("Sel");
|
|
header[1] = GTXT ("Size");
|
|
header[2] = GTXT ("Segment");
|
|
|
|
int size = lobjs->size ();
|
|
lists[0] = new char*[size];
|
|
lists[1] = new char*[size];
|
|
lists[2] = new char*[size];
|
|
|
|
char *lo_name;
|
|
int new_index = 0;
|
|
Vec_loop (LoadObject*, lobjs, index, lo)
|
|
{
|
|
lo_name = lo->get_name ();
|
|
if (lo_name != NULL)
|
|
{
|
|
size_t len = strlen (lo_name);
|
|
if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
|
|
continue;
|
|
}
|
|
bool expand = dbev->get_lo_expand (lo->seg_idx);
|
|
lists[0][new_index] = strdup (expand ? GTXT ("yes") : GTXT ("no"));
|
|
lists[1][new_index] = dbe_sprintf (NTXT ("%lld"), (ll_t) lo->get_size ());
|
|
lists[2][new_index] = strdup (lo->get_pathname ());
|
|
new_index++;
|
|
}
|
|
|
|
disp_list (3, new_index, align, header, lists);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j < new_index; j++)
|
|
free (lists[i][j]);
|
|
delete[] lists[i];
|
|
}
|
|
delete lobjs;
|
|
}
|
|
|
|
void
|
|
er_print::filter_list (CmdType cmd_type)
|
|
{
|
|
FilterNumeric *select;
|
|
int index;
|
|
int align[MAX_NUM_HEADER];
|
|
char *header[MAX_NUM_HEADER];
|
|
char **lists[MAX_NUM_HEADER];
|
|
char *pattern;
|
|
|
|
// first ensure that the data has been read
|
|
MetricList *mlist = dbev->get_metric_list (MET_INDX);
|
|
Hist_data *data = dbev->get_hist_data (mlist, Histable::INDEXOBJ, 0, Hist_data::ALL);
|
|
delete data;
|
|
|
|
align[0] = 1; // right-justify
|
|
align[1] = -1; // left-justify
|
|
align[2] = 1; // right-justify
|
|
align[3] = 1; // right-justify
|
|
header[0] = GTXT ("Exp");
|
|
header[1] = GTXT ("Sel");
|
|
header[2] = GTXT ("Total");
|
|
header[3] = GTXT ("Status");
|
|
|
|
int size = dbeSession->nexps ();
|
|
lists[0] = new char*[size];
|
|
lists[1] = new char*[size];
|
|
lists[2] = new char*[size];
|
|
lists[3] = new char*[size];
|
|
int new_index = 0;
|
|
for (index = 0; index < size; index++)
|
|
{
|
|
switch (cmd_type)
|
|
{
|
|
case SAMPLE_LIST:
|
|
select = dbev->get_FilterNumeric (index, SAMPLE_FILTER_IDX);
|
|
break;
|
|
case THREAD_LIST:
|
|
select = dbev->get_FilterNumeric (index, THREAD_FILTER_IDX);
|
|
break;
|
|
case LWP_LIST:
|
|
select = dbev->get_FilterNumeric (index, LWP_FILTER_IDX);
|
|
break;
|
|
case CPU_LIST:
|
|
select = dbev->get_FilterNumeric (index, CPU_FILTER_IDX);
|
|
break;
|
|
default:
|
|
abort (); // internal error
|
|
}
|
|
if (select == NULL)
|
|
continue;
|
|
lists[0][new_index] = dbe_sprintf (NTXT ("%d"), index + 1);
|
|
pattern = dbev->get_exp_enable (index) ? select->get_pattern () : NULL;
|
|
lists[1][new_index] = strdup (pattern && *pattern ? pattern : GTXT ("none"));
|
|
lists[2][new_index] = dbe_sprintf (NTXT ("%lld"), (ll_t) select->nelem ());
|
|
lists[3][new_index] = select->get_status ();
|
|
new_index++;
|
|
}
|
|
disp_list (3, size, align, header, lists);
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j < new_index; j++)
|
|
free (lists[i][j]);
|
|
delete[] lists[i];
|
|
}
|
|
}
|
|
|
|
int
|
|
er_print::check_exp_id (int exp_id, char *sel)
|
|
{
|
|
if (exp_id < 0 || exp_id >= dbeSession->nexps ())
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Invalid number entered: %s\nType \"exp_list\" for a list of all experiments.\n"),
|
|
sel);
|
|
return -1;
|
|
}
|
|
return exp_id;
|
|
}
|
|
|
|
int
|
|
er_print::get_exp_id (char *sel, int &bgn_index, int &end_index)
|
|
{
|
|
int id, exp_id;
|
|
if (sel == NULL || strcmp (sel, NTXT ("all")) == 0)
|
|
{
|
|
// loop over all experiments
|
|
bgn_index = 0;
|
|
end_index = dbeSession->nexps () - 1;
|
|
}
|
|
else
|
|
{
|
|
id = (int) strtol (sel, (char **) NULL, 10) - 1;
|
|
exp_id = check_exp_id (id, sel);
|
|
if (exp_id == -1)
|
|
return -1;
|
|
bgn_index = end_index = exp_id;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
er_print::print_objects ()
|
|
{
|
|
Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
|
|
char *msg = pr_load_objects (lobjs, NTXT (""));
|
|
delete lobjs;
|
|
fprintf (out_file, NTXT ("%s\n"), msg);
|
|
free (msg);
|
|
}
|
|
|
|
void
|
|
er_print::print_overview ()
|
|
{
|
|
//fprintf(out_file, NTXT("%s\n"), GTXT("Not implemented yet."));//YXXX
|
|
Vector<char*> *status = dbeGetOverviewText (dbevindex);
|
|
StringBuilder sb;
|
|
sb.append (GTXT ("Experiment(s):\n\n"));
|
|
for (int i = 0; i < status->size (); i++)
|
|
sb.appendf (NTXT ("%s\n"), status->fetch (i));
|
|
sb.append (GTXT ("Metrics:\n"));
|
|
sb.toFile (out_file);
|
|
|
|
Vector<void*> *data = dbeGetRefMetricTree (dbevindex, false);
|
|
Vector<char *> *metric_cmds = new Vector<char *>();
|
|
Vector<char *> *non_metric_cmds = new Vector<char *>();
|
|
print_overview_nodes (data, 0, metric_cmds, non_metric_cmds);
|
|
Vector<void*> *values = dbeGetRefMetricTreeValues (0, metric_cmds, non_metric_cmds);
|
|
print_overview_tree (data, 0, values, metric_cmds, non_metric_cmds);
|
|
|
|
StringBuilder sb2;
|
|
sb2.append (GTXT ("\nNotes: '*' indicates hot metrics, '[X]' indicates currently enabled metrics.\n"));
|
|
sb2.append (GTXT (" The metrics command can be used to change selections. The metric_list command lists all available metrics.\n"));
|
|
sb2.toFile (out_file);
|
|
}
|
|
|
|
void
|
|
er_print::print_overview_nodes (Vector<void*> * data, int level, Vector<char *> *metric_cmds, Vector<char *> *non_metric_cmds)
|
|
{
|
|
Vector<void*> *fields = (Vector<void*> *) data->fetch (0);
|
|
Vector<void*> *children = (Vector<void*> *) data->fetch (1);
|
|
char *name = ((Vector<char*> *)fields->fetch (0))->fetch (0);
|
|
int vstyles_capable = ((Vector<int>*) fields->fetch (5))->fetch (0); //bitmask e.g.VAL_TIMEVAL
|
|
bool has_value = ((Vector<bool>*) fields->fetch (10))->fetch (0);
|
|
bool selectable = (vstyles_capable != 0) ? true : false;
|
|
if (selectable)
|
|
metric_cmds->append (name);
|
|
else if (has_value)
|
|
non_metric_cmds->append (name);
|
|
|
|
level++;
|
|
for (int i = 0; i < children->size (); i++)
|
|
print_overview_nodes ((Vector<void*> *)(children->fetch (i)), level, metric_cmds, non_metric_cmds);
|
|
}
|
|
|
|
void
|
|
er_print::print_overview_tree (Vector<void*> * data, int level, Vector<void*> * values, Vector<char *> *metric_cmds, Vector<char *> *non_metric_cmds)
|
|
{
|
|
Vector<void*> * fields = (Vector<void*> *) data->fetch (0);
|
|
Vector<void*> * children = (Vector<void*> *) data->fetch (1);
|
|
char *name = ((Vector<char*> *)fields->fetch (0))->fetch (0);
|
|
char *username = ((Vector<char*> *)fields->fetch (1))->fetch (0);
|
|
int flavors = ((Vector<int>*) fields->fetch (3))->fetch (0); //bitmask e.g. EXCLUSIVE
|
|
int vstyles_capable = ((Vector<int>*) fields->fetch (5))->fetch (0); //bitmask e.g.VAL_TIMEVAL
|
|
// bool aggregation = ((Vector<bool>*) fields->fetch(9))->fetch(0);
|
|
// bool has_value = ((Vector<bool>*) fields->fetch(10))->fetch(0);
|
|
char *unit = ((Vector<char*> *) fields->fetch (11))->fetch (0);
|
|
|
|
StringBuilder sb;
|
|
for (int i = 0; i < level * 2; i++)
|
|
sb.append (NTXT (" ")); // NOI18N
|
|
|
|
bool selectable = (vstyles_capable != 0) ? true : false;
|
|
if (selectable)
|
|
{
|
|
bool isSelected = dbev->get_metric_list (MET_NORMAL)->find_metric_by_name (name) == NULL ? false : true;
|
|
if (isSelected)
|
|
sb.append (NTXT ("[X]"));
|
|
else
|
|
sb.append (NTXT ("[ ]"));
|
|
}
|
|
if ((unit != NULL && dbe_strcmp (unit, UNIT_SECONDS) == 0)
|
|
|| (unit == NULL && vstyles_capable & VAL_TIMEVAL))
|
|
unit = GTXT ("Seconds");
|
|
|
|
bool isHiddenInOverview = ((flavors & BaseMetric::STATIC) != 0);
|
|
if (name != NULL && dbe_strcmp (name, L1_STATIC) == 0)
|
|
isHiddenInOverview = true;
|
|
if (!dbeSession->has_java () && name != NULL && dbe_strcmp (name, L1_GCDURATION) == 0)
|
|
isHiddenInOverview = true;
|
|
if (isHiddenInOverview)
|
|
return;
|
|
|
|
sb.append (username == NULL ? NTXT ("") : username); // NOI18N
|
|
int show = 0;
|
|
if (name == NULL)
|
|
show = 0;
|
|
else if (strstr (name, NTXT ("PROFDATA_TYPE_")) == NULL)
|
|
show = 1;
|
|
|
|
if (show)
|
|
{
|
|
sb.append (username == NULL ? NTXT ("") : NTXT (" - ")); // NOI18N
|
|
sb.append (name == NULL ? NTXT ("") : name); // NOI18N
|
|
}
|
|
|
|
// "Bugs 16624403 and 19539622" (leave this string intact for searches)
|
|
// add an extra condition for now
|
|
// once we have proper fixes, eliminate test on Bug16624402_extra_condition
|
|
int Bug16624402_extra_condition = 1;
|
|
if (username)
|
|
{
|
|
if (strcmp (username, NTXT ("Block Covered %")) == 0) Bug16624402_extra_condition = 0;
|
|
if (strcmp (username, NTXT ("Instr Covered %")) == 0) Bug16624402_extra_condition = 0;
|
|
}
|
|
if (Bug16624402_extra_condition > 0 && values->size () > 0)
|
|
{
|
|
Vector<void*> * valueColumns = (Vector<void*> *)values->fetch (0);
|
|
Vector<void*> * highlightColumns = (Vector<void*> *)values->fetch (1);
|
|
int jj = 0;
|
|
int found = 0;
|
|
for (jj = 0; jj < valueColumns->size (); jj++)
|
|
{
|
|
const char *value_name = "";
|
|
if (jj < metric_cmds->size ())
|
|
value_name = metric_cmds->fetch (jj);
|
|
else
|
|
value_name = non_metric_cmds->fetch (jj - metric_cmds->size ());
|
|
if (dbe_strcmp (value_name, name) != 0)
|
|
continue;
|
|
else
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
{
|
|
Vector<void*> * valueVec = (Vector<void*> *)valueColumns->fetch (jj);
|
|
Vector<bool> * highlights = (Vector<bool> *)highlightColumns->fetch (jj);
|
|
for (int kk = 0; kk < valueVec->size (); kk++)
|
|
{
|
|
char * value_str;
|
|
int show_value = 0;
|
|
switch (valueVec->type ())
|
|
{
|
|
case VEC_INTEGER:
|
|
value_str = dbe_sprintf (NTXT ("%ld"), (long) (((Vector<int> *)valueVec)->fetch (kk)));
|
|
show_value = 1;
|
|
break;
|
|
case VEC_DOUBLE:
|
|
value_str = dbe_sprintf (NTXT ("%.3f"), (double) (((Vector<double> *)valueVec)->fetch (kk)));
|
|
show_value = 1;
|
|
break;
|
|
case VEC_LLONG:
|
|
value_str = dbe_sprintf (NTXT ("%lld"), (long long) (((Vector<long> *)valueVec)->fetch (kk)));
|
|
show_value = 1;
|
|
break;
|
|
case VEC_STRING:
|
|
value_str = NTXT ("");
|
|
break;
|
|
default:
|
|
value_str = NTXT ("");
|
|
}
|
|
if (show_value)
|
|
{
|
|
if (kk == 0)
|
|
{
|
|
sb.append (unit == NULL ? NTXT ("") : NTXT (" ("));
|
|
sb.append (unit == NULL ? NTXT ("") : unit);
|
|
sb.append (unit == NULL ? NTXT ("") : NTXT (")"));
|
|
sb.append (NTXT (":"));
|
|
}
|
|
bool highlight = highlights->fetch (kk);
|
|
const char * hilite = highlight ? NTXT ("*") : NTXT ("");
|
|
sb.append (NTXT (" ["));
|
|
sb.append (hilite);
|
|
sb.append (value_str);
|
|
sb.append (NTXT ("]"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sb.append (NTXT ("\n"));
|
|
sb.toFile (out_file);
|
|
level++;
|
|
for (int i = 0; i < children->size (); i++)
|
|
print_overview_tree ((Vector<void*> *)(children->fetch (i)), level, values, metric_cmds, non_metric_cmds);
|
|
}
|
|
|
|
void
|
|
er_print::print_segments ()
|
|
{
|
|
Vector<LoadObject*> *lobjs = dbeSession->get_text_segments ();
|
|
char *msg = pr_load_objects (lobjs, NTXT (""));
|
|
delete lobjs;
|
|
fprintf (dis_file, NTXT ("Not implemented yet!\n"));
|
|
free (msg);
|
|
}
|
|
|
|
void
|
|
er_print::print_dobj (Print_mode mode, MetricList *mlist1,
|
|
char *dobj_name, char *sel)
|
|
{
|
|
Hist_data *hist_data = NULL;
|
|
char *errstr;
|
|
er_print_common_display *cd;
|
|
int list_limit = limit;
|
|
Histable *sobj = NULL;
|
|
Dprintf (DEBUG_DATAOBJ, NTXT ("er_print::print_dobj(mode=%d,dobj=%s,sel=%s)\n"),
|
|
mode, (dobj_name == NULL) ? NTXT ("0") : dobj_name, (sel == NULL) ? NTXT ("0") : sel);
|
|
char *name = dbev->getSort (MET_DATA);
|
|
switch (mode)
|
|
{
|
|
case MODE_LIST:
|
|
hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::ALL);
|
|
break;
|
|
case MODE_DETAIL:
|
|
// if specified, find the dataobject from the name
|
|
if (dobj_name && strcmp (dobj_name, NTXT ("<All>")))
|
|
{
|
|
if (!dbeSession->find_obj (dis_file, inp_file, sobj, dobj_name,
|
|
sel, Histable::DOBJECT, (inp_file != stdin)))
|
|
return;
|
|
if (sobj == NULL)
|
|
{ // dataobject/segment not found
|
|
hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::DETAIL);
|
|
if (!dbeSession->find_obj (dis_file, inp_file, sobj, dobj_name,
|
|
sel, Histable::DOBJECT, (inp_file != stdin)))
|
|
return;
|
|
if (sobj == NULL)
|
|
{ // dataobject/segment not found
|
|
fprintf (stderr, GTXT ("Error: No dataobject with given name `%s' found.\n"),
|
|
dobj_name);
|
|
return;
|
|
}
|
|
}
|
|
|
|
list_limit = 1;
|
|
}
|
|
if (!hist_data)
|
|
hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::DETAIL);
|
|
break;
|
|
case MODE_ANNOTATED:
|
|
hist_data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::LAYOUT);
|
|
break;
|
|
default: // MODE_GPROF is not relevant for DataObjects
|
|
abort ();
|
|
}
|
|
|
|
if (hist_data->get_status () != Hist_data::SUCCESS)
|
|
{
|
|
// XXXX is this error message adequate?
|
|
errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
|
|
if (errstr)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: %s\n"), errstr);
|
|
free (errstr);
|
|
}
|
|
delete hist_data;
|
|
return;
|
|
}
|
|
cd = (er_print_common_display *) new er_print_histogram (dbev, hist_data,
|
|
hist_data->get_metric_list (), mode, list_limit, name, sobj, false, false);
|
|
free (name);
|
|
print_cmd (cd);
|
|
|
|
delete hist_data;
|
|
delete cd;
|
|
}
|
|
|
|
void
|
|
er_print::print_func (Histable::Type type, Print_mode mode, MetricList *mlist1,
|
|
MetricList *mlist2, char *func_name, char *sel)
|
|
{
|
|
Hist_data *hist_data;
|
|
Hist_data::HistItem *hitem;
|
|
int index;
|
|
char *errstr;
|
|
int list_limit = limit;
|
|
Histable *sobj = NULL;
|
|
MetricList *mlist;
|
|
StringBuilder sb;
|
|
char *sname = dbev->getSort (MET_NORMAL);
|
|
sb.append (sname);
|
|
free (sname);
|
|
|
|
switch (mode)
|
|
{
|
|
case MODE_DETAIL:
|
|
{
|
|
// The first metric list, mlist1, is only used to pick out the sort
|
|
// mlist2 is the one used to generate the data
|
|
char *prevsort = NULL;
|
|
// if specified, find the function from the function name
|
|
if (func_name && strcmp (func_name, NTXT ("<All>")))
|
|
{
|
|
if ((!dbeSession->find_obj (dis_file, inp_file, sobj, func_name,
|
|
sel, Histable::FUNCTION, (inp_file != stdin)) || (sobj == NULL)) &&
|
|
!dbeSession->find_obj (dis_file, inp_file, sobj, func_name,
|
|
sel, Histable::LOADOBJECT, (inp_file != stdin)))
|
|
return;
|
|
if (sobj == NULL)
|
|
{ // function/segment object not found
|
|
fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"),
|
|
func_name);
|
|
return;
|
|
}
|
|
list_limit = 1;
|
|
}
|
|
else
|
|
{
|
|
// find the sort metric from the reference list
|
|
prevsort = mlist2->get_sort_cmd ();
|
|
|
|
// find the current sort metric from the current list
|
|
char *cursort = mlist1->get_sort_cmd ();
|
|
|
|
// find the corresponding metric in the reference list
|
|
(void) mlist2->set_sort (cursort, false);
|
|
free (cursort);
|
|
// if it fails, nothing is needed
|
|
}
|
|
hist_data = dbev->get_hist_data (mlist2, type, 0, Hist_data::ALL);
|
|
|
|
// restore
|
|
if (sobj == NULL)
|
|
{
|
|
if (prevsort == NULL)
|
|
abort ();
|
|
(void) mlist2->set_sort (prevsort, false);
|
|
}
|
|
mlist = mlist2;
|
|
free (prevsort);
|
|
break;
|
|
}
|
|
case MODE_GPROF:
|
|
// if specified, find the function from the function name
|
|
if (func_name && strcmp (func_name, NTXT ("<All>")))
|
|
{
|
|
if (!dbeSession->find_obj (dis_file, inp_file, sobj, func_name,
|
|
sel, Histable::FUNCTION, (inp_file != stdin)))
|
|
return;
|
|
if (sobj == NULL)
|
|
{ // function/segment object not found
|
|
fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"),
|
|
func_name);
|
|
return;
|
|
}
|
|
list_limit = 1;
|
|
sb.setLength (0);
|
|
}
|
|
sb.append (GTXT ("\nCallers and callees sorted by metric: "));
|
|
sname = dbev->getSort (MET_CALL);
|
|
sb.append (sname);
|
|
free (sname);
|
|
|
|
// Use mlist2 to generate the sort order.
|
|
// mlist1 is used to generate the data.
|
|
hist_data = dbev->get_hist_data (mlist2, type, 0, Hist_data::ALL);
|
|
mlist = mlist1;
|
|
break;
|
|
default:
|
|
hist_data = dbev->get_hist_data (mlist1, type, 0, Hist_data::ALL);
|
|
mlist = mlist1;
|
|
}
|
|
|
|
if (hist_data->get_status () != Hist_data::SUCCESS)
|
|
{
|
|
errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
|
|
if (errstr)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: %s\n"), errstr);
|
|
free (errstr);
|
|
}
|
|
delete hist_data;
|
|
return;
|
|
}
|
|
|
|
if (type == Histable::FUNCTION)
|
|
{
|
|
for (index = 0; index < hist_data->size (); index++)
|
|
{
|
|
hitem = hist_data->fetch (index);
|
|
if (hitem->obj->get_type () == Histable::FUNCTION)
|
|
// fetch the name, since that will force a format conversion
|
|
((Function *) hitem->obj)->get_name ();
|
|
}
|
|
}
|
|
|
|
char *name = sb.toString ();
|
|
er_print_histogram *cd = new er_print_histogram (dbev, hist_data,
|
|
mlist, mode, list_limit, name, sobj, false, false);
|
|
print_cmd (cd);
|
|
delete hist_data;
|
|
free (name);
|
|
delete cd;
|
|
}
|
|
|
|
void
|
|
er_print::print_gprof (CmdType cmd_type, char *func_name, char *sel)
|
|
{
|
|
Histable *sobj = NULL;
|
|
if (func_name != NULL)
|
|
{
|
|
if ((!dbeSession->find_obj (dis_file, inp_file, sobj, func_name,
|
|
sel, Histable::FUNCTION, (inp_file != stdin))
|
|
|| sobj == NULL)
|
|
&& !dbeSession->find_obj (dis_file, inp_file, sobj, func_name,
|
|
sel, Histable::LOADOBJECT, (inp_file != stdin)))
|
|
return;
|
|
if (sobj == NULL)
|
|
{ // function/segment object not found
|
|
fprintf (stderr, GTXT ("Error: No function with given name `%s' found.\n"),
|
|
func_name);
|
|
return;
|
|
}
|
|
}
|
|
if (cmd_type == CPREPEND)
|
|
{
|
|
if (sobj == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
|
|
return;
|
|
}
|
|
cstack->insert (0, sobj);
|
|
}
|
|
else if (cmd_type == CAPPEND)
|
|
{
|
|
if (sobj == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
|
|
return;
|
|
}
|
|
cstack->append (sobj);
|
|
}
|
|
else if (cmd_type == CSINGLE)
|
|
{
|
|
if (sobj != NULL)
|
|
{
|
|
cstack->reset ();
|
|
cstack->append (sobj);
|
|
}
|
|
else if (cstack->size () == 0)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: No function name has been specified.\n"));
|
|
return;
|
|
}
|
|
}
|
|
else if (cmd_type == CRMFIRST)
|
|
{
|
|
if (cstack->size () <= 1)
|
|
{
|
|
fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n"));
|
|
return;
|
|
}
|
|
cstack->remove (0);
|
|
}
|
|
else if (cmd_type == CRMLAST)
|
|
{
|
|
if (cstack->size () <= 1)
|
|
{
|
|
fprintf (stderr, GTXT ("Warning: there is only one function in the stack segment; cannot remove it.\n"));
|
|
return;
|
|
}
|
|
cstack->remove (cstack->size () - 1);
|
|
}
|
|
|
|
er_print_gprof *cd = new er_print_gprof (dbev, cstack);
|
|
print_cmd (cd);
|
|
delete cd;
|
|
}
|
|
|
|
/*
|
|
* Method print_ctree() prints Functions Call Tree.
|
|
*/
|
|
void
|
|
er_print::print_ctree (CmdType cmd_type)
|
|
{
|
|
if (cmd_type != CALLTREE)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Invalid command type: %d\n"), cmd_type);
|
|
return;
|
|
}
|
|
|
|
Histable *sobj = dbeSession->get_Total_Function ();
|
|
Vector<Histable*> *ctree_cstack = new Vector<Histable*>();
|
|
ctree_cstack->reset ();
|
|
er_print_ctree *cd = new er_print_ctree (dbev, ctree_cstack, sobj, limit);
|
|
print_cmd (cd);
|
|
delete ctree_cstack;
|
|
delete cd;
|
|
}
|
|
|
|
void
|
|
er_print::memobj (char *name, int cparam)
|
|
{
|
|
int type;
|
|
if (name != NULL)
|
|
{
|
|
// find the memory object index for the name
|
|
MemObjType_t *mot = MemorySpace::findMemSpaceByName (name);
|
|
if (mot == NULL)
|
|
{
|
|
// unknown type, report the error
|
|
fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name);
|
|
return;
|
|
}
|
|
type = mot->type;
|
|
}
|
|
else
|
|
{
|
|
MemObjType_t *mot = MemorySpace::findMemSpaceByIndex (cparam);
|
|
if (mot == NULL)
|
|
{
|
|
// unknown type, report the error
|
|
fprintf (stderr, GTXT ("Error: Unknown Memory Object type: %s\n"), name);
|
|
return;
|
|
}
|
|
type = cparam;
|
|
}
|
|
dbePrintData (0, DSP_MEMOBJ, type, NULL, NULL, out_file);
|
|
}
|
|
|
|
void
|
|
er_print::mo_define (char *moname, char *mo_index_exp, char *machmodel, char *short_desc, char *long_desc)
|
|
{
|
|
char *ret = MemorySpace::mobj_define (moname, mo_index_exp, machmodel, short_desc, long_desc);
|
|
if (ret != NULL)
|
|
fprintf (stderr, GTXT ("mobj_define for %s failed: %s\n"), moname, ret);
|
|
}
|
|
|
|
void
|
|
er_print::mo_list (bool showtab, FILE *outf)
|
|
{
|
|
Vector<bool> *mtab = NULL;
|
|
Vector<void*>*res = MemorySpace::getMemObjects ();
|
|
if (showtab)
|
|
mtab = dbev->get_MemTabState ();
|
|
if (res == NULL)
|
|
// Since we checked already, this is an internal error
|
|
abort ();
|
|
|
|
// unpack the return
|
|
// Vector<char*> *index = (Vector<int> *)res->fetch(0); // not used
|
|
Vector<char*> *mo_names = (Vector<char*> *)res->fetch (1);
|
|
// Vector<char*> *mnemonic = (Vector<char> *)res->fetch(2); // not used
|
|
Vector<char*> *mo_expr = (Vector<char*> *)res->fetch (3);
|
|
Vector<char*> *mo_mach_m = (Vector<char*> *)res->fetch (4);
|
|
// Vector<char*> *tmpOrder = (Vector<int> *)res->fetch(5); // not used
|
|
|
|
int size = mo_names->size ();
|
|
if (size == 0)
|
|
{
|
|
if (!getenv ("_BUILDING_MANPAGE"))
|
|
fprintf (outf, GTXT (" No Memory Object Types Defined\n"));
|
|
}
|
|
else
|
|
{
|
|
if (!getenv ("_BUILDING_MANPAGE"))
|
|
fprintf (outf, GTXT (" Memory Object Types Available:\n"));
|
|
else
|
|
fprintf (outf, GTXT ("*Memory Object Types*\n"));
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
if (mtab)
|
|
fprintf (outf, NTXT (" %c %s\n"), mtab->fetch (i) ? 'T' : 'F',
|
|
mo_names->fetch (i));
|
|
else
|
|
{
|
|
if (mo_mach_m->fetch (i) != NULL)
|
|
fprintf (outf, NTXT (" %s\t\t\"%s\"\t\t(machinemodel: %s)\n"),
|
|
mo_names->fetch (i), mo_expr->fetch (i), mo_mach_m->fetch (i));
|
|
else
|
|
fprintf (outf, NTXT (" %s\t\t\"%s\"\n"),
|
|
mo_names->fetch (i), mo_expr->fetch (i));
|
|
}
|
|
}
|
|
}
|
|
delete mo_names;
|
|
delete mo_expr;
|
|
delete mo_mach_m;
|
|
delete res;
|
|
}
|
|
|
|
void
|
|
er_print::indxobj (char *name, int cparam)
|
|
{
|
|
int type;
|
|
if (name != NULL)
|
|
{
|
|
// find the index object index for the name
|
|
type = dbeSession->findIndexSpaceByName (name);
|
|
if (type < 0)
|
|
{
|
|
// unknown type, report the error
|
|
fprintf (stderr, GTXT ("Error: Unknown Index Object type: %s\n"), name);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char *indxname = dbeSession->getIndexSpaceName (cparam);
|
|
if (indxname == NULL)
|
|
{
|
|
// unknown type, report the error
|
|
fprintf (stderr, GTXT ("Error: Unknown Index Object type: %d\n"), cparam);
|
|
return;
|
|
}
|
|
type = cparam;
|
|
}
|
|
dbePrintData (0, DSP_INDXOBJ, type, NULL, NULL, out_file);
|
|
}
|
|
|
|
void
|
|
er_print::indxo_define (char *ioname, char *io_index_exp, char *sdesc, char *ldesc)
|
|
{
|
|
char *ret = dbeDefineIndxObj (ioname, io_index_exp, sdesc, ldesc);
|
|
if (ret != NULL)
|
|
fprintf (stderr, GTXT ("indxobj_define for %s failed: %s\n"), ioname, ret);
|
|
}
|
|
|
|
void
|
|
er_print::indxo_list (bool showtab, FILE *outf)
|
|
{
|
|
Vector<bool> *indxtab = NULL;
|
|
char *name;
|
|
char *i18n_name;
|
|
if (!getenv ("_BUILDING_MANPAGE"))
|
|
fprintf (outf, GTXT (" Index Object Types Available:\n"));
|
|
else
|
|
fprintf (outf, GTXT ("*Index Object Types*\n"));
|
|
Vector<void*>*res = dbeGetIndxObjDescriptions (0);
|
|
if (showtab)
|
|
indxtab = dbev->get_IndxTabState ();
|
|
if (res == NULL) // If none is defined
|
|
return;
|
|
Vector<char*> *indxo_names = (Vector<char*> *)res->fetch (1);
|
|
Vector<char*> *indxo_i18nnames = (Vector<char*> *)res->fetch (3);
|
|
Vector<char*> *indxo_exprlist = (Vector<char*> *)res->fetch (5);
|
|
int size = indxo_names->size ();
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
name = indxo_names->fetch (i);
|
|
i18n_name = indxo_i18nnames->fetch (i);
|
|
if (indxtab)
|
|
{
|
|
if ((i18n_name != NULL) && (strcmp (i18n_name, name) != 0))
|
|
fprintf (outf, NTXT (" %c %s (%s)\n"), indxtab->fetch (i) ? 'T' : 'F',
|
|
i18n_name, name);
|
|
else
|
|
fprintf (outf, NTXT (" %c %s\n"), indxtab->fetch (i) ? 'T' : 'F', name);
|
|
}
|
|
else
|
|
{
|
|
if (i18n_name != NULL && strcmp (i18n_name, indxo_names->fetch (i)) != 0)
|
|
fprintf (outf, NTXT (" %s (%s)"), i18n_name, name);
|
|
else
|
|
fprintf (outf, NTXT (" %s"), name);
|
|
}
|
|
char *exprs = indxo_exprlist->fetch (i);
|
|
if (exprs != NULL)
|
|
fprintf (outf, NTXT (" \t%s\n"), exprs);
|
|
else
|
|
fprintf (outf, NTXT ("\n"));
|
|
}
|
|
delete indxo_names;
|
|
if (showtab)
|
|
delete res;
|
|
}
|
|
|
|
void
|
|
er_print::ifreq ()
|
|
{
|
|
dbev->ifreq (out_file);
|
|
}
|
|
|
|
void
|
|
er_print::dump_nodes ()
|
|
{
|
|
dbev->dump_nodes (out_file);
|
|
}
|
|
|
|
void
|
|
er_print::dump_stacks ()
|
|
{
|
|
dbeSession->dump_stacks (out_file);
|
|
}
|
|
|
|
void
|
|
er_print::dump_unk_pcs ()
|
|
{
|
|
// Dump the nodes associated with the <Unknown> function
|
|
dbev->get_path_tree ()->dumpNodes (out_file, dbeSession->get_Unknown_Function ());
|
|
|
|
// Dump the nodes associated with the <no Java callstack recorded> function
|
|
Vector<Function *> *matches = dbeSession->match_func_names ("<no Java callstack recorded>", dbev->get_name_format ());
|
|
if (matches == NULL || matches->size () == 0)
|
|
fprintf (out_file, GTXT ("No %s functions found\n"), "<no Java callstack recorded>");
|
|
else
|
|
{
|
|
Function *fitem;
|
|
int index;
|
|
Vec_loop (Function*, matches, index, fitem)
|
|
{
|
|
dbev->get_path_tree ()->dumpNodes (out_file, fitem);
|
|
}
|
|
delete matches;
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::dump_funcs (char *arg1)
|
|
{
|
|
if (arg1 == NULL || strlen (arg1) == 0)
|
|
dbeSession->dump_segments (out_file);
|
|
else
|
|
{
|
|
Vector<Function *> *matches = dbeSession->match_func_names (arg1, dbev->get_name_format ());
|
|
if (matches == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1);
|
|
return;
|
|
}
|
|
fprintf (out_file, GTXT ("%d Function's match `%s'\n"), (int) matches->size (), arg1);
|
|
Function *fitem;
|
|
int index;
|
|
Vec_loop (Function*, matches, index, fitem)
|
|
{
|
|
fprintf (out_file, NTXT (" %5lld -- %s (%s) [%s]\n"),
|
|
(ll_t) fitem->id, fitem->get_name (),
|
|
(fitem->module ? fitem->module->file_name : NTXT ("<unknown>")),
|
|
((fitem->module && fitem->module->loadobject) ?
|
|
get_basename (fitem->module->loadobject->get_name ()) : NTXT ("<unknown>")));
|
|
}
|
|
delete matches;
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::dump_dataobjects (char *arg1)
|
|
{
|
|
// Force computation of data objects, to update master table; discard it
|
|
MetricList *mlist1 = dbev->get_metric_list (MET_DATA);
|
|
Hist_data *data = dbev->get_hist_data (mlist1, Histable::DOBJECT, 0, Hist_data::ALL);
|
|
delete data;
|
|
|
|
if (arg1 == NULL || strlen (arg1) == 0)
|
|
dbeSession->dump_dataobjects (out_file);
|
|
else
|
|
{
|
|
Vector<DataObject *> *matches = dbeSession->match_dobj_names (arg1);
|
|
if (matches == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Invalid argument `%s' -- not a regular expression\n"), arg1);
|
|
return;
|
|
}
|
|
fprintf (out_file, GTXT ("%d DataObject's match `%s'\n"), (int) matches->size (), arg1);
|
|
DataObject *ditem;
|
|
int index;
|
|
Vec_loop (DataObject*, matches, index, ditem)
|
|
{
|
|
fprintf (out_file, NTXT (" %5lld -- %s\n"), (ll_t) ditem->id, ditem->get_name ());
|
|
}
|
|
delete matches;
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::dump_map ()
|
|
{
|
|
dbeSession->dump_map (out_file);
|
|
}
|
|
|
|
void
|
|
er_print::dump_entities ()
|
|
{
|
|
int ent_prop_ids[] = {PROP_THRID, PROP_LWPID, PROP_CPUID, PROP_EXPID, -1};
|
|
|
|
// loop over experiments
|
|
for (int exp_id = 0; exp_id < dbeSession->nexps (); exp_id++)
|
|
{
|
|
Experiment *exp = dbeSession->get_exp (exp_id);
|
|
fprintf (out_file, GTXT ("Experiment %d (%s)\n"),
|
|
exp_id, exp->get_expt_name ());
|
|
|
|
for (int kk = 0; ent_prop_ids[kk] != -1; kk++)
|
|
{
|
|
int ent_prop_id = ent_prop_ids[kk];
|
|
Vector<void*> *elist = dbeGetEntities (0, exp_id, ent_prop_id);
|
|
if (!elist)
|
|
continue;
|
|
Vector<int> *entity_vals = (Vector<int> *) elist->fetch (0);
|
|
Vector<char*> *jthr_names = (Vector<char*> *)elist->fetch (1);
|
|
Vector<char*> *jthr_g_names = (Vector<char*> *)elist->fetch (2);
|
|
Vector<char*> *jthr_p_names = (Vector<char*> *)elist->fetch (3);
|
|
Vector<char*> *entity_name = (Vector<char*> *)elist->fetch (4);
|
|
int nent = entity_vals->size ();
|
|
char *entName = entity_name->fetch (0);
|
|
if (!entName)
|
|
entName = NTXT ("<unknown>");
|
|
fprintf (out_file, GTXT (" %s\n"), entName);
|
|
for (int i = 0; i < nent; i++)
|
|
fprintf (out_file, GTXT (" %s=%d: %s, %s, %s\n"),
|
|
entName, entity_vals->fetch (i),
|
|
jthr_names->fetch (i) != NULL ? jthr_names->fetch (i) : NTXT ("N/A"),
|
|
jthr_g_names->fetch (i) != NULL ? jthr_g_names->fetch (i) : NTXT ("N/A"),
|
|
jthr_p_names->fetch (i) != NULL ? jthr_names->fetch (i) : NTXT ("N/A"));
|
|
destroy (elist);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
er_print::dump_stats ()
|
|
{
|
|
Emsg *m = dbev->get_path_tree ()->fetch_stats ();
|
|
while (m != NULL)
|
|
{
|
|
fprintf (out_file, NTXT ("%s\n"), m->get_msg ());
|
|
m = m->next;
|
|
}
|
|
dbev->get_path_tree ()->delete_stats ();
|
|
}
|
|
|
|
void
|
|
er_print::dump_proc_warnings ()
|
|
{
|
|
PathTree *p = dbev->get_path_tree ();
|
|
if (p == NULL)
|
|
return;
|
|
Emsg *m = p->fetch_warnings ();
|
|
while (m != NULL)
|
|
{
|
|
fprintf (out_file, NTXT ("%s\n"), m->get_msg ());
|
|
m = m->next;
|
|
}
|
|
dbev->get_path_tree ()->delete_warnings ();
|
|
}
|
|
|
|
void
|
|
er_print::print_cmd (er_print_common_display *cd)
|
|
{
|
|
cd->set_out_file (out_file);
|
|
cd->data_dump ();
|
|
}
|
|
|
|
FILE *
|
|
er_print::set_outfile (char *cmd, FILE *&set_file, bool append)
|
|
{
|
|
FILE *new_file;
|
|
char *home;
|
|
if (!strcasecmp (cmd, NTXT ("-")))
|
|
{
|
|
new_file = stdout;
|
|
out_fname = NTXT ("<stdout>");
|
|
}
|
|
else if (!strcasecmp (cmd, NTXT ("--")))
|
|
{
|
|
new_file = stderr;
|
|
out_fname = NTXT ("<stderr>");
|
|
}
|
|
else
|
|
{
|
|
char *fname;
|
|
char *path = NULL;
|
|
// Handle ~ in file names
|
|
home = getenv (NTXT ("HOME"));
|
|
if ((fname = strstr (cmd, NTXT ("~/"))) != NULL && home != NULL)
|
|
path = dbe_sprintf (NTXT ("%s/%s"), home, fname + 2);
|
|
else if ((fname = strstr (cmd, NTXT ("~"))) != NULL && home != NULL)
|
|
path = dbe_sprintf (NTXT ("/home/%s"), fname + 1);
|
|
else
|
|
path = strdup (cmd);
|
|
new_file = fopen (path, append ? NTXT ("a") : NTXT ("w"));
|
|
if (new_file == NULL)
|
|
{
|
|
fprintf (stderr, GTXT ("Error: Unable to open file: %s\n"), cmd);
|
|
free (path);
|
|
return NULL;
|
|
}
|
|
out_fname = path;
|
|
}
|
|
if (set_file && set_file != stdout)
|
|
fclose (set_file);
|
|
set_file = new_file;
|
|
return set_file;
|
|
}
|