14e98e3e1Schristos /* New version of run front end support for simulators. 2*88241920Schristos Copyright (C) 1997-2024 Free Software Foundation, Inc. 34e98e3e1Schristos 44e98e3e1Schristos This program is free software; you can redistribute it and/or modify 54e98e3e1Schristos it under the terms of the GNU General Public License as published by 64e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 74e98e3e1Schristos (at your option) any later version. 84e98e3e1Schristos 94e98e3e1Schristos This program is distributed in the hope that it will be useful, 104e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 114e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 124e98e3e1Schristos GNU General Public License for more details. 134e98e3e1Schristos 144e98e3e1Schristos You should have received a copy of the GNU General Public License 154e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 164e98e3e1Schristos 17a2e2270fSchristos /* Need to be before general includes, to pick up e.g. _GNU_SOURCE. */ 184b169a6bSchristos #include "defs.h" 19a2e2270fSchristos 204e98e3e1Schristos #include <signal.h> 218dffb485Schristos #include <stdlib.h> 22a2e2270fSchristos /* For strsignal. */ 23a2e2270fSchristos #include <string.h> 244e98e3e1Schristos /* For chdir. */ 254e98e3e1Schristos #include <unistd.h> 264e98e3e1Schristos 274b169a6bSchristos #include "bfd.h" 284b169a6bSchristos #include "environ.h" 294b169a6bSchristos 304b169a6bSchristos #include "sim-main.h" 314b169a6bSchristos #include "sim-signal.h" 324b169a6bSchristos #include "sim/callback.h" 334b169a6bSchristos 344b169a6bSchristos #ifndef HAVE_STRSIGNAL 354b169a6bSchristos /* While libiberty provides a fallback, it doesn't provide a prototype. */ 364b169a6bSchristos extern const char *strsignal (int); 374b169a6bSchristos #endif 384b169a6bSchristos 394e98e3e1Schristos static void usage (void); 404e98e3e1Schristos 414e98e3e1Schristos extern host_callback default_callback; 424e98e3e1Schristos 43ba340e45Schristos static const char *myname; 444e98e3e1Schristos 454e98e3e1Schristos static SIM_DESC sd; 464e98e3e1Schristos 474e98e3e1Schristos static RETSIGTYPE 484e98e3e1Schristos cntrl_c (int sig) 494e98e3e1Schristos { 504e98e3e1Schristos if (! sim_stop (sd)) 514e98e3e1Schristos { 524e98e3e1Schristos fprintf (stderr, "Quit!\n"); 534e98e3e1Schristos exit (1); 544e98e3e1Schristos } 554e98e3e1Schristos } 564e98e3e1Schristos 574e98e3e1Schristos int 584e98e3e1Schristos main (int argc, char **argv) 594e98e3e1Schristos { 60ba340e45Schristos const char *name; 614e98e3e1Schristos char **prog_argv = NULL; 624b169a6bSchristos char **prog_envp = NULL; 634e98e3e1Schristos struct bfd *prog_bfd; 644e98e3e1Schristos enum sim_stop reason; 654e98e3e1Schristos int sigrc = 0; 664e98e3e1Schristos int single_step = 0; 674e98e3e1Schristos RETSIGTYPE (*prev_sigint) (); 684e98e3e1Schristos 69ba340e45Schristos myname = lbasename (argv[0]); 704e98e3e1Schristos 714e98e3e1Schristos /* INTERNAL: When MYNAME is `step', single step the simulator 724e98e3e1Schristos instead of allowing it to run free. The sole purpose of this 734e98e3e1Schristos HACK is to allow the sim_resume interface's step argument to be 744e98e3e1Schristos tested without having to build/run gdb. */ 754e98e3e1Schristos if (strlen (myname) > 4 && strcmp (myname - 4, "step") == 0) 764e98e3e1Schristos { 774e98e3e1Schristos single_step = 1; 784e98e3e1Schristos } 794e98e3e1Schristos 804e98e3e1Schristos /* Create an instance of the simulator. */ 814e98e3e1Schristos default_callback.init (&default_callback); 824e98e3e1Schristos sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, NULL, argv); 834e98e3e1Schristos if (sd == 0) 844e98e3e1Schristos exit (1); 854e98e3e1Schristos if (STATE_MAGIC (sd) != SIM_MAGIC_NUMBER) 864e98e3e1Schristos { 874e98e3e1Schristos fprintf (stderr, "Internal error - bad magic number in simulator struct\n"); 884e98e3e1Schristos abort (); 894e98e3e1Schristos } 904e98e3e1Schristos 914b169a6bSchristos /* We can't set the endianness in the callback structure until sim_config is 924b169a6bSchristos called, which happens in sim_open. If it's still the default, switch it. 934b169a6bSchristos Don't use CURRENT_TARGET_BYTE_ORDER as all its internal processing already 944b169a6bSchristos happened in sim_config. */ 954b169a6bSchristos if (default_callback.target_endian == BFD_ENDIAN_UNKNOWN) 964b169a6bSchristos default_callback.target_endian = current_target_byte_order; 974e98e3e1Schristos 984e98e3e1Schristos /* Was there a program to run? */ 994e98e3e1Schristos prog_argv = STATE_PROG_ARGV (sd); 1004b169a6bSchristos prog_envp = STATE_PROG_ENVP (sd) ? : environ; 1014e98e3e1Schristos prog_bfd = STATE_PROG_BFD (sd); 1024e98e3e1Schristos if (prog_argv == NULL || *prog_argv == NULL) 1034e98e3e1Schristos usage (); 1044e98e3e1Schristos 1054b169a6bSchristos name = STATE_PROG_FILE (sd); 1064e98e3e1Schristos 1074e98e3e1Schristos /* For simulators that don't open prog during sim_open() */ 1084e98e3e1Schristos if (prog_bfd == NULL) 1094e98e3e1Schristos { 1104e98e3e1Schristos prog_bfd = bfd_openr (name, 0); 1114e98e3e1Schristos if (prog_bfd == NULL) 1124e98e3e1Schristos { 1134e98e3e1Schristos fprintf (stderr, "%s: can't open \"%s\": %s\n", 1144e98e3e1Schristos myname, name, bfd_errmsg (bfd_get_error ())); 1154e98e3e1Schristos exit (1); 1164e98e3e1Schristos } 1174e98e3e1Schristos if (!bfd_check_format (prog_bfd, bfd_object)) 1184e98e3e1Schristos { 1194e98e3e1Schristos fprintf (stderr, "%s: \"%s\" is not an object file: %s\n", 1204e98e3e1Schristos myname, name, bfd_errmsg (bfd_get_error ())); 1214e98e3e1Schristos exit (1); 1224e98e3e1Schristos } 1234e98e3e1Schristos } 1244e98e3e1Schristos 1254e98e3e1Schristos if (STATE_VERBOSE_P (sd)) 1264e98e3e1Schristos printf ("%s %s\n", myname, name); 1274e98e3e1Schristos 1284e98e3e1Schristos /* Load the program into the simulator. */ 1294e98e3e1Schristos if (sim_load (sd, name, prog_bfd, 0) == SIM_RC_FAIL) 1304e98e3e1Schristos exit (1); 1314e98e3e1Schristos 1324e98e3e1Schristos /* Prepare the program for execution. */ 1334b169a6bSchristos sim_create_inferior (sd, prog_bfd, prog_argv, prog_envp); 1344e98e3e1Schristos 1354e98e3e1Schristos /* To accommodate relative file paths, chdir to sysroot now. We 1364e98e3e1Schristos mustn't do this until BFD has opened the program, else we wouldn't 1374e98e3e1Schristos find the executable if it has a relative file path. */ 1384e98e3e1Schristos if (simulator_sysroot[0] != '\0' && chdir (simulator_sysroot) < 0) 1394e98e3e1Schristos { 1404e98e3e1Schristos fprintf (stderr, "%s: can't change directory to \"%s\"\n", 1414e98e3e1Schristos myname, simulator_sysroot); 1424e98e3e1Schristos exit (1); 1434e98e3e1Schristos } 1444e98e3e1Schristos 1454e98e3e1Schristos /* Run/Step the program. */ 1464e98e3e1Schristos if (single_step) 1474e98e3e1Schristos { 1484e98e3e1Schristos do 1494e98e3e1Schristos { 1504e98e3e1Schristos prev_sigint = signal (SIGINT, cntrl_c); 1514e98e3e1Schristos sim_resume (sd, 1/*step*/, 0); 1524e98e3e1Schristos signal (SIGINT, prev_sigint); 1534e98e3e1Schristos sim_stop_reason (sd, &reason, &sigrc); 1544e98e3e1Schristos 1554e98e3e1Schristos if ((reason == sim_stopped) && 1564e98e3e1Schristos (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) 1574e98e3e1Schristos break; /* exit on control-C */ 1584e98e3e1Schristos } 1594e98e3e1Schristos /* remain on breakpoint or signals in oe mode*/ 1604e98e3e1Schristos while (((reason == sim_signalled) && 1614e98e3e1Schristos (sigrc == sim_signal_to_host (sd, SIM_SIGTRAP))) || 1624e98e3e1Schristos ((reason == sim_stopped) && 1634e98e3e1Schristos (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT))); 1644e98e3e1Schristos } 1654e98e3e1Schristos else 1664e98e3e1Schristos { 1674e98e3e1Schristos do 1684e98e3e1Schristos { 1694e98e3e1Schristos #if defined (HAVE_SIGACTION) && defined (SA_RESTART) 1704e98e3e1Schristos struct sigaction sa, osa; 1714e98e3e1Schristos sa.sa_handler = cntrl_c; 1724e98e3e1Schristos sigemptyset (&sa.sa_mask); 1734e98e3e1Schristos sa.sa_flags = 0; 1744e98e3e1Schristos sigaction (SIGINT, &sa, &osa); 1754e98e3e1Schristos prev_sigint = osa.sa_handler; 1764e98e3e1Schristos #else 1774e98e3e1Schristos prev_sigint = signal (SIGINT, cntrl_c); 1784e98e3e1Schristos #endif 1794e98e3e1Schristos sim_resume (sd, 0, sigrc); 1804e98e3e1Schristos signal (SIGINT, prev_sigint); 1814e98e3e1Schristos sim_stop_reason (sd, &reason, &sigrc); 1824e98e3e1Schristos 1834e98e3e1Schristos if ((reason == sim_stopped) && 1844e98e3e1Schristos (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) 1854e98e3e1Schristos break; /* exit on control-C */ 1864e98e3e1Schristos 1874e98e3e1Schristos /* remain on signals in oe mode */ 1884e98e3e1Schristos } while ((reason == sim_stopped) && 1894e98e3e1Schristos (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)); 1904e98e3e1Schristos 1914e98e3e1Schristos } 1924e98e3e1Schristos /* Print any stats the simulator collected. */ 1934e98e3e1Schristos if (STATE_VERBOSE_P (sd)) 1944e98e3e1Schristos sim_info (sd, 0); 1954e98e3e1Schristos 1964e98e3e1Schristos /* Shutdown the simulator. */ 1974e98e3e1Schristos sim_close (sd, 0); 1984e98e3e1Schristos 1994e98e3e1Schristos /* If reason is sim_exited, then sigrc holds the exit code which we want 2004e98e3e1Schristos to return. If reason is sim_stopped or sim_signalled, then sigrc holds 2014e98e3e1Schristos the signal that the simulator received; we want to return that to 2024e98e3e1Schristos indicate failure. */ 2034e98e3e1Schristos 2044e98e3e1Schristos /* Why did we stop? */ 2054e98e3e1Schristos switch (reason) 2064e98e3e1Schristos { 2074e98e3e1Schristos case sim_signalled: 2084e98e3e1Schristos case sim_stopped: 2094e98e3e1Schristos if (sigrc != 0) 210a2e2270fSchristos fprintf (stderr, "program stopped with signal %d (%s).\n", sigrc, 211a2e2270fSchristos strsignal (sigrc)); 2124e98e3e1Schristos break; 2134e98e3e1Schristos 2144e98e3e1Schristos case sim_exited: 2154e98e3e1Schristos break; 2164e98e3e1Schristos 2174e98e3e1Schristos default: 2184e98e3e1Schristos fprintf (stderr, "program in undefined state (%d:%d)\n", reason, sigrc); 2194e98e3e1Schristos break; 2204e98e3e1Schristos 2214e98e3e1Schristos } 2224e98e3e1Schristos 2234e98e3e1Schristos return sigrc; 2244e98e3e1Schristos } 2254e98e3e1Schristos 2264e98e3e1Schristos static void 2274e98e3e1Schristos usage (void) 2284e98e3e1Schristos { 2294b169a6bSchristos fprintf (stderr, "Usage: %s [options] [VAR=VAL|--] program [program args]\n", 2304b169a6bSchristos myname); 2314e98e3e1Schristos fprintf (stderr, "Run `%s --help' for full list of options.\n", myname); 2324e98e3e1Schristos exit (1); 2334e98e3e1Schristos } 234