xref: /netbsd-src/usr.sbin/acpitools/amldb/debug.c (revision 2e0bf311b34bf9507e08ee74157213840e9994d3)
1 /*	$NetBSD: debug.c,v 1.2 2021/08/17 22:00:33 andvar Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999 Takanori Watanabe
5  * Copyright (c) 1999, 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	Id: debug.c,v 1.19 2000/08/16 18:15:00 iwasaki Exp
30  *	$FreeBSD: src/usr.sbin/acpi/amldb/debug.c,v 1.3 2000/11/09 06:24:40 iwasaki Exp $
31  */
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: debug.c,v 1.2 2021/08/17 22:00:33 andvar Exp $");
34 
35 #include <sys/param.h>
36 
37 #include <acpi_common.h>
38 #include <aml/aml_name.h>
39 #include <aml/aml_amlmem.h>
40 #include <aml/aml_status.h>
41 #include <aml/aml_env.h>
42 #include <aml/aml_obj.h>
43 #include <aml/aml_evalobj.h>
44 #include <aml/aml_parse.h>
45 #include <aml/aml_region.h>
46 #include <aml/aml_store.h>
47 #include <aml/aml_common.h>
48 
49 #include <assert.h>
50 #include <err.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #include "debug.h"
57 
58 static int
print_named_object(struct aml_name * name,va_list ap)59 print_named_object(struct aml_name *name, va_list ap)
60 {
61 
62 	aml_print_curname(name);
63 	printf("\n");
64 
65 	return (0);	/* always return success to continue the search */
66 }
67 
68 void
aml_dbgr(struct aml_environ * env1,struct aml_environ * env2)69 aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
70 {
71 #define CMDBUFLEN	512
72 #define ARGBUFLEN	512
73 	static	char lastcommand[CMDBUFLEN];
74 	char	commandline[CMDBUFLEN];
75 	char	argbuf[7][ARGBUFLEN];
76 	char	*ptr, *method;
77 	char	*np, *ep;
78 	int 	i;
79 	int	argnum;
80 	struct	aml_name *name;
81 	union	aml_object argv[7], *retval;
82 
83 	while (1) {
84 		fputs("AML>", stderr);
85 		fgets(commandline, 512, stdin);
86 		commandline[512 - 1] = '\n';	/* safety */
87 		if (feof(stdin)) {
88 			commandline[0] = 'q';
89 		}
90 		if (commandline[0] == '\n') {
91 			memcpy(commandline, lastcommand, sizeof commandline);
92 		}
93 		memcpy(lastcommand, commandline, sizeof commandline);
94 		switch (commandline[0]) {
95 		case 's':
96 			if (env2 != NULL) {
97 				env2->stat = aml_stat_step;
98 			}
99 			/* FALLTHROUGH */
100 		case 'n':
101 			env1->stat = aml_stat_step;
102 			return;
103 		case 'c':
104 			env1->stat = aml_stat_none;
105 			return;
106 		case 'q':
107 			env1->stat = aml_stat_panic;
108 			return;
109 		case 't':
110 			/* NULL terminate */
111 			ptr = &commandline[1];
112 			while (ptr[0] != '\n')
113 				ptr++;
114 			ptr[0] = '\0';
115 
116 			/* move pointer to object name */
117 			ptr = &commandline[1];
118 			while (ptr[0] == ' ')
119 				ptr++;
120 
121 			/* show current tree if no argument */
122 			if (ptr[0] == '\0') {
123 				aml_showtree(env1->curname, 0);
124 				goto show_variables;
125 			}
126 			/* start from root? */
127 			if (ptr[0] == '\\') {
128 				if (ptr[1] == '\0') {
129 					aml_showtree(aml_get_rootname(), 0);
130 					goto show_variables;
131 				}
132 				if ((name = aml_find_from_namespace(aml_get_rootname(), ptr))) {
133 					aml_showtree(name, 0);
134 					goto show_variables;
135 				}
136 			}
137 			if ((name = aml_find_from_namespace(env1->curname, ptr))) {
138 				aml_showtree(name, 0);
139 			}
140 show_variables:
141 			for (i = 0; i < 7; i++) {
142 				struct aml_name *tmp =
143 				aml_local_stack_getArgX(NULL, i);
144 
145 				if (tmp == NULL || tmp->property == NULL) {
146 					break;
147 				}
148 				printf("  Arg%d    ", i);
149 				aml_showobject(tmp->property);
150 			}
151 			for (i = 0; i < 8; i++) {
152 				struct aml_name *tmp =
153 				aml_local_stack_getLocalX(i);
154 
155 				if (tmp == NULL || tmp->property == NULL) {
156 					continue;
157 				}
158 				printf("  Local%d  ", i);
159 				aml_showobject(tmp->property);
160 			}
161 			break;
162 		case 'i':
163 			aml_debug_prompt_reginput =
164 			    (aml_debug_prompt_reginput == 0) ? 1 : 0;
165 			if (aml_debug_prompt_reginput)
166 				fputs("REGION INPUT ON\n", stderr);
167 			else
168 				fputs("REGION INPUT OFF\n", stderr);
169 			break;
170 		case 'o':
171 			aml_debug_prompt_regoutput =
172 			    (aml_debug_prompt_regoutput == 0) ? 1 : 0;
173 			if (aml_debug_prompt_regoutput)
174 				fputs("REGION OUTPUT ON\n", stderr);
175 			else
176 				fputs("REGION OUTPUT OFF\n", stderr);
177 			break;
178 		case 'm':
179 			memman_statistics(aml_memman);
180 			break;
181 		case 'r':
182 			/* NULL terminate */
183 			ptr = &commandline[1];
184 			while (ptr[0] != '\n')
185 				ptr++;
186 			ptr[0] = '\0';
187 
188 			/* move pointer to method name */
189 			ptr = &commandline[1];
190 			while (ptr[0] == ' ')
191 				ptr++;
192 
193 			if (ptr[0] == '\0') {
194 				break;
195 			}
196 			name = aml_find_from_namespace(aml_get_rootname(), ptr);
197 			if (name == NULL) {
198 				printf("%s:%d:aml_dbgr: not found name %s\n",
199 				    __FILE__, __LINE__, ptr);
200 				break;
201 			}
202 			if (name->property == NULL ||
203 			    name->property->type != aml_t_method) {
204 				printf("%s:%d:aml_dbgr: not method %s\n",
205 				    __FILE__, __LINE__, ptr);
206 				break;
207 			}
208 			aml_showobject(name->property);
209 			method = ptr;
210 
211 			argnum = name->property->meth.argnum & 0x07;
212 			if (argnum) {
213 				fputs("  Enter argument values "
214 				      "(ex. number 1 / string foo). "
215 				      "'q' to quit.\n", stderr);
216 			}
217 			/* get and parse argument values */
218 			for (i = 0; i < argnum; i++) {
219 retry:
220 				fprintf(stderr, "  Arg%d ? ", i);
221 				if (read(0, argbuf[i], ARGBUFLEN) == 0) {
222 					fputs("\n", stderr);
223 					goto retry;
224 				}
225 				argbuf[i][ARGBUFLEN - 1] = '\n';
226 				if (argbuf[i][0] == 'q') {
227 					goto finish_execution;
228 				}
229 				if (argbuf[i][0] == '\n') {
230 					goto retry;
231 				}
232 				/* move pointer to the value */
233 				ptr = &argbuf[i][0];
234 				while (ptr[0] != ' ' && ptr[0] != '\n') {
235 					ptr++;
236 				}
237 				while (ptr[0] == ' ') {
238 					ptr++;
239 				}
240 				if (ptr[0] == '\n') {
241 					goto retry;
242 				}
243 				switch (argbuf[i][0]) {
244 				case 'n':
245 					argv[i].type = aml_t_num;
246 					np = ptr;
247 					if (ptr[0] == '0' &&
248 					    ptr[1] == 'x') {
249 						argv[i].num.number = strtoq(ptr, &ep, 16);
250 					} else {
251 						argv[i].num.number = strtoq(ptr, &ep, 10);
252 					}
253 					if (np == ep) {
254 						fputs("Wrong value for number.\n",
255 						    stderr);
256 						goto retry;
257 					}
258 					break;
259 				case 's':
260 					argv[i].type = aml_t_string;
261 					argv[i].str.needfree = 0;
262 					argv[i].str.string = (u_int8_t *)ptr;
263 					/* NULL ternimate */
264 					while (ptr[0] != '\n') {
265 						ptr++;
266 					}
267 					ptr[0] = '\0';
268 					break;
269 				default:
270 					fputs("Invalid data type "
271 					      "(supports number or string only)\n",
272 					    stderr);
273 					goto retry;
274 				}
275 			}
276 			bzero(lastcommand, sizeof lastcommand);
277 			fprintf(stderr, "==== Running %s. ====\n", method);
278 			aml_local_stack_push(aml_local_stack_create());
279 			retval = aml_invoke_method_by_name(method, argnum, argv);
280 			aml_showobject(retval);
281 			aml_local_stack_delete(aml_local_stack_pop());
282 			fprintf(stderr, "==== %s finished. ====\n", method);
283 finish_execution:
284 			break;
285 		case 'f':
286 			/* NULL terminate */
287 			ptr = &commandline[1];
288 			while (ptr[0] != '\n')
289 				ptr++;
290 			ptr[0] = '\0';
291 
292 			/* move pointer to object name */
293 			ptr = &commandline[1];
294 			while (ptr[0] == ' ')
295 				ptr++;
296 
297 			aml_apply_foreach_found_objects(aml_get_rootname(),
298 			    ptr, print_named_object);
299 			break;
300 		case 'h':
301 			fputs("s	Single step\n"
302 			      "n	Step program\n"
303 			      "c	Continue program being debugged\n"
304 			      "q	Quit method execution\n"
305 			      "t	Show local name space tree and variables\n"
306 			      "i	Toggle region input prompt\n"
307 			      "o	Toggle region output prompt\n"
308 			      "m	Show memory management statistics\n"
309 			      "r	Run specified method\n"
310 			      "f	Find named objects from namespace.\n"
311 			      "h	Show this message\n", stderr);
312 			break;
313 		}
314 	}
315 }
316