mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
This commit tidies up and rationalises what could be called the "messaging" system -- that part of V to do with presenting output to the user. In particular it brings significant improvements to XML output. Changes are: * XML and normal text output now have separate file descriptors, which solves longstanding problems for XML consumers caused by the XML output getting polluted by unexpected non-XML output. * This also means that we no longer have to hardwire all manner of output settings (verbosity, etc) when XML is requested. * The XML output format has been revised, cleaned up, and made more suitable for use by error detecting tools in general (various Memcheck-specific features have been removed). XML output is enabled for Ptrcheck and Helgrind, and Memcheck is updated to the new format. * One side effect is that the behaviour of VG_(message) has been made to be consistent with printf: it no longer automatically adds a newline at the end of the output. This means multiple calls to it can be used to build up a single line message; or a single call can write a multi-line message. The ==pid== preamble is automatically inserted at each newline. * VG_(message)(Vg_UserMsg, ..args..) now has the abbreviated form VG_(UMSG)(..args..); ditto VG_(DMSG) for Vg_DebugMsg and VG_(EMSG) for Vg_DebugExtraMsg. A couple of other useful printf derivatives have been added to pub_tool_libcprint.h, most particularly VG_(vcbprintf). * There's a small change in the core-tool interface to do with error handling: VG_(needs_tool_errors) has a new method void (*before_pp_Error)(Error* err) which, if non-NULL, is called just before void (*pp_Error)(Error* err). This is to give tools the chance to look at errors before any part of them is printed, so they can print any XML preamble they like. * coregrind/m_errormgr.c has been overhauled and cleaned up, and is a bit simpler and more commented. In particular pp_Error and VG_(maybe_record_error) are significantly changed. The diff is huge, but mostly very boring. Most of the changes are of the form - VG_(message)(Vg_UserMsg, "this is a message %d", n); + VG_(message)(Vg_UserMsg, "this is a message %d\n", n); Unfortunately as a result of this, it touches a large number of source files. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10465
251 lines
8.1 KiB
C
251 lines
8.1 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- Command line handling. m_commandline.c ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2000-2009 Julian Seward
|
|
jseward@acm.org
|
|
|
|
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 2 of the
|
|
License, 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, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307, USA.
|
|
|
|
The GNU General Public License is contained in the file COPYING.
|
|
*/
|
|
|
|
#include "pub_core_basics.h"
|
|
#include "pub_core_vki.h"
|
|
#include "pub_core_libcassert.h"
|
|
#include "pub_core_libcbase.h"
|
|
#include "pub_core_libcfile.h"
|
|
#include "pub_core_libcprint.h"
|
|
#include "pub_core_libcproc.h"
|
|
#include "pub_core_mallocfree.h"
|
|
#include "pub_core_xarray.h"
|
|
#include "pub_core_clientstate.h"
|
|
#include "pub_core_commandline.h" /* self */
|
|
|
|
|
|
/* Add a string to an expandable array of strings. */
|
|
|
|
static void add_string ( XArray* /* of HChar* */xa, HChar* str )
|
|
{
|
|
(void) VG_(addToXA)( xa, (void*)(&str) );
|
|
}
|
|
|
|
|
|
/* Read the contents of .valgrindrc in 'dir' into malloc'd memory. */
|
|
// Note that we deliberately don't free the malloc'd memory. See
|
|
// comment at call site.
|
|
|
|
static HChar* read_dot_valgrindrc ( HChar* dir )
|
|
{
|
|
Int n;
|
|
SysRes fd;
|
|
struct vg_stat stat_buf;
|
|
HChar* f_clo = NULL;
|
|
HChar filename[VKI_PATH_MAX];
|
|
|
|
VG_(snprintf)(filename, VKI_PATH_MAX, "%s/.valgrindrc",
|
|
( NULL == dir ? "" : dir ) );
|
|
fd = VG_(open)(filename, 0, VKI_S_IRUSR);
|
|
if ( !sr_isError(fd) ) {
|
|
Int res = VG_(fstat)( sr_Res(fd), &stat_buf );
|
|
// Ignore if not owned by current user or world writeable (CVE-2008-4865)
|
|
if (!res && stat_buf.uid == VG_(geteuid)()
|
|
&& (!(stat_buf.mode & VKI_S_IWOTH))) {
|
|
if ( stat_buf.size > 0 ) {
|
|
f_clo = VG_(malloc)("commandline.rdv.1", stat_buf.size+1);
|
|
vg_assert(f_clo);
|
|
n = VG_(read)(sr_Res(fd), f_clo, stat_buf.size);
|
|
if (n == -1) n = 0;
|
|
vg_assert(n >= 0 && n <= stat_buf.size+1);
|
|
f_clo[n] = '\0';
|
|
}
|
|
}
|
|
else
|
|
VG_(message)(Vg_UserMsg,
|
|
"%s was not read as it is world writeable or not owned by the "
|
|
"current user\n", filename);
|
|
|
|
VG_(close)(sr_Res(fd));
|
|
}
|
|
return f_clo;
|
|
}
|
|
|
|
|
|
// Add args from a string into VG_(args_for_valgrind), splitting the
|
|
// string at whitespace and adding each component as a separate arg.
|
|
|
|
static void add_args_from_string ( HChar* s )
|
|
{
|
|
HChar* tmp;
|
|
HChar* cp = s;
|
|
vg_assert(cp);
|
|
while (True) {
|
|
// We have alternating sequences: blanks, non-blanks, blanks...
|
|
// copy the non-blanks sequences, and add terminating '\0'
|
|
while (VG_(isspace)(*cp)) cp++;
|
|
if (*cp == 0) break;
|
|
tmp = cp;
|
|
while ( !VG_(isspace)(*cp) && *cp != 0 ) cp++;
|
|
if ( *cp != 0 ) *cp++ = '\0'; // terminate if not the last
|
|
add_string( VG_(args_for_valgrind), tmp );
|
|
}
|
|
}
|
|
|
|
|
|
/* Split up the args presented by the launcher to m_main.main(), and
|
|
park them in VG_(args_for_client) and VG_(args_for_valgrind).
|
|
|
|
The resulting arg list is the concatenation of the following:
|
|
- contents of ~/.valgrindrc
|
|
- contents of $VALGRIND_OPTS
|
|
- contents of ./.valgrindrc
|
|
- args from the command line
|
|
in the stated order.
|
|
|
|
VG_(args_for_valgrind_noexecpass) is set to be the number of items
|
|
in the first three categories. They are not passed to child invokations
|
|
at exec, whereas the last group is.
|
|
|
|
If the last group contains --command-line-only=yes, then the
|
|
first three groups are left empty.
|
|
|
|
Scheme: first examine the last group (the supplied argc/argv).
|
|
It should look like this.
|
|
|
|
args-for-v exe_name args-for-c
|
|
|
|
args-for-v are taken until either they don't start with '-' or
|
|
a "--" is seen.
|
|
|
|
The exe name and args-for-c are recorded without further ado.
|
|
Note that args-for-c[0] is the first real arg for the client, not
|
|
its executable name.
|
|
|
|
args-for-v are then copied into tmp_xarray.
|
|
|
|
if args-for-v does not include --command-line-only=yes:
|
|
contents of ~/.valgrindrc, $VALGRIND_OPTS and ./.valgrindrc
|
|
are copied into VG_(args_for_valgrind).
|
|
else
|
|
VG_(args_for_valgrind) is made empty.
|
|
|
|
Finally, tmp_xarray is copied onto the end of VG_(args_for_valgrind).
|
|
*/
|
|
|
|
void VG_(split_up_argv)( Int argc, HChar** argv )
|
|
{
|
|
Int i;
|
|
Bool augment = True;
|
|
static Bool already_called = False;
|
|
|
|
XArray* /* of HChar* */ tmp_xarray;
|
|
|
|
/* This function should be called once, at startup, and then never
|
|
again. */
|
|
vg_assert(!already_called);
|
|
already_called = True;
|
|
|
|
tmp_xarray = VG_(newXA)( VG_(malloc), "commandline.sua.1",
|
|
VG_(free), sizeof(HChar*) );
|
|
vg_assert(tmp_xarray);
|
|
|
|
vg_assert( ! VG_(args_for_valgrind) );
|
|
VG_(args_for_valgrind)
|
|
= VG_(newXA)( VG_(malloc), "commandline.sua.2",
|
|
VG_(free), sizeof(HChar*) );
|
|
vg_assert( VG_(args_for_valgrind) );
|
|
|
|
vg_assert( ! VG_(args_for_client) );
|
|
VG_(args_for_client)
|
|
= VG_(newXA)( VG_(malloc), "commandline.sua.3",
|
|
VG_(free), sizeof(HChar*) );
|
|
vg_assert( VG_(args_for_client) );
|
|
|
|
/* Collect up the args-for-V. */
|
|
i = 1; /* skip the exe (stage2) name. */
|
|
for (; i < argc; i++) {
|
|
vg_assert(argv[i]);
|
|
if (0 == VG_(strcmp)(argv[i], "--")) {
|
|
i++;
|
|
break;
|
|
}
|
|
if (0 == VG_(strcmp)(argv[i], "--command-line-only=yes"))
|
|
augment = False;
|
|
if (argv[i][0] != '-')
|
|
break;
|
|
add_string( tmp_xarray, argv[i] );
|
|
}
|
|
|
|
/* Should now be looking at the exe name. */
|
|
if (i < argc) {
|
|
vg_assert(argv[i]);
|
|
VG_(args_the_exename) = argv[i];
|
|
i++;
|
|
}
|
|
|
|
/* The rest are args for the client. */
|
|
for (; i < argc; i++) {
|
|
vg_assert(argv[i]);
|
|
add_string( VG_(args_for_client), argv[i] );
|
|
}
|
|
|
|
/* Get extra args from ~/.valgrindrc, $VALGRIND_OPTS and
|
|
./.valgrindrc into VG_(args_for_valgrind). */
|
|
if (augment) {
|
|
// read_dot_valgrindrc() allocates the return value with
|
|
// VG_(malloc)(). We do not free f1_clo and f2_clo as they get
|
|
// put into VG_(args_for_valgrind) and so must persist.
|
|
HChar* home = VG_(getenv)("HOME");
|
|
HChar* f1_clo = home ? read_dot_valgrindrc( home ) : NULL;
|
|
HChar* env_clo = VG_(strdup)( "commandline.sua.4",
|
|
VG_(getenv)(VALGRIND_OPTS) );
|
|
HChar* f2_clo = NULL;
|
|
|
|
// Don't read ./.valgrindrc if "." is the same as "$HOME", else its
|
|
// contents will be applied twice. (bug #142488)
|
|
if (home) {
|
|
HChar cwd[VKI_PATH_MAX+1];
|
|
Bool cwd_ok = VG_(get_startup_wd)(cwd, VKI_PATH_MAX);
|
|
f2_clo = ( (cwd_ok && VG_STREQ(home, cwd))
|
|
? NULL : read_dot_valgrindrc(".") );
|
|
}
|
|
|
|
if (f1_clo) add_args_from_string( f1_clo );
|
|
if (env_clo) add_args_from_string( env_clo );
|
|
if (f2_clo) add_args_from_string( f2_clo );
|
|
}
|
|
|
|
/* .. and record how many extras we got. */
|
|
VG_(args_for_valgrind_noexecpass)
|
|
= VG_(sizeXA)( VG_(args_for_valgrind) );
|
|
|
|
/* Finally, copy tmp_xarray onto the end. */
|
|
for (i = 0; i < VG_(sizeXA)( tmp_xarray ); i++)
|
|
add_string( VG_(args_for_valgrind),
|
|
* (HChar**)VG_(indexXA)( tmp_xarray, i ) );
|
|
|
|
VG_(deleteXA)( tmp_xarray );
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end ---*/
|
|
/*--------------------------------------------------------------------*/
|