dbxface.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: dbxface - AML Debugger external interfaces
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #include "amlcode.h"
  10. #include "acdebug.h"
  11. #include "acinterp.h"
  12. #include "acparser.h"
  13. #define _COMPONENT ACPI_CA_DEBUGGER
  14. ACPI_MODULE_NAME("dbxface")
  15. /* Local prototypes */
  16. static acpi_status
  17. acpi_db_start_command(struct acpi_walk_state *walk_state,
  18. union acpi_parse_object *op);
  19. #ifdef ACPI_OBSOLETE_FUNCTIONS
  20. void acpi_db_method_end(struct acpi_walk_state *walk_state);
  21. #endif
  22. #ifdef ACPI_DISASSEMBLER
  23. static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
  24. *walk_state,
  25. union acpi_parse_object
  26. *op);
  27. #endif
  28. /*******************************************************************************
  29. *
  30. * FUNCTION: acpi_db_start_command
  31. *
  32. * PARAMETERS: walk_state - Current walk
  33. * op - Current executing Op, from AML interpreter
  34. *
  35. * RETURN: Status
  36. *
  37. * DESCRIPTION: Enter debugger command loop
  38. *
  39. ******************************************************************************/
  40. static acpi_status
  41. acpi_db_start_command(struct acpi_walk_state *walk_state,
  42. union acpi_parse_object *op)
  43. {
  44. acpi_status status;
  45. /* TBD: [Investigate] are there namespace locking issues here? */
  46. /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
  47. /* Go into the command loop and await next user command */
  48. acpi_gbl_method_executing = TRUE;
  49. status = AE_CTRL_TRUE;
  50. while (status == AE_CTRL_TRUE) {
  51. /* Notify the completion of the command */
  52. status = acpi_os_notify_command_complete();
  53. if (ACPI_FAILURE(status)) {
  54. goto error_exit;
  55. }
  56. /* Wait the readiness of the command */
  57. status = acpi_os_wait_command_ready();
  58. if (ACPI_FAILURE(status)) {
  59. goto error_exit;
  60. }
  61. status =
  62. acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
  63. op);
  64. }
  65. /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
  66. error_exit:
  67. if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
  68. ACPI_EXCEPTION((AE_INFO, status,
  69. "While parsing/handling command line"));
  70. }
  71. return (status);
  72. }
  73. /*******************************************************************************
  74. *
  75. * FUNCTION: acpi_db_signal_break_point
  76. *
  77. * PARAMETERS: walk_state - Current walk
  78. *
  79. * RETURN: Status
  80. *
  81. * DESCRIPTION: Called for AML_BREAKPOINT_OP
  82. *
  83. ******************************************************************************/
  84. void acpi_db_signal_break_point(struct acpi_walk_state *walk_state)
  85. {
  86. #ifndef ACPI_APPLICATION
  87. if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
  88. return;
  89. }
  90. #endif
  91. /*
  92. * Set the single-step flag. This will cause the debugger (if present)
  93. * to break to the console within the AML debugger at the start of the
  94. * next AML instruction.
  95. */
  96. acpi_gbl_cm_single_step = TRUE;
  97. acpi_os_printf("**break** Executed AML BreakPoint opcode\n");
  98. }
  99. #ifdef ACPI_DISASSEMBLER
  100. /*******************************************************************************
  101. *
  102. * FUNCTION: acpi_db_get_display_op
  103. *
  104. * PARAMETERS: walk_state - Current walk
  105. * op - Current executing op (from aml interpreter)
  106. *
  107. * RETURN: Opcode to display
  108. *
  109. * DESCRIPTION: Find the opcode to display during single stepping
  110. *
  111. ******************************************************************************/
  112. static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
  113. *walk_state,
  114. union acpi_parse_object
  115. *op)
  116. {
  117. union acpi_parse_object *display_op;
  118. union acpi_parse_object *parent_op;
  119. display_op = op;
  120. parent_op = op->common.parent;
  121. if (parent_op) {
  122. if ((walk_state->control_state) &&
  123. (walk_state->control_state->common.state ==
  124. ACPI_CONTROL_PREDICATE_EXECUTING)) {
  125. /*
  126. * We are executing the predicate of an IF or WHILE statement
  127. * Search upwards for the containing IF or WHILE so that the
  128. * entire predicate can be displayed.
  129. */
  130. while (parent_op) {
  131. if ((parent_op->common.aml_opcode == AML_IF_OP)
  132. || (parent_op->common.aml_opcode ==
  133. AML_WHILE_OP)) {
  134. display_op = parent_op;
  135. break;
  136. }
  137. parent_op = parent_op->common.parent;
  138. }
  139. } else {
  140. while (parent_op) {
  141. if ((parent_op->common.aml_opcode == AML_IF_OP)
  142. || (parent_op->common.aml_opcode ==
  143. AML_ELSE_OP)
  144. || (parent_op->common.aml_opcode ==
  145. AML_SCOPE_OP)
  146. || (parent_op->common.aml_opcode ==
  147. AML_METHOD_OP)
  148. || (parent_op->common.aml_opcode ==
  149. AML_WHILE_OP)) {
  150. break;
  151. }
  152. display_op = parent_op;
  153. parent_op = parent_op->common.parent;
  154. }
  155. }
  156. }
  157. return display_op;
  158. }
  159. #endif
  160. /*******************************************************************************
  161. *
  162. * FUNCTION: acpi_db_single_step
  163. *
  164. * PARAMETERS: walk_state - Current walk
  165. * op - Current executing op (from aml interpreter)
  166. * opcode_class - Class of the current AML Opcode
  167. *
  168. * RETURN: Status
  169. *
  170. * DESCRIPTION: Called just before execution of an AML opcode.
  171. *
  172. ******************************************************************************/
  173. acpi_status
  174. acpi_db_single_step(struct acpi_walk_state *walk_state,
  175. union acpi_parse_object *op, u32 opcode_class)
  176. {
  177. union acpi_parse_object *next;
  178. acpi_status status = AE_OK;
  179. u32 original_debug_level;
  180. u32 aml_offset;
  181. ACPI_FUNCTION_ENTRY();
  182. #ifndef ACPI_APPLICATION
  183. if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
  184. return (AE_OK);
  185. }
  186. #endif
  187. /* Check the abort flag */
  188. if (acpi_gbl_abort_method) {
  189. acpi_gbl_abort_method = FALSE;
  190. return (AE_ABORT_METHOD);
  191. }
  192. aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
  193. walk_state->parser_state.aml_start);
  194. /* Check for single-step breakpoint */
  195. if (walk_state->method_breakpoint &&
  196. (walk_state->method_breakpoint <= aml_offset)) {
  197. /* Check if the breakpoint has been reached or passed */
  198. /* Hit the breakpoint, resume single step, reset breakpoint */
  199. acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
  200. acpi_gbl_cm_single_step = TRUE;
  201. acpi_gbl_step_to_next_call = FALSE;
  202. walk_state->method_breakpoint = 0;
  203. }
  204. /* Check for user breakpoint (Must be on exact Aml offset) */
  205. else if (walk_state->user_breakpoint &&
  206. (walk_state->user_breakpoint == aml_offset)) {
  207. acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
  208. aml_offset);
  209. acpi_gbl_cm_single_step = TRUE;
  210. acpi_gbl_step_to_next_call = FALSE;
  211. walk_state->method_breakpoint = 0;
  212. }
  213. /*
  214. * Check if this is an opcode that we are interested in --
  215. * namely, opcodes that have arguments
  216. */
  217. if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
  218. return (AE_OK);
  219. }
  220. switch (opcode_class) {
  221. case AML_CLASS_UNKNOWN:
  222. case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */
  223. return (AE_OK);
  224. default:
  225. /* All other opcodes -- continue */
  226. break;
  227. }
  228. /*
  229. * Under certain debug conditions, display this opcode and its operands
  230. */
  231. if ((acpi_gbl_db_output_to_file) ||
  232. (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
  233. if ((acpi_gbl_db_output_to_file) ||
  234. (acpi_dbg_level & ACPI_LV_PARSE)) {
  235. acpi_os_printf
  236. ("\nAML Debug: Next AML Opcode to execute:\n");
  237. }
  238. /*
  239. * Display this op (and only this op - zero out the NEXT field
  240. * temporarily, and disable parser trace output for the duration of
  241. * the display because we don't want the extraneous debug output)
  242. */
  243. original_debug_level = acpi_dbg_level;
  244. acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
  245. next = op->common.next;
  246. op->common.next = NULL;
  247. /* Now we can disassemble and display it */
  248. #ifdef ACPI_DISASSEMBLER
  249. acpi_dm_disassemble(walk_state,
  250. acpi_db_get_display_op(walk_state, op),
  251. ACPI_UINT32_MAX);
  252. #else
  253. /*
  254. * The AML Disassembler is not configured - at least we can
  255. * display the opcode value and name
  256. */
  257. acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode,
  258. acpi_ps_get_opcode_name(op->common.aml_opcode));
  259. #endif
  260. if ((op->common.aml_opcode == AML_IF_OP) ||
  261. (op->common.aml_opcode == AML_WHILE_OP)) {
  262. if (walk_state->control_state->common.value) {
  263. acpi_os_printf
  264. ("Predicate = [True], IF block was executed\n");
  265. } else {
  266. acpi_os_printf
  267. ("Predicate = [False], Skipping IF block\n");
  268. }
  269. } else if (op->common.aml_opcode == AML_ELSE_OP) {
  270. acpi_os_printf
  271. ("Predicate = [False], ELSE block was executed\n");
  272. }
  273. /* Restore everything */
  274. op->common.next = next;
  275. acpi_os_printf("\n");
  276. if ((acpi_gbl_db_output_to_file) ||
  277. (acpi_dbg_level & ACPI_LV_PARSE)) {
  278. acpi_os_printf("\n");
  279. }
  280. acpi_dbg_level = original_debug_level;
  281. }
  282. /* If we are not single stepping, just continue executing the method */
  283. if (!acpi_gbl_cm_single_step) {
  284. return (AE_OK);
  285. }
  286. /*
  287. * If we are executing a step-to-call command,
  288. * Check if this is a method call.
  289. */
  290. if (acpi_gbl_step_to_next_call) {
  291. if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
  292. /* Not a method call, just keep executing */
  293. return (AE_OK);
  294. }
  295. /* Found a method call, stop executing */
  296. acpi_gbl_step_to_next_call = FALSE;
  297. }
  298. /*
  299. * If the next opcode is a method call, we will "step over" it
  300. * by default.
  301. */
  302. if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
  303. /* Force no more single stepping while executing called method */
  304. acpi_gbl_cm_single_step = FALSE;
  305. /*
  306. * Set the breakpoint on/before the call, it will stop execution
  307. * as soon as we return
  308. */
  309. walk_state->method_breakpoint = 1; /* Must be non-zero! */
  310. }
  311. acpi_ex_exit_interpreter();
  312. status = acpi_db_start_command(walk_state, op);
  313. acpi_ex_enter_interpreter();
  314. /* User commands complete, continue execution of the interrupted method */
  315. return (status);
  316. }
  317. /*******************************************************************************
  318. *
  319. * FUNCTION: acpi_initialize_debugger
  320. *
  321. * PARAMETERS: None
  322. *
  323. * RETURN: Status
  324. *
  325. * DESCRIPTION: Init and start debugger
  326. *
  327. ******************************************************************************/
  328. acpi_status acpi_initialize_debugger(void)
  329. {
  330. acpi_status status;
  331. ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
  332. /* Init globals */
  333. acpi_gbl_db_buffer = NULL;
  334. acpi_gbl_db_filename = NULL;
  335. acpi_gbl_db_output_to_file = FALSE;
  336. acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
  337. acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
  338. acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
  339. acpi_gbl_db_opt_no_ini_methods = FALSE;
  340. acpi_gbl_db_opt_no_region_support = FALSE;
  341. acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
  342. if (!acpi_gbl_db_buffer) {
  343. return_ACPI_STATUS(AE_NO_MEMORY);
  344. }
  345. memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
  346. /* Initial scope is the root */
  347. acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
  348. acpi_gbl_db_scope_buf[1] = 0;
  349. acpi_gbl_db_scope_node = acpi_gbl_root_node;
  350. /* Initialize user commands loop */
  351. acpi_gbl_db_terminate_loop = FALSE;
  352. /*
  353. * If configured for multi-thread support, the debug executor runs in
  354. * a separate thread so that the front end can be in another address
  355. * space, environment, or even another machine.
  356. */
  357. if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
  358. /* These were created with one unit, grab it */
  359. status = acpi_os_initialize_debugger();
  360. if (ACPI_FAILURE(status)) {
  361. acpi_os_printf("Could not get debugger mutex\n");
  362. return_ACPI_STATUS(status);
  363. }
  364. /* Create the debug execution thread to execute commands */
  365. acpi_gbl_db_threads_terminated = FALSE;
  366. status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
  367. acpi_db_execute_thread, NULL);
  368. if (ACPI_FAILURE(status)) {
  369. ACPI_EXCEPTION((AE_INFO, status,
  370. "Could not start debugger thread"));
  371. acpi_gbl_db_threads_terminated = TRUE;
  372. return_ACPI_STATUS(status);
  373. }
  374. } else {
  375. acpi_gbl_db_thread_id = acpi_os_get_thread_id();
  376. }
  377. return_ACPI_STATUS(AE_OK);
  378. }
  379. ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
  380. /*******************************************************************************
  381. *
  382. * FUNCTION: acpi_terminate_debugger
  383. *
  384. * PARAMETERS: None
  385. *
  386. * RETURN: None
  387. *
  388. * DESCRIPTION: Stop debugger
  389. *
  390. ******************************************************************************/
  391. void acpi_terminate_debugger(void)
  392. {
  393. /* Terminate the AML Debugger */
  394. acpi_gbl_db_terminate_loop = TRUE;
  395. if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
  396. /* Wait the AML Debugger threads */
  397. while (!acpi_gbl_db_threads_terminated) {
  398. acpi_os_sleep(100);
  399. }
  400. acpi_os_terminate_debugger();
  401. }
  402. if (acpi_gbl_db_buffer) {
  403. acpi_os_free(acpi_gbl_db_buffer);
  404. acpi_gbl_db_buffer = NULL;
  405. }
  406. /* Ensure that debug output is now disabled */
  407. acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
  408. }
  409. ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
  410. /*******************************************************************************
  411. *
  412. * FUNCTION: acpi_set_debugger_thread_id
  413. *
  414. * PARAMETERS: thread_id - Debugger thread ID
  415. *
  416. * RETURN: None
  417. *
  418. * DESCRIPTION: Set debugger thread ID
  419. *
  420. ******************************************************************************/
  421. void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
  422. {
  423. acpi_gbl_db_thread_id = thread_id;
  424. }
  425. ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)