Commit | Line | Data |
---|---|---|
cb747ec5 DE |
1 | /* Remote debugging interface for SPARC64 Simulator. |
2 | Copyright 1992 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. Hacked from Steve Chamberlain's Z8000 work | |
4 | by Doug Evans. (dje@cygnus.com). | |
5 | ||
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include "inferior.h" | |
24 | #include "wait.h" | |
25 | #include "value.h" | |
26 | #include <string.h> | |
27 | #include <ctype.h> | |
28 | #include <fcntl.h> | |
29 | #include <signal.h> | |
30 | #include <setjmp.h> | |
31 | #include <errno.h> | |
32 | #include "terminal.h" | |
33 | #include "target.h" | |
34 | #include "gdbcore.h" | |
35 | #include "sp64sim.h" | |
36 | ||
37 | /* Naming conventions: | |
38 | ||
39 | simif_xxx are internal objects that describe top level interfaces to the | |
40 | simulator (simif for SIMulator InterFace). | |
41 | ||
42 | sim_xxx are external counterparts to the simif_xxx objects that must be | |
43 | provided by the simulator. */ | |
44 | ||
45 | /* Forward data declarations */ | |
46 | extern struct target_ops simif_ops; | |
47 | ||
48 | int simif_verbose = 0; /* available to the simulator to use */ | |
49 | ||
50 | static int program_loaded = 0; | |
51 | ||
52 | static void dump_mem (); | |
53 | ||
54 | static void | |
55 | simif_fetch_register (regno) | |
56 | int regno; | |
57 | { | |
58 | if (regno == -1) | |
59 | { | |
60 | if (simif_verbose) | |
61 | printf_filtered ("simif_fetch_register: %d\n", regno); | |
62 | for (regno = 0; regno < 16; regno++) | |
63 | simif_fetch_register (regno); | |
64 | } | |
65 | else | |
66 | { | |
67 | char buf[MAX_REGISTER_RAW_SIZE]; | |
68 | ||
69 | sim_fetch_register (regno, buf); | |
70 | supply_register (regno, buf); | |
71 | if (simif_verbose) | |
72 | { | |
73 | printf_filtered ("simif_fetch_register: %d", regno); | |
74 | dump_mem (buf, sizeof (REGISTER_TYPE)); | |
75 | } | |
76 | } | |
77 | } | |
78 | ||
79 | static void | |
80 | simif_store_register (regno) | |
81 | int regno; | |
82 | { | |
83 | if (regno == -1) | |
84 | { | |
85 | if (simif_verbose) | |
86 | printf_filtered ("simif_store_register: %d\n", regno); | |
87 | for (regno = 0; regno < 16; regno++) | |
88 | simif_store_register (regno); | |
89 | } | |
90 | else | |
91 | { | |
92 | char value[sizeof (REGISTER_TYPE)]; | |
93 | ||
94 | read_register_gen (regno, value); | |
95 | SWAP_TARGET_AND_HOST (value, sizeof (REGISTER_TYPE)); | |
96 | sim_store_register (regno, value); | |
97 | if (simif_verbose) | |
98 | { | |
99 | printf_filtered ("simif_store_register: %d", regno); | |
100 | dump_mem (value, sizeof (REGISTER_TYPE)); | |
101 | } | |
102 | } | |
103 | } | |
104 | ||
105 | static void | |
106 | simif_kill (arg,from_tty) | |
107 | char *arg; | |
108 | int from_tty; | |
109 | { | |
110 | if (simif_verbose) | |
111 | printf_filtered ("simif_kill: arg \"%s\"\n", arg); | |
112 | ||
113 | sim_kill (); /* close fd's, remove mappings */ | |
114 | inferior_pid = 0; | |
115 | } | |
116 | ||
117 | /* Download a file specified in 'args', to the sim. */ | |
118 | ||
119 | static void | |
120 | simif_load (args, fromtty) | |
121 | char *args; | |
122 | int fromtty; | |
123 | { | |
124 | bfd *abfd; | |
125 | ||
126 | if (simif_verbose) | |
127 | printf_filtered ("simif_load: args \"%s\"\n", args); | |
128 | ||
129 | inferior_pid = 0; | |
130 | program_loaded = 0; | |
131 | /* FIXME: a.out should be a config parm and/or an arg. */ | |
132 | abfd = bfd_openr (args,"a.out-sunos-big"); | |
133 | ||
134 | if (!abfd) | |
135 | error ("Unable to open file %s.", args); | |
136 | ||
137 | if (bfd_check_format (abfd, bfd_object) ==0) | |
138 | error ("File is not an object file."); | |
139 | ||
140 | if (sim_load (abfd, args) != 0) | |
141 | return; | |
142 | ||
143 | program_loaded = 1; | |
144 | ||
145 | /* It is sim_load()'s job to set this. */ | |
146 | /*sim_set_pc (abfd->start_address); - can't do 'cus we use RMTVaddr */ | |
147 | } | |
148 | ||
149 | /* This is called not only when we first attach, but also when the | |
150 | user types "run" after having attached. */ | |
151 | ||
152 | static void | |
153 | simif_create_inferior (exec_file, args, env) | |
154 | char *exec_file; | |
155 | char *args; | |
156 | char **env; | |
157 | { | |
158 | int len,entry_pt; | |
159 | char *arg_buf,**argv; | |
160 | ||
161 | if (! program_loaded) | |
162 | error ("No program loaded."); | |
163 | ||
164 | if (simif_verbose) | |
165 | printf_filtered ("simif_create_inferior: exec_file \"%s\", args \"%s\"\n", | |
166 | exec_file, args); | |
167 | ||
168 | if (exec_file == 0 || exec_bfd == 0) | |
169 | error ("No exec file specified."); | |
170 | ||
171 | entry_pt = (int) bfd_get_start_address (exec_bfd); | |
172 | ||
173 | simif_kill (NULL, NULL); | |
174 | remove_breakpoints (); | |
175 | init_wait_for_inferior (); | |
176 | ||
177 | len = 5 + strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10; | |
178 | arg_buf = (char *) alloca (len); | |
179 | arg_buf[0] = '\0'; | |
180 | strcat (arg_buf, exec_file); | |
181 | strcat (arg_buf, " "); | |
182 | strcat (arg_buf, args); | |
183 | argv = buildargv (arg_buf); | |
184 | make_cleanup (freeargv, (char *) argv); | |
185 | sim_set_args (argv, env); | |
186 | ||
187 | inferior_pid = 42; | |
188 | insert_breakpoints (); /* Needed to get correct instruction in cache */ | |
189 | proceed (entry_pt, -1, 0); | |
190 | } | |
191 | ||
192 | /* Called when selecting the simulator. EG: (gdb) target sim name. | |
193 | NAME unused at present. */ | |
194 | ||
195 | static void | |
196 | simif_open (name, from_tty) | |
197 | char *name; | |
198 | int from_tty; | |
199 | { | |
200 | if (simif_verbose) | |
201 | printf_filtered ("simif_open: name \"%s\"\n", name); | |
202 | ||
203 | if (sim_init (name) != 0) | |
204 | { | |
205 | error ("Unable to initialize simulator (insufficient memory?)."); | |
206 | return; | |
207 | } | |
208 | ||
209 | push_target (&simif_ops); | |
210 | target_fetch_registers (-1); | |
211 | ||
212 | printf_filtered ("Connected to the simulator.\n"); | |
213 | } | |
214 | ||
215 | /* Close out all files and local state before this target loses control. */ | |
216 | ||
217 | static void | |
218 | simif_close (quitting) | |
219 | int quitting; | |
220 | { | |
221 | if (simif_verbose) | |
222 | printf_filtered ("simif_close: quitting %d\n", quitting); | |
223 | ||
224 | program_loaded = 0; | |
225 | ||
226 | /* FIXME: Need to call sim_close() to close all files and | |
227 | delete all mappings. */ | |
228 | } | |
229 | ||
230 | /* Terminate the open connection to the remote debugger. | |
231 | Use this when you want to detach and do something else | |
232 | with your gdb. */ | |
233 | ||
234 | static void | |
235 | simif_detach (args,from_tty) | |
236 | char *args; | |
237 | int from_tty; | |
238 | { | |
239 | if (simif_verbose) | |
240 | printf_filtered ("simif_detach: args \"%s\"\n", args); | |
241 | ||
242 | pop_target (); /* calls simif_close to do the real work */ | |
243 | if (from_tty) | |
244 | printf_filtered ("Ending simulator %s debugging\n", target_shortname); | |
245 | } | |
246 | ||
247 | /* Tell the remote machine to resume. */ | |
248 | /* FIXME: What are A and B? */ | |
249 | ||
250 | static void | |
251 | simif_resume (a,b) | |
252 | { | |
253 | if (simif_verbose) | |
254 | printf_filtered ("simif_resume: %d/%d\n", a, b); | |
255 | ||
256 | sim_resume (a, b); | |
257 | } | |
258 | ||
259 | /* Wait until the remote machine stops, then return, | |
260 | storing status in STATUS just as `wait' would. */ | |
261 | ||
262 | static int | |
263 | simif_wait (status) | |
264 | WAITTYPE *status; | |
265 | { | |
266 | if (simif_verbose) | |
267 | printf_filtered ("simif_wait: "); | |
268 | #if 1 | |
269 | *status = sim_stop_signal (); | |
270 | #else | |
271 | WSETSTOP (*status, sim_stop_signal ()); | |
272 | #endif | |
273 | if (simif_verbose) | |
274 | printf_filtered ("status %d\n", *status); | |
275 | return 0; | |
276 | } | |
277 | ||
278 | /* Get ready to modify the registers array. On machines which store | |
279 | individual registers, this doesn't need to do anything. On machines | |
280 | which store all the registers in one fell swoop, this makes sure | |
281 | that registers contains all the registers from the program being | |
282 | debugged. */ | |
283 | ||
284 | static void | |
285 | simif_prepare_to_store () | |
286 | { | |
287 | /* Do nothing, since we can store individual regs */ | |
288 | } | |
289 | ||
290 | static int | |
291 | simif_xfer_inferior_memory (memaddr, myaddr, len, write, target) | |
292 | CORE_ADDR memaddr; | |
293 | char *myaddr; | |
294 | int len; | |
295 | int write; | |
296 | struct target_ops *target; /* ignored */ | |
297 | { | |
298 | if (simif_verbose) | |
299 | { | |
300 | printf_filtered ("simif_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n", | |
301 | myaddr, memaddr, len, write); | |
302 | if (simif_verbose && write) | |
303 | dump_mem(myaddr, len); | |
304 | } | |
305 | ||
306 | if (! program_loaded) | |
307 | error ("No program loaded."); | |
308 | ||
309 | if (write) | |
310 | { | |
311 | len = sim_write (memaddr, myaddr, len); | |
312 | } | |
313 | else | |
314 | { | |
315 | len = sim_read (memaddr, myaddr, len); | |
316 | if (simif_verbose && len > 0) | |
317 | dump_mem(myaddr, len); | |
318 | } | |
319 | return len; | |
320 | } | |
321 | ||
322 | static void | |
323 | simif_files_info () | |
324 | { | |
325 | char *file = "nothing"; | |
326 | ||
327 | if (exec_bfd) | |
328 | file = bfd_get_filename (exec_bfd); | |
329 | ||
330 | if (simif_verbose) | |
331 | printf_filtered ("simif_files_info: file \"%s\"\n", file); | |
332 | ||
333 | if (exec_bfd) | |
334 | printf_filtered ("\tAttached to %s running program %s\n", | |
335 | target_shortname, file); | |
336 | } | |
337 | ||
338 | /* Clear the sims notion of what the break points are */ | |
339 | static void | |
340 | simif_mourn () | |
341 | { | |
342 | if (simif_verbose) | |
343 | printf_filtered ("simif_mourn:\n"); | |
344 | ||
345 | remove_breakpoints (); | |
346 | generic_mourn_inferior (); | |
347 | } | |
348 | ||
349 | /* Define the target subroutine names */ | |
350 | ||
351 | struct target_ops simif_ops = | |
352 | { | |
353 | "sim", "SPARC64 Simulator", | |
354 | "Use the SPARC64 Simulator", | |
355 | simif_open, simif_close, | |
356 | 0, simif_detach, simif_resume, simif_wait, /* attach */ | |
357 | simif_fetch_register, simif_store_register, | |
358 | simif_prepare_to_store, | |
359 | simif_xfer_inferior_memory, | |
360 | simif_files_info, | |
361 | 0, 0, /* Breakpoints */ | |
362 | 0, 0, 0, 0, 0, /* Terminal handling */ | |
363 | simif_kill, /* FIXME, kill */ | |
364 | simif_load, | |
365 | 0, /* lookup_symbol */ | |
366 | simif_create_inferior, /* create_inferior */ | |
367 | simif_mourn, /* mourn_inferior FIXME */ | |
368 | 0, /* can_run */ | |
369 | 0, /* notice_signals */ | |
370 | process_stratum, 0, /* next */ | |
371 | 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ | |
372 | 0, 0, /* Section pointers */ | |
373 | OPS_MAGIC, /* Always the last thing */ | |
374 | }; | |
375 | ||
376 | static void | |
377 | simif_snoop () | |
378 | { | |
379 | simif_verbose = ! simif_verbose; | |
380 | if (simif_verbose) | |
381 | printf_filtered ("Snoop enabled\n"); | |
382 | else | |
383 | printf_filtered ("Snoop disabled\n"); | |
384 | ||
385 | } | |
386 | ||
387 | /***********************************************************************/ | |
388 | ||
389 | void | |
390 | _initialize_remote_sim () | |
391 | { | |
392 | add_target (&simif_ops); | |
393 | add_com ("snoop", class_obscure, simif_snoop, | |
394 | "Show what commands are going to the simulator"); | |
395 | } | |
396 | ||
397 | static void | |
398 | dump_mem (buf, len) | |
399 | char *buf; | |
400 | int len; | |
401 | { | |
402 | if (len <= 8) | |
403 | { | |
404 | if (len == 8 || len == 4) | |
405 | { | |
406 | long l[2]; | |
407 | memcpy (l, buf, len); | |
408 | printf_filtered ("\t0x%x", l[0]); | |
409 | printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]); | |
410 | } | |
411 | else | |
412 | { | |
413 | int i; | |
414 | printf_filtered ("\t"); | |
415 | for (i = 0; i < len; i++) | |
416 | printf_filtered ("0x%x ", buf[i]); | |
417 | printf_filtered ("\n"); | |
418 | } | |
419 | } | |
420 | } |