1*b077aed3SPierre Pronchery=pod 2*b077aed3SPierre Pronchery 3*b077aed3SPierre Pronchery=head1 NAME 4*b077aed3SPierre Pronchery 5*b077aed3SPierre ProncheryOSSL_trace_enabled, OSSL_trace_begin, OSSL_trace_end, 6*b077aed3SPierre ProncheryOSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL, 7*b077aed3SPierre ProncheryOSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4, 8*b077aed3SPierre ProncheryOSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9, 9*b077aed3SPierre ProncheryOSSL_TRACEV, 10*b077aed3SPierre ProncheryOSSL_TRACE_ENABLED 11*b077aed3SPierre Pronchery- OpenSSL Tracing API 12*b077aed3SPierre Pronchery 13*b077aed3SPierre Pronchery=head1 SYNOPSIS 14*b077aed3SPierre Pronchery 15*b077aed3SPierre Pronchery=for openssl generic 16*b077aed3SPierre Pronchery 17*b077aed3SPierre Pronchery #include <openssl/trace.h> 18*b077aed3SPierre Pronchery 19*b077aed3SPierre Pronchery int OSSL_trace_enabled(int category); 20*b077aed3SPierre Pronchery 21*b077aed3SPierre Pronchery BIO *OSSL_trace_begin(int category); 22*b077aed3SPierre Pronchery void OSSL_trace_end(int category, BIO *channel); 23*b077aed3SPierre Pronchery 24*b077aed3SPierre Pronchery /* trace group macros */ 25*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(category) { 26*b077aed3SPierre Pronchery ... 27*b077aed3SPierre Pronchery if (some_error) { 28*b077aed3SPierre Pronchery /* Leave trace group prematurely in case of an error */ 29*b077aed3SPierre Pronchery OSSL_TRACE_CANCEL(category); 30*b077aed3SPierre Pronchery goto err; 31*b077aed3SPierre Pronchery } 32*b077aed3SPierre Pronchery ... 33*b077aed3SPierre Pronchery } OSSL_TRACE_END(category); 34*b077aed3SPierre Pronchery 35*b077aed3SPierre Pronchery /* one-shot trace macros */ 36*b077aed3SPierre Pronchery OSSL_TRACE1(category, format, arg1) 37*b077aed3SPierre Pronchery OSSL_TRACE2(category, format, arg1, arg2) 38*b077aed3SPierre Pronchery ... 39*b077aed3SPierre Pronchery OSSL_TRACE9(category, format, arg1, ..., arg9) 40*b077aed3SPierre Pronchery 41*b077aed3SPierre Pronchery /* check whether a trace category is enabled */ 42*b077aed3SPierre Pronchery if (OSSL_TRACE_ENABLED(category)) { 43*b077aed3SPierre Pronchery ... 44*b077aed3SPierre Pronchery } 45*b077aed3SPierre Pronchery 46*b077aed3SPierre Pronchery=head1 DESCRIPTION 47*b077aed3SPierre Pronchery 48*b077aed3SPierre ProncheryThe functions described here are mainly interesting for those who provide 49*b077aed3SPierre ProncheryOpenSSL functionality, either in OpenSSL itself or in engine modules 50*b077aed3SPierre Proncheryor similar. 51*b077aed3SPierre Pronchery 52*b077aed3SPierre ProncheryIf tracing is enabled (see L</NOTES> below), these functions are used to 53*b077aed3SPierre Proncherygenerate free text tracing output. 54*b077aed3SPierre Pronchery 55*b077aed3SPierre ProncheryThe tracing output is divided into types which are enabled 56*b077aed3SPierre Proncheryindividually by the application. 57*b077aed3SPierre ProncheryThe tracing types are described in detail in 58*b077aed3SPierre ProncheryL<OSSL_trace_set_callback(3)/Trace types>. 59*b077aed3SPierre ProncheryThe fallback type B<OSSL_TRACE_CATEGORY_ALL> should I<not> be used 60*b077aed3SPierre Proncherywith the functions described here. 61*b077aed3SPierre Pronchery 62*b077aed3SPierre ProncheryTracing for a specific category is enabled if a so called 63*b077aed3SPierre ProncheryI<trace channel> is attached to it. A trace channel is simply a 64*b077aed3SPierre ProncheryBIO object to which the application can write its trace output. 65*b077aed3SPierre Pronchery 66*b077aed3SPierre ProncheryThe application has two different ways of registering a trace channel, 67*b077aed3SPierre Proncheryeither by directly providing a BIO object using OSSL_trace_set_channel(), 68*b077aed3SPierre Proncheryor by providing a callback routine using OSSL_trace_set_callback(). 69*b077aed3SPierre ProncheryThe latter is wrapped internally by a dedicated BIO object, so for the 70*b077aed3SPierre Proncherytracing code both channel types are effectively indistinguishable. 71*b077aed3SPierre ProncheryWe call them a I<simple trace channel> and a I<callback trace channel>, 72*b077aed3SPierre Proncheryrespectively. 73*b077aed3SPierre Pronchery 74*b077aed3SPierre ProncheryTo produce trace output, it is necessary to obtain a pointer to the 75*b077aed3SPierre Proncherytrace channel (i.e., the BIO object) using OSSL_trace_begin(), write 76*b077aed3SPierre Proncheryto it using arbitrary BIO output routines, and finally releases the 77*b077aed3SPierre Proncherychannel using OSSL_trace_end(). The OSSL_trace_begin()/OSSL_trace_end() 78*b077aed3SPierre Proncherycalls surrounding the trace output create a group, which acts as a 79*b077aed3SPierre Proncherycritical section (guarded by a mutex) to ensure that the trace output 80*b077aed3SPierre Proncheryof different threads does not get mixed up. 81*b077aed3SPierre Pronchery 82*b077aed3SPierre ProncheryThe tracing code normally does not call OSSL_trace_{begin,end}() directly, 83*b077aed3SPierre Proncherybut rather uses a set of convenience macros, see the L</Macros> section below. 84*b077aed3SPierre Pronchery 85*b077aed3SPierre Pronchery 86*b077aed3SPierre Pronchery=head2 Functions 87*b077aed3SPierre Pronchery 88*b077aed3SPierre ProncheryOSSL_trace_enabled() can be used to check if tracing for the given 89*b077aed3SPierre ProncheryI<category> is enabled. 90*b077aed3SPierre Pronchery 91*b077aed3SPierre ProncheryOSSL_trace_begin() is used to starts a tracing section, and get the 92*b077aed3SPierre Proncherychannel for the given I<category> in form of a BIO. 93*b077aed3SPierre ProncheryThis BIO can only be used for output. 94*b077aed3SPierre Pronchery 95*b077aed3SPierre ProncheryOSSL_trace_end() is used to end a tracing section. 96*b077aed3SPierre Pronchery 97*b077aed3SPierre ProncheryUsing OSSL_trace_begin() and OSSL_trace_end() to wrap tracing sections 98*b077aed3SPierre Proncheryis I<mandatory>. 99*b077aed3SPierre ProncheryThe result of trying to produce tracing output outside of such 100*b077aed3SPierre Proncherysections is undefined. 101*b077aed3SPierre Pronchery 102*b077aed3SPierre Pronchery=head2 Macros 103*b077aed3SPierre Pronchery 104*b077aed3SPierre ProncheryThere are a number of convenience macros defined, to make tracing 105*b077aed3SPierre Proncheryeasy and consistent. 106*b077aed3SPierre Pronchery 107*b077aed3SPierre ProncheryOSSL_TRACE_BEGIN() and OSSL_TRACE_END() reserve the B<BIO> C<trc_out> and are 108*b077aed3SPierre Proncheryused as follows to wrap a trace section: 109*b077aed3SPierre Pronchery 110*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(TLS) { 111*b077aed3SPierre Pronchery 112*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ... ); 113*b077aed3SPierre Pronchery 114*b077aed3SPierre Pronchery } OSSL_TRACE_END(TLS); 115*b077aed3SPierre Pronchery 116*b077aed3SPierre ProncheryThis will normally expand to: 117*b077aed3SPierre Pronchery 118*b077aed3SPierre Pronchery do { 119*b077aed3SPierre Pronchery BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS); 120*b077aed3SPierre Pronchery if (trc_out != NULL) { 121*b077aed3SPierre Pronchery ... 122*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ...); 123*b077aed3SPierre Pronchery } 124*b077aed3SPierre Pronchery OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); 125*b077aed3SPierre Pronchery } while (0); 126*b077aed3SPierre Pronchery 127*b077aed3SPierre ProncheryOSSL_TRACE_CANCEL() must be used before returning from or jumping out of a 128*b077aed3SPierre Proncherytrace section: 129*b077aed3SPierre Pronchery 130*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(TLS) { 131*b077aed3SPierre Pronchery 132*b077aed3SPierre Pronchery if (some_error) { 133*b077aed3SPierre Pronchery OSSL_TRACE_CANCEL(TLS); 134*b077aed3SPierre Pronchery goto err; 135*b077aed3SPierre Pronchery } 136*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ... ); 137*b077aed3SPierre Pronchery 138*b077aed3SPierre Pronchery } OSSL_TRACE_END(TLS); 139*b077aed3SPierre Pronchery 140*b077aed3SPierre ProncheryThis will normally expand to: 141*b077aed3SPierre Pronchery 142*b077aed3SPierre Pronchery do { 143*b077aed3SPierre Pronchery BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS); 144*b077aed3SPierre Pronchery if (trc_out != NULL) { 145*b077aed3SPierre Pronchery if (some_error) { 146*b077aed3SPierre Pronchery OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); 147*b077aed3SPierre Pronchery goto err; 148*b077aed3SPierre Pronchery } 149*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ... ); 150*b077aed3SPierre Pronchery } 151*b077aed3SPierre Pronchery OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); 152*b077aed3SPierre Pronchery } while (0); 153*b077aed3SPierre Pronchery 154*b077aed3SPierre Pronchery 155*b077aed3SPierre ProncheryOSSL_TRACE() and OSSL_TRACE1(), OSSL_TRACE2(), ... OSSL_TRACE9() are 156*b077aed3SPierre Proncheryso-called one-shot macros: 157*b077aed3SPierre Pronchery 158*b077aed3SPierre ProncheryThe macro call C<OSSL_TRACE(category, text)>, produces literal text trace output. 159*b077aed3SPierre Pronchery 160*b077aed3SPierre ProncheryThe macro call C<OSSL_TRACEn(category, format, arg1, ..., argn)> produces 161*b077aed3SPierre Proncheryprintf-style trace output with n format field arguments (n=1,...,9). 162*b077aed3SPierre ProncheryIt expands to: 163*b077aed3SPierre Pronchery 164*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(category) { 165*b077aed3SPierre Pronchery BIO_printf(trc_out, format, arg1, ..., argN) 166*b077aed3SPierre Pronchery } OSSL_TRACE_END(category) 167*b077aed3SPierre Pronchery 168*b077aed3SPierre ProncheryInternally, all one-shot macros are implemented using a generic OSSL_TRACEV() 169*b077aed3SPierre Proncherymacro, since C90 does not support variadic macros. This helper macro has a rather 170*b077aed3SPierre Proncheryweird synopsis and should not be used directly. 171*b077aed3SPierre Pronchery 172*b077aed3SPierre ProncheryThe OSSL_TRACE_ENABLED() macro can be used to conditionally execute some code 173*b077aed3SPierre Proncheryonly if a specific trace category is enabled. 174*b077aed3SPierre ProncheryIn some situations this is simpler than entering a trace section using 175*b077aed3SPierre ProncheryOSSL_TRACE_BEGIN() and OSSL_TRACE_END(). 176*b077aed3SPierre ProncheryFor example, the code 177*b077aed3SPierre Pronchery 178*b077aed3SPierre Pronchery if (OSSL_TRACE_ENABLED(TLS)) { 179*b077aed3SPierre Pronchery ... 180*b077aed3SPierre Pronchery } 181*b077aed3SPierre Pronchery 182*b077aed3SPierre Proncheryexpands to 183*b077aed3SPierre Pronchery 184*b077aed3SPierre Pronchery if (OSSL_trace_enabled(OSSL_TRACE_CATEGORY_TLS) { 185*b077aed3SPierre Pronchery ... 186*b077aed3SPierre Pronchery } 187*b077aed3SPierre Pronchery 188*b077aed3SPierre Pronchery=head1 NOTES 189*b077aed3SPierre Pronchery 190*b077aed3SPierre ProncheryIf producing the trace output requires carrying out auxiliary calculations, 191*b077aed3SPierre Proncherythis auxiliary code should be placed inside a conditional block which is 192*b077aed3SPierre Proncheryexecuted only if the trace category is enabled. 193*b077aed3SPierre Pronchery 194*b077aed3SPierre ProncheryThe most natural way to do this is to place the code inside the trace section 195*b077aed3SPierre Proncheryitself because it already introduces such a conditional block. 196*b077aed3SPierre Pronchery 197*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(TLS) { 198*b077aed3SPierre Pronchery int var = do_some_auxiliary_calculation(); 199*b077aed3SPierre Pronchery 200*b077aed3SPierre Pronchery BIO_printf(trc_out, "var = %d\n", var); 201*b077aed3SPierre Pronchery 202*b077aed3SPierre Pronchery } OSSL_TRACE_END(TLS); 203*b077aed3SPierre Pronchery 204*b077aed3SPierre ProncheryIn some cases it is more advantageous to use a simple conditional group instead 205*b077aed3SPierre Proncheryof a trace section. This is the case if calculations and tracing happen in 206*b077aed3SPierre Proncherydifferent locations of the code, or if the calculations are so time consuming 207*b077aed3SPierre Proncherythat placing them inside a (critical) trace section would create too much 208*b077aed3SPierre Proncherycontention. 209*b077aed3SPierre Pronchery 210*b077aed3SPierre Pronchery if (OSSL_TRACE_ENABLED(TLS)) { 211*b077aed3SPierre Pronchery int var = do_some_auxiliary_calculation(); 212*b077aed3SPierre Pronchery 213*b077aed3SPierre Pronchery OSSL_TRACE1("var = %d\n", var); 214*b077aed3SPierre Pronchery } 215*b077aed3SPierre Pronchery 216*b077aed3SPierre ProncheryNote however that premature optimization of tracing code is in general futile 217*b077aed3SPierre Proncheryand it's better to keep the tracing code as simple as possible. 218*b077aed3SPierre ProncheryBecause most often the limiting factor for the application's speed is the time 219*b077aed3SPierre Proncheryit takes to print the trace output, not to calculate it. 220*b077aed3SPierre Pronchery 221*b077aed3SPierre Pronchery=head2 Configure Tracing 222*b077aed3SPierre Pronchery 223*b077aed3SPierre ProncheryBy default, the OpenSSL library is built with tracing disabled. To 224*b077aed3SPierre Proncheryuse the tracing functionality documented here, it is therefore 225*b077aed3SPierre Proncherynecessary to configure and build OpenSSL with the 'enable-trace' option. 226*b077aed3SPierre Pronchery 227*b077aed3SPierre ProncheryWhen the library is built with tracing disabled: 228*b077aed3SPierre Pronchery 229*b077aed3SPierre Pronchery=over 4 230*b077aed3SPierre Pronchery 231*b077aed3SPierre Pronchery=item * 232*b077aed3SPierre Pronchery 233*b077aed3SPierre ProncheryThe macro B<OPENSSL_NO_TRACE> is defined in F<< <openssl/opensslconf.h> >>. 234*b077aed3SPierre Pronchery 235*b077aed3SPierre Pronchery=item * 236*b077aed3SPierre Pronchery 237*b077aed3SPierre Proncheryall functions are still present, but OSSL_trace_enabled() will always 238*b077aed3SPierre Proncheryreport the categories as disabled, and all other functions will do 239*b077aed3SPierre Proncherynothing. 240*b077aed3SPierre Pronchery 241*b077aed3SPierre Pronchery=item * 242*b077aed3SPierre Pronchery 243*b077aed3SPierre Proncherythe convenience macros are defined to produce dead code. 244*b077aed3SPierre ProncheryFor example, take this example from L</Macros> section above: 245*b077aed3SPierre Pronchery 246*b077aed3SPierre Pronchery OSSL_TRACE_BEGIN(TLS) { 247*b077aed3SPierre Pronchery 248*b077aed3SPierre Pronchery if (condition) { 249*b077aed3SPierre Pronchery OSSL_TRACE_CANCEL(TLS); 250*b077aed3SPierre Pronchery goto err; 251*b077aed3SPierre Pronchery } 252*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ... ); 253*b077aed3SPierre Pronchery 254*b077aed3SPierre Pronchery } OSSL_TRACE_END(TLS); 255*b077aed3SPierre Pronchery 256*b077aed3SPierre ProncheryWhen the tracing API isn't operational, that will expand to: 257*b077aed3SPierre Pronchery 258*b077aed3SPierre Pronchery do { 259*b077aed3SPierre Pronchery BIO *trc_out = NULL; 260*b077aed3SPierre Pronchery if (0) { 261*b077aed3SPierre Pronchery if (condition) { 262*b077aed3SPierre Pronchery ((void)0); 263*b077aed3SPierre Pronchery goto err; 264*b077aed3SPierre Pronchery } 265*b077aed3SPierre Pronchery BIO_fprintf(trc_out, ... ); 266*b077aed3SPierre Pronchery } 267*b077aed3SPierre Pronchery } while (0); 268*b077aed3SPierre Pronchery 269*b077aed3SPierre Pronchery=back 270*b077aed3SPierre Pronchery 271*b077aed3SPierre Pronchery=head1 RETURN VALUES 272*b077aed3SPierre Pronchery 273*b077aed3SPierre ProncheryOSSL_trace_enabled() returns 1 if tracing for the given I<type> is 274*b077aed3SPierre Proncheryoperational and enabled, otherwise 0. 275*b077aed3SPierre Pronchery 276*b077aed3SPierre ProncheryOSSL_trace_begin() returns a B<BIO> pointer if the given I<type> is enabled, 277*b077aed3SPierre Proncheryotherwise NULL. 278*b077aed3SPierre Pronchery 279*b077aed3SPierre Pronchery=head1 HISTORY 280*b077aed3SPierre Pronchery 281*b077aed3SPierre ProncheryThe OpenSSL Tracing API was added in OpenSSL 3.0. 282*b077aed3SPierre Pronchery 283*b077aed3SPierre Pronchery=head1 COPYRIGHT 284*b077aed3SPierre Pronchery 285*b077aed3SPierre ProncheryCopyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 286*b077aed3SPierre Pronchery 287*b077aed3SPierre ProncheryLicensed under the Apache License 2.0 (the "License"). You may not use 288*b077aed3SPierre Proncherythis file except in compliance with the License. You can obtain a copy 289*b077aed3SPierre Proncheryin the file LICENSE in the source distribution or at 290*b077aed3SPierre ProncheryL<https://www.openssl.org/source/license.html>. 291*b077aed3SPierre Pronchery 292*b077aed3SPierre Pronchery=cut 293