1 /* 2 * Trace Recorder for Tracealyzer v4.5.1 3 * Copyright 2021 Percepio AB 4 * www.percepio.com 5 * 6 * SPDX-License-Identifier: Apache-2.0 7 * 8 * The extension interface of the recorder library, allowing for tracing 9 * function calls to any API without modifications. All that is needed is a 10 * single #include line in the .c files calling the API. 11 * 12 * This can be used to provide more detailed traces, including calls to e.g. 13 * middleware, drivers or important APIs in your application code. This can be 14 * applied selectively to specified functions and may include selected 15 * parameters as well as the return value. 16 * 17 * Unlike the "User Event" concept, an extension is intended for systematic use 18 * and can benefit from all powerful features in Tracealyzer via host-side XML 19 * files that configure how Tracealyzer should interpret each event. 20 * 21 * Extensions are self-contained and easy to integrate, which makes them 22 * convenient for distribution. Software vendors can thus develop such 23 * extensions and provide trace support for their users. 24 * 25 * An extension consists of two files: 26 * 27 * - An extension header file (e.g. "api.tzext.h") - this defines how to 28 * trace the API function calls. 29 * 30 * - An XML file for the Tracealyzer application (e.g. "api-v1.0.0.xml"). 31 * This needs to match the tracing setup in your extension header file. 32 * 33 * 34 * USAGE 35 * 36 * This description assumes you already have the extension files for the APIs you 37 * like to trace. To include them, follow these steps: 38 * 39 * 1. Update trcExtensions.h with respect to: 40 * 41 * 1.1. TRC_CFG_EXTENSION_COUNT: The number of extensions to enable (max 4). 42 * 43 * 1.2. The name(s) of the extension header file(s) to include. 44 * 45 * 1.3. The Extension Prefix, i.e., the first part of the definition names 46 * used in each header file. 47 * 48 * 2. Add #include "trcExtensions.h" in all .c files calling the API: 49 * 50 * #include ... 51 * #include "api.h" // The API you like to trace 52 * #include ... 53 * #include "trcExtensions.h" 54 * 55 * We recommend to put this as the LAST #include statement. 56 * 57 * HOWEVER, don't include "trcExtensions.h" in the .c files containing the 58 * functions you intend to trace. The compiler will then complain about 59 * multiple definitions of the trace wrapper function. 60 * 61 * 3. Copy the extension XML file to the "Tracealyzer 4/cfg" folder. 62 * On Windows this is typically 63 * 64 * C:\Program Files\Percepio\Tracealyzer 4\cfg 65 * 66 * 67 * HOW IT WORKS 68 * 69 * By including "trcExtensions.h" in your .c files, the preprocessor will 70 * redefine all calls of the functions specified in the extension header file. 71 * Calls to those functions will now instead call the "trace wrapper functions" 72 * defined in the extension header. The trace wrapper functions then call the 73 * original function as well as the trace recorder library. 74 * 75 * call foo(a) ----> foo__trace(a) -----> foo(a) 76 * -----> trace recorder library 77 * 78 * Note that the trace wrapper function should have the same declaration as the 79 * original function (apart from the name) and also returns any return value 80 * back to the original caller. So functionally this is completely transparent. 81 * 82 * This works also for calls via function pointers, as the assignments of the 83 * function pointers will be affected, so the function pointers will point to 84 * the trace wrapper function. 85 * 86 * It even works when calling binary libraries, since only the calling code 87 * is modified, not the API itself. 88 * 89 * Extensions include a version code (Major.Minor.Patch), which is registered 90 * in the trace and also part of the XML file name. This way, Tracealyzer 91 * automatically finds the matching XML file, even if you open a old trace 92 * recorded using a earlier version of the extension (e.g. if the API has 93 * changed). 94 * 95 * LIMITATIONS 96 * 97 * The main limitation of this automatic approach is that it only allows for 98 * tracing call between different .c files. Moreover, you can't trace multiple 99 * APIs with calls between them. This since the calling file must include 100 * trcExtensions.h, while the called file must NOT include this. 101 * 102 * It is however possible to get around this limitation. You need to add 103 * #undef lines for each affected function to locally disable the redefinition, 104 * and modify each function call to instead call the trace wrapper function. 105 * 106 * #include "trcExtensions.h" 107 * #undef foo 108 * ... 109 * void foo(int a) 110 * { 111 * ... 112 * } 113 * ... 114 * foo__trace(a); // in another function - call foo and trace it 115 * 116 * These changes can remain in your code if you like, as the trace wrappers 117 * works even if the recorder is disabled. 118 * 119 * MAKING YOUR OWN EXTENSIONS 120 * 121 * Examples are found in the extensions directory. We recommend that you start 122 * by looking at aws_secure_sockets files (.h and .xml) that provides a basic 123 * example. The aws_wifi files provides a more advanced example. 124 * The header files include detailed documentation about how to design them, 125 * 126 * The XML files should have the same name as specified in the NAME property 127 * in the header file, followed by the version, i.e. 128 * 129 * <NAME>-v<VERSION_MAJOR>.<<VERSION_MINOR>.<VERSION_PATCH>.xml 130 * 131 * Documentation for the XML file format is not yet available, but is under 132 * development. 133 */ 134 135 #ifndef TRCEXTENSIONS_H_ 136 #define TRCEXTENSIONS_H_ 137 138 #include "trcRecorder.h" 139 140 /****************************************************************************** 141 * TRC_CFG_EXTENSION_COUNT 142 * 143 * Defines the number of extensions included in the trace. Maximum 4 extensions 144 * can be included. 145 * 146 * Default value is 0 (extension support disabled). 147 * 148 *****************************************************************************/ 149 #define TRC_CFG_EXTENSION_COUNT 0 150 151 /****************************************************************************** 152 * TRC_CFG_EXT_MAX_NAME_LEN 153 * 154 * Defines the maximum length of extension name(s), i.e. the <EXTENSION>_NAME 155 * macro(s) in trcExtensions.h. 156 * 157 * This value should will by rounded up to the nearest multiple of 4, and must 158 * not be zero. To disable extension support, see TRC_CFG_EXTENSION_COUNT. 159 * 160 * It is important that this setting is large enough so extension names are 161 * not truncated, otherwise the host-side Tracealyzer application won't be able 162 * to find the corresponding XML file. 163 * 164 * You may adjust this to reduce memory usage, or increase it to allow for 165 * longer extension names. 166 * 167 * Default value is 20. 168 *****************************************************************************/ 169 #define TRC_CFG_EXT_MAX_NAME_LEN 20 170 171 /****************************************************************************** 172 * TRC_EXTENSION_EVENTCODE_BASE 173 * 174 * The first event code used for the Extension system. This will be the first 175 * event code of the first extension, and other event codes are relative to 176 * this. This can be modified but this is normally not required. 177 *****************************************************************************/ 178 #define TRC_EXTENSION_EVENTCODE_BASE 256 179 180 /*** Included Extensions ****************************************************** 181 * 182 * Below you specify what extensions to include. For each 183 * extension you must define: 184 * 185 * - HEADER: The header file that defines the trace extension. 186 * 187 * - EXTENSION_PREFIX: The first part of the HEADER definition names. 188 * 189 *****************************************************************************/ 190 #define TRC_EXT1_HEADER "aws_secure_sockets.tzext.h" 191 #define TRC_EXT1_PREFIX TRC_EXT_SOCKETS 192 193 #define TRC_EXT2_HEADER "aws_wifi.tzext.h" 194 #define TRC_EXT2_PREFIX TRC_EXT_WIFI 195 196 #define TRC_EXT3_HEADER "Here you specify the header file for Extensions 3." 197 #define TRC_EXT3_PREFIX NOT_DEFINED 198 199 #define TRC_EXT4_HEADER "Here you specify the header file for Extensions 4." 200 #define TRC_EXT4_PREFIX NOT_DEFINED 201 202 /*** Don't modify below ******************************************************/ 203 204 #define ROUNDUP4(n) (4*((n+3)/4)) 205 206 typedef struct{ 207 uint16_t firstEventCode; 208 uint16_t lastEventCode; 209 uint16_t patchVersion; 210 uint8_t minorVersion; 211 uint8_t majorVersion; 212 char name[ROUNDUP4(TRC_CFG_EXT_MAX_NAME_LEN)]; 213 } PSFExtensionEntryType; 214 215 typedef struct{ 216 uint16_t extensionEntryCount; 217 uint16_t baseEventCode; 218 #if (TRC_CFG_EXTENSION_COUNT > 0) 219 uint8_t extensionEntryNameMaxLength; 220 uint8_t extensionEntrySize; 221 PSFExtensionEntryType extension[TRC_CFG_EXTENSION_COUNT]; 222 #endif 223 } PSFExtensionInfoType; 224 225 226 extern PSFExtensionInfoType PSFExtensionInfo; 227 228 #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) 229 #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ 230 231 #define TRC_EXT_BASECODE (PSFExtensionInfo.extension[TRC_EXT_NUMBER-1].firstEventCode) 232 233 #if (TRC_CFG_EXTENSION_COUNT >= 1) 234 #ifdef TRC_EXT1_HEADER 235 #define TRC_EXT_NUMBER 1 236 #include TRC_EXT1_HEADER 237 #undef TRC_EXT_NUMBER 238 #endif 239 #endif 240 241 #if (TRC_CFG_EXTENSION_COUNT >= 2) 242 #ifdef TRC_EXT2_HEADER 243 #define TRC_EXT_NUMBER 2 244 #include TRC_EXT2_HEADER 245 #undef TRC_EXT_NUMBER 246 #endif 247 #endif 248 249 #if (TRC_CFG_EXTENSION_COUNT >= 3) 250 #ifdef TRC_EXT3_HEADER 251 #define TRC_EXT_NUMBER 3 252 #include TRC_EXT3_HEADER 253 #undef TRC_EXT_NUMBER 254 #endif 255 #endif 256 257 #if (TRC_CFG_EXTENSION_COUNT == 4) 258 #ifdef TRC_EXT3_HEADER 259 #define TRC_EXT_NUMBER 4 260 #include TRC_EXT4_HEADER 261 #undef TRC_EXT_NUMBER 262 #endif 263 #endif 264 265 #define TRC_EXT1_COUNT CAT(TRC_EXT1_PREFIX, _COUNT) 266 #define TRC_EXT2_COUNT CAT(TRC_EXT2_PREFIX, _COUNT) 267 #define TRC_EXT3_COUNT CAT(TRC_EXT3_PREFIX, _COUNT) 268 #define TRC_EXT4_COUNT CAT(TRC_EXT4_PREFIX, _COUNT) 269 270 #define TRC_EXT1_NAME CAT(TRC_EXT1_PREFIX, _NAME) 271 #define TRC_EXT2_NAME CAT(TRC_EXT2_PREFIX, _NAME) 272 #define TRC_EXT3_NAME CAT(TRC_EXT3_PREFIX, _NAME) 273 #define TRC_EXT4_NAME CAT(TRC_EXT4_PREFIX, _NAME) 274 275 #define TRC_EXT1_VERSION_MAJOR CAT(TRC_EXT1_PREFIX, _VERSION_MAJOR) 276 #define TRC_EXT2_VERSION_MAJOR CAT(TRC_EXT2_PREFIX, _VERSION_MAJOR) 277 #define TRC_EXT3_VERSION_MAJOR CAT(TRC_EXT3_PREFIX, _VERSION_MAJOR) 278 #define TRC_EXT4_VERSION_MAJOR CAT(TRC_EXT4_PREFIX, _VERSION_MAJOR) 279 280 #define TRC_EXT1_VERSION_MINOR CAT(TRC_EXT1_PREFIX, _VERSION_MINOR) 281 #define TRC_EXT2_VERSION_MINOR CAT(TRC_EXT2_PREFIX, _VERSION_MINOR) 282 #define TRC_EXT3_VERSION_MINOR CAT(TRC_EXT3_PREFIX, _VERSION_MINOR) 283 #define TRC_EXT4_VERSION_MINOR CAT(TRC_EXT4_PREFIX, _VERSION_MINOR) 284 285 #define TRC_EXT1_VERSION_PATCH CAT(TRC_EXT1_PREFIX, _VERSION_PATCH) 286 #define TRC_EXT2_VERSION_PATCH CAT(TRC_EXT2_PREFIX, _VERSION_PATCH) 287 #define TRC_EXT3_VERSION_PATCH CAT(TRC_EXT3_PREFIX, _VERSION_PATCH) 288 #define TRC_EXT4_VERSION_PATCH CAT(TRC_EXT4_PREFIX, _VERSION_PATCH) 289 290 #if ((TRC_CFG_EXTENSION_COUNT > 4) || (TRC_CFG_EXTENSION_COUNT < 0)) 291 #error "TRC_CFG_EXTENSION_COUNT must be in range [0..4]" 292 #endif 293 294 #if (TRC_CFG_EXTENSION_COUNT == 0) 295 #define TRC_EXTENSIONS_DATA 296 #endif 297 298 #if (TRC_CFG_EXTENSION_COUNT == 1) 299 #define TRC_EXTENSIONS_DATA \ 300 { \ 301 { TRC_EXTENSION_EVENTCODE_BASE, \ 302 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ 303 TRC_EXT1_VERSION_PATCH, \ 304 TRC_EXT1_VERSION_MINOR, \ 305 TRC_EXT1_VERSION_MAJOR, \ 306 TRC_EXT1_NAME } \ 307 } 308 #endif 309 310 #if (TRC_CFG_EXTENSION_COUNT == 2) 311 #define TRC_EXTENSIONS_DATA \ 312 { \ 313 { TRC_EXTENSION_EVENTCODE_BASE, \ 314 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ 315 TRC_EXT1_VERSION_PATCH, \ 316 TRC_EXT1_VERSION_MINOR, \ 317 TRC_EXT1_VERSION_MAJOR, \ 318 TRC_EXT1_NAME } \ 319 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ 320 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ 321 TRC_EXT2_VERSION_PATCH, \ 322 TRC_EXT2_VERSION_MINOR, \ 323 TRC_EXT2_VERSION_MAJOR, \ 324 TRC_EXT2_NAME } \ 325 } 326 #endif 327 328 #if (TRC_CFG_EXTENSION_COUNT == 3) 329 #define TRC_EXTENSIONS_DATA \ 330 { \ 331 { TRC_EXTENSION_EVENTCODE_BASE, \ 332 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ 333 TRC_EXT1_VERSION_PATCH, \ 334 TRC_EXT1_VERSION_MINOR, \ 335 TRC_EXT1_VERSION_MAJOR, \ 336 TRC_EXT1_NAME } \ 337 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ 338 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ 339 TRC_EXT2_VERSION_PATCH, \ 340 TRC_EXT2_VERSION_MINOR, \ 341 TRC_EXT2_VERSION_MAJOR, \ 342 TRC_EXT2_NAME } \ 343 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT, \ 344 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT - 1, \ 345 TRC_EXT3_VERSION_PATCH, \ 346 TRC_EXT3_VERSION_MINOR, \ 347 TRC_EXT3_VERSION_MAJOR, \ 348 TRC_EXT3_NAME } \ 349 } 350 #endif 351 #if (TRC_CFG_EXTENSION_COUNT == 4) 352 #define TRC_EXTENSIONS_DATA \ 353 { \ 354 { TRC_EXTENSION_EVENTCODE_BASE, \ 355 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT-1, \ 356 TRC_EXT1_VERSION_PATCH, \ 357 TRC_EXT1_VERSION_MINOR, \ 358 TRC_EXT1_VERSION_MAJOR, \ 359 TRC_EXT1_NAME } \ 360 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT, \ 361 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT-1, \ 362 TRC_EXT2_VERSION_PATCH, \ 363 TRC_EXT2_VERSION_MINOR, \ 364 TRC_EXT2_VERSION_MAJOR, \ 365 TRC_EXT2_NAME } \ 366 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT, \ 367 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT - 1, \ 368 TRC_EXT3_VERSION_PATCH, \ 369 TRC_EXT3_VERSION_MINOR, \ 370 TRC_EXT3_VERSION_MAJOR, \ 371 TRC_EXT3_NAME } \ 372 ,{ TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT, \ 373 TRC_EXTENSION_EVENTCODE_BASE + TRC_EXT1_COUNT + TRC_EXT2_COUNT + TRC_EXT3_COUNT + TRC_EXT4_COUNT- 1, \ 374 TRC_EXT4_VERSION_PATCH, \ 375 TRC_EXT4_VERSION_MINOR, \ 376 TRC_EXT4_VERSION_MAJOR, \ 377 TRC_EXT4_NAME } \ 378 } 379 #endif 380 381 #if (TRC_CFG_EXTENSION_COUNT > 0) 382 #define TRC_EXTENSION_INFO {TRC_CFG_EXTENSION_COUNT, TRC_EXTENSION_EVENTCODE_BASE, ROUNDUP4(TRC_CFG_EXT_MAX_NAME_LEN), sizeof(PSFExtensionEntryType), TRC_EXTENSIONS_DATA} 383 #else 384 #define TRC_EXTENSION_INFO {TRC_CFG_EXTENSION_COUNT, TRC_EXTENSION_EVENTCODE_BASE} 385 #endif 386 387 #endif /* TRCEXTENSIONS_H_ */ 388