1/* New version of run front end support for simulators. 2 Copyright (C) 1997, 2004, 2007, 2008, 2009, 2010, 2011 3 Free Software Foundation, Inc. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License as published by 7the Free Software Foundation; either version 3 of the License, or 8(at your option) any later version. 9 10This program is distributed in the hope that it will be useful, 11but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <signal.h> 19#include "sim-main.h" 20 21#include "bfd.h" 22 23#ifdef HAVE_ENVIRON 24extern char **environ; 25#endif 26 27#ifdef HAVE_UNISTD_H 28/* For chdir. */ 29#include <unistd.h> 30#endif 31 32static void usage (void); 33 34extern host_callback default_callback; 35 36static char *myname; 37 38static SIM_DESC sd; 39 40static RETSIGTYPE 41cntrl_c (int sig) 42{ 43 if (! sim_stop (sd)) 44 { 45 fprintf (stderr, "Quit!\n"); 46 exit (1); 47 } 48} 49 50int 51main (int argc, char **argv) 52{ 53 char *name; 54 char **prog_argv = NULL; 55 struct bfd *prog_bfd; 56 enum sim_stop reason; 57 int sigrc = 0; 58 int single_step = 0; 59 RETSIGTYPE (*prev_sigint) (); 60 61 myname = argv[0] + strlen (argv[0]); 62 while (myname > argv[0] && myname[-1] != '/') 63 --myname; 64 65 /* INTERNAL: When MYNAME is `step', single step the simulator 66 instead of allowing it to run free. The sole purpose of this 67 HACK is to allow the sim_resume interface's step argument to be 68 tested without having to build/run gdb. */ 69 if (strlen (myname) > 4 && strcmp (myname - 4, "step") == 0) 70 { 71 single_step = 1; 72 } 73 74 /* Create an instance of the simulator. */ 75 default_callback.init (&default_callback); 76 sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, NULL, argv); 77 if (sd == 0) 78 exit (1); 79 if (STATE_MAGIC (sd) != SIM_MAGIC_NUMBER) 80 { 81 fprintf (stderr, "Internal error - bad magic number in simulator struct\n"); 82 abort (); 83 } 84 85 /* We can't set the endianness in the callback structure until 86 sim_config is called, which happens in sim_open. */ 87 default_callback.target_endian 88 = (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN 89 ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE); 90 91 /* Was there a program to run? */ 92 prog_argv = STATE_PROG_ARGV (sd); 93 prog_bfd = STATE_PROG_BFD (sd); 94 if (prog_argv == NULL || *prog_argv == NULL) 95 usage (); 96 97 name = *prog_argv; 98 99 /* For simulators that don't open prog during sim_open() */ 100 if (prog_bfd == NULL) 101 { 102 prog_bfd = bfd_openr (name, 0); 103 if (prog_bfd == NULL) 104 { 105 fprintf (stderr, "%s: can't open \"%s\": %s\n", 106 myname, name, bfd_errmsg (bfd_get_error ())); 107 exit (1); 108 } 109 if (!bfd_check_format (prog_bfd, bfd_object)) 110 { 111 fprintf (stderr, "%s: \"%s\" is not an object file: %s\n", 112 myname, name, bfd_errmsg (bfd_get_error ())); 113 exit (1); 114 } 115 } 116 117 if (STATE_VERBOSE_P (sd)) 118 printf ("%s %s\n", myname, name); 119 120 /* Load the program into the simulator. */ 121 if (sim_load (sd, name, prog_bfd, 0) == SIM_RC_FAIL) 122 exit (1); 123 124 /* Prepare the program for execution. */ 125#ifdef HAVE_ENVIRON 126 sim_create_inferior (sd, prog_bfd, prog_argv, environ); 127#else 128 sim_create_inferior (sd, prog_bfd, prog_argv, NULL); 129#endif 130 131 /* To accommodate relative file paths, chdir to sysroot now. We 132 mustn't do this until BFD has opened the program, else we wouldn't 133 find the executable if it has a relative file path. */ 134 if (simulator_sysroot[0] != '\0' && chdir (simulator_sysroot) < 0) 135 { 136 fprintf (stderr, "%s: can't change directory to \"%s\"\n", 137 myname, simulator_sysroot); 138 exit (1); 139 } 140 141 /* Run/Step the program. */ 142 if (single_step) 143 { 144 do 145 { 146 prev_sigint = signal (SIGINT, cntrl_c); 147 sim_resume (sd, 1/*step*/, 0); 148 signal (SIGINT, prev_sigint); 149 sim_stop_reason (sd, &reason, &sigrc); 150 151 if ((reason == sim_stopped) && 152 (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) 153 break; /* exit on control-C */ 154 } 155 /* remain on breakpoint or signals in oe mode*/ 156 while (((reason == sim_signalled) && 157 (sigrc == sim_signal_to_host (sd, SIM_SIGTRAP))) || 158 ((reason == sim_stopped) && 159 (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT))); 160 } 161 else 162 { 163 do 164 { 165#if defined (HAVE_SIGACTION) && defined (SA_RESTART) 166 struct sigaction sa, osa; 167 sa.sa_handler = cntrl_c; 168 sigemptyset (&sa.sa_mask); 169 sa.sa_flags = 0; 170 sigaction (SIGINT, &sa, &osa); 171 prev_sigint = osa.sa_handler; 172#else 173 prev_sigint = signal (SIGINT, cntrl_c); 174#endif 175 sim_resume (sd, 0, sigrc); 176 signal (SIGINT, prev_sigint); 177 sim_stop_reason (sd, &reason, &sigrc); 178 179 if ((reason == sim_stopped) && 180 (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) 181 break; /* exit on control-C */ 182 183 /* remain on signals in oe mode */ 184 } while ((reason == sim_stopped) && 185 (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)); 186 187 } 188 /* Print any stats the simulator collected. */ 189 if (STATE_VERBOSE_P (sd)) 190 sim_info (sd, 0); 191 192 /* Shutdown the simulator. */ 193 sim_close (sd, 0); 194 195 /* If reason is sim_exited, then sigrc holds the exit code which we want 196 to return. If reason is sim_stopped or sim_signalled, then sigrc holds 197 the signal that the simulator received; we want to return that to 198 indicate failure. */ 199 200 /* Why did we stop? */ 201 switch (reason) 202 { 203 case sim_signalled: 204 case sim_stopped: 205 if (sigrc != 0) 206 fprintf (stderr, "program stopped with signal %d.\n", sigrc); 207 break; 208 209 case sim_exited: 210 break; 211 212 default: 213 fprintf (stderr, "program in undefined state (%d:%d)\n", reason, sigrc); 214 break; 215 216 } 217 218 return sigrc; 219} 220 221static void 222usage (void) 223{ 224 fprintf (stderr, "Usage: %s [options] program [program args]\n", myname); 225 fprintf (stderr, "Run `%s --help' for full list of options.\n", myname); 226 exit (1); 227} 228