1 /* load.c --- loading object files into the RL78 simulator. 2 3 Copyright (C) 2005-2016 Free Software Foundation, Inc. 4 Contributed by Red Hat, Inc. 5 6 This file is part of the GNU simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 23 #include "config.h" 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 28 #include "libiberty.h" 29 #include "bfd.h" 30 #include "elf-bfd.h" 31 #include "elf/rl78.h" 32 #include "cpu.h" 33 #include "mem.h" 34 #include "load.h" 35 #include "elf/internal.h" 36 #include "elf/common.h" 37 38 /* Helper function for invoking a GDB-specified printf. */ 39 static void 40 xprintf (host_callback *callback, const char *fmt, ...) 41 { 42 va_list ap; 43 44 va_start (ap, fmt); 45 46 (*callback->vprintf_filtered) (callback, fmt, ap); 47 48 va_end (ap); 49 } 50 51 /* Given a file offset, look up the section name. */ 52 static const char * 53 find_section_name_by_offset (bfd *abfd, file_ptr filepos) 54 { 55 asection *s; 56 57 for (s = abfd->sections; s; s = s->next) 58 if (s->filepos == filepos) 59 return bfd_get_section_name (abfd, s); 60 61 return "(unknown)"; 62 } 63 64 void 65 rl78_load (bfd *prog, host_callback *callbacks, const char * const simname) 66 { 67 Elf_Internal_Phdr * phdrs; 68 long sizeof_phdrs; 69 int num_headers; 70 int i; 71 int max_rom = 0; 72 73 init_cpu (); 74 75 /* Note we load by ELF program header not by BFD sections. 76 This is because BFD sections get their information from 77 the ELF section structure, which only includes a VMA value 78 and not an LMA value. */ 79 sizeof_phdrs = bfd_get_elf_phdr_upper_bound (prog); 80 if (sizeof_phdrs == 0) 81 { 82 fprintf (stderr, "%s: Failed to get size of program headers\n", simname); 83 return; 84 } 85 phdrs = xmalloc (sizeof_phdrs); 86 87 num_headers = bfd_get_elf_phdrs (prog, phdrs); 88 if (num_headers < 1) 89 { 90 fprintf (stderr, "%s: Failed to read program headers\n", simname); 91 return; 92 } 93 94 switch (elf_elfheader (prog)->e_flags & E_FLAG_RL78_CPU_MASK) 95 { 96 case E_FLAG_RL78_G10: 97 rl78_g10_mode = 1; 98 g13_multiply = 0; 99 g14_multiply = 0; 100 mem_set_mirror (0, 0xf8000, 4096); 101 break; 102 case E_FLAG_RL78_G13: 103 rl78_g10_mode = 0; 104 g13_multiply = 1; 105 g14_multiply = 0; 106 break; 107 case E_FLAG_RL78_G14: 108 rl78_g10_mode = 0; 109 g13_multiply = 0; 110 g14_multiply = 1; 111 break; 112 default: 113 /* Keep whatever was manually specified. */ 114 break; 115 } 116 117 for (i = 0; i < num_headers; i++) 118 { 119 Elf_Internal_Phdr * p = phdrs + i; 120 char *buf; 121 bfd_vma size; 122 bfd_vma base; 123 file_ptr offset; 124 125 size = p->p_filesz; 126 if (size <= 0) 127 continue; 128 129 base = p->p_paddr; 130 if (verbose > 1) 131 fprintf (stderr, "[load segment: lma=%08x vma=%08x size=%08x]\n", 132 (int) base, (int) p->p_vaddr, (int) size); 133 if (callbacks) 134 xprintf (callbacks, 135 "Loading section %s, size %#lx lma %08lx vma %08lx\n", 136 find_section_name_by_offset (prog, p->p_offset), 137 size, base, p->p_vaddr); 138 139 buf = xmalloc (size); 140 141 offset = p->p_offset; 142 if (bfd_seek (prog, offset, SEEK_SET) != 0) 143 { 144 fprintf (stderr, "%s, Failed to seek to offset %lx\n", simname, (long) offset); 145 continue; 146 } 147 148 if (bfd_bread (buf, size, prog) != size) 149 { 150 fprintf (stderr, "%s: Failed to read %lx bytes\n", simname, size); 151 continue; 152 } 153 154 if (base > 0xeffff || base + size > 0xeffff) 155 { 156 fprintf (stderr, "%s, Can't load image to RAM/SFR space: 0x%lx - 0x%lx\n", 157 simname, base, base+size); 158 continue; 159 } 160 if (max_rom < base + size) 161 max_rom = base + size; 162 163 mem_put_blk (base, buf, size); 164 free (buf); 165 } 166 167 free (phdrs); 168 169 mem_rom_size (max_rom); 170 171 pc = prog->start_address; 172 173 if (strcmp (bfd_get_target (prog), "srec") == 0 174 || pc == 0) 175 { 176 pc = mem_get_hi (0); 177 } 178 179 if (verbose > 1) 180 fprintf (stderr, "[start pc=%08x]\n", (unsigned int) pc); 181 } 182