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