]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_macro.c
xnu-1228.tar.gz
[apple/xnu.git] / osfmk / ddb / db_macro.c
1 /*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
57 */
58 #include <kern/thread.h>
59 #include <string.h> /* For strncmp(), strlcpy() */
60
61 #include <machine/db_machdep.h>
62 #include <ddb/db_command.h>
63 #include <ddb/db_expr.h>
64 #include <ddb/db_lex.h>
65 #include <ddb/db_macro.h>
66 #include <ddb/db_output.h> /* For db_printf() */
67 #include <ddb/db_sym.h>
68 #include <ddb/db_variables.h>
69
70 /*
71 * debugger macro support
72 */
73
74 #define DB_NUSER_MACRO 10 /* max user macros */
75
76 int db_macro_free = DB_NUSER_MACRO;
77 struct db_user_macro {
78 char m_name[TOK_STRING_SIZE];
79 char m_lbuf[DB_LEX_LINE_SIZE];
80 int m_size;
81 } db_user_macro[DB_NUSER_MACRO];
82
83 int db_macro_level = -1;
84 db_expr_t db_macro_args[DB_MACRO_LEVEL][DB_MACRO_NARGS];
85
86
87 /* Prototypes for functions local to this file.
88 */
89 static struct db_user_macro *db_lookup_macro(char *name);
90
91
92 static struct db_user_macro *
93 db_lookup_macro(char *name)
94 {
95 register struct db_user_macro *mp;
96
97 for (mp = db_user_macro; mp < &db_user_macro[DB_NUSER_MACRO]; mp++) {
98 if (mp->m_name[0] == 0)
99 continue;
100 if (strncmp(mp->m_name, name, TOK_STRING_SIZE) == 0)
101 return(mp);
102 }
103 return(0);
104 }
105
106 void
107 db_def_macro_cmd(void)
108 {
109 register char *p;
110 register int c;
111 register struct db_user_macro *mp, *ep;
112
113 if (db_read_token() != tIDENT) {
114 db_printf("Bad macro name \"%s\"\n", db_tok_string);
115 db_error(0);
116 /* NOTREACHED */
117 }
118 if ((mp = db_lookup_macro(db_tok_string)) == 0) {
119 if (db_macro_free <= 0)
120 db_error("Too many macros\n");
121 /* NOTREACHED */
122 ep = &db_user_macro[DB_NUSER_MACRO];
123 for (mp = db_user_macro; mp < ep && mp->m_name[0]; mp++);
124 if (mp >= ep)
125 db_error("ddb: internal error(macro)\n");
126 /* NOTREACHED */
127 db_macro_free--;
128 strlcpy(mp->m_name, db_tok_string, TOK_STRING_SIZE);
129 }
130 for (c = db_read_char(); c == ' ' || c == '\t'; c = db_read_char());
131 for (p = mp->m_lbuf; c > 0; c = db_read_char())
132 *p++ = c;
133 *p = 0;
134 mp->m_size = p - mp->m_lbuf;
135 }
136
137 void
138 db_del_macro_cmd(void)
139 {
140 struct db_user_macro *mp = NULL;
141
142 if (db_read_token() != tIDENT
143 || (mp = db_lookup_macro(db_tok_string)) == 0) {
144 db_printf("No such macro \"%s\"\n", db_tok_string);
145 db_error(0);
146 /* NOTREACHED */
147 }
148 mp->m_name[0] = 0;
149 db_macro_free++;
150 }
151
152 void
153 db_show_macro(void)
154 {
155 register struct db_user_macro *mp;
156 int t;
157 char *name = 0;
158
159 if ((t = db_read_token()) == tIDENT)
160 name = db_tok_string;
161 else
162 db_unread_token(t);
163 for (mp = db_user_macro; mp < &db_user_macro[DB_NUSER_MACRO]; mp++) {
164 if (mp->m_name[0] == 0)
165 continue;
166 if (name && strncmp(mp->m_name, name, TOK_STRING_SIZE))
167 continue;
168 db_printf("%s: %s", mp->m_name, mp->m_lbuf);
169 }
170 }
171
172 int
173 db_exec_macro(char *name)
174 {
175 register struct db_user_macro *mp;
176 register int n;
177
178 if ((mp = db_lookup_macro(name)) == 0)
179 return(-1);
180 if (db_macro_level+1 >= DB_MACRO_LEVEL) {
181 db_macro_level = -1;
182 db_error("Too many macro nest\n");
183 /* NOTREACHED */
184 }
185 for (n = 0;
186 n < DB_MACRO_NARGS &&
187 db_expression(&db_macro_args[db_macro_level+1][n]);
188 n++);
189 while (n < DB_MACRO_NARGS)
190 db_macro_args[db_macro_level+1][n++] = 0;
191 db_macro_level++;
192 db_exec_cmd_nest(mp->m_lbuf, mp->m_size);
193 db_macro_level--;
194 return(0);
195 }
196
197 int
198 db_arg_variable(__unused struct db_variable *vp, db_expr_t *valuep, int flag,
199 db_var_aux_param_t ap)
200 {
201 db_expr_t value;
202 char *name;
203 db_addr_t offset;
204
205 if (flag == DB_VAR_SHOW) {
206 value = db_macro_args[ap->hidden_level][ap->suffix[0]-1];
207 db_printf("%#lln", (unsigned long long)value);
208 db_find_xtrn_task_sym_and_offset(value, &name, &offset, TASK_NULL);
209 if (name != (char *)0 && offset <= db_maxoff && offset != value) {
210 db_printf("\t%s", name);
211 if (offset != 0)
212 db_printf("+%#llr", (unsigned long long)offset);
213 }
214 return(0);
215 }
216
217 if (ap->level != 1 || ap->suffix[0] < 1 ||
218 ap->suffix[0] > DB_MACRO_NARGS) {
219 db_error("Bad $arg variable\n");
220 /* NOTREACHED */
221 }
222 if (flag == DB_VAR_GET)
223 *valuep = db_macro_args[db_macro_level][ap->suffix[0]-1];
224 else
225 db_macro_args[db_macro_level][ap->suffix[0]-1] = *valuep;
226 return(0);
227 }