1 /*
2 * Percepio Trace Recorder for Tracealyzer v4.8.1
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation for strings.
9 */
10 
11 #include <trcRecorder.h>
12 
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14 
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
16 
17 #include <trcTypes.h>
18 
19 #ifndef TRC_SEND_NAME_ONLY_ON_DELETE
20 #define TRC_SEND_NAME_ONLY_ON_DELETE 0
21 #endif
22 
23 traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName, uint32_t uiLength);
24 
25 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegisterInternal(uint32_t uiEventCode,void * const pvObject,const char * szName,TraceUnsignedBaseType_t uxStateCount,const TraceUnsignedBaseType_t uxStates[],TraceUnsignedBaseType_t uxOptions,TraceObjectHandle_t * pxObjectHandle)26 traceResult xTraceObjectRegisterInternal(uint32_t uiEventCode, void* const pvObject, const char* szName, TraceUnsignedBaseType_t uxStateCount, const TraceUnsignedBaseType_t uxStates[], TraceUnsignedBaseType_t uxOptions, TraceObjectHandle_t* pxObjectHandle)
27 {
28 	TraceEntryHandle_t xEntryHandle;
29 	TraceEventHandle_t xEventHandle = 0;
30 	TraceUnsignedBaseType_t i;
31 	void *pvAddress;
32 
33 	TRACE_ALLOC_CRITICAL_SECTION();
34 
35 	/* This should never fail */
36 	TRC_ASSERT(pxObjectHandle != (void*)0);
37 
38 	/* This should never fail */
39 	TRC_ASSERT(uxStateCount <= (uint32_t)(TRC_ENTRY_TABLE_STATE_COUNT));
40 
41 	TRACE_ENTER_CRITICAL_SECTION();
42 
43 	if (pvObject != (void*)0)
44 	{
45 		/* An address was supplied */
46 		if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
47 		{
48 			TRACE_EXIT_CRITICAL_SECTION();
49 
50 			return TRC_FAIL;
51 		}
52 
53 		pvAddress = pvObject;
54 	}
55 	else
56 	{
57 		/* No address was supplied */
58 		if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL)
59 		{
60 			TRACE_EXIT_CRITICAL_SECTION();
61 
62 			return TRC_FAIL;
63 		}
64 
65 		TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress(xEntryHandle, &pvAddress) == TRC_SUCCESS);
66 	}
67 
68 	for (i = 0u; i < uxStateCount; i++)
69 	{
70 		/* This should never fail */
71 		TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, (uint32_t)i, uxStates[i]) == TRC_SUCCESS);
72 	}
73 
74 	/* This should never fail */
75 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions(xEntryHandle, (uint32_t)uxOptions) == TRC_SUCCESS);
76 
77 	*pxObjectHandle = (TraceObjectHandle_t)xEntryHandle;
78 
79 	TRACE_EXIT_CRITICAL_SECTION();
80 
81 	if ((szName != (void*)0) && (szName[0] != (char)0)) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
82 	{
83 		/* Not a null or empty string */
84 		/* This will set the symbol and create an event for it */
85 		/* This should never fail */
86 		TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName) == TRC_SUCCESS);
87 	}
88 
89 	/* Send the create event, if possible */
90 	/*We need to check this */
91 	if (xTraceEventBegin(uiEventCode, sizeof(void*) + (uxStateCount * sizeof(TraceUnsignedBaseType_t)), &xEventHandle) == TRC_SUCCESS)
92 	{
93 		(void)xTraceEventAddPointer(xEventHandle, pvAddress);
94 		for (i = 0u; i < uxStateCount; i++)
95 		{
96 			(void)xTraceEventAddUnsignedBaseType(xEventHandle, uxStates[i]);
97 		}
98 		(void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/
99 	}
100 
101 	return TRC_SUCCESS;
102 }
103 
104 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegister(uint32_t uiEventCode,void * const pvObject,const char * szName,TraceUnsignedBaseType_t uxState,TraceObjectHandle_t * pxObjectHandle)105 traceResult xTraceObjectRegister(uint32_t uiEventCode, void* const pvObject, const char* szName, TraceUnsignedBaseType_t uxState, TraceObjectHandle_t *pxObjectHandle)
106 {
107 	return xTraceObjectRegisterInternal(uiEventCode, pvObject, szName, 1u, &uxState, 0u, pxObjectHandle);
108 }
109 
xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle,uint32_t uiEventCode,TraceUnsignedBaseType_t uxState)110 traceResult xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle, uint32_t uiEventCode, TraceUnsignedBaseType_t uxState)
111 {
112 	void* pvObject = (void*)0;
113 	const char *szName = (void*)0; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
114 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 1)
115 	uint32_t uiLength;
116 	uint32_t i;
117 #endif
118 
119 	/* If asserts are disabled this variable will not get used, this stops warnings. */
120 	(void)szName;
121 
122 	/* This should never fail */
123 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
124 
125 	/* This should never fail */
126 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetSymbol((TraceEntryHandle_t)xObjectHandle, &szName) == TRC_SUCCESS);
127 
128 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 1)
129 	/* Send name event because this is a delete */
130 
131 	for (i = 0u; (szName[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
132 
133 	uiLength = i;
134 	/* This should never fail */
135 	TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName, uiLength) == TRC_SUCCESS);
136 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 1) */
137 
138 	/* Send the delete event, if possible */
139 	(void)xTraceEventCreate2(uiEventCode, (TraceUnsignedBaseType_t)(pvObject), uxState);  /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/
140 
141 	return xTraceEntryDelete(xObjectHandle);
142 }
143 
144 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectSetName(TraceObjectHandle_t xObjectHandle,const char * szName)145 traceResult xTraceObjectSetName(TraceObjectHandle_t xObjectHandle, const char* szName)
146 {
147 	void* pvObject = (void*)0;
148 	uint32_t uiLength;
149 	uint32_t i;
150 
151     /* If asserts are disabled this variable will not get used, this stops warnings. */
152 	(void)pvObject;
153 
154 	if (szName == (void*)0)
155 	{
156 		szName = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
157 	}
158 
159 	/* This should never fail */
160 	TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
161 
162 	for (i = 0u; (szName[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
163 
164 	uiLength = i;
165 
166 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 0)
167 	/* Send name event now since we don't do it on delete events */
168 	/* This should never fail */
169 	TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName, uiLength) == TRC_SUCCESS);
170 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 0) */
171 
172 	return xTraceEntrySetSymbol((TraceEntryHandle_t)xObjectHandle, szName, uiLength);
173 }
174 
175 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode,void * pvObject,const char * szName,TraceUnsignedBaseType_t uxState)176 traceResult xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxState)
177 {
178 	TraceObjectHandle_t xObjectHandle;
179 
180 	return xTraceObjectRegister(uiEventCode, pvObject, szName, uxState, &xObjectHandle);
181 }
182 
xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode,void * pvObject,TraceUnsignedBaseType_t uxState)183 traceResult xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState)
184 {
185 	TraceEntryHandle_t xEntryHandle;
186 	traceResult xResult;
187 
188 	TRACE_ALLOC_CRITICAL_SECTION();
189 
190 	TRACE_ENTER_CRITICAL_SECTION();
191 
192 	if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
193 	{
194 		TRACE_EXIT_CRITICAL_SECTION();
195 
196 		return TRC_FAIL;
197 	}
198 
199 	xResult = xTraceObjectUnregister((TraceObjectHandle_t)xEntryHandle, uiEventCode, uxState);
200 
201 	TRACE_EXIT_CRITICAL_SECTION();
202 
203 	return xResult;
204 }
205 
206 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectSetNameWithoutHandle(void * pvObject,const char * szName)207 traceResult xTraceObjectSetNameWithoutHandle(void* pvObject, const char* szName)
208 {
209 	TraceEntryHandle_t xEntryHandle;
210 	traceResult xResult;
211 
212 	TRACE_ALLOC_CRITICAL_SECTION();
213 
214 	TRACE_ENTER_CRITICAL_SECTION();
215 
216 	if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
217 	{
218 		/* No previous entry found. Create one. */
219 		if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
220 		{
221 			TRACE_EXIT_CRITICAL_SECTION();
222 
223 			return TRC_FAIL;
224 		}
225 	}
226 
227 	xResult = xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName);
228 
229 	TRACE_EXIT_CRITICAL_SECTION();
230 
231 	return xResult;
232 }
233 
xTraceObjectSetSpecificStateWithoutHandle(void * pvObject,uint32_t uiIndex,TraceUnsignedBaseType_t uxState)234 traceResult xTraceObjectSetSpecificStateWithoutHandle(void* pvObject, uint32_t uiIndex, TraceUnsignedBaseType_t uxState)
235 {
236 	TraceEntryHandle_t xEntryHandle;
237 	traceResult xResult;
238 
239 	TRACE_ALLOC_CRITICAL_SECTION();
240 
241 	TRACE_ENTER_CRITICAL_SECTION();
242 
243 	if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
244 	{
245 		TRACE_EXIT_CRITICAL_SECTION();
246 
247 		return TRC_FAIL;
248 	}
249 
250 	xResult = xTraceObjectSetSpecificState((TraceObjectHandle_t)xEntryHandle, uiIndex, uxState);
251 
252 	TRACE_EXIT_CRITICAL_SECTION();
253 
254 	return xResult;
255 }
256 
xTraceObjectSetOptionsWithoutHandle(void * pvObject,uint32_t uiMask)257 traceResult xTraceObjectSetOptionsWithoutHandle(void* pvObject, uint32_t uiMask)
258 {
259 	TraceEntryHandle_t xEntryHandle;
260 	traceResult xResult;
261 
262 	TRACE_ALLOC_CRITICAL_SECTION();
263 
264 	TRACE_ENTER_CRITICAL_SECTION();
265 
266 	if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
267 	{
268 		/* No previous entry found. Create one. */
269 		if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
270 		{
271 			TRACE_EXIT_CRITICAL_SECTION();
272 
273 			return TRC_FAIL;
274 		}
275 	}
276 
277 	xResult = xTraceObjectSetOptions((TraceObjectHandle_t)xEntryHandle, uiMask);
278 
279 	TRACE_EXIT_CRITICAL_SECTION();
280 
281 	return xResult;
282 }
283 
284 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
prvTraceObjectSendNameEvent(void * const pvObject,const char * szName,uint32_t uiLength)285 traceResult prvTraceObjectSendNameEvent(void* const pvObject, const char* szName, uint32_t uiLength)
286 {
287 	uint32_t uiValue = 0u;
288 	TraceEventHandle_t xEventHandle = 0;
289 
290 	if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS)
291 	{
292 		(void)xTraceEventAddPointer(xEventHandle, pvObject);
293 		(void)xTraceEventAddString(xEventHandle, szName, uiLength);
294 
295 		/* Check if we can truncate */
296 		(void)xTraceEventPayloadRemaining(xEventHandle, &uiValue);
297 		if (uiValue > 0u)
298 		{
299 			(void)xTraceEventAdd8(xEventHandle, 0u);
300 		}
301 
302 		(void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/
303 	}
304 
305 	return TRC_SUCCESS;
306 }
307 
308 #endif
309 
310 #endif
311