14e98e3e1Schristos /* Miscellaneous simulator utilities. 2*88241920Schristos Copyright (C) 1997-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224e98e3e1Schristos 234b169a6bSchristos #include <stdarg.h> 244e98e3e1Schristos #include <stdlib.h> 254b169a6bSchristos #include <string.h> 264e98e3e1Schristos #include <time.h> 274e98e3e1Schristos #ifdef HAVE_SYS_RESOURCE_H 284e98e3e1Schristos #include <sys/resource.h> 294e98e3e1Schristos #endif 304b169a6bSchristos #include <sys/time.h> /* needed by sys/resource.h */ 314e98e3e1Schristos 324e98e3e1Schristos #include "bfd.h" 334b169a6bSchristos #include "libiberty.h" 344b169a6bSchristos 354b169a6bSchristos #include "sim-main.h" 364b169a6bSchristos #include "sim-assert.h" 374e98e3e1Schristos #include "sim-utils.h" 384e98e3e1Schristos 394e98e3e1Schristos /* Allocate zero filled memory with xcalloc - xcalloc aborts if the 404e98e3e1Schristos allocation fails. */ 414e98e3e1Schristos 424e98e3e1Schristos void * 434e98e3e1Schristos zalloc (unsigned long size) 444e98e3e1Schristos { 454e98e3e1Schristos return xcalloc (1, size); 464e98e3e1Schristos } 474e98e3e1Schristos 484e98e3e1Schristos /* Allocate a sim_state struct. */ 494e98e3e1Schristos 504e98e3e1Schristos SIM_DESC 514b169a6bSchristos sim_state_alloc_extra (SIM_OPEN_KIND kind, host_callback *callback, 524b169a6bSchristos size_t extra_bytes) 534e98e3e1Schristos { 544e98e3e1Schristos SIM_DESC sd = ZALLOC (struct sim_state); 554e98e3e1Schristos 564e98e3e1Schristos STATE_MAGIC (sd) = SIM_MAGIC_NUMBER; 574e98e3e1Schristos STATE_CALLBACK (sd) = callback; 584e98e3e1Schristos STATE_OPEN_KIND (sd) = kind; 594e98e3e1Schristos 604b169a6bSchristos if (extra_bytes) 614b169a6bSchristos STATE_ARCH_DATA (sd) = zalloc (extra_bytes); 624b169a6bSchristos 634e98e3e1Schristos #if 0 644e98e3e1Schristos { 654e98e3e1Schristos int cpu_nr; 664e98e3e1Schristos 674e98e3e1Schristos /* Initialize the back link from the cpu struct to the state struct. */ 684e98e3e1Schristos /* ??? I can envision a design where the state struct contains an array 694e98e3e1Schristos of pointers to cpu structs, rather than an array of structs themselves. 704e98e3e1Schristos Implementing this is trickier as one may not know what to allocate until 714e98e3e1Schristos one has parsed the args. Parsing the args twice wouldn't be unreasonable, 724e98e3e1Schristos IMHO. If the state struct ever does contain an array of pointers then we 734e98e3e1Schristos can't do this here. 744e98e3e1Schristos ??? See also sim_post_argv_init*/ 754e98e3e1Schristos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 764e98e3e1Schristos { 774e98e3e1Schristos CPU_STATE (STATE_CPU (sd, cpu_nr)) = sd; 784e98e3e1Schristos CPU_INDEX (STATE_CPU (sd, cpu_nr)) = cpu_nr; 794e98e3e1Schristos } 804e98e3e1Schristos } 814e98e3e1Schristos #endif 824e98e3e1Schristos 834e98e3e1Schristos #ifdef SIM_STATE_INIT 844e98e3e1Schristos SIM_STATE_INIT (sd); 854e98e3e1Schristos #endif 864e98e3e1Schristos 874e98e3e1Schristos return sd; 884e98e3e1Schristos } 894e98e3e1Schristos 904e98e3e1Schristos /* Free a sim_state struct. */ 914e98e3e1Schristos 924e98e3e1Schristos void 934e98e3e1Schristos sim_state_free (SIM_DESC sd) 944e98e3e1Schristos { 95ba340e45Schristos ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 964e98e3e1Schristos 974e98e3e1Schristos #ifdef SIM_STATE_FREE 984e98e3e1Schristos SIM_STATE_FREE (sd); 994e98e3e1Schristos #endif 1004e98e3e1Schristos 1014b169a6bSchristos free (STATE_PROG_FILE (sd)); 1024b169a6bSchristos free (STATE_PROG_ARGV0 (sd)); 1034b169a6bSchristos freeargv (STATE_PROG_ENVP (sd)); 1044e98e3e1Schristos free (sd); 1054e98e3e1Schristos } 1064e98e3e1Schristos 1074e98e3e1Schristos /* Return a pointer to the cpu data for CPU_NAME, or NULL if not found. */ 1084e98e3e1Schristos 1094e98e3e1Schristos sim_cpu * 1104e98e3e1Schristos sim_cpu_lookup (SIM_DESC sd, const char *cpu_name) 1114e98e3e1Schristos { 1124e98e3e1Schristos int i; 1134e98e3e1Schristos 1144e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 1154e98e3e1Schristos if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0) 1164e98e3e1Schristos return STATE_CPU (sd, i); 1174e98e3e1Schristos return NULL; 1184e98e3e1Schristos } 1194e98e3e1Schristos 1204e98e3e1Schristos /* Return the prefix to use for a CPU specific message (typically an 1214e98e3e1Schristos error message). */ 1224e98e3e1Schristos 1234e98e3e1Schristos const char * 1244e98e3e1Schristos sim_cpu_msg_prefix (sim_cpu *cpu) 1254e98e3e1Schristos { 1264e98e3e1Schristos static char *prefix; 1274e98e3e1Schristos 128*88241920Schristos if (MAX_NR_PROCESSORS == 1) 129*88241920Schristos return ""; 130*88241920Schristos 1314e98e3e1Schristos if (prefix == NULL) 1324e98e3e1Schristos { 133*88241920Schristos SIM_DESC sd = CPU_STATE (cpu); 1344e98e3e1Schristos int maxlen = 0; 135*88241920Schristos int i; 136*88241920Schristos 1374e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 1384e98e3e1Schristos { 1394e98e3e1Schristos int len = strlen (CPU_NAME (STATE_CPU (sd, i))); 1404e98e3e1Schristos if (len > maxlen) 1414e98e3e1Schristos maxlen = len; 1424e98e3e1Schristos } 1434e98e3e1Schristos prefix = (char *) xmalloc (maxlen + 5); 1444e98e3e1Schristos } 1454e98e3e1Schristos sprintf (prefix, "%s: ", CPU_NAME (cpu)); 146*88241920Schristos 1474e98e3e1Schristos return prefix; 1484e98e3e1Schristos } 1494e98e3e1Schristos 1504e98e3e1Schristos /* Cover fn to sim_io_eprintf. */ 1514e98e3e1Schristos 1524e98e3e1Schristos void 1534e98e3e1Schristos sim_io_eprintf_cpu (sim_cpu *cpu, const char *fmt, ...) 1544e98e3e1Schristos { 1554e98e3e1Schristos SIM_DESC sd = CPU_STATE (cpu); 1564e98e3e1Schristos va_list ap; 1574e98e3e1Schristos 1584e98e3e1Schristos va_start (ap, fmt); 1594e98e3e1Schristos sim_io_eprintf (sd, "%s", sim_cpu_msg_prefix (cpu)); 1604e98e3e1Schristos sim_io_evprintf (sd, fmt, ap); 1614e98e3e1Schristos va_end (ap); 1624e98e3e1Schristos } 1634e98e3e1Schristos 1644e98e3e1Schristos /* Turn VALUE into a string with commas. */ 1654e98e3e1Schristos 1664e98e3e1Schristos char * 1674e98e3e1Schristos sim_add_commas (char *buf, int sizeof_buf, unsigned long value) 1684e98e3e1Schristos { 1694e98e3e1Schristos int comma = 3; 1704e98e3e1Schristos char *endbuf = buf + sizeof_buf - 1; 1714e98e3e1Schristos 1724e98e3e1Schristos *--endbuf = '\0'; 1734e98e3e1Schristos do { 1744e98e3e1Schristos if (comma-- == 0) 1754e98e3e1Schristos { 1764e98e3e1Schristos *--endbuf = ','; 1774e98e3e1Schristos comma = 2; 1784e98e3e1Schristos } 1794e98e3e1Schristos 1804e98e3e1Schristos *--endbuf = (value % 10) + '0'; 1814e98e3e1Schristos } while ((value /= 10) != 0); 1824e98e3e1Schristos 1834e98e3e1Schristos return endbuf; 1844e98e3e1Schristos } 1854e98e3e1Schristos 1864e98e3e1Schristos /* Analyze PROG_NAME/PROG_BFD and set these fields in the state struct: 1874e98e3e1Schristos STATE_ARCHITECTURE, if not set already and can be determined from the bfd 1884e98e3e1Schristos STATE_PROG_BFD 1894e98e3e1Schristos STATE_START_ADDR 1904e98e3e1Schristos STATE_TEXT_SECTION 1914e98e3e1Schristos STATE_TEXT_START 1924e98e3e1Schristos STATE_TEXT_END 1934e98e3e1Schristos 1944e98e3e1Schristos PROG_NAME is the file name of the executable or NULL. 1954e98e3e1Schristos PROG_BFD is its bfd or NULL. 1964e98e3e1Schristos 1974e98e3e1Schristos If both PROG_NAME and PROG_BFD are NULL, this function returns immediately. 1984e98e3e1Schristos If PROG_BFD is not NULL, PROG_NAME is ignored. 1994e98e3e1Schristos 2004e98e3e1Schristos Implicit inputs: STATE_MY_NAME(sd), STATE_TARGET(sd), 2014e98e3e1Schristos STATE_ARCHITECTURE(sd). 2024e98e3e1Schristos 2034e98e3e1Schristos A new bfd is created so the app isn't required to keep its copy of the 2044e98e3e1Schristos bfd open. */ 2054e98e3e1Schristos 2064e98e3e1Schristos SIM_RC 207837edd6bSchristos sim_analyze_program (SIM_DESC sd, const char *prog_name, bfd *prog_bfd) 2084e98e3e1Schristos { 2094e98e3e1Schristos asection *s; 2104e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 2114e98e3e1Schristos 2124e98e3e1Schristos if (prog_bfd != NULL) 2134e98e3e1Schristos { 2144e98e3e1Schristos if (prog_bfd == STATE_PROG_BFD (sd)) 2154e98e3e1Schristos /* already analyzed */ 2164e98e3e1Schristos return SIM_RC_OK; 2174e98e3e1Schristos else 2184e98e3e1Schristos /* duplicate needed, save the name of the file to be re-opened */ 2194e98e3e1Schristos prog_name = bfd_get_filename (prog_bfd); 2204e98e3e1Schristos } 2214e98e3e1Schristos 2224e98e3e1Schristos /* do we need to duplicate anything? */ 2234e98e3e1Schristos if (prog_name == NULL) 2244e98e3e1Schristos return SIM_RC_OK; 2254e98e3e1Schristos 2264e98e3e1Schristos /* open a new copy of the prog_bfd */ 2274e98e3e1Schristos prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd)); 2284e98e3e1Schristos if (prog_bfd == NULL) 2294e98e3e1Schristos { 2304e98e3e1Schristos sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n", 2314e98e3e1Schristos STATE_MY_NAME (sd), 2324e98e3e1Schristos prog_name, 2334e98e3e1Schristos bfd_errmsg (bfd_get_error ())); 2344e98e3e1Schristos return SIM_RC_FAIL; 2354e98e3e1Schristos } 2364e98e3e1Schristos if (!bfd_check_format (prog_bfd, bfd_object)) 2374e98e3e1Schristos { 2384e98e3e1Schristos sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n", 2394e98e3e1Schristos STATE_MY_NAME (sd), 2404e98e3e1Schristos prog_name, 2414e98e3e1Schristos bfd_errmsg (bfd_get_error ())); 2424e98e3e1Schristos bfd_close (prog_bfd); 2434e98e3e1Schristos return SIM_RC_FAIL; 2444e98e3e1Schristos } 2454e98e3e1Schristos if (STATE_ARCHITECTURE (sd) != NULL) 2464e98e3e1Schristos bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd)); 2474e98e3e1Schristos else 2484e98e3e1Schristos { 2494e98e3e1Schristos if (bfd_get_arch (prog_bfd) != bfd_arch_unknown 2504e98e3e1Schristos && bfd_get_arch (prog_bfd) != bfd_arch_obscure) 2514e98e3e1Schristos { 2524e98e3e1Schristos STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd); 2534e98e3e1Schristos } 2544e98e3e1Schristos } 2554e98e3e1Schristos 2564e98e3e1Schristos /* update the sim structure */ 2574e98e3e1Schristos if (STATE_PROG_BFD (sd) != NULL) 2584e98e3e1Schristos bfd_close (STATE_PROG_BFD (sd)); 2594e98e3e1Schristos STATE_PROG_BFD (sd) = prog_bfd; 2604e98e3e1Schristos STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd); 2614e98e3e1Schristos 2624e98e3e1Schristos for (s = prog_bfd->sections; s; s = s->next) 2638dffb485Schristos if (strcmp (bfd_section_name (s), ".text") == 0) 2644e98e3e1Schristos { 2654e98e3e1Schristos STATE_TEXT_SECTION (sd) = s; 2668dffb485Schristos STATE_TEXT_START (sd) = bfd_section_vma (s); 2678dffb485Schristos STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (s); 2684e98e3e1Schristos break; 2694e98e3e1Schristos } 2704e98e3e1Schristos 2714e98e3e1Schristos bfd_cache_close (prog_bfd); 2724e98e3e1Schristos 2734e98e3e1Schristos return SIM_RC_OK; 2744e98e3e1Schristos } 2754e98e3e1Schristos 2764e98e3e1Schristos /* Simulator timing support. */ 2774e98e3e1Schristos 2784e98e3e1Schristos /* Called before sim_elapsed_time_since to get a reference point. */ 2794e98e3e1Schristos 2804e98e3e1Schristos SIM_ELAPSED_TIME 2814e98e3e1Schristos sim_elapsed_time_get (void) 2824e98e3e1Schristos { 2834e98e3e1Schristos #ifdef HAVE_GETRUSAGE 2844e98e3e1Schristos struct rusage mytime; 2854e98e3e1Schristos if (getrusage (RUSAGE_SELF, &mytime) == 0) 2864e98e3e1Schristos return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000)); 2874e98e3e1Schristos return 1; 2884e98e3e1Schristos #else 2894e98e3e1Schristos #ifdef HAVE_TIME 2904e98e3e1Schristos return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0); 2914e98e3e1Schristos #else 2924e98e3e1Schristos return 1; 2934e98e3e1Schristos #endif 2944e98e3e1Schristos #endif 2954e98e3e1Schristos } 2964e98e3e1Schristos 2974e98e3e1Schristos /* Return the elapsed time in milliseconds since START. 2984e98e3e1Schristos The actual time may be cpu usage (preferred) or wall clock. */ 2994e98e3e1Schristos 3004e98e3e1Schristos unsigned long 3014e98e3e1Schristos sim_elapsed_time_since (SIM_ELAPSED_TIME start) 3024e98e3e1Schristos { 3034e98e3e1Schristos #ifdef HAVE_GETRUSAGE 3044e98e3e1Schristos return sim_elapsed_time_get () - start; 3054e98e3e1Schristos #else 3064e98e3e1Schristos #ifdef HAVE_TIME 3074e98e3e1Schristos return (sim_elapsed_time_get () - start) * 1000; 3084e98e3e1Schristos #else 3094e98e3e1Schristos return 0; 3104e98e3e1Schristos #endif 3114e98e3e1Schristos #endif 3124e98e3e1Schristos } 3134e98e3e1Schristos 3144e98e3e1Schristos 3154e98e3e1Schristos 3164e98e3e1Schristos /* do_command but with printf style formatting of the arguments */ 3174e98e3e1Schristos void 3184e98e3e1Schristos sim_do_commandf (SIM_DESC sd, 3194e98e3e1Schristos const char *fmt, 3204e98e3e1Schristos ...) 3214e98e3e1Schristos { 3224e98e3e1Schristos va_list ap; 3234e98e3e1Schristos char *buf; 324ba340e45Schristos int ret; 325ba340e45Schristos 3264e98e3e1Schristos va_start (ap, fmt); 327ba340e45Schristos ret = vasprintf (&buf, fmt, ap); 328ba340e45Schristos va_end (ap); 329ba340e45Schristos 330ba340e45Schristos if (ret < 0) 3314e98e3e1Schristos { 3324e98e3e1Schristos sim_io_eprintf (sd, "%s: asprintf failed for `%s'\n", 3334e98e3e1Schristos STATE_MY_NAME (sd), fmt); 3344e98e3e1Schristos return; 3354e98e3e1Schristos } 336ba340e45Schristos 3374e98e3e1Schristos sim_do_command (sd, buf); 3384e98e3e1Schristos free (buf); 3394e98e3e1Schristos } 3404e98e3e1Schristos 3414e98e3e1Schristos 3424e98e3e1Schristos /* sim-basics.h defines a number of enumerations, convert each of them 3434e98e3e1Schristos to a string representation */ 3444e98e3e1Schristos const char * 3454e98e3e1Schristos map_to_str (unsigned map) 3464e98e3e1Schristos { 3474e98e3e1Schristos switch (map) 3484e98e3e1Schristos { 3494e98e3e1Schristos case read_map: return "read"; 3504e98e3e1Schristos case write_map: return "write"; 3514e98e3e1Schristos case exec_map: return "exec"; 3524e98e3e1Schristos case io_map: return "io"; 3534e98e3e1Schristos default: 3544e98e3e1Schristos { 3558dffb485Schristos static char str[16]; 3568dffb485Schristos snprintf (str, sizeof(str), "(%ld)", (long) map); 3574e98e3e1Schristos return str; 3584e98e3e1Schristos } 3594e98e3e1Schristos } 3604e98e3e1Schristos } 3614e98e3e1Schristos 3624e98e3e1Schristos const char * 3634e98e3e1Schristos access_to_str (unsigned access) 3644e98e3e1Schristos { 3654e98e3e1Schristos switch (access) 3664e98e3e1Schristos { 3674e98e3e1Schristos case access_invalid: return "invalid"; 3684e98e3e1Schristos case access_read: return "read"; 3694e98e3e1Schristos case access_write: return "write"; 3704e98e3e1Schristos case access_exec: return "exec"; 3714e98e3e1Schristos case access_io: return "io"; 3724e98e3e1Schristos case access_read_write: return "read_write"; 3734e98e3e1Schristos case access_read_exec: return "read_exec"; 3744e98e3e1Schristos case access_write_exec: return "write_exec"; 3754e98e3e1Schristos case access_read_write_exec: return "read_write_exec"; 3764e98e3e1Schristos case access_read_io: return "read_io"; 3774e98e3e1Schristos case access_write_io: return "write_io"; 3784e98e3e1Schristos case access_read_write_io: return "read_write_io"; 3794e98e3e1Schristos case access_exec_io: return "exec_io"; 3804e98e3e1Schristos case access_read_exec_io: return "read_exec_io"; 3814e98e3e1Schristos case access_write_exec_io: return "write_exec_io"; 3824e98e3e1Schristos case access_read_write_exec_io: return "read_write_exec_io"; 3834e98e3e1Schristos default: 3844e98e3e1Schristos { 3858dffb485Schristos static char str[16]; 3868dffb485Schristos snprintf (str, sizeof(str), "(%ld)", (long) access); 3874e98e3e1Schristos return str; 3884e98e3e1Schristos } 3894e98e3e1Schristos } 3904e98e3e1Schristos } 3914e98e3e1Schristos 3924e98e3e1Schristos const char * 3934e98e3e1Schristos transfer_to_str (unsigned transfer) 3944e98e3e1Schristos { 3954e98e3e1Schristos switch (transfer) 3964e98e3e1Schristos { 3974e98e3e1Schristos case read_transfer: return "read"; 3984e98e3e1Schristos case write_transfer: return "write"; 3994e98e3e1Schristos default: return "(error)"; 4004e98e3e1Schristos } 4014e98e3e1Schristos } 402