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