ftmemsim-valgrind/coregrind/pub_core_libcprint.h
Philippe Waroquiers 3a803036f7 Allow the user to change a set of command line options during execution.
This patch changes the option parsing framework to allow a set of
core or tool (currently only memcheck) options to be changed dynamically.

Here is a summary of the new functionality (extracted from NEWS):
* It is now possible to dynamically change the value of many command
  line options while your program (or its children) are running under
  Valgrind.
  To have the list of dynamically changeable options, run
     valgrind --help-dyn-options
  You can change the options from the shell by using vgdb to launch
  the monitor command "v.clo <clo option>...".
  The same monitor command can be used from a gdb connected
  to the valgrind gdbserver.
  Your program can also change the dynamically changeable options using
  the client request VALGRIND_CLO_CHANGE(option).

Here is a brief description of the code changes.
* the command line options parsing macros are now checking a 'parsing' mode
  to decide if the given option must be handled or not.
  (more about the parsing mode below).

* the 'main' command option parsing code has been split in a function
  'process_option' that can be called now by:
     - early_process_cmd_line_options
        (looping over args, calling process_option in mode "Early")
     - main_process_cmd_line_options
        (looping over args, calling process_option in mode "Processing")
     - the new function VG_(process_dynamic_option) called from
       gdbserver or from VALGRIND_CLO_CHANGE (calling
        process_option in mode "Dynamic" or "Help")

* So, now, during startup, process_option is called twice for each arg:
   - once during Early phase
   - once during normal Processing
  Then process_option can then be called again during execution.

So, the parsing mode is defined so that the option parsing code
behaves differently (e.g. allows or not to handle the option)
depending on the mode.

// Command line option parsing happens in the following modes:
//   cloE : Early processing, used by coregrind m_main.c to parse the
//      command line  options that must be handled early on.
//   cloP : Processing,  used by coregrind and tools during startup, when
//      doing command line options Processing.
//   clodD : Dynamic, used to dynamically change options after startup.
//      A subset of the command line options can be changed dynamically
//      after startup.
//   cloH : Help, special mode to produce the list of dynamically changeable
//      options for --help-dyn-options.
typedef
   enum {
      cloE = 1,
      cloP = 2,
      cloD = 4,
      cloH = 8
   } Clo_Mode;

The option parsing macros in pub_tool_options.h have now all a new variant
*_CLOM with the mode(s) in which the given option is accepted.
The old variant is kept and calls the new variant with mode cloP.
The function VG_(check_clom) in the macro compares the current mode
with the modes allowed for the option, and returns True if qq_arg
should be further processed.

For example:

// String argument, eg. --foo=yes or --foo=no
   (VG_(check_clom)                                                     \
    (qq_mode, qq_arg, qq_option,                                        \
     VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=")) &&      \
    ({const HChar* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ];         \
      if      VG_STREQ(val, "yes") (qq_var) = True;                     \
      else if VG_STREQ(val, "no")  (qq_var) = False;                    \
      else VG_(fmsg_bad_option)(qq_arg, "Invalid boolean value '%s'"    \
                                " (should be 'yes' or 'no')\n", val);   \
      True; }))

   VG_BOOL_CLOM(cloP, qq_arg, qq_option, qq_var)

To make an option dynamically excutable, it is typically enough to replace
    VG_BOOL_CLO(...)
by
    VG_BOOL_CLOM(cloPD, ...)

For example:
-   else if VG_BOOL_CLO(arg, "--show-possibly-lost", tmp_show) {
+   else if VG_BOOL_CLOM(cloPD, arg, "--show-possibly-lost", tmp_show) {

cloPD means the option value is set/changed during the main command
Processing (P) and Dynamically during execution (D).

Note that the 'body/further processing' of a command is only executed when
the option is recognised and the current parsing mode is ok for this option.
2019-08-31 14:41:10 +02:00

97 lines
3.5 KiB
C

/*--------------------------------------------------------------------*/
/*--- Printing libc stuff. pub_core_libcprint.h ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2000-2017 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, see <http://www.gnu.org/licenses/>.
The GNU General Public License is contained in the file COPYING.
*/
#ifndef __PUB_CORE_LIBCPRINT_H
#define __PUB_CORE_LIBCPRINT_H
//--------------------------------------------------------------------
// PURPOSE: This module contains all the libc code that is related to
// higher-level (ie. higher than DebugLog) printing, eg. VG_(printf)().
//--------------------------------------------------------------------
#include "pub_tool_libcprint.h"
typedef
enum {
VgLogTo_Fd,
VgLogTo_File,
VgLogTo_Socket
}
VgLogTo;
/* An output file descriptor wrapped up with its type and expanded name. */
typedef
struct {
Int fd;
VgLogTo type;
HChar *fsname_expanded; // 'fs' stands for file or socket
}
OutputSink;
/* And the destinations for normal and XML output. */
extern OutputSink VG_(log_output_sink);
extern OutputSink VG_(xml_output_sink);
/* Initializes normal log and xml sinks (of type fd, file, or socket).
Any problem encountered is considered a hard error and causes V. to exit. */
extern void VG_(init_log_xml_sinks)(VgLogTo log_to, VgLogTo xml_to,
Int /*initial*/log_fd, Int /*initial*/xml_fd);
extern void VG_(print_preamble)(Bool logging_to_fd);
extern void VG_(logging_atfork_child)(ThreadId tid);
/* Get the elapsed wallclock time since startup into buf which has size
bufsize. The function will assert if bufsize is not large enough.
Upon return, buf will contain the zero-terminated wallclock time as
a string. The function also relies on the
millisecond timer having been set to zero by an initial read in
m_main during startup. */
void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf, SizeT bufsize );
/* Call this if the executable is missing. This function prints an
error message, then shuts down the entire system. */
__attribute__((noreturn))
extern void VG_(err_missing_prog) ( void );
/* Similarly - complain and stop if there is some kind of config
error. */
__attribute__((noreturn))
extern void VG_(err_config_error) ( const HChar* format, ... );
/* Called by main_process_cmd_line_options to indicate an unrecognised
command line option.
It shutdowns the system if Clo_Mode is cloE or cloP.*/
extern void VG_(fmsg_unknown_option) ( const HChar *opt );
#endif // __PUB_CORE_LIBCPRINT_H
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/