]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/run.c
sim:
[thirdparty/binutils-gdb.git] / sim / common / run.c
1 /* run front end support for all the simulators.
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3 2002, 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 /* Steve Chamberlain sac@cygnus.com,
19 and others at Cygnus. */
20
21 #ifdef HAVE_CONFIG_H
22 #include "cconfig.h"
23 #include "tconfig.h"
24 #endif
25
26 #include <signal.h>
27 #include <stdio.h>
28 #ifdef __STDC__
29 #include <stdarg.h>
30 #else
31 #include <varargs.h>
32 #endif
33
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37
38 #ifdef HAVE_STRING_H
39 #include <string.h>
40 #else
41 #ifdef HAVE_STRINGS_H
42 #include <strings.h>
43 #endif
44 #endif
45
46 #include "libiberty.h"
47 #include "bfd.h"
48 #include "gdb/callback.h"
49 #include "gdb/remote-sim.h"
50 #include "ansidecl.h"
51 #include "run-sim.h"
52 #include "version.h"
53
54 static void usage PARAMS ((int help));
55 static void print_version PARAMS ((void));
56 extern int optind;
57 extern char *optarg;
58
59 extern host_callback default_callback;
60
61 static char *myname;
62
63 extern int getopt ();
64
65 #ifdef NEED_UI_LOOP_HOOK
66 /* Gdb foolery. This is only needed for gdb using a gui. */
67 int (*deprecated_ui_loop_hook) PARAMS ((int signo));
68 #endif
69
70 static SIM_DESC sd;
71
72 static RETSIGTYPE
73 cntrl_c (int sig ATTRIBUTE_UNUSED)
74 {
75 if (! sim_stop (sd))
76 {
77 fprintf (stderr, "Quit!\n");
78 exit (1);
79 }
80 }
81
82 int
83 main (ac, av)
84 int ac;
85 char **av;
86 {
87 RETSIGTYPE (*prev_sigint) ();
88 bfd *abfd;
89 int i;
90 int verbose = 0;
91 int trace = 0;
92 #ifdef SIM_HAVE_ENVIRONMENT
93 int operating_p = 0;
94 #endif
95 char *name;
96 static char *no_args[4];
97 char **sim_argv = &no_args[0];
98 char **prog_args;
99 enum sim_stop reason;
100 int sigrc;
101
102 myname = av[0] + strlen (av[0]);
103 while (myname > av[0] && myname[-1] != '/')
104 --myname;
105
106 /* The first element of sim_open's argv is the program name. */
107 no_args[0] = av[0];
108 #ifdef SIM_HAVE_BIENDIAN
109 no_args[1] = "-E";
110 no_args[2] = "set-later";
111 #endif
112
113 /* FIXME: This is currently being migrated into sim_open.
114 Simulators that use functions such as sim_size() still require
115 this. */
116 default_callback.init (&default_callback);
117 sim_set_callbacks (&default_callback);
118
119 #ifdef SIM_TARGET_SWITCHES
120 ac = sim_target_parse_command_line (ac, av);
121 #endif
122
123 for (i = 1; av[i]; ++i)
124 {
125 if (strcmp (av[i], "--help") == 0)
126 {
127 usage (1);
128 }
129 else if (strcmp (av[i], "--version") == 0)
130 {
131 print_version ();
132 return 0;
133 }
134 }
135
136 /* FIXME: This is currently being rewritten to have each simulator
137 do all argv processing. */
138
139 while ((i = getopt (ac, av, "a:c:m:op:s:tv")) != EOF)
140 switch (i)
141 {
142 case 'a':
143 /* FIXME: Temporary hack. */
144 {
145 int len = strlen (av[0]) + strlen (optarg);
146 char *argbuf = (char *) alloca (len + 2 + 50);
147 sprintf (argbuf, "%s %s", av[0], optarg);
148 #ifdef SIM_HAVE_BIENDIAN
149 /* The desired endianness must be passed to sim_open.
150 The value for "set-later" is set when we know what it is.
151 -E support isn't yet part of the published interface. */
152 strcat (argbuf, " -E set-later");
153 #endif
154 sim_argv = buildargv (argbuf);
155 }
156 break;
157 #ifdef SIM_HAVE_SIMCACHE
158 case 'c':
159 sim_set_simcache_size (atoi (optarg));
160 break;
161 #endif
162 case 'm':
163 /* FIXME: Rename to sim_set_mem_size. */
164 sim_size (atoi (optarg));
165 break;
166 #ifdef SIM_HAVE_ENVIRONMENT
167 case 'o':
168 /* Operating enironment where any signals are delivered to the
169 target. */
170 operating_p = 1;
171 break;
172 #endif
173 #ifdef SIM_HAVE_PROFILE
174 case 'p':
175 sim_set_profile (atoi (optarg));
176 break;
177 case 's':
178 sim_set_profile_size (atoi (optarg));
179 break;
180 #endif
181 case 't':
182 trace = 1;
183 break;
184 case 'v':
185 /* Things that are printed with -v are the kinds of things that
186 gcc -v prints. This is not meant to include detailed tracing
187 or debugging information, just summaries. */
188 verbose = 1;
189 /* sim_set_verbose (1); */
190 break;
191 /* FIXME: Quick hack, to be replaced by more general facility. */
192 default:
193 usage (0);
194 }
195
196 ac -= optind;
197 av += optind;
198 if (ac <= 0)
199 usage (0);
200
201 name = *av;
202 prog_args = av;
203
204 if (verbose)
205 {
206 printf ("%s %s\n", myname, name);
207 }
208
209 abfd = bfd_openr (name, 0);
210 if (!abfd)
211 {
212 fprintf (stderr, "%s: can't open %s: %s\n",
213 myname, name, bfd_errmsg (bfd_get_error ()));
214 exit (1);
215 }
216
217 if (!bfd_check_format (abfd, bfd_object))
218 {
219 fprintf (stderr, "%s: can't load %s: %s\n",
220 myname, name, bfd_errmsg (bfd_get_error ()));
221 exit (1);
222 }
223
224 #ifdef SIM_HAVE_BIENDIAN
225 /* The endianness must be passed to sim_open because one may wish to
226 examine/set registers before calling sim_load [which is the other
227 place where one can determine endianness]. We previously passed the
228 endianness via global `target_byte_order' but that's not a clean
229 interface. */
230 for (i = 1; sim_argv[i + 1] != NULL; ++i)
231 continue;
232 if (bfd_big_endian (abfd))
233 sim_argv[i] = "big";
234 else
235 sim_argv[i] = "little";
236 #endif
237
238 /* Ensure that any run-time initialisation that needs to be
239 performed by the simulator can occur. */
240 sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv);
241 if (sd == 0)
242 exit (1);
243
244 if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL)
245 exit (1);
246
247 if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL)
248 exit (1);
249
250 #ifdef SIM_HAVE_ENVIRONMENT
251 /* NOTE: An old simulator supporting the operating environment MUST
252 provide sim_set_trace() and not sim_trace(). That way
253 sim_stop_reason() can be used to determine any stop reason. */
254 if (trace)
255 sim_set_trace ();
256 sigrc = 0;
257 do
258 {
259 prev_sigint = signal (SIGINT, cntrl_c);
260 sim_resume (sd, 0, sigrc);
261 signal (SIGINT, prev_sigint);
262 sim_stop_reason (sd, &reason, &sigrc);
263 }
264 while (operating_p && reason == sim_stopped && sigrc != SIGINT);
265 #else
266 if (trace)
267 {
268 int done = 0;
269 prev_sigint = signal (SIGINT, cntrl_c);
270 while (!done)
271 {
272 done = sim_trace (sd);
273 }
274 signal (SIGINT, prev_sigint);
275 sim_stop_reason (sd, &reason, &sigrc);
276 }
277 else
278 {
279 prev_sigint = signal (SIGINT, cntrl_c);
280 sigrc = 0;
281 sim_resume (sd, 0, sigrc);
282 signal (SIGINT, prev_sigint);
283 sim_stop_reason (sd, &reason, &sigrc);
284 }
285 #endif
286
287 if (verbose)
288 sim_info (sd, 0);
289 sim_close (sd, 0);
290
291 /* If reason is sim_exited, then sigrc holds the exit code which we want
292 to return. If reason is sim_stopped or sim_signalled, then sigrc holds
293 the signal that the simulator received; we want to return that to
294 indicate failure. */
295
296 /* Why did we stop? */
297 switch (reason)
298 {
299 case sim_signalled:
300 case sim_stopped:
301 if (sigrc != 0)
302 fprintf (stderr, "program stopped with signal %d.\n", sigrc);
303 break;
304
305 case sim_exited:
306 break;
307
308 case sim_running:
309 case sim_polling: /* These indicate a serious problem. */
310 abort ();
311 break;
312
313 }
314
315 return sigrc;
316 }
317
318 static void
319 usage (int help)
320 {
321 FILE *stream = help ? stdout : stderr;
322
323 fprintf (stream, "Usage: %s [options] program [program args]\n", myname);
324 fprintf (stream, "Options:\n");
325 fprintf (stream, "-a args Pass `args' to simulator.\n");
326 #ifdef SIM_HAVE_SIMCACHE
327 fprintf (stream, "-c size Set simulator cache size to `size'.\n");
328 #endif
329 fprintf (stream, "-m size Set memory size of simulator, in bytes.\n");
330 #ifdef SIM_HAVE_ENVIRONMENT
331 fprintf (stream, "-o Select operating (kernel) environment.\n");
332 #endif
333 #ifdef SIM_HAVE_PROFILE
334 fprintf (stream, "-p freq Set profiling frequency.\n");
335 fprintf (stream, "-s size Set profiling size.\n");
336 #endif
337 fprintf (stream, "-t Perform instruction tracing.\n");
338 fprintf (stream, " Note: Very few simulators support tracing.\n");
339 fprintf (stream, "-v Verbose output.\n");
340 fprintf (stream, "\n");
341 fprintf (stream, "program args Arguments to pass to simulated program.\n");
342 fprintf (stream, " Note: Very few simulators support this.\n");
343 #ifdef SIM_TARGET_SWITCHES
344 fprintf (stream, "\nTarget specific options:\n");
345 sim_target_display_usage (help);
346 #endif
347
348 if (help && REPORT_BUGS_TO[0])
349 printf ("Report bugs to %s\n", REPORT_BUGS_TO);
350
351 exit (help ? 0 : 1);
352 }
353
354 static void
355 print_version ()
356 {
357 printf ("GNU simulator %s%s\n", PKGVERSION, version);
358 }