1 | /* |
---|
2 | * @(#)monitor.c 1.6 - 95/04/24 |
---|
3 | * |
---|
4 | */ |
---|
5 | |
---|
6 | /* |
---|
7 | * mon-task.c |
---|
8 | * |
---|
9 | * Description: |
---|
10 | * RTEMS monitor task |
---|
11 | * |
---|
12 | * |
---|
13 | * |
---|
14 | * TODO: |
---|
15 | * add pause command (monitor sleeps for 'n' ticks, then wakes up) |
---|
16 | * |
---|
17 | */ |
---|
18 | |
---|
19 | #include <rtems.h> |
---|
20 | /* #include <bsp.h> */ |
---|
21 | |
---|
22 | #include "symbols.h" |
---|
23 | #include "monitor.h" |
---|
24 | |
---|
25 | #include <stdio.h> |
---|
26 | #include <string.h> |
---|
27 | #include <stdlib.h> |
---|
28 | #include <unistd.h> |
---|
29 | |
---|
30 | #define STREQ(a,b) (strcmp(a,b) == 0) |
---|
31 | |
---|
32 | /* set by trap handler */ |
---|
33 | extern rtems_tcb *debugger_interrupted_task; |
---|
34 | extern rtems_context *debugger_interrupted_task_context; |
---|
35 | extern rtems_unsigned32 debugger_trap; |
---|
36 | |
---|
37 | /* our task id needs to be public so any debugger can resume us */ |
---|
38 | rtems_unsigned32 rtems_monitor_task_id; |
---|
39 | |
---|
40 | |
---|
41 | rtems_symbol_table_t *rtems_monitor_symbols; |
---|
42 | |
---|
43 | |
---|
44 | #ifndef MONITOR_PROMPT |
---|
45 | #define MONITOR_PROMPT "rtems> " |
---|
46 | #endif |
---|
47 | |
---|
48 | #define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0 |
---|
49 | |
---|
50 | /* |
---|
51 | * Function: rtems_monitor_init |
---|
52 | * |
---|
53 | * Description: |
---|
54 | * Create the RTEMS monitor task |
---|
55 | * |
---|
56 | * Parameters: |
---|
57 | * 'monitor_suspend' arg is passed as initial arg to monitor task |
---|
58 | * If TRUE, monitor will suspend itself as it starts up. Otherwise |
---|
59 | * it will begin its command loop. |
---|
60 | * |
---|
61 | * Returns: |
---|
62 | * |
---|
63 | * |
---|
64 | * Side Effects: |
---|
65 | * |
---|
66 | * |
---|
67 | * Notes: |
---|
68 | * |
---|
69 | * |
---|
70 | * Deficiencies/ToDo: |
---|
71 | * |
---|
72 | * |
---|
73 | */ |
---|
74 | |
---|
75 | /* |
---|
76 | * make_argv(cp): token-count |
---|
77 | * Break up the command line in 'cp' into global argv[] and argc (return |
---|
78 | * value). |
---|
79 | */ |
---|
80 | |
---|
81 | int |
---|
82 | rtems_monitor_make_argv( |
---|
83 | char *cp, |
---|
84 | int *argc_p, |
---|
85 | char **argv) |
---|
86 | { |
---|
87 | int argc = 0; |
---|
88 | |
---|
89 | while ((cp = strtok(cp, " \t\n\r"))) |
---|
90 | { |
---|
91 | argv[argc++] = cp; |
---|
92 | cp = (char *) NULL; |
---|
93 | } |
---|
94 | argv[argc] = (char *) NULL; /* end of argv */ |
---|
95 | |
---|
96 | return *argc_p = argc; |
---|
97 | } |
---|
98 | |
---|
99 | void |
---|
100 | rtems_monitor_init(rtems_boolean monitor_suspend) |
---|
101 | { |
---|
102 | rtems_status_code status; |
---|
103 | |
---|
104 | status = rtems_task_create(rtems_build_name('R', 'M', 'O', 'N'), |
---|
105 | 1, 0/*stack*/, RTEMS_NO_PREEMPT | RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &rtems_monitor_task_id); |
---|
106 | if (status != RTEMS_SUCCESSFUL) |
---|
107 | { |
---|
108 | printf("could not create monitor task\n"); |
---|
109 | goto done; |
---|
110 | } |
---|
111 | |
---|
112 | rtems_monitor_symbols_loadup(); |
---|
113 | |
---|
114 | status = rtems_task_start(rtems_monitor_task_id, rtems_monitor_task, monitor_suspend); |
---|
115 | if (status != RTEMS_SUCCESSFUL) |
---|
116 | { |
---|
117 | printf("could not start monitor!\n"); |
---|
118 | goto done; |
---|
119 | } |
---|
120 | |
---|
121 | done: |
---|
122 | } |
---|
123 | |
---|
124 | rtems_status_code |
---|
125 | rtems_monitor_suspend(rtems_interval timeout) |
---|
126 | { |
---|
127 | rtems_event_set event_set; |
---|
128 | rtems_status_code status; |
---|
129 | |
---|
130 | status = rtems_event_receive(MONITOR_WAKEUP_EVENT, RTEMS_DEFAULT_OPTIONS, timeout, &event_set); |
---|
131 | return status; |
---|
132 | } |
---|
133 | |
---|
134 | void |
---|
135 | rtems_monitor_wakeup(void) |
---|
136 | { |
---|
137 | rtems_status_code status; |
---|
138 | |
---|
139 | status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT); |
---|
140 | } |
---|
141 | |
---|
142 | |
---|
143 | /* |
---|
144 | * Read and break up a monitor command |
---|
145 | * |
---|
146 | * We have to loop on the gets call, since it will return NULL under UNIX |
---|
147 | * RTEMS when we get a signal (eg: SIGALRM). |
---|
148 | */ |
---|
149 | |
---|
150 | int |
---|
151 | rtems_monitor_read_command(char *command, |
---|
152 | int *argc, |
---|
153 | char **argv) |
---|
154 | { |
---|
155 | printf("%s", MONITOR_PROMPT); fflush(stdout); |
---|
156 | while (gets(command) == (char *) 0) |
---|
157 | ; |
---|
158 | return rtems_monitor_make_argv(command, argc, argv); |
---|
159 | } |
---|
160 | |
---|
161 | void |
---|
162 | rtems_monitor_task(rtems_task_argument monitor_suspend) |
---|
163 | { |
---|
164 | rtems_tcb *debugee = 0; |
---|
165 | char command[513]; |
---|
166 | rtems_context *rp; |
---|
167 | rtems_context_fp *fp; |
---|
168 | char *cp; |
---|
169 | int argc; |
---|
170 | char *argv[64]; |
---|
171 | |
---|
172 | if ((rtems_boolean) monitor_suspend) |
---|
173 | (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT); |
---|
174 | |
---|
175 | for (;;) |
---|
176 | { |
---|
177 | extern rtems_tcb * _Thread_Executing; |
---|
178 | debugee = _Thread_Executing; |
---|
179 | rp = &debugee->Registers; |
---|
180 | fp = (rtems_context_fp *) debugee->fp_context; /* possibly 0 */ |
---|
181 | |
---|
182 | if (0 == rtems_monitor_read_command(command, &argc, argv)) |
---|
183 | continue; |
---|
184 | |
---|
185 | if (STREQ(argv[0], "quit")) |
---|
186 | rtems_monitor_suspend(RTEMS_NO_TIMEOUT); |
---|
187 | else if (STREQ(argv[0], "pause")) |
---|
188 | rtems_monitor_suspend(1); |
---|
189 | |
---|
190 | #ifdef CPU_INVOKE_DEBUGGER |
---|
191 | else if (STREQ(argv[0], "debug")) |
---|
192 | { |
---|
193 | CPU_INVOKE_DEBUGGER; |
---|
194 | } |
---|
195 | #endif |
---|
196 | else if (STREQ(argv[0], "symbol")) |
---|
197 | { |
---|
198 | char *symbol; |
---|
199 | char *value; |
---|
200 | |
---|
201 | if (argc != 3) |
---|
202 | { |
---|
203 | printf("usage: symbol symname symvalue\n"); |
---|
204 | continue; |
---|
205 | } |
---|
206 | |
---|
207 | symbol = argv[1]; |
---|
208 | value = argv[2]; |
---|
209 | if (symbol && value) |
---|
210 | { |
---|
211 | rtems_symbol_t *sp; |
---|
212 | sp = rtems_symbol_create(rtems_monitor_symbols, |
---|
213 | symbol, |
---|
214 | (rtems_unsigned32) strtoul(value, 0, 16)); |
---|
215 | if (sp) |
---|
216 | printf("symbol defined is at %p\n", sp); |
---|
217 | else |
---|
218 | printf("could not define symbol\n"); |
---|
219 | } |
---|
220 | else |
---|
221 | printf("parsing error\n"); |
---|
222 | } |
---|
223 | else |
---|
224 | { |
---|
225 | printf("Unrecognized command: '%s'\n", argv[0]); |
---|
226 | } |
---|
227 | } |
---|
228 | } |
---|
229 | |
---|
230 | /* |
---|
231 | * Function: rtems_monitor_symbols_loadup |
---|
232 | * |
---|
233 | * Description: |
---|
234 | * Create and load the monitor's symbol table. |
---|
235 | * We are reading the output format of 'gnm' which looks like this: |
---|
236 | * |
---|
237 | * 400a7068 ? _Rate_monotonic_Information |
---|
238 | * 400a708c ? _Thread_Dispatch_disable_level |
---|
239 | * 400a7090 ? _Configuration_Table |
---|
240 | * |
---|
241 | * |
---|
242 | * We ignore the type field. |
---|
243 | * |
---|
244 | * Parameters: |
---|
245 | * |
---|
246 | * |
---|
247 | * Returns: |
---|
248 | * |
---|
249 | * |
---|
250 | * Side Effects: |
---|
251 | * Creates and fills in 'rtems_monitor_symbols' table |
---|
252 | * |
---|
253 | * Notes: |
---|
254 | * |
---|
255 | * |
---|
256 | * Deficiencies/ToDo: |
---|
257 | * Someday this should know BFD |
---|
258 | * Maybe we could get objcopy to just copy the symbol areas |
---|
259 | * and copy that down. |
---|
260 | * |
---|
261 | */ |
---|
262 | |
---|
263 | void |
---|
264 | rtems_monitor_symbols_loadup(void) |
---|
265 | { |
---|
266 | FILE *fp; |
---|
267 | char buffer[128]; |
---|
268 | |
---|
269 | rtems_monitor_symbols = rtems_symbol_table_create(10); |
---|
270 | if (rtems_monitor_symbols == 0) |
---|
271 | return; |
---|
272 | |
---|
273 | fp = fdopen(8, "r"); |
---|
274 | if (fp == 0) |
---|
275 | return; |
---|
276 | |
---|
277 | while (fgets(buffer, sizeof(buffer) - 1, fp)) |
---|
278 | { |
---|
279 | char *symbol; |
---|
280 | char *value; |
---|
281 | char *ignored_type; |
---|
282 | |
---|
283 | value = strtok(buffer, " \t\n"); |
---|
284 | ignored_type = strtok(0, " \t\n"); |
---|
285 | symbol = strtok(0, " \t\n"); |
---|
286 | |
---|
287 | if (symbol && ignored_type && value) |
---|
288 | { |
---|
289 | rtems_symbol_t *sp; |
---|
290 | sp = rtems_symbol_create(rtems_monitor_symbols, |
---|
291 | symbol, |
---|
292 | (rtems_unsigned32) strtoul(value, 0, 16)); |
---|
293 | if (sp == 0) |
---|
294 | { |
---|
295 | printf("could not define symbol\n"); |
---|
296 | goto done; |
---|
297 | } |
---|
298 | } |
---|
299 | else |
---|
300 | { |
---|
301 | printf("parsing error\n"); |
---|
302 | goto done; |
---|
303 | } |
---|
304 | } |
---|
305 | |
---|
306 | done: |
---|
307 | } |
---|