* cris/sim-if.c: Include errno.h.
authorHans-Peter Nilsson <hp@axis.com>
Sun, 18 Jan 2009 22:17:03 +0000 (22:17 +0000)
committerHans-Peter Nilsson <hp@axis.com>
Sun, 18 Jan 2009 22:17:03 +0000 (22:17 +0000)
(cris_start_address, cris_program_offset): New variables.
(OPTION_CRIS_PROGRAM_OFFSET, OPTION_CRIS_STARTADDR): New option
enums.
(cris_options): New options --cris-program-offset and
--cris-start-address.
(cris_option_handler): Handle new options.
(cris_program_offset_write, cris_set_section_offset_iterator)
(cris_offset_sections, cris_offset_sections): New functions.
(sim_load): Use cris_program_offset_write as function argument to
cris_load_elf_file, not sim_write.
(struct offsetinfo): New struct.
(cris_handle_interpreter): Fix typo in comment.
(sim_open): Call cris_offset_sections as soon as the bfd of the
infile is available.  Gate bfd validity checks on abfd non-NULL.
(sim_create_inferior): Let cris_start_address when != -1 override
other start-address choices.

sim/ChangeLog
sim/cris/sim-if.c

index 87cbc8c..72439b1 100644 (file)
@@ -1,3 +1,23 @@
+2009-01-18  Hans-Peter Nilsson  <hp@axis.com>
+
+       * cris/sim-if.c: Include errno.h.
+       (cris_start_address, cris_program_offset): New variables.
+       (OPTION_CRIS_PROGRAM_OFFSET, OPTION_CRIS_STARTADDR): New option
+       enums.
+       (cris_options): New options --cris-program-offset and
+       --cris-start-address.
+       (cris_option_handler): Handle new options.
+       (cris_program_offset_write, cris_set_section_offset_iterator)
+       (cris_offset_sections, cris_offset_sections): New functions.
+       (sim_load): Use cris_program_offset_write as function argument to
+       cris_load_elf_file, not sim_write.
+       (struct offsetinfo): New struct.
+       (cris_handle_interpreter): Fix typo in comment.
+       (sim_open): Call cris_offset_sections as soon as the bfd of the
+       infile is available.  Gate bfd validity checks on abfd non-NULL.
+       (sim_create_inferior): Let cris_start_address when != -1 override
+       other start-address choices.
+
 2009-01-06  Hans-Peter Nilsson  <hp@axis.com>
 
        * cris/traps.c (abort): Define to call sim_io_error.
index 9f26abf..9135ccb 100644 (file)
@@ -29,6 +29,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
+#include <errno.h>
 #include "sim-options.h"
 #include "dis-asm.h"
 
@@ -67,6 +68,15 @@ static char cris_bare_iron = 0;
 /* Whether 0x9000000xx have simulator-specific meanings.  */
 char cris_have_900000xxif = 0;
 
+/* Used to optionally override the default start address of the
+   simulation.  */
+static USI cris_start_address = 0xffffffffu;
+
+/* Used to optionally add offsets to the loaded image and its start
+   address.  (Not used for the interpreter of dynamically loaded
+   programs or the DSO:s.)  */
+static int cris_program_offset = 0;
+
 /* What to do when we face a more or less unknown syscall.  */
 enum cris_unknown_syscall_action_type cris_unknown_syscall_action
   = CRIS_USYSC_MSG_STOP;
@@ -80,6 +90,8 @@ typedef enum {
   OPTION_CRIS_STATS = OPTION_START,
   OPTION_CRIS_TRACE,
   OPTION_CRIS_NAKED,
+  OPTION_CRIS_PROGRAM_OFFSET,
+  OPTION_CRIS_STARTADDR,
   OPTION_CRIS_900000XXIF,
   OPTION_CRIS_UNKNOWN_SYSCALL
 } CRIS_OPTIONS;
@@ -104,6 +116,14 @@ static const OPTION cris_options[] =
      OPTION_CRIS_UNKNOWN_SYSCALL},
      '\0', "stop|enosys|enosys-quiet", "Action at an unknown system call",
      cris_option_handler, NULL },
+  { {"cris-program-offset", required_argument, NULL,
+     OPTION_CRIS_PROGRAM_OFFSET},
+      '\0', "OFFSET",
+    "Offset image addresses and default start address of a program",
+      cris_option_handler },
+  { {"cris-start-address", required_argument, NULL, OPTION_CRIS_STARTADDR},
+      '\0', "ADDRESS", "Set start address",
+      cris_option_handler },
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL, NULL }
 };
 \f
@@ -130,6 +150,7 @@ cris_option_handler (SIM_DESC sd, sim_cpu *cpu ATTRIBUTE_UNUSED, int opt,
      to the module-specific CPU data when we store things in the
      cpu-specific structure.  */
   char *tracefp = STATE_TRACE_FLAGS (sd);
+  char *chp = arg;
 
   switch ((CRIS_OPTIONS) opt)
     {
@@ -173,6 +194,30 @@ cris_option_handler (SIM_DESC sd, sim_cpu *cpu ATTRIBUTE_UNUSED, int opt,
        cris_have_900000xxif = 1;
        break;
 
+      case OPTION_CRIS_STARTADDR:
+       errno = 0;
+       cris_start_address = (USI) strtoul (chp, &chp, 0);
+
+       if (errno != 0 || *chp != 0)
+         {
+           sim_io_eprintf (sd, "Invalid option `--cris-start-address=%s'\n",
+                           arg);
+           return SIM_RC_FAIL;
+         }
+       break;
+
+      case OPTION_CRIS_PROGRAM_OFFSET:
+       errno = 0;
+       cris_program_offset = (int) strtol (chp, &chp, 0);
+
+       if (errno != 0 || *chp != 0)
+         {
+           sim_io_eprintf (sd, "Invalid option `--cris-program-offset=%s'\n",
+                           arg);
+           return SIM_RC_FAIL;
+         }
+       break;
+
       case OPTION_CRIS_UNKNOWN_SYSCALL:
        if (strcmp (arg, "enosys") == 0)
          cris_unknown_syscall_action = CRIS_USYSC_MSG_ENOSYS;
@@ -284,6 +329,16 @@ cris_load_elf_file (SIM_DESC sd, struct bfd *abfd, sim_write_fn do_write)
   return TRUE;
 }
 
+/* Helper for sim_load (needed just for ELF files): like sim_write,
+   but offset load at cris_program_offset offset.  */
+
+static int
+cris_program_offset_write (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf,
+                          int length)
+{
+  return sim_write (sd, mem + cris_program_offset, buf, length);
+}
+
 /* Replacement for ../common/sim-hload.c:sim_load, so we can treat ELF
    files differently.  */
 
@@ -316,7 +371,7 @@ sim_load (SIM_DESC sd, char *prog_name, struct bfd *prog_bfd,
       return SIM_RC_OK;
     }
 
-  return cris_load_elf_file (sd, prog_bfd, sim_write)
+  return cris_load_elf_file (sd, prog_bfd, cris_program_offset_write)
     ? SIM_RC_OK : SIM_RC_FAIL;
 }
 
@@ -331,6 +386,60 @@ free_state (SIM_DESC sd)
   sim_state_free (sd);
 }
 
+/* Helper struct for cris_set_section_offset_iterator.  */
+
+struct offsetinfo
+{
+  SIM_DESC sd;
+  int offset;
+};
+
+/* BFD section iterator to offset the LMA and VMA.  */
+
+static void
+cris_set_section_offset_iterator (bfd *abfd, asection *s, void *vp)
+{
+  struct offsetinfo *p = (struct offsetinfo *) vp;
+  SIM_DESC sd = p->sd;
+  int offset = p->offset;
+
+  if ((bfd_get_section_flags (abfd, s) & SEC_ALLOC))
+    {
+      bfd_vma vma = bfd_get_section_vma (abfd, s);
+      
+      bfd_set_section_vma (abfd, s, vma + offset);
+    }
+
+  /* This seems clumsy and inaccurate, but let's stick to doing it the
+     same way as sim_analyze_program for consistency.  */
+  if (strcmp (bfd_get_section_name (abfd, s), ".text") == 0)
+    STATE_TEXT_START (sd) = bfd_get_section_vma (abfd, s);
+}
+
+/* Adjust the start-address, LMA and VMA of a SD.  Must be called
+   after sim_analyze_program.  */
+
+static void
+cris_offset_sections (SIM_DESC sd, int offset)
+{
+  bfd_boolean ret;
+  struct bfd *abfd = STATE_PROG_BFD (sd);
+  asection *text;
+  struct offsetinfo oi;
+
+  /* Only happens for usage error.  */
+  if (abfd == NULL)
+    return;
+
+  oi.sd = sd;
+  oi.offset = offset;
+
+  bfd_map_over_sections (abfd, cris_set_section_offset_iterator, &oi);
+  ret = bfd_set_start_address (abfd, bfd_get_start_address (abfd) + offset);
+
+  STATE_START_ADDR (sd) = bfd_get_start_address (abfd);
+}
+
 /* BFD section iterator to find the highest and lowest allocated and
    non-allocated section addresses (plus one).  */
 
@@ -520,7 +629,7 @@ cris_handle_interpreter (SIM_DESC sd, struct bfd *abfd)
       if (ibfd == NULL)
        goto interpname_failed;
 
-      /* The interpreter is at leat something readable to BFD; make
+      /* The interpreter is at least something readable to BFD; make
         sure it's an ELF non-archive file.  */
       if (!bfd_check_format (ibfd, bfd_object)
          || bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
@@ -688,7 +797,12 @@ sim_open (SIM_OPEN_KIND kind, host_callback *callback, struct bfd *abfd,
   if (abfd == NULL)
     abfd = STATE_PROG_BFD (sd);
 
-  if (bfd_get_arch (abfd) == bfd_arch_unknown)
+  /* Adjust the addresses of the program at this point.  Unfortunately
+     this does not affect ELF program headers, so we have to handle
+     that separately.  */
+  cris_offset_sections (sd, cris_program_offset);
+
+  if (abfd != NULL && bfd_get_arch (abfd) == bfd_arch_unknown)
     {
       if (STATE_PROG_ARGV (sd) != NULL)
        sim_io_eprintf (sd, "%s: `%s' is not a CRIS program\n",
@@ -963,8 +1077,11 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
   SIM_ADDR addr;
 
   if (sd != NULL)
-    addr = interp_start_addr != 0
-      ? interp_start_addr : bfd_get_start_address (abfd);
+    addr = cris_start_address != (SIM_ADDR) -1
+      ? cris_start_address
+      : (interp_start_addr != 0
+        ? interp_start_addr
+        : bfd_get_start_address (abfd));
   else
     addr = 0;
   sim_pc_set (current_cpu, addr);