Blame sim/rl78/load.c

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