📄 cyg_trac.h
字号:
#ifndef CYGONCE_INFRA_CYG_TRAC_H
#define CYGONCE_INFRA_CYG_TRAC_H
//==========================================================================
//
// cyg_trac.h
//
// Macros and prototypes for the tracing system
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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 or (at your option) any later version.
//
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg from an original by hmt
// Contributors: nickg
// Date: 1998-04-23
// Purpose: Use traces to log procedure entry, and "print" stuff
// Description: Runtime logging messages that compile to nothing in
// release versions of the code, to allow
// as-you-go tracing of alternate builds.
// Usage: #include <cyg/infra/cyg_trac.h>
// ...
// CYG_TRACE2( PIPE_TRACE, "pipe %x, data %d", ppipe, oword );
//
// which can result, for example, in a message of the form:
// "TRACE: pipemgr.cxx:1340, write_pipe(): pipe 0x8004c, data 17"
//
//####DESCRIPTIONEND####
//
/****************************************************************************
Explicit tracing
================
CYG_TRACE0( bool, msg );
CYG_TRACE1( bool, msg, arg1 );
CYG_TRACE2( bool, msg, arg1, arg2 );
....
CYG_TRACE8( bool, msg, .... [with 8 args] );
In general, the bool controls whether or not the tracing occurs for a
particular invocation of the macro. The msg is a printf-style string,
though exactly which formats are supported depends on the underlying
implementation. Typically, at least %d, %x, %08x, %c and %s will be
supported. Of course a most compact implementation might print
TRACE:z1dbuff.c[92]get_nextdata(): data pointer %x offset %d: 42BD8 1C
or some such, leaving you to work it out for yourself.
It is expected that the boolean would rarely actually be a complex
expression; it is more likely that it would either be "1", tracing being
controlled for the whole compilation unit or subsystem by means of the
CYGDBG_USE_TRACING symbol, or a local symbol for tracing over the whole
file, defined to 0 or to 1. For runtime control of tracing in a debugging
session, it is typical to use symbols defined to expressions such as:
static int xxx_trace = 0;
#define TL1 (0 < xxx_trace)
#define TL2 (1 < xxx_trace)
so you set xxx_trace to 1 to enable those messages conditioned by TL1
(trace level 1) and so on.
CYG_TRACE1( TL1, "Major argument is %d", zz );
CYG_TRACE4( TL2, "...minor details %d %d %d %d", m1, m2, m3 ,m4 );
To assist with the case where the same symbol or expression is used
throughout a compilation unit, the programmer can define the symbol
CYG_TRACE_USER_BOOL as they choose and then use convenience macros with the
suffix 'B' in the obvious manner:
#define CYG_TRACE_USER_BOOL (xxx_trace > 0)
CYG_TRACE2B( "Counters are %d, %d", countlo, counthi );
For the case where you just want to print a load of numbers in hex, or
decimal, convenience suffices X, D and Y are provided. X uses %08x, D %d
and Y an unadorned %x for each argument.
CYG_TRACE3D( TL2, m1, m2, d );
If you want to do something similar but with a little more comment, the
names (strictly spellings) of the variables you are printing can be used by
appending a V to the X, D or Y.
CYG_TRACE3DV( TL2, m1, m2, d );
might output:
TRACE:z1dbuff.c[92]get_nextdata(): m1=23 m2=-4 d=55
These conveniences can be combined, and they apply equally to tracing with
up to 8 variables; the B for Bool goes last:
CYG_TRACE4DVB( i, i*i, i*i*i, i*i*i*i );
might output:
TRACE:table.c[12]main(): i=3 i*i=9 i*i*i=27 i*i*i*i=81
Function Tracing
================
There are also facities for easily reporting function entry and exit,
printing the function arguments, and detecting returns without logging (or
without a value!).
The basic facility is
CYG_REPORT_FUNCTION();
In C, place this between the local variable declarations and the first
statement or errors will ensue. C++ is more flexible; place the macro as
the first line of all functions you wish to trace. The following
variations are also provided:
CYG_REPORT_FUNCTYPE( exitmsg ) provide a printf string for the type
of the returned value
CYG_REPORT_FUNCNAME( name ) supply a function name explicitly, for
if __FUNCTION__ is not supported
CYG_REPORT_FUNCNAMETYPE( name, exitmsg ) both of the above extensions
These are unconditional; the assumption is that if function reporting is
used at all it will be used for all functions within a compilation unit.
However, it is useful to be able to control function reporting at finer
grain without editing the source files concerned, at compile time or at
runtime. To support this, conditioned versions (with suffix 'C') are
provided for the above four macros, which only procduce trace output if the
macro CYG_REPORT_USER_BOOL evaluates true.
CYG_REPORT_FUNCTIONC()
CYG_REPORT_FUNCNAMEC( name )
CYG_REPORT_FUNCTYPEC( exitmsg )
CYG_REPORT_FUNCNAMETYPEC( name, exitmsg )
You can define CYG_REPORT_USER_BOOL to anything you like before invoking
these macros; using a simple -DCYG_REPORT_USER_BOOL=0 or ...=1 on the
compiler command line would do the trick, but there is more flexibility to
be gained by something like:
#define CYG_REPORT_USER_BOOL (reporting_bool_FOO)
#ifdef TRACE_FOO
int reporting_bool_FOO = 1;
#else
int reporting_bool_FOO = 0;
#endif
where FOO relates to the module name. Thus an external symbol sets the
default, but it can be overridden in a debugging session by setting the
variable reporting_bool_FOO.
Note that the condition applied to the initial CYG_REPORT_FUNC...() macro
controls all function-related reporting (not tracing) from that function;
the underlying mechanisms still operate even if no output is created. Thus
no conditioned variants of CYG_REPORT_FUNCARG[s] nor of CYG_REPORT_RETURN
are needed.
Examples:
int myfunction()
{
CYG_REPORT_FUNCTYPE( "recode is %d" );
A function return is traced using
CYG_REPORT_RETURN() a void return
CYG_REPORT_RETVAL( value ) returning a value
With the CYG_REPORT_FUNCTYPE example, the latter might produce a message
like:
TRACE:myprog.c[40]fact(): enter
TRACE:myprog.c[53]fact(): retcode is 24
It is also useful to trace the values of the arguments to a function:
CYG_REPORT_FUNCARGVOID confirms that the function is void
CYG_REPORT_FUNCARG1( format, arg ) printf-style
to
CYG_REPORT_FUNCARG8( format, arg1...arg8 ) printf-style
The CYG_REPORT_FUNCARG[1-8] macros are also offered with the convenience
extensions: D, X, or Y, and V like the explicit tracing macros. For
example:
int fact( int number )
{
CYG_REPORT_FUNCTYPE( "recode is %d" );
CYG_REPORT_FUNCARG1DV( number );
int result = number;
while ( --number > 1 ) result *= number
CYG_REPORT_RETVAL( result );
return result;
}
might produce:
TRACE:myprog.c[40]fact(): enter
TRACE:myprog.c[40]fact(): number=4
TRACE:myprog.c[53]fact(): retcode is 24
If no exit message is provided, a default of %08x is used.
General Configury
=================
If CYGDBG_INFRA_DEBUG_FUNCTION_PSEUDOMACRO is *not* defined, it is assumed
that __PRETTY_FUNCTION__ or equivalents do not exist, so no function name
tracing is possible; only file and line number.
If CYGDBG_INFRA_DEBUG_TRACE_MESSAGE is *not* defined, the message and
arguments to all tracing macros are not used; only "execution was here"
type information, by file, function and line number, is available. This
can greatly reduce the size of an image with tracing disabled, which may be
crucial in debugging on actual shipped hardware with limited memory.
If configured for buffered tracing then CYG_TRACE_PRINT() can be used to
output the contents of the trace buffer on demand.
CYG_TRACE_DUMP() outputs a form of "core dump" containing info on the
scheduler and threads at the time. This information will be invalid if
the kernel is not running.
C/C++: in C++ the function reporting is implemented using a class object
with a destructor; this allows reporting of a return which has not been
explicitly reported, and detection of accidental multiple return reports.
This helps you write the function reporting correctly. In C it is not
possible to be so sophisticated, so the implementation is not so helpful in
detecting errors in the use of the tracing system.
Note that for all of the above variations, the internal API to the
functions which are called in consequence of tracing remains the same, so
these variations can be mixed in the same executable, by configuring the
tracing macros differently in different compilation units or subsystems.
Summary
=======
Explicit tracing
----------------
CYG_TRACE0( bool, msg ) if bool, print msg
CYG_TRACE1( bool, msg, arg ) if bool, printf-style
to
CYG_TRACE8( bool, msg, arg1...arg8 ) if bool, printf-style
CYG_TRACE0B( msg, args... ) to CYG_TRACE8B() use CYG_TRACE_USER_BOOL
CYG_TRACE1X( bool, args... ) to CYG_TRACE8X() print args using %08x
CYG_TRACE1Y( bool, args... ) to CYG_TRACE8Y() print args using %x
CYG_TRACE1D( bool, args... ) to CYG_TRACE8D() print args using %d
CYG_TRACE1XV( bool, args... ) to CYG_TRACE8XV() print args using "arg=%08x"
CYG_TRACE1YV( bool, args... ) to CYG_TRACE8YV() print args using "arg=%x"
CYG_TRACE1DV( bool, args... ) to CYG_TRACE8DV() print args using "arg=%d"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -