Commit | Line | Data |
---|---|---|
bd5635a1 RP |
1 | /* Select target systems and architectures at runtime for GDB. |
2 | Copyright (C) 1990 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | GDB is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 1, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GDB is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GDB; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | #include <stdio.h> | |
22 | #include <errno.h> | |
23 | #include <ctype.h> | |
24 | #include "defs.h" | |
25 | #include "target.h" | |
26 | #include "gdbcmd.h" | |
27 | #include "symtab.h" | |
28 | #include "inferior.h" | |
29 | #include "bfd.h" | |
30 | #include "symfile.h" | |
31 | ||
32 | extern int memory_insert_breakpoint(), memory_remove_breakpoint(); | |
33 | extern void host_convert_to_virtual(), host_convert_from_virtual(); | |
fc47a10d | 34 | extern void add_syms_addr_command(); |
bd5635a1 RP |
35 | |
36 | static void cleanup_target (); | |
37 | ||
38 | /* Pointer to array of target architecture structures; the size of the | |
39 | array; the current index into the array; the allocated size of the | |
40 | array. */ | |
41 | struct target_ops **target_structs; | |
42 | unsigned target_struct_size; | |
43 | unsigned target_struct_index; | |
44 | unsigned target_struct_allocsize; | |
45 | #define DEFAULT_ALLOCSIZE 10 | |
46 | ||
47 | /* The initial current target, so that there is always a semi-valid | |
48 | current target. */ | |
49 | ||
50 | struct target_ops dummy_target = {"None", "None", | |
51 | 0, 0, 0, 0, /* open, close, attach, detach */ | |
52 | 0, 0, /* resume, wait */ | |
53 | 0, 0, 0, 0, 0, /* registers */ | |
54 | 0, 0, /* memory */ | |
55 | 0, 0, /* bkpts */ | |
56 | 0, 0, 0, 0, 0, /* terminal */ | |
fc47a10d JG |
57 | 0, 0, /* kill, load */ |
58 | add_syms_addr_command, /* add_syms */ | |
bd5635a1 RP |
59 | 0, 0, /* call_function, lookup_symbol */ |
60 | 0, 0, /* create_inferior, mourn_inferior */ | |
61 | dummy_stratum, 0, /* stratum, next */ | |
62 | 0, 0, 0, 0, 0, /* all mem, mem, stack, regs, exec */ | |
63 | OPS_MAGIC, | |
64 | }; | |
65 | ||
66 | /* The target structure we are currently using to talk to a process | |
67 | or file or whatever "inferior" we have. */ | |
68 | ||
69 | struct target_ops *current_target; | |
70 | ||
71 | /* The stack of target structures that have been pushed. */ | |
72 | ||
73 | struct target_ops **current_target_stack; | |
74 | ||
75 | ||
76 | /* Add a possible target architecture to the list. */ | |
77 | ||
78 | void | |
79 | add_target (t) | |
80 | struct target_ops *t; | |
81 | { | |
82 | if (t->to_magic != OPS_MAGIC) | |
83 | { | |
84 | fprintf(stderr, "Magic number of %s target struct wrong\n", | |
85 | t->to_shortname); | |
86 | abort(); | |
87 | } | |
88 | ||
89 | if (!target_structs) | |
90 | { | |
91 | target_struct_allocsize = DEFAULT_ALLOCSIZE; | |
92 | target_structs = (struct target_ops **) xmalloc | |
93 | (target_struct_allocsize * sizeof (*target_structs)); | |
94 | } | |
95 | if (target_struct_size >= target_struct_allocsize) | |
96 | { | |
97 | target_struct_allocsize *= 2; | |
98 | target_structs = (struct target_ops **) xrealloc (target_structs, | |
99 | target_struct_allocsize * sizeof (*target_structs)); | |
100 | } | |
101 | target_structs[target_struct_size++] = t; | |
102 | cleanup_target (t); | |
103 | } | |
104 | ||
105 | /* Stub functions */ | |
106 | ||
107 | static void | |
108 | ignore () | |
109 | { | |
110 | } | |
111 | ||
112 | /* ARGSUSED */ | |
113 | static int | |
114 | nomemory (memaddr, myaddr, len, write) | |
115 | CORE_ADDR memaddr; | |
116 | char *myaddr; | |
117 | int len; | |
118 | int write; | |
119 | { | |
120 | return 0; /* No bytes handled */ | |
121 | } | |
122 | ||
123 | static void | |
124 | tcomplain () | |
125 | { | |
126 | error ("You can't do that when your target is `%s'", | |
127 | current_target->to_shortname); | |
128 | } | |
129 | ||
130 | static int | |
131 | noprocess () | |
132 | { | |
133 | error ("You can't do that without a process to debug"); | |
134 | } | |
135 | ||
136 | static int | |
137 | nosymbol (name, addrp) | |
138 | char *name; | |
139 | CORE_ADDR *addrp; | |
140 | { | |
141 | return 1; /* Symbol does not exist in target env */ | |
142 | } | |
143 | ||
144 | static void | |
145 | default_terminal_info (args, from_tty) | |
146 | char *args; | |
147 | int from_tty; | |
148 | { | |
149 | printf("No saved terminal information.\n"); | |
150 | } | |
151 | ||
152 | #if 0 | |
153 | /* With strata, this function is no longer needed. FIXME. */ | |
154 | /* This is the default target_create_inferior function. It looks up | |
155 | the stack for some target that cares to create inferiors, then | |
156 | calls it -- or complains if not found. */ | |
157 | ||
158 | static void | |
159 | upstack_create_inferior (exec, args, env) | |
160 | char *exec; | |
161 | char *args; | |
162 | char **env; | |
163 | { | |
164 | struct target_ops *t; | |
165 | ||
166 | for (t = current_target; | |
167 | t; | |
168 | t = t->to_next) | |
169 | { | |
170 | if (t->to_create_inferior != upstack_create_inferior) | |
171 | { | |
172 | t->to_create_inferior (exec, args, env); | |
173 | return; | |
174 | } | |
175 | ||
176 | } | |
177 | tcomplain(); | |
178 | } | |
179 | #endif | |
180 | ||
181 | /* This is the default target_create_inferior and target_attach function. | |
182 | If the current target is executing, it asks whether to kill it off. | |
183 | If this function returns without calling error(), it has killed off | |
184 | the target, and the operation should be attempted. */ | |
185 | ||
186 | static void | |
187 | kill_or_be_killed (from_tty) | |
188 | int from_tty; | |
189 | { | |
190 | struct target_ops *savecur; | |
191 | ||
192 | if (target_has_execution) | |
193 | { | |
194 | printf ("You are already running a program:\n"); | |
195 | target_files_info (); | |
196 | if (query ("Kill it? ")) { | |
197 | savecur = current_target; | |
198 | target_kill (0, from_tty); | |
199 | if (target_has_execution) | |
200 | error ("Killing the program did not help."); | |
201 | return; | |
202 | } else { | |
203 | error ("Program not killed."); | |
204 | } | |
205 | } | |
206 | tcomplain(); | |
207 | } | |
208 | ||
209 | static void | |
210 | maybe_kill_then_attach (args, from_tty) | |
211 | char *args; | |
212 | int from_tty; | |
213 | { | |
214 | kill_or_be_killed (from_tty); | |
215 | target_attach (args, from_tty); | |
216 | } | |
217 | ||
218 | static void | |
219 | maybe_kill_then_create_inferior (exec, args, env) | |
220 | char *exec; | |
221 | char *args; | |
222 | char **env; | |
223 | { | |
224 | kill_or_be_killed (0); | |
225 | target_create_inferior (exec, args, env); | |
226 | } | |
227 | ||
228 | /* Clean up a target struct so it no longer has any zero pointers in it. | |
229 | We default entries, at least to stubs that print error messages. */ | |
230 | ||
231 | static void | |
232 | cleanup_target (t) | |
233 | struct target_ops *t; | |
234 | { | |
235 | ||
236 | /* Check magic number. If wrong, it probably means someone changed | |
237 | the struct definition, but not all the places that initialize one. */ | |
238 | if (t->to_magic != OPS_MAGIC) | |
239 | { | |
240 | fprintf(stderr, "Magic number of %s target struct wrong\n", | |
241 | t->to_shortname); | |
242 | abort(); | |
243 | } | |
244 | ||
245 | #define de_fault(field, value) \ | |
246 | if (!t->field) t->field = value | |
247 | ||
248 | /* FIELD DEFAULT VALUE */ | |
249 | ||
250 | de_fault (to_open, tcomplain); | |
251 | de_fault (to_close, (void (*)())ignore); | |
252 | de_fault (to_attach, maybe_kill_then_attach); | |
253 | de_fault (to_detach, (void (*)())ignore); | |
254 | de_fault (to_resume, (void (*)())noprocess); | |
255 | de_fault (to_wait, noprocess); | |
256 | de_fault (to_fetch_registers, noprocess); | |
257 | de_fault (to_store_registers, noprocess); | |
258 | de_fault (to_prepare_to_store, (void (*)())noprocess); | |
259 | de_fault (to_convert_to_virtual, host_convert_to_virtual); | |
260 | de_fault (to_convert_from_virtual, host_convert_from_virtual); | |
261 | de_fault (to_xfer_memory, nomemory); | |
262 | de_fault (to_files_info, ignore); | |
263 | de_fault (to_insert_breakpoint, memory_insert_breakpoint); | |
264 | de_fault (to_remove_breakpoint, memory_remove_breakpoint); | |
265 | de_fault (to_terminal_init, ignore); | |
266 | de_fault (to_terminal_inferior, ignore); | |
267 | de_fault (to_terminal_ours_for_output,ignore); | |
268 | de_fault (to_terminal_ours, ignore); | |
269 | de_fault (to_terminal_info, default_terminal_info); | |
270 | de_fault (to_kill, (void (*)())noprocess); | |
271 | de_fault (to_load, tcomplain); | |
272 | de_fault (to_add_syms, tcomplain); | |
273 | de_fault (to_call_function, (struct value *(*)())noprocess); | |
274 | de_fault (to_lookup_symbol, nosymbol); | |
275 | de_fault (to_create_inferior, maybe_kill_then_create_inferior); | |
276 | de_fault (to_mourn_inferior, (void (*)())noprocess); | |
277 | de_fault (to_next, 0); | |
278 | de_fault (to_has_all_memory, 0); | |
279 | de_fault (to_has_memory, 0); | |
280 | de_fault (to_has_stack, 0); | |
281 | de_fault (to_has_registers, 0); | |
282 | de_fault (to_has_execution, 0); | |
283 | ||
284 | #undef de_fault | |
285 | } | |
286 | ||
287 | /* Push a new target type into the stack of the existing target accessors, | |
288 | possibly superseding some of the existing accessors. | |
289 | ||
290 | Result is zero if the pushed target ended up on top of the stack, | |
291 | nonzero if at least one target is on top of it. | |
292 | ||
293 | Rather than allow an empty stack, we always have the dummy target at | |
294 | the bottom stratum, so we can call the function vectors without | |
295 | checking them. */ | |
296 | ||
297 | int | |
298 | push_target (t) | |
299 | struct target_ops *t; | |
300 | { | |
301 | struct target_ops *st, *prev; | |
302 | ||
303 | for (prev = 0, st = current_target; | |
304 | st; | |
305 | prev = st, st = st->to_next) { | |
306 | if ((int)(t->to_stratum) >= (int)(st->to_stratum)) | |
307 | break; | |
308 | } | |
309 | ||
310 | while (t->to_stratum == st->to_stratum) { | |
311 | /* There's already something on this stratum. Close it off. */ | |
312 | (st->to_close) (0); | |
313 | if (prev) | |
314 | prev->to_next = st->to_next; /* Unchain old target_ops */ | |
315 | else | |
316 | current_target = st->to_next; /* Unchain first on list */ | |
317 | st = st->to_next; | |
318 | } | |
319 | ||
320 | /* We have removed all targets in our stratum, now add ourself. */ | |
321 | t->to_next = st; | |
322 | if (prev) | |
323 | prev->to_next = t; | |
324 | else | |
325 | current_target = t; | |
326 | ||
327 | cleanup_target (current_target); | |
328 | return prev != 0; | |
329 | } | |
330 | ||
331 | /* Remove a target_ops vector from the stack, wherever it may be. | |
332 | Return how many times it was removed (0 or 1 unless bug). */ | |
333 | ||
334 | int | |
335 | unpush_target (t) | |
336 | struct target_ops *t; | |
337 | { | |
338 | struct target_ops *u, *v; | |
339 | int result = 0; | |
340 | ||
341 | for (u = current_target, v = 0; | |
342 | u; | |
343 | v = u, u = u->to_next) | |
344 | if (u == t) | |
345 | { | |
346 | if (v == 0) | |
347 | pop_target(); /* unchain top copy */ | |
348 | else { | |
349 | (t->to_close)(0); /* Let it clean up */ | |
350 | v->to_next = t->to_next; /* unchain middle copy */ | |
351 | } | |
352 | result++; | |
353 | } | |
354 | return result; | |
355 | } | |
356 | ||
357 | void | |
358 | pop_target () | |
359 | { | |
360 | (current_target->to_close)(0); /* Let it clean up */ | |
361 | current_target = current_target->to_next; | |
362 | if (!current_target) /* At bottom, push dummy. */ | |
363 | push_target (&dummy_target); | |
364 | } | |
365 | ||
366 | /* Print things about the whole set of targets and about the | |
367 | current target stack. */ | |
368 | static void | |
369 | targets_info () | |
370 | { | |
371 | int i; | |
372 | ||
373 | printf("Possible targets:\n\n"); | |
374 | for (i = 0; i < target_struct_size; i++) | |
375 | printf ("%-15s %s\n", | |
376 | target_structs[i]->to_shortname, | |
377 | target_structs[i]->to_longname); | |
378 | } | |
379 | ||
380 | /* Move memory to or from the targets. Iterate until all of it has | |
381 | been moved, if necessary. The top target gets priority; anything | |
382 | it doesn't want, is offered to the next one down, etc. Note the | |
383 | business with curlen: if an early target says "no, but I have a | |
384 | boundary overlapping this xfer" then we shorten what we offer to | |
385 | the subsequent targets so the early guy will get a chance at the | |
386 | tail before the subsequent ones do. | |
387 | ||
388 | Result is 0 or errno value. */ | |
389 | ||
390 | int | |
391 | target_read_memory (memaddr, myaddr, len) | |
392 | CORE_ADDR memaddr; | |
393 | char *myaddr; | |
394 | int len; | |
395 | { | |
396 | return target_xfer_memory (memaddr, myaddr, len, 0); | |
397 | } | |
398 | ||
399 | int | |
400 | target_write_memory (memaddr, myaddr, len) | |
401 | CORE_ADDR memaddr; | |
402 | char *myaddr; | |
403 | int len; | |
404 | { | |
405 | return target_xfer_memory (memaddr, myaddr, len, 1); | |
406 | } | |
407 | ||
408 | int | |
409 | target_xfer_memory (memaddr, myaddr, len, write) | |
410 | CORE_ADDR memaddr; | |
411 | char *myaddr; | |
412 | int len; | |
413 | int write; | |
414 | { | |
415 | int curlen; | |
416 | int res; | |
417 | struct target_ops *t; | |
418 | ||
419 | /* The quick case is that the top target does it all. */ | |
420 | res = current_target->to_xfer_memory(memaddr, myaddr, len, write); | |
421 | if (res == len) | |
422 | return 0; | |
423 | ||
424 | if (res > 0) | |
425 | goto bump; | |
426 | /* If res <= 0 then we call it again in the loop. Ah well. */ | |
427 | ||
428 | for (; len > 0;) | |
429 | { | |
430 | curlen = len; /* Want to do it all */ | |
431 | for (t = current_target; | |
432 | t; | |
433 | t = t->to_has_all_memory? 0: t->to_next) | |
434 | { | |
435 | res = t->to_xfer_memory(memaddr, myaddr, curlen, write); | |
436 | if (res > 0) break; /* Handled all or part of xfer */ | |
437 | if (res == 0) continue; /* Handled none */ | |
438 | curlen = -res; /* Could handle once we get past res bytes */ | |
439 | } | |
440 | if (res <= 0) | |
441 | { | |
442 | /* If this address is for nonexistent memory, | |
443 | read zeros if reading, or do nothing if writing. Return error. */ | |
444 | if (!write) | |
445 | bzero (myaddr, len); | |
446 | return EIO; | |
447 | } | |
448 | bump: | |
449 | memaddr += res; | |
450 | myaddr += res; | |
451 | len -= res; | |
452 | } | |
453 | return 0; /* We managed to cover it all somehow. */ | |
454 | } | |
455 | ||
456 | ||
457 | static void | |
458 | target_info (args, from_tty) | |
459 | char *args; | |
460 | int from_tty; | |
461 | { | |
462 | struct target_ops *t; | |
463 | int has_all_mem = 0; | |
464 | ||
465 | if (symfile != 0) | |
466 | printf ("Symbols from \"%s\".\n", symfile); | |
467 | ||
468 | #ifdef FILES_INFO_HOOK | |
469 | if (FILES_INFO_HOOK ()) | |
470 | return; | |
471 | #endif | |
472 | ||
473 | for (t = current_target; | |
474 | t; | |
475 | t = t->to_next) | |
476 | { | |
477 | if ((int)(t->to_stratum) <= (int)dummy_stratum) | |
478 | continue; | |
479 | if (has_all_mem) | |
480 | printf("\tWhile running this, gdb does not access memory from...\n"); | |
481 | printf("%s:\n", t->to_longname); | |
482 | (t->to_files_info)(); | |
483 | has_all_mem = t->to_has_all_memory; | |
484 | } | |
485 | } | |
486 | ||
487 | /* The target command selects a target and calls its open routine. | |
488 | The open routine takes the rest of the parameters from the command, | |
489 | and (if successful) pushes a new target onto the stack. */ | |
490 | ||
491 | static void | |
492 | target_command (args, from_tty) | |
493 | char *args; | |
494 | int from_tty; | |
495 | { | |
fc47a10d | 496 | int i, possible; |
bd5635a1 | 497 | char *rest; |
fc47a10d | 498 | char *argend; |
bd5635a1 RP |
499 | |
500 | dont_repeat(); | |
501 | ||
502 | if (!args) | |
503 | error ( | |
504 | "Argument required (target name). `info targets' lists possible targets"); | |
505 | ||
506 | if (target_has_execution) | |
507 | { | |
508 | if (query ("A program is being debugged already. Kill it? ")) | |
509 | target_kill ((char *)0, from_tty); | |
510 | else | |
511 | error ("Program not killed."); | |
512 | } | |
513 | ||
514 | /* Skip to first space, or end of args */ | |
515 | for (rest = args; *rest && !isspace(*rest); rest++) ; | |
fc47a10d | 516 | argend = rest; |
bd5635a1 RP |
517 | if (*rest == '\0') |
518 | rest = 0; /* Only one word in args */ | |
519 | else | |
520 | { | |
bd5635a1 RP |
521 | for (rest++; isspace (*rest); rest++) ; |
522 | if (*rest == '\0') /* Only one word w/trailing blanks */ | |
523 | rest = 0; | |
524 | } | |
525 | ||
526 | /* Search target list for a match */ | |
527 | ||
fc47a10d | 528 | possible = -1; |
bd5635a1 RP |
529 | for (i = 0; i < target_struct_size; i++) |
530 | { | |
fc47a10d JG |
531 | if (!strncmp (args, target_structs[i]->to_shortname, argend - args)) { |
532 | /* If we have an exact match, it's time to quit. */ | |
533 | if (target_structs[i]->to_shortname[args-argend] == '\0') { | |
534 | possible = i; | |
535 | break; | |
536 | } | |
537 | if (possible > 0) | |
538 | error ("Ambiguous target. `info targets' will list all targets"); | |
539 | possible = i; | |
540 | } | |
bd5635a1 | 541 | } |
fc47a10d JG |
542 | if (possible < 0) |
543 | error ("No such target. `info targets' will list all targets"); | |
bd5635a1 | 544 | |
fc47a10d | 545 | (*target_structs[possible]->to_open) (rest, from_tty); |
bd5635a1 RP |
546 | } |
547 | ||
548 | static char targ_desc[] = | |
549 | "Names of targets and files being debugged.\n\ | |
550 | Shows the entire stack of targets currently in use (including the exec-file,\n\ | |
551 | core-file, and process, if any), as well as the symbol file name."; | |
552 | ||
553 | void | |
554 | _initialize_targets () | |
555 | { | |
556 | current_target = &dummy_target; | |
557 | cleanup_target (current_target); | |
558 | ||
559 | add_info ("targets", targets_info, | |
560 | "Names of all possible targets.\n\ | |
561 | A target is typically a protocol for talking to debugging facilities;\n\ | |
562 | for example, `child' for Unix child processes, or `vxworks' for a\n\ | |
563 | TCP/IP link to a VxWorks system."); | |
564 | ||
565 | add_info ("target", target_info, targ_desc); | |
566 | add_info ("files", target_info, targ_desc); | |
567 | ||
568 | add_com ("target", class_run, target_command, | |
569 | "Connect to a target machine or process.\n\ | |
570 | The first argument is the type or protocol of the target machine. Remaining\n\ | |
571 | arguments are interpreted by the target protocol, but typically include\n\ | |
572 | things like device names or host names to connect with, process numbers,\n\ | |
573 | baud rates, etc. You can list all possible targets with the `info targets'\n\ | |
574 | command."); | |
575 | } |