1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Callgrind, a Valgrind tool for call graph
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   profiling programs.
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2002-2011, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This tool is derived from and contains lot of code from Cachegrind
8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2002-2011 Nicholas Nethercote (njn@valgrind.org)
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Functions related to interactive commands via "callgrind.cmd"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_threadstate.h" // VG_N_THREADS
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Version for the syntax in command/result files for interactive control
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define COMMAND_VERSION "1.0"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char outbuf[FILENAME_LEN + FN_NAME_LEN + OBJ_NAME_LEN];
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* command_file = 0;
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* command_file2 = 0;
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* current_command_file = 0;
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* result_file = 0;
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* result_file2 = 0;
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* current_result_file = 0;
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* info_file = 0;
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* out_file = 0;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int thisPID = 0;
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Setup for interactive control of a callgrind run
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setup_control(void)
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int fd, size;
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  SysRes res;
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Char* dir;
61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  const HChar *tmpdir;
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(thisPID != 0);
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  fd = -1;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  dir = CLG_(get_out_directory)();
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out_file = CLG_(get_out_file)();
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* name of command file */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_COMMANDNAME) +10;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  command_file = (char*) CLG_MALLOC("cl.command.sc.1", size);
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(command_file != 0);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(command_file, "%s/%s.%d",
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       dir, DEFAULT_COMMANDNAME, thisPID);
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* This is for compatibility with the "Force Now" Button of current
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * KCachegrind releases, as it doesn't use ".pid" to distinguish
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * different callgrind instances from same base directory.
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  command_file2 = (char*) CLG_MALLOC("cl.command.sc.2", size);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(command_file2 != 0);
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(command_file2, "%s/%s",
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       dir, DEFAULT_COMMANDNAME);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  size = VG_(strlen)(dir) + VG_(strlen)(DEFAULT_RESULTNAME) +10;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  result_file = (char*) CLG_MALLOC("cl.command.sc.3", size);
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(result_file != 0);
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(result_file, "%s/%s.%d",
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       dir, DEFAULT_RESULTNAME, thisPID);
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* If we get a command from a command file without .pid, use
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * a result file without .pid suffix
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  result_file2 = (char*) CLG_MALLOC("cl.command.sc.4", size);
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(result_file2 != 0);
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(result_file2, "%s/%s",
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dir, DEFAULT_RESULTNAME);
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  tmpdir = VG_(tmpdir)();
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  info_file = (char*) CLG_MALLOC("cl.command.sc.5",
101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov				 VG_(strlen)(tmpdir) +
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 VG_(strlen)(DEFAULT_INFONAME) + 10);
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_ASSERT(info_file != 0);
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_(sprintf)(info_file, "%s/%s.%d", tmpdir, DEFAULT_INFONAME, thisPID);
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "Setup for interactive control (PID: %d):\n", thisPID);
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "  output file:    '%s'\n", out_file);
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "  command file:   '%s'\n", command_file);
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "  result file:    '%s'\n", result_file);
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(1, "  info file:      '%s'\n", info_file);
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* create info file to indicate that we are running */
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  res = VG_(open)(info_file, VKI_O_WRONLY|VKI_O_TRUNC, 0);
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (sr_isError(res)) {
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    res = VG_(open)(info_file, VKI_O_CREAT|VKI_O_WRONLY,
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   VKI_S_IRUSR|VKI_S_IWUSR);
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sr_isError(res)) {
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   "warning: can't write info file '%s'\n", info_file);
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info_file = 0;
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd = -1;
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!sr_isError(res))
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd = (Int) sr_Res(res);
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (fd>=0) {
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Char buf[512];
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int i;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd,
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       "# This file is generated by Callgrind-" VERSION ".\n"
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       "# It is used to enable controlling the supervision of\n"
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       "#  '", VG_(args_the_exename), "'\n"
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       "# by external tools.\n\n");
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd, "base: ", dir, "\n");
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd, "dumps: ", out_file, "\n");
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd, "control: ", command_file, "\n");
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd, "result: ", result_file, "\n");
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!arg) continue;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	WRITE_STR2(fd, " ", arg);
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, "\n", 1);
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(close)(fd);
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(init_command)()
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  thisPID = VG_(getpid)();
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  setup_control();
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(finish_command)()
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* unlink info file */
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (info_file) VG_(unlink)(info_file);
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int createRes(Int fd)
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SysRes res;
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fd > -2) return fd;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fd == -2: No error, but we need to create the file */
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(current_result_file != 0);
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    res = VG_(open)(current_result_file,
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   VKI_S_IRUSR|VKI_S_IWUSR);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* VG_(open) can return any negative number on error. Remap errors to -1,
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * to not confuse it with our special value -2
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sr_isError(res)) fd = -1;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else fd = (Int) sr_Res(res);
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return fd;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run Info: Persistant information of the callgrind run */
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int dump_info(Int fd)
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Char* buf = outbuf;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( (fd = createRes(fd)) <0) return fd;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* creator */
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "creator: callgrind-" VERSION "\n");
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* version */
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n");
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "pid:" line */
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "pid: %d\n", VG_(getpid)());
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "base:" line */
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR3(fd, "base: ", out_file, "\n");
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "cmd:" line */
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WRITE_STR2(fd, "cmd: ", VG_(args_the_exename));
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i );
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!arg) continue;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	WRITE_STR2(fd, " ", arg);
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, "\n", 1);
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return fd;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Helper for dump_state */
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt dump_fd;
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid static dump_state_of_thread(thread_info* ti)
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Char* buf = outbuf;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t = CLG_(current_tid);
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int p, i;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static FullCost sum = 0, tmp = 0;
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BBCC *from, *to;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    call_entry* ce;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "events-%d: ", t);
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(init_cost_lz)( CLG_(sets).full, &sum );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(add_diff_cost)( CLG_(sets).full, sum,
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			ti->lastdump_cost,
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			ti->states.entry[0]->cost);
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum);
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += VG_(sprintf)(buf+p, "\n");
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(dump_fd, (void*)buf, p);
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "frames-%d: %d\n", t,
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     CLG_(current_call_stack).sp);
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(dump_fd, (void*)buf, p);
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ce = 0;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i = 0; i < CLG_(current_call_stack).sp; i++) {
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ce = CLG_(get_call_entry)(i);
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if this frame is skipped, we don't have counters */
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ce->jcc) continue;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      from = ce->jcc->from;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       from->cxt->fn[0]->name);
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(dump_fd, (void*)buf, p);
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = VG_(sprintf)(buf, "calls-%d-%d: ",t, i);
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p+= VG_(sprintf)(buf+p, "%llu\n", ce->jcc->call_counter);
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(dump_fd, (void*)buf, p);
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME: EventSets! */
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(add_diff_cost)( CLG_(sets).full, sum,
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			  ce->enter_cost, CLG_(current_state).cost );
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p += CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p += VG_(sprintf)(buf+p, "\n");
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(dump_fd, (void*)buf, p);
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ce && ce->jcc) {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to = ce->jcc->to;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = VG_(sprintf)(buf, "function-%d-%d: %s\n",t, i,
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       to->cxt->fn[0]->name );
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(dump_fd, (void*)buf, p);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dump info on current callgrind state */
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int dump_state(Int fd)
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Char* buf = outbuf;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    thread_info** th;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int t, p;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int orig_tid = CLG_(current_tid);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( (fd = createRes(fd)) <0) return fd;
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "instrumentation: %s\n",
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 CLG_(instrument_state) ? "on":"off");
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(instrument_state)) return fd;
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "executed-bbs: %llu\n", CLG_(stat).bb_executions);
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "executed-calls: %llu\n", CLG_(stat).call_counter);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "distinct-calls: %d\n", CLG_(stat).distinct_jccs);
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "distinct-functions: %d\n", CLG_(stat).distinct_fns);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "events:" line. Given here because it will be dynamic in the future */
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "events: ");
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, "\n", 1);
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* "part:" line (number of last part. Is 0 at start */
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "\npart: %d\n", CLG_(get_dump_counter)());
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* threads */
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    th = CLG_(get_threads)();
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p = VG_(sprintf)(buf, "threads:");
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(t=1;t<VG_N_THREADS;t++) {
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (!th[t]) continue;
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	p += VG_(sprintf)(buf+p, " %d", t);
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p += VG_(sprintf)(buf+p, "\n");
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, p);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(buf, "current-tid: %d\n", orig_tid);
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* current event counters */
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    dump_fd = fd;
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(forall_threads)(dump_state_of_thread);
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return fd;
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(check_command)()
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* check for dumps needed */
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static Char buf[512];
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static Char cmdBuffer[512];
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Char *cmdPos = 0, *cmdNextLine = 0;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int fd, bytesRead = 0, do_kill = 0;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    SysRes res;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int currentPID;
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    static Int check_counter = 0;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Check for PID change, i.e. whether we run as child after a fork.
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * If yes, we setup interactive control for the new process
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    currentPID = VG_(getpid)();
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (thisPID != currentPID) {
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	thisPID = currentPID;
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	setup_control();
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Toggle between 2 command files, with/without ".pid" postfix
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * (needed for compatibility with KCachegrind, which wants to trigger
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *  a dump by writing into a command file without the ".pid" postfix)
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    check_counter++;
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (check_counter % 2) {
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	current_command_file = command_file;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	current_result_file  = result_file;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	current_command_file = command_file2;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	current_result_file  = result_file2;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    res = VG_(open)(current_command_file, VKI_O_RDONLY,0);
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sr_isError(res)) {
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fd = (Int) sr_Res(res);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bytesRead = VG_(read)(fd,cmdBuffer,500);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmdBuffer[500] = 0; /* no command overrun please */
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(close)(fd);
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* don't delete command file on read error (e.g. EAGAIN) */
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (bytesRead>0) {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cmdPos = cmdBuffer;
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* force creation of result file if needed */
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fd = -2;
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while((bytesRead>0) && *cmdPos) {
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Calculate pointer for next line */
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmdNextLine = cmdPos+1;
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	while((bytesRead>0) && *cmdNextLine && (*cmdNextLine != '\n')) {
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdNextLine++;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  bytesRead--;
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((bytesRead>0) && (*cmdNextLine == '\n')) {
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  *cmdNextLine = 0;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdNextLine++;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  bytesRead--;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Command with integer option */
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((*cmdPos >= '0') && (*cmdPos <='9')) {
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  int value = *cmdPos-'0';
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdPos++;
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  while((*cmdPos >= '0') && (*cmdPos <='9')) {
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    value = 10*value + (*cmdPos-'0');
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cmdPos++;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  switch(*cmdPos) {
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_ENABLE_DEBUG
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* verbosity */
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  case 'V':
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  case 'v':
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(clo).verbose = value;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  default:
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdPos = cmdNextLine;
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  continue;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Command with boolean/switch option */
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((*cmdPos=='+') ||
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    (*cmdPos=='-')) {
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  int value = (cmdPos[0] == '+');
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdPos++;
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  while((*cmdPos == ' ') || (*cmdPos == '\t')) cmdPos++;
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  switch(*cmdPos) {
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  case 'I':
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  case 'i':
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(set_instrument_state)("Command", value);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  default:
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cmdPos = cmdNextLine;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  continue;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* regular command */
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	switch(*cmdPos) {
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'D':
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'd':
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  /* DUMP */
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  /* skip command */
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  while(*cmdPos && (*cmdPos != ' ')) cmdPos++;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (*cmdPos)
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "Dump Command:%s", cmdPos);
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  else
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "Dump Command");
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  CLG_(dump_profile)(buf, False);
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  break;
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'Z':
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'z':
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(zero_all_cost)(False);
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'K':
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'k':
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Kill: Delay to be able to remove command file before. */
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    do_kill = 1;
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'I':
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'i':
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fd = dump_info(fd);
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 's':
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'S':
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    fd = dump_state(fd);
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'O':
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case 'o':
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Options Info */
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if ( (fd = createRes(fd)) <0) break;
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "\ndesc: Option: --skip-plt=%s\n",
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 CLG_(clo).skip_plt ? "yes" : "no");
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "desc: Option: --collect-jumps=%s\n",
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 CLG_(clo).collect_jumps ? "yes" : "no");
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "desc: Option: --separate-recs=%d\n",
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 CLG_(clo).separate_recursions);
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(sprintf)(buf, "desc: Option: --separate-callers=%d\n",
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 CLG_(clo).separate_callers);
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default:
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  break;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmdPos = cmdNextLine;
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* If command executed, delete command file */
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (cmdPos) VG_(unlink)(current_command_file);
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (fd>=0) VG_(close)(fd);
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_kill) {
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   "Killed because of command from %s\n",
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   current_command_file);
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(fini)(0);
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(exit)(1);
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
536