14e98e3e1Schristos /* load.c --- loading object files into the RX simulator. 24e98e3e1Schristos 3*1f4e7eb9Schristos Copyright (C) 2005-2024 Free Software Foundation, Inc. 44e98e3e1Schristos Contributed by Red Hat, Inc. 54e98e3e1Schristos 64e98e3e1Schristos This file is part of the GNU simulators. 74e98e3e1Schristos 84e98e3e1Schristos This program is free software; you can redistribute it and/or modify 94e98e3e1Schristos it under the terms of the GNU General Public License as published by 104e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 114e98e3e1Schristos (at your option) any later version. 124e98e3e1Schristos 134e98e3e1Schristos This program is distributed in the hope that it will be useful, 144e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 154e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 164e98e3e1Schristos GNU General Public License for more details. 174e98e3e1Schristos 184e98e3e1Schristos You should have received a copy of the GNU General Public License 194e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 204e98e3e1Schristos 214b169a6bSchristos /* This must come before any other includes. */ 224b169a6bSchristos #include "defs.h" 234e98e3e1Schristos 244e98e3e1Schristos #include <stdlib.h> 254e98e3e1Schristos #include <stdio.h> 264e98e3e1Schristos #include <string.h> 274e98e3e1Schristos 284e98e3e1Schristos #include "bfd.h" 294e98e3e1Schristos #include "cpu.h" 304e98e3e1Schristos #include "mem.h" 31a2e2270fSchristos #include "load.h" 32*1f4e7eb9Schristos #include "bfd/elf-bfd.h" 334e98e3e1Schristos 34a2e2270fSchristos /* Helper function for invoking a GDB-specified printf. */ 35a2e2270fSchristos static void 36a2e2270fSchristos xprintf (host_callback *callback, const char *fmt, ...) 37a2e2270fSchristos { 38a2e2270fSchristos va_list ap; 39a2e2270fSchristos 40a2e2270fSchristos va_start (ap, fmt); 41a2e2270fSchristos 42a2e2270fSchristos (*callback->vprintf_filtered) (callback, fmt, ap); 43a2e2270fSchristos 44a2e2270fSchristos va_end (ap); 45a2e2270fSchristos } 46a2e2270fSchristos 47a2e2270fSchristos /* Given a file offset, look up the section name. */ 48a2e2270fSchristos static const char * 49a2e2270fSchristos find_section_name_by_offset (bfd *abfd, file_ptr filepos) 50a2e2270fSchristos { 51a2e2270fSchristos asection *s; 52a2e2270fSchristos 53a2e2270fSchristos for (s = abfd->sections; s; s = s->next) 54a2e2270fSchristos if (s->filepos == filepos) 558dffb485Schristos return bfd_section_name (s); 56a2e2270fSchristos 57a2e2270fSchristos return "(unknown)"; 58a2e2270fSchristos } 59a2e2270fSchristos 604e98e3e1Schristos /* A note about endianness and swapping... 614e98e3e1Schristos 624e98e3e1Schristos The RX chip is CISC-like in that the opcodes are variable length 634e98e3e1Schristos and are read as a stream of bytes. However, the chip itself shares 644e98e3e1Schristos the code prefetch block with the data fetch block, so when it's 654e98e3e1Schristos configured for big endian mode, the memory fetched for opcodes is 664e98e3e1Schristos word-swapped. To compensate for this, the ELF file has the code 674e98e3e1Schristos sections pre-swapped. Our BFD knows this, and for the convenience 684e98e3e1Schristos of all the other tools, hides this swapping at a very low level. 694e98e3e1Schristos I.e. it swaps words on the way out and on the way back in. 704e98e3e1Schristos 714e98e3e1Schristos Fortunately the iovector routines are unaffected by this, so we 724e98e3e1Schristos can use them to read in the segments directly, without having 734e98e3e1Schristos to worry about byte swapping anything. 744e98e3e1Schristos 754e98e3e1Schristos However, our opcode decoder and disassemblers need to swap the data 764e98e3e1Schristos after reading it from the chip memory, just like the chip does. 774e98e3e1Schristos All in all, the code words are swapped four times between the 784e98e3e1Schristos assembler and our decoder. 794e98e3e1Schristos 804e98e3e1Schristos If the chip is running in little-endian mode, no swapping is done 814e98e3e1Schristos anywhere. Note also that the *operands* within opcodes are always 824e98e3e1Schristos encoded in little-endian format. */ 834e98e3e1Schristos 844e98e3e1Schristos void 85a2e2270fSchristos rx_load (bfd *prog, host_callback *callback) 864e98e3e1Schristos { 874e98e3e1Schristos unsigned long highest_addr_loaded = 0; 884e98e3e1Schristos Elf_Internal_Phdr * phdrs; 894e98e3e1Schristos long sizeof_phdrs; 904e98e3e1Schristos int num_headers; 914e98e3e1Schristos int i; 924e98e3e1Schristos 934e98e3e1Schristos rx_big_endian = bfd_big_endian (prog); 944e98e3e1Schristos 954e98e3e1Schristos /* Note we load by ELF program header not by BFD sections. 964e98e3e1Schristos This is because BFD sections get their information from 974e98e3e1Schristos the ELF section structure, which only includes a VMA value 984e98e3e1Schristos and not an LMA value. */ 994e98e3e1Schristos sizeof_phdrs = bfd_get_elf_phdr_upper_bound (prog); 1004e98e3e1Schristos if (sizeof_phdrs == 0) 1014e98e3e1Schristos { 1024e98e3e1Schristos fprintf (stderr, "Failed to get size of program headers\n"); 1034e98e3e1Schristos return; 1044e98e3e1Schristos } 1054e98e3e1Schristos phdrs = malloc (sizeof_phdrs); 1064e98e3e1Schristos if (phdrs == NULL) 1074e98e3e1Schristos { 1084e98e3e1Schristos fprintf (stderr, "Failed allocate memory to hold program headers\n"); 1094e98e3e1Schristos return; 1104e98e3e1Schristos } 1114e98e3e1Schristos num_headers = bfd_get_elf_phdrs (prog, phdrs); 1124e98e3e1Schristos if (num_headers < 1) 1134e98e3e1Schristos { 1144e98e3e1Schristos fprintf (stderr, "Failed to read program headers\n"); 1154e98e3e1Schristos return; 1164e98e3e1Schristos } 1174e98e3e1Schristos 1184e98e3e1Schristos for (i = 0; i < num_headers; i++) 1194e98e3e1Schristos { 1204e98e3e1Schristos Elf_Internal_Phdr * p = phdrs + i; 1214e98e3e1Schristos char *buf; 1224e98e3e1Schristos bfd_vma size; 1234e98e3e1Schristos bfd_vma base; 1244e98e3e1Schristos file_ptr offset; 1254e98e3e1Schristos 1264e98e3e1Schristos size = p->p_filesz; 1274e98e3e1Schristos if (size <= 0) 1284e98e3e1Schristos continue; 1294e98e3e1Schristos 1304e98e3e1Schristos base = p->p_paddr; 1314e98e3e1Schristos if (verbose > 1) 1324b169a6bSchristos fprintf (stderr, 1334b169a6bSchristos "[load segment: lma=%08" PRIx64 " vma=%08" PRIx64 " " 1344b169a6bSchristos "size=%08" PRIx64 "]\n", 1354b169a6bSchristos (uint64_t) base, (uint64_t) p->p_vaddr, (uint64_t) size); 136a2e2270fSchristos if (callback) 137a2e2270fSchristos xprintf (callback, 1384b169a6bSchristos "Loading section %s, size %#" PRIx64 " lma %08" PRIx64 1394b169a6bSchristos " vma %08" PRIx64 "\n", 140a2e2270fSchristos find_section_name_by_offset (prog, p->p_offset), 1414b169a6bSchristos (uint64_t) size, (uint64_t) base, (uint64_t) p->p_vaddr); 1424e98e3e1Schristos 1434e98e3e1Schristos buf = malloc (size); 1444e98e3e1Schristos if (buf == NULL) 1454e98e3e1Schristos { 1464e98e3e1Schristos fprintf (stderr, "Failed to allocate buffer to hold program segment\n"); 1474e98e3e1Schristos continue; 1484e98e3e1Schristos } 1494e98e3e1Schristos 1504e98e3e1Schristos offset = p->p_offset; 151ba340e45Schristos if (bfd_seek (prog, offset, SEEK_SET) != 0) 1524e98e3e1Schristos { 1534e98e3e1Schristos fprintf (stderr, "Failed to seek to offset %lx\n", (long) offset); 1544e98e3e1Schristos continue; 1554e98e3e1Schristos } 156*1f4e7eb9Schristos if (bfd_read (buf, size, prog) != size) 1574e98e3e1Schristos { 1584b169a6bSchristos fprintf (stderr, "Failed to read %" PRIx64 " bytes\n", 1594b169a6bSchristos (uint64_t) size); 1604e98e3e1Schristos continue; 1614e98e3e1Schristos } 1624e98e3e1Schristos 1634e98e3e1Schristos mem_put_blk (base, buf, size); 1644e98e3e1Schristos free (buf); 1654e98e3e1Schristos if (highest_addr_loaded < base + size - 1 && size >= 4) 1664e98e3e1Schristos highest_addr_loaded = base + size - 1; 1674e98e3e1Schristos } 1684e98e3e1Schristos 1694e98e3e1Schristos free (phdrs); 1704e98e3e1Schristos 1714e98e3e1Schristos regs.r_pc = prog->start_address; 1724e98e3e1Schristos 1734e98e3e1Schristos if (strcmp (bfd_get_target (prog), "srec") == 0 1744e98e3e1Schristos || regs.r_pc == 0) 1754e98e3e1Schristos { 1764e98e3e1Schristos regs.r_pc = mem_get_si (0xfffffffc); 1774e98e3e1Schristos heaptop = heapbottom = 0; 1784e98e3e1Schristos } 1794e98e3e1Schristos 1804e98e3e1Schristos reset_decoder (); 1814e98e3e1Schristos 1824e98e3e1Schristos if (verbose > 1) 1834e98e3e1Schristos fprintf (stderr, "[start pc=%08x %s]\n", 1844e98e3e1Schristos (unsigned int) regs.r_pc, 1854e98e3e1Schristos rx_big_endian ? "BE" : "LE"); 1864e98e3e1Schristos } 187