14e98e3e1Schristos /* Utility to load a file into the simulator. 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 174e98e3e1Schristos /* This is a standalone loader, independent of the sim-basic.h machinery, 184e98e3e1Schristos as it is used by simulators that don't use it [though that doesn't mean 194e98e3e1Schristos to suggest that they shouldn't :-)]. */ 204e98e3e1Schristos 214b169a6bSchristos /* This must come before any other includes. */ 224b169a6bSchristos #include "defs.h" 234b169a6bSchristos 244e98e3e1Schristos #include <stdarg.h> 254b169a6bSchristos #include <stdio.h> /* for NULL */ 264e98e3e1Schristos #include <stdlib.h> 274e98e3e1Schristos #include <time.h> 284e98e3e1Schristos 294b169a6bSchristos #include "ansidecl.h" 304e98e3e1Schristos #include "bfd.h" 314e98e3e1Schristos 324b169a6bSchristos #include "sim/callback.h" 334b169a6bSchristos #include "sim/sim.h" 344b169a6bSchristos #include "sim-utils.h" 354e98e3e1Schristos 3603467a24Schristos static void eprintf (host_callback *, const char *, ...); 3703467a24Schristos static void xprintf (host_callback *, const char *, ...); 384e98e3e1Schristos static void report_transfer_performance 3903467a24Schristos (host_callback *, unsigned long, time_t, time_t); 404e98e3e1Schristos 414b169a6bSchristos /* Load program PROG into the simulator using the function DO_WRITE. 424e98e3e1Schristos If PROG_BFD is non-NULL, the file has already been opened. 434e98e3e1Schristos If VERBOSE_P is non-zero statistics are printed of each loaded section 444e98e3e1Schristos and the transfer rate (for consistency with gdb). 454e98e3e1Schristos If LMA_P is non-zero the program sections are loaded at the LMA 464e98e3e1Schristos rather than the VMA 474e98e3e1Schristos If this fails an error message is printed and NULL is returned. 484e98e3e1Schristos If it succeeds the bfd is returned. 494e98e3e1Schristos NOTE: For historical reasons, older hardware simulators incorrectly 504e98e3e1Schristos write the program sections at LMA interpreted as a virtual address. 514e98e3e1Schristos This is still accommodated for backward compatibility reasons. */ 524e98e3e1Schristos 534e98e3e1Schristos 544e98e3e1Schristos bfd * 55837edd6bSchristos sim_load_file (SIM_DESC sd, const char *myname, host_callback *callback, 56837edd6bSchristos const char *prog, bfd *prog_bfd, int verbose_p, int lma_p, 57837edd6bSchristos sim_write_fn do_write) 584e98e3e1Schristos { 594e98e3e1Schristos asection *s; 604e98e3e1Schristos /* Record separately as we don't want to close PROG_BFD if it was passed. */ 614e98e3e1Schristos bfd *result_bfd; 624e98e3e1Schristos time_t start_time = 0; /* Start and end times of download */ 634e98e3e1Schristos time_t end_time = 0; 644e98e3e1Schristos unsigned long data_count = 0; /* Number of bytes transferred to memory */ 654e98e3e1Schristos int found_loadable_section; 664e98e3e1Schristos 674e98e3e1Schristos if (prog_bfd != NULL) 684e98e3e1Schristos result_bfd = prog_bfd; 694e98e3e1Schristos else 704e98e3e1Schristos { 714e98e3e1Schristos result_bfd = bfd_openr (prog, 0); 724e98e3e1Schristos if (result_bfd == NULL) 734e98e3e1Schristos { 744e98e3e1Schristos eprintf (callback, "%s: can't open \"%s\": %s\n", 754e98e3e1Schristos myname, prog, bfd_errmsg (bfd_get_error ())); 764e98e3e1Schristos return NULL; 774e98e3e1Schristos } 784e98e3e1Schristos } 794e98e3e1Schristos 804e98e3e1Schristos if (!bfd_check_format (result_bfd, bfd_object)) 814e98e3e1Schristos { 824e98e3e1Schristos eprintf (callback, "%s: \"%s\" is not an object file: %s\n", 834e98e3e1Schristos myname, prog, bfd_errmsg (bfd_get_error ())); 844e98e3e1Schristos /* Only close if we opened it. */ 854e98e3e1Schristos if (prog_bfd == NULL) 864e98e3e1Schristos bfd_close (result_bfd); 874e98e3e1Schristos return NULL; 884e98e3e1Schristos } 894e98e3e1Schristos 904e98e3e1Schristos if (verbose_p) 914e98e3e1Schristos start_time = time (NULL); 924e98e3e1Schristos 934e98e3e1Schristos found_loadable_section = 0; 944e98e3e1Schristos for (s = result_bfd->sections; s; s = s->next) 954e98e3e1Schristos { 964e98e3e1Schristos if (s->flags & SEC_LOAD) 974e98e3e1Schristos { 984e98e3e1Schristos bfd_size_type size; 994e98e3e1Schristos 1008dffb485Schristos size = bfd_section_size (s); 1014e98e3e1Schristos if (size > 0) 1024e98e3e1Schristos { 1034e98e3e1Schristos unsigned char *buffer; 1044e98e3e1Schristos bfd_vma lma; 1054e98e3e1Schristos 1064e98e3e1Schristos buffer = malloc (size); 1074e98e3e1Schristos if (buffer == NULL) 1084e98e3e1Schristos { 1094e98e3e1Schristos eprintf (callback, 1104e98e3e1Schristos "%s: insufficient memory to load \"%s\"\n", 1114e98e3e1Schristos myname, prog); 1124e98e3e1Schristos /* Only close if we opened it. */ 1134e98e3e1Schristos if (prog_bfd == NULL) 1144e98e3e1Schristos bfd_close (result_bfd); 1154e98e3e1Schristos return NULL; 1164e98e3e1Schristos } 1174e98e3e1Schristos if (lma_p) 1188dffb485Schristos lma = bfd_section_lma (s); 1194e98e3e1Schristos else 1208dffb485Schristos lma = bfd_section_vma (s); 1214e98e3e1Schristos if (verbose_p) 1224e98e3e1Schristos { 1234b169a6bSchristos xprintf (callback, 1244b169a6bSchristos "Loading section %s, size 0x%" PRIx64 1254b169a6bSchristos " %s %" PRIx64 "\n", 1264b169a6bSchristos bfd_section_name (s), (uint64_t) size, 1274b169a6bSchristos lma_p ? "lma" : "vma", (uint64_t) lma); 1284e98e3e1Schristos } 1294e98e3e1Schristos data_count += size; 1304e98e3e1Schristos bfd_get_section_contents (result_bfd, s, buffer, 0, size); 1314e98e3e1Schristos do_write (sd, lma, buffer, size); 1324e98e3e1Schristos found_loadable_section = 1; 1334e98e3e1Schristos free (buffer); 1344e98e3e1Schristos } 1354e98e3e1Schristos } 1364e98e3e1Schristos } 1374e98e3e1Schristos 1384e98e3e1Schristos if (!found_loadable_section) 1394e98e3e1Schristos { 1404e98e3e1Schristos eprintf (callback, 1414e98e3e1Schristos "%s: no loadable sections \"%s\"\n", 1424e98e3e1Schristos myname, prog); 1434e98e3e1Schristos return NULL; 1444e98e3e1Schristos } 1454e98e3e1Schristos 1464e98e3e1Schristos if (verbose_p) 1474e98e3e1Schristos { 1484e98e3e1Schristos end_time = time (NULL); 1494b169a6bSchristos xprintf (callback, "Start address %" PRIx64 "\n", 1504b169a6bSchristos (uint64_t) bfd_get_start_address (result_bfd)); 1514e98e3e1Schristos report_transfer_performance (callback, data_count, start_time, end_time); 1524e98e3e1Schristos } 1534e98e3e1Schristos 1544e98e3e1Schristos bfd_cache_close (result_bfd); 1554e98e3e1Schristos 1564e98e3e1Schristos return result_bfd; 1574e98e3e1Schristos } 1584e98e3e1Schristos 1594e98e3e1Schristos static void 16003467a24Schristos xprintf (host_callback *callback, const char *fmt, ...) 1614e98e3e1Schristos { 1624e98e3e1Schristos va_list ap; 1634e98e3e1Schristos 16403467a24Schristos va_start (ap, fmt); 1654e98e3e1Schristos 1664e98e3e1Schristos (*callback->vprintf_filtered) (callback, fmt, ap); 1674e98e3e1Schristos 1684e98e3e1Schristos va_end (ap); 1694e98e3e1Schristos } 1704e98e3e1Schristos 1714e98e3e1Schristos static void 17203467a24Schristos eprintf (host_callback *callback, const char *fmt, ...) 1734e98e3e1Schristos { 1744e98e3e1Schristos va_list ap; 1754e98e3e1Schristos 17603467a24Schristos va_start (ap, fmt); 1774e98e3e1Schristos 1784e98e3e1Schristos (*callback->evprintf_filtered) (callback, fmt, ap); 1794e98e3e1Schristos 1804e98e3e1Schristos va_end (ap); 1814e98e3e1Schristos } 1824e98e3e1Schristos 1834e98e3e1Schristos /* Report how fast the transfer went. */ 1844e98e3e1Schristos 1854e98e3e1Schristos static void 186837edd6bSchristos report_transfer_performance (host_callback *callback, unsigned long data_count, 187837edd6bSchristos time_t start_time, time_t end_time) 1884e98e3e1Schristos { 1894e98e3e1Schristos xprintf (callback, "Transfer rate: "); 1904e98e3e1Schristos if (end_time != start_time) 1914e98e3e1Schristos xprintf (callback, "%ld bits/sec", 1924e98e3e1Schristos (data_count * 8) / (end_time - start_time)); 1934e98e3e1Schristos else 1944e98e3e1Schristos xprintf (callback, "%ld bits in <1 sec", (data_count * 8)); 1954e98e3e1Schristos xprintf (callback, ".\n"); 1964e98e3e1Schristos } 197