1 /****************************************************************************** 2 * 3 * Module Name: extrace - Support for interpreter execution tracing 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2026, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acinterp.h" 48 49 50 #define _COMPONENT ACPI_EXECUTER 51 ACPI_MODULE_NAME ("extrace") 52 53 54 static ACPI_OPERAND_OBJECT *AcpiGbl_TraceMethodObject = NULL; 55 56 /* Local prototypes */ 57 58 #ifdef ACPI_DEBUG_OUTPUT 59 static const char * 60 AcpiExGetTraceEventName ( 61 ACPI_TRACE_EVENT_TYPE Type); 62 #endif 63 64 65 /******************************************************************************* 66 * 67 * FUNCTION: AcpiExInterpreterTraceEnabled 68 * 69 * PARAMETERS: Name - Whether method name should be matched, 70 * this should be checked before starting 71 * the tracer 72 * 73 * RETURN: TRUE if interpreter trace is enabled. 74 * 75 * DESCRIPTION: Check whether interpreter trace is enabled 76 * 77 ******************************************************************************/ 78 79 static BOOLEAN 80 AcpiExInterpreterTraceEnabled ( 81 char *Name) 82 { 83 84 /* Check if tracing is enabled */ 85 86 if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED)) 87 { 88 return (FALSE); 89 } 90 91 /* 92 * Check if tracing is filtered: 93 * 94 * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have 95 * been filled by the trace starter 96 * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be 97 * matched if it is specified 98 * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should 99 * not be cleared by the trace stopper during the first match 100 */ 101 if (AcpiGbl_TraceMethodObject) 102 { 103 return (TRUE); 104 } 105 106 if (Name && 107 (AcpiGbl_TraceMethodName && 108 strcmp (AcpiGbl_TraceMethodName, Name))) 109 { 110 return (FALSE); 111 } 112 113 if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) && 114 !AcpiGbl_TraceMethodName) 115 { 116 return (FALSE); 117 } 118 119 return (TRUE); 120 } 121 122 123 /******************************************************************************* 124 * 125 * FUNCTION: AcpiExGetTraceEventName 126 * 127 * PARAMETERS: Type - Trace event type 128 * 129 * RETURN: Trace event name. 130 * 131 * DESCRIPTION: Used to obtain the full trace event name. 132 * 133 ******************************************************************************/ 134 135 #ifdef ACPI_DEBUG_OUTPUT 136 137 static const char * 138 AcpiExGetTraceEventName ( 139 ACPI_TRACE_EVENT_TYPE Type) 140 { 141 142 switch (Type) 143 { 144 case ACPI_TRACE_AML_METHOD: 145 146 return "Method"; 147 148 case ACPI_TRACE_AML_OPCODE: 149 150 return "Opcode"; 151 152 case ACPI_TRACE_AML_REGION: 153 154 return "Region"; 155 156 default: 157 158 return ""; 159 } 160 } 161 162 #endif 163 164 /******************************************************************************* 165 * 166 * FUNCTION: AcpiExTraceArgs 167 * 168 * PARAMETERS: Params - AML method arguments 169 * Count - numer of method arguments 170 * 171 * RETURN: None 172 * 173 * DESCRIPTION: Trace any arguments 174 * 175 ******************************************************************************/ 176 177 void 178 AcpiExTraceArgs(ACPI_OPERAND_OBJECT **Params, UINT32 Count) 179 { 180 UINT32 i; 181 182 ACPI_FUNCTION_NAME(ExTraceArgs); 183 184 for (i = 0; i < Count; i++) 185 { 186 ACPI_OPERAND_OBJECT *obj_desc = Params[i]; 187 188 if (!i) 189 { 190 ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, " ")); 191 } 192 193 switch (obj_desc->Common.Type) 194 { 195 case ACPI_TYPE_INTEGER: 196 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "%" PRIx64 "", obj_desc->Integer.Value)); 197 break; 198 199 case ACPI_TYPE_STRING: 200 if (!obj_desc->String.Length) 201 { 202 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "NULL")); 203 break; 204 } 205 if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_TRACE_POINT, _COMPONENT)) 206 { 207 AcpiUtPrintString(obj_desc->String.Pointer, ACPI_UINT8_MAX); 208 } 209 break; 210 211 default: 212 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "Unknown")); 213 break; 214 } 215 216 if ((i + 1) == Count) 217 { 218 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "\n")); 219 } 220 else 221 { 222 ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, ", ")); 223 } 224 } 225 } 226 227 /******************************************************************************* 228 * 229 * FUNCTION: AcpiExTracePoint 230 * 231 * PARAMETERS: Type - Trace event type 232 * Begin - TRUE if before execution 233 * Aml - Executed AML address 234 * Pathname - Object path 235 * 236 * RETURN: None 237 * 238 * DESCRIPTION: Internal interpreter execution trace. 239 * 240 ******************************************************************************/ 241 242 void 243 AcpiExTracePoint ( 244 ACPI_TRACE_EVENT_TYPE Type, 245 BOOLEAN Begin, 246 UINT8 *Aml, 247 char *Pathname) 248 { 249 250 ACPI_FUNCTION_NAME (ExTracePoint); 251 252 253 if (Pathname) 254 { 255 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 256 "%s %s [%s] execution.\n", 257 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 258 Pathname)); 259 } 260 else 261 { 262 ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, 263 "%s %s [0x%p] execution.\n", 264 AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", 265 Aml)); 266 } 267 } 268 269 270 /******************************************************************************* 271 * 272 * FUNCTION: AcpiExStartTraceMethod 273 * 274 * PARAMETERS: MethodNode - Node of the method 275 * ObjDesc - The method object 276 * WalkState - current state, NULL if not yet executing 277 * a method. 278 * 279 * RETURN: None 280 * 281 * DESCRIPTION: Start control method execution trace 282 * 283 ******************************************************************************/ 284 285 void 286 AcpiExStartTraceMethod ( 287 ACPI_NAMESPACE_NODE *MethodNode, 288 ACPI_OPERAND_OBJECT *ObjDesc, 289 ACPI_WALK_STATE *WalkState) 290 { 291 char *Pathname = NULL; 292 BOOLEAN Enabled = FALSE; 293 294 295 ACPI_FUNCTION_NAME (ExStartTraceMethod); 296 297 298 if (MethodNode) 299 { 300 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 301 } 302 303 Enabled = AcpiExInterpreterTraceEnabled (Pathname); 304 if (Enabled && !AcpiGbl_TraceMethodObject) 305 { 306 AcpiGbl_TraceMethodObject = ObjDesc; 307 AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; 308 AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; 309 AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL; 310 AcpiDbgLayer = ACPI_TRACE_LAYER_ALL; 311 312 if (AcpiGbl_TraceDbgLevel) 313 { 314 AcpiDbgLevel = AcpiGbl_TraceDbgLevel; 315 } 316 317 if (AcpiGbl_TraceDbgLayer) 318 { 319 AcpiDbgLayer = AcpiGbl_TraceDbgLayer; 320 } 321 } 322 323 if (Enabled) 324 { 325 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE, 326 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 327 } 328 329 if (Pathname) 330 { 331 ACPI_FREE (Pathname); 332 } 333 } 334 335 336 /******************************************************************************* 337 * 338 * FUNCTION: AcpiExStopTraceMethod 339 * 340 * PARAMETERS: MethodNode - Node of the method 341 * ObjDesc - The method object 342 * WalkState - current state, NULL if not yet executing 343 * a method. 344 * 345 * RETURN: None 346 * 347 * DESCRIPTION: Stop control method execution trace 348 * 349 ******************************************************************************/ 350 351 void 352 AcpiExStopTraceMethod ( 353 ACPI_NAMESPACE_NODE *MethodNode, 354 ACPI_OPERAND_OBJECT *ObjDesc, 355 ACPI_WALK_STATE *WalkState) 356 { 357 char *Pathname = NULL; 358 BOOLEAN Enabled; 359 360 361 ACPI_FUNCTION_NAME (ExStopTraceMethod); 362 363 364 if (MethodNode) 365 { 366 Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 367 } 368 369 Enabled = AcpiExInterpreterTraceEnabled (NULL); 370 371 if (Enabled) 372 { 373 ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, 374 ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); 375 } 376 377 /* Check whether the tracer should be stopped */ 378 379 if (AcpiGbl_TraceMethodObject == ObjDesc) 380 { 381 /* Disable further tracing if type is one-shot */ 382 383 if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) 384 { 385 AcpiGbl_TraceMethodName = NULL; 386 } 387 388 AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; 389 AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; 390 AcpiGbl_TraceMethodObject = NULL; 391 } 392 393 if (Pathname) 394 { 395 ACPI_FREE (Pathname); 396 } 397 } 398 399 400 /******************************************************************************* 401 * 402 * FUNCTION: AcpiExStartTraceOpcode 403 * 404 * PARAMETERS: Op - The parser opcode object 405 * WalkState - current state, NULL if not yet executing 406 * a method. 407 * 408 * RETURN: None 409 * 410 * DESCRIPTION: Start opcode execution trace 411 * 412 ******************************************************************************/ 413 414 void 415 AcpiExStartTraceOpcode ( 416 ACPI_PARSE_OBJECT *Op, 417 ACPI_WALK_STATE *WalkState) 418 { 419 420 ACPI_FUNCTION_NAME (ExStartTraceOpcode); 421 422 423 if (AcpiExInterpreterTraceEnabled (NULL) && 424 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 425 { 426 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE, 427 Op->Common.Aml, Op->Common.AmlOpName); 428 } 429 } 430 431 432 /******************************************************************************* 433 * 434 * FUNCTION: AcpiExStopTraceOpcode 435 * 436 * PARAMETERS: Op - The parser opcode object 437 * WalkState - current state, NULL if not yet executing 438 * a method. 439 * 440 * RETURN: None 441 * 442 * DESCRIPTION: Stop opcode execution trace 443 * 444 ******************************************************************************/ 445 446 void 447 AcpiExStopTraceOpcode ( 448 ACPI_PARSE_OBJECT *Op, 449 ACPI_WALK_STATE *WalkState) 450 { 451 452 ACPI_FUNCTION_NAME (ExStopTraceOpcode); 453 454 455 if (AcpiExInterpreterTraceEnabled (NULL) && 456 (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) 457 { 458 ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE, 459 Op->Common.Aml, Op->Common.AmlOpName); 460 } 461 } 462