diff options
Diffstat (limited to 'sim/rl78/load.c')
-rw-r--r-- | sim/rl78/load.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/sim/rl78/load.c b/sim/rl78/load.c new file mode 100644 index 0000000..cb50d21 --- /dev/null +++ b/sim/rl78/load.c @@ -0,0 +1,158 @@ +/* load.c --- loading object files into the RL78 simulator. + + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + Contributed by Red Hat, Inc. + + This file is part of the GNU simulators. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "libiberty.h" +#include "bfd.h" +#include "libbfd.h" +#include "cpu.h" +#include "mem.h" +#include "load.h" +#include "elf/internal.h" +#include "elf/common.h" + +/* Helper function for invoking a GDB-specified printf. */ +static void +xprintf (host_callback *callback, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + + (*callback->vprintf_filtered) (callback, fmt, ap); + + va_end (ap); +} + +/* Given a file offset, look up the section name. */ +static const char * +find_section_name_by_offset (bfd *abfd, file_ptr filepos) +{ + asection *s; + + for (s = abfd->sections; s; s = s->next) + if (s->filepos == filepos) + return bfd_get_section_name (abfd, s); + + return "(unknown)"; +} + +void +rl78_load (bfd *prog, host_callback *callbacks, const char * const simname) +{ + Elf_Internal_Phdr * phdrs; + long sizeof_phdrs; + int num_headers; + int i; + int max_rom = 0; + + init_cpu (); + + /* Note we load by ELF program header not by BFD sections. + This is because BFD sections get their information from + the ELF section structure, which only includes a VMA value + and not an LMA value. */ + sizeof_phdrs = bfd_get_elf_phdr_upper_bound (prog); + if (sizeof_phdrs == 0) + { + fprintf (stderr, "%s: Failed to get size of program headers\n", simname); + return; + } + phdrs = xmalloc (sizeof_phdrs); + + num_headers = bfd_get_elf_phdrs (prog, phdrs); + if (num_headers < 1) + { + fprintf (stderr, "%s: Failed to read program headers\n", simname); + return; + } + + for (i = 0; i < num_headers; i++) + { + Elf_Internal_Phdr * p = phdrs + i; + char *buf; + bfd_vma size; + bfd_vma base; + file_ptr offset; + + size = p->p_filesz; + if (size <= 0) + continue; + + base = p->p_paddr; + if (verbose > 1) + fprintf (stderr, "[load segment: lma=%08x vma=%08x size=%08x]\n", + (int) base, (int) p->p_vaddr, (int) size); + if (callbacks) + xprintf (callbacks, + "Loading section %s, size %#lx lma %08lx vma %08lx\n", + find_section_name_by_offset (prog, p->p_offset), + size, base, p->p_vaddr); + + buf = xmalloc (size); + + offset = p->p_offset; + if (prog->iovec->bseek (prog, offset, SEEK_SET) != 0) + { + fprintf (stderr, "%s, Failed to seek to offset %lx\n", simname, (long) offset); + continue; + } + + if (prog->iovec->bread (prog, buf, size) != size) + { + fprintf (stderr, "%s: Failed to read %lx bytes\n", simname, size); + continue; + } + + if (base > 0xeffff || base + size > 0xeffff) + { + fprintf (stderr, "%s, Can't load image to RAM/SFR space: 0x%lx - 0x%lx\n", + simname, base, base+size); + continue; + } + if (max_rom < base + size) + max_rom = base + size; + + mem_put_blk (base, buf, size); + free (buf); + } + + free (phdrs); + + mem_rom_size (max_rom); + + pc = prog->start_address; + + if (strcmp (bfd_get_target (prog), "srec") == 0 + || pc == 0) + { + pc = mem_get_hi (0); + } + + if (verbose > 1) + fprintf (stderr, "[start pc=%08x]\n", (unsigned int) pc); +} |