123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855 |
- /* gdb-if.c -- sim interface to GDB.
- Copyright (C) 2008-2022 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/>. */
- /* This must come before any other includes. */
- #include "defs.h"
- #include <stdio.h>
- #include <assert.h>
- #include <signal.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include "ansidecl.h"
- #include "libiberty.h"
- #include "sim/callback.h"
- #include "sim/sim.h"
- #include "gdb/signals.h"
- #include "gdb/sim-rx.h"
- #include "cpu.h"
- #include "mem.h"
- #include "load.h"
- #include "syscalls.h"
- #include "err.h"
- #include "trace.h"
- /* Ideally, we'd wrap up all the minisim's data structures in an
- object and pass that around. However, neither GDB nor run needs
- that ability.
- So we just have one instance, that lives in global variables, and
- each time we open it, we re-initialize it. */
- struct sim_state
- {
- const char *message;
- };
- static struct sim_state the_minisim = {
- "This is the sole rx minisim instance. See libsim.a's global variables."
- };
- static int rx_sim_is_open;
- SIM_DESC
- sim_open (SIM_OPEN_KIND kind,
- struct host_callback_struct *callback,
- struct bfd *abfd, char * const *argv)
- {
- if (rx_sim_is_open)
- fprintf (stderr, "rx minisim: re-opened sim\n");
- /* The 'run' interface doesn't use this function, so we don't care
- about KIND; it's always SIM_OPEN_DEBUG. */
- if (kind != SIM_OPEN_DEBUG)
- fprintf (stderr, "rx minisim: sim_open KIND != SIM_OPEN_DEBUG: %d\n",
- kind);
- set_callbacks (callback);
- /* We don't expect any command-line arguments. */
- init_mem ();
- init_regs ();
- execution_error_init_debugger ();
- sim_disasm_init (abfd);
- rx_sim_is_open = 1;
- return &the_minisim;
- }
- static void
- check_desc (SIM_DESC sd)
- {
- if (sd != &the_minisim)
- fprintf (stderr, "rx minisim: desc != &the_minisim\n");
- }
- void
- sim_close (SIM_DESC sd, int quitting)
- {
- check_desc (sd);
- /* Not much to do. At least free up our memory. */
- init_mem ();
- rx_sim_is_open = 0;
- }
- static bfd *
- open_objfile (const char *filename)
- {
- bfd *prog = bfd_openr (filename, 0);
- if (!prog)
- {
- fprintf (stderr, "Can't read %s\n", filename);
- return 0;
- }
- if (!bfd_check_format (prog, bfd_object))
- {
- fprintf (stderr, "%s not a rx program\n", filename);
- return 0;
- }
- return prog;
- }
- static struct swap_list
- {
- bfd_vma start, end;
- struct swap_list *next;
- } *swap_list = NULL;
- static void
- free_swap_list (void)
- {
- while (swap_list)
- {
- struct swap_list *next = swap_list->next;
- free (swap_list);
- swap_list = next;
- }
- }
- /* When running in big endian mode, we must do an additional
- byte swap of memory areas used to hold instructions. See
- the comment preceding rx_load in load.c to see why this is
- so.
- Construct a list of memory areas that must be byte swapped.
- This list will be consulted when either reading or writing
- memory. */
- static void
- build_swap_list (struct bfd *abfd)
- {
- asection *s;
- free_swap_list ();
-
- /* Nothing to do when in little endian mode. */
- if (!rx_big_endian)
- return;
- for (s = abfd->sections; s; s = s->next)
- {
- if ((s->flags & SEC_LOAD) && (s->flags & SEC_CODE))
- {
- struct swap_list *sl;
- bfd_size_type size;
- size = bfd_section_size (s);
- if (size <= 0)
- continue;
-
- sl = malloc (sizeof (struct swap_list));
- assert (sl != NULL);
- sl->next = swap_list;
- sl->start = bfd_section_lma (s);
- sl->end = sl->start + size;
- swap_list = sl;
- }
- }
- }
- static int
- addr_in_swap_list (bfd_vma addr)
- {
- struct swap_list *s;
- for (s = swap_list; s; s = s->next)
- {
- if (s->start <= addr && addr < s->end)
- return 1;
- }
- return 0;
- }
- SIM_RC
- sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty)
- {
- check_desc (sd);
- if (!abfd)
- abfd = open_objfile (prog);
- if (!abfd)
- return SIM_RC_FAIL;
- rx_load (abfd, get_callbacks ());
- build_swap_list (abfd);
- return SIM_RC_OK;
- }
- SIM_RC
- sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
- char * const *argv, char * const *env)
- {
- check_desc (sd);
- if (abfd)
- {
- rx_load (abfd, NULL);
- build_swap_list (abfd);
- }
- return SIM_RC_OK;
- }
- int
- sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length)
- {
- int i;
- check_desc (sd);
- if (mem == 0)
- return 0;
- execution_error_clear_last_error ();
- for (i = 0; i < length; i++)
- {
- bfd_vma addr = mem + i;
- int do_swap = addr_in_swap_list (addr);
- buf[i] = mem_get_qi (addr ^ (do_swap ? 3 : 0));
- if (execution_error_get_last_error () != SIM_ERR_NONE)
- return i;
- }
- return length;
- }
- int
- sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length)
- {
- int i;
- check_desc (sd);
- execution_error_clear_last_error ();
- for (i = 0; i < length; i++)
- {
- bfd_vma addr = mem + i;
- int do_swap = addr_in_swap_list (addr);
- mem_put_qi (addr ^ (do_swap ? 3 : 0), buf[i]);
- if (execution_error_get_last_error () != SIM_ERR_NONE)
- return i;
- }
- return length;
- }
- /* Read the LENGTH bytes at BUF as an little-endian value. */
- static DI
- get_le (unsigned char *buf, int length)
- {
- DI acc = 0;
- while (--length >= 0)
- acc = (acc << 8) + buf[length];
- return acc;
- }
- /* Read the LENGTH bytes at BUF as a big-endian value. */
- static DI
- get_be (unsigned char *buf, int length)
- {
- DI acc = 0;
- while (length-- > 0)
- acc = (acc << 8) + *buf++;
- return acc;
- }
- /* Store VAL as a little-endian value in the LENGTH bytes at BUF. */
- static void
- put_le (unsigned char *buf, int length, DI val)
- {
- int i;
- for (i = 0; i < length; i++)
- {
- buf[i] = val & 0xff;
- val >>= 8;
- }
- }
- /* Store VAL as a big-endian value in the LENGTH bytes at BUF. */
- static void
- put_be (unsigned char *buf, int length, DI val)
- {
- int i;
- for (i = length-1; i >= 0; i--)
- {
- buf[i] = val & 0xff;
- val >>= 8;
- }
- }
- static int
- check_regno (enum sim_rx_regnum regno)
- {
- return 0 <= regno && regno < sim_rx_num_regs;
- }
- static size_t
- reg_size (enum sim_rx_regnum regno)
- {
- size_t size;
- switch (regno)
- {
- case sim_rx_r0_regnum:
- size = sizeof (regs.r[0]);
- break;
- case sim_rx_r1_regnum:
- size = sizeof (regs.r[1]);
- break;
- case sim_rx_r2_regnum:
- size = sizeof (regs.r[2]);
- break;
- case sim_rx_r3_regnum:
- size = sizeof (regs.r[3]);
- break;
- case sim_rx_r4_regnum:
- size = sizeof (regs.r[4]);
- break;
- case sim_rx_r5_regnum:
- size = sizeof (regs.r[5]);
- break;
- case sim_rx_r6_regnum:
- size = sizeof (regs.r[6]);
- break;
- case sim_rx_r7_regnum:
- size = sizeof (regs.r[7]);
- break;
- case sim_rx_r8_regnum:
- size = sizeof (regs.r[8]);
- break;
- case sim_rx_r9_regnum:
- size = sizeof (regs.r[9]);
- break;
- case sim_rx_r10_regnum:
- size = sizeof (regs.r[10]);
- break;
- case sim_rx_r11_regnum:
- size = sizeof (regs.r[11]);
- break;
- case sim_rx_r12_regnum:
- size = sizeof (regs.r[12]);
- break;
- case sim_rx_r13_regnum:
- size = sizeof (regs.r[13]);
- break;
- case sim_rx_r14_regnum:
- size = sizeof (regs.r[14]);
- break;
- case sim_rx_r15_regnum:
- size = sizeof (regs.r[15]);
- break;
- case sim_rx_isp_regnum:
- size = sizeof (regs.r_isp);
- break;
- case sim_rx_usp_regnum:
- size = sizeof (regs.r_usp);
- break;
- case sim_rx_intb_regnum:
- size = sizeof (regs.r_intb);
- break;
- case sim_rx_pc_regnum:
- size = sizeof (regs.r_pc);
- break;
- case sim_rx_ps_regnum:
- size = sizeof (regs.r_psw);
- break;
- case sim_rx_bpc_regnum:
- size = sizeof (regs.r_bpc);
- break;
- case sim_rx_bpsw_regnum:
- size = sizeof (regs.r_bpsw);
- break;
- case sim_rx_fintv_regnum:
- size = sizeof (regs.r_fintv);
- break;
- case sim_rx_fpsw_regnum:
- size = sizeof (regs.r_fpsw);
- break;
- case sim_rx_acc_regnum:
- size = sizeof (regs.r_acc);
- break;
- default:
- size = 0;
- break;
- }
- return size;
- }
- int
- sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
- {
- size_t size;
- DI val;
- check_desc (sd);
- if (!check_regno (regno))
- return 0;
- size = reg_size (regno);
- if (length != size)
- return 0;
- switch (regno)
- {
- case sim_rx_r0_regnum:
- val = get_reg (0);
- break;
- case sim_rx_r1_regnum:
- val = get_reg (1);
- break;
- case sim_rx_r2_regnum:
- val = get_reg (2);
- break;
- case sim_rx_r3_regnum:
- val = get_reg (3);
- break;
- case sim_rx_r4_regnum:
- val = get_reg (4);
- break;
- case sim_rx_r5_regnum:
- val = get_reg (5);
- break;
- case sim_rx_r6_regnum:
- val = get_reg (6);
- break;
- case sim_rx_r7_regnum:
- val = get_reg (7);
- break;
- case sim_rx_r8_regnum:
- val = get_reg (8);
- break;
- case sim_rx_r9_regnum:
- val = get_reg (9);
- break;
- case sim_rx_r10_regnum:
- val = get_reg (10);
- break;
- case sim_rx_r11_regnum:
- val = get_reg (11);
- break;
- case sim_rx_r12_regnum:
- val = get_reg (12);
- break;
- case sim_rx_r13_regnum:
- val = get_reg (13);
- break;
- case sim_rx_r14_regnum:
- val = get_reg (14);
- break;
- case sim_rx_r15_regnum:
- val = get_reg (15);
- break;
- case sim_rx_isp_regnum:
- val = get_reg (isp);
- break;
- case sim_rx_usp_regnum:
- val = get_reg (usp);
- break;
- case sim_rx_intb_regnum:
- val = get_reg (intb);
- break;
- case sim_rx_pc_regnum:
- val = get_reg (pc);
- break;
- case sim_rx_ps_regnum:
- val = get_reg (psw);
- break;
- case sim_rx_bpc_regnum:
- val = get_reg (bpc);
- break;
- case sim_rx_bpsw_regnum:
- val = get_reg (bpsw);
- break;
- case sim_rx_fintv_regnum:
- val = get_reg (fintv);
- break;
- case sim_rx_fpsw_regnum:
- val = get_reg (fpsw);
- break;
- case sim_rx_acc_regnum:
- val = ((DI) get_reg (acchi) << 32) | get_reg (acclo);
- break;
- default:
- fprintf (stderr, "rx minisim: unrecognized register number: %d\n",
- regno);
- return -1;
- }
- if (rx_big_endian)
- put_be (buf, length, val);
- else
- put_le (buf, length, val);
- return size;
- }
- int
- sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length)
- {
- size_t size;
- DI val;
- check_desc (sd);
- if (!check_regno (regno))
- return -1;
- size = reg_size (regno);
- if (length != size)
- return -1;
- if (rx_big_endian)
- val = get_be (buf, length);
- else
- val = get_le (buf, length);
- switch (regno)
- {
- case sim_rx_r0_regnum:
- put_reg (0, val);
- break;
- case sim_rx_r1_regnum:
- put_reg (1, val);
- break;
- case sim_rx_r2_regnum:
- put_reg (2, val);
- break;
- case sim_rx_r3_regnum:
- put_reg (3, val);
- break;
- case sim_rx_r4_regnum:
- put_reg (4, val);
- break;
- case sim_rx_r5_regnum:
- put_reg (5, val);
- break;
- case sim_rx_r6_regnum:
- put_reg (6, val);
- break;
- case sim_rx_r7_regnum:
- put_reg (7, val);
- break;
- case sim_rx_r8_regnum:
- put_reg (8, val);
- break;
- case sim_rx_r9_regnum:
- put_reg (9, val);
- break;
- case sim_rx_r10_regnum:
- put_reg (10, val);
- break;
- case sim_rx_r11_regnum:
- put_reg (11, val);
- break;
- case sim_rx_r12_regnum:
- put_reg (12, val);
- break;
- case sim_rx_r13_regnum:
- put_reg (13, val);
- break;
- case sim_rx_r14_regnum:
- put_reg (14, val);
- break;
- case sim_rx_r15_regnum:
- put_reg (15, val);
- break;
- case sim_rx_isp_regnum:
- put_reg (isp, val);
- break;
- case sim_rx_usp_regnum:
- put_reg (usp, val);
- break;
- case sim_rx_intb_regnum:
- put_reg (intb, val);
- break;
- case sim_rx_pc_regnum:
- put_reg (pc, val);
- break;
- case sim_rx_ps_regnum:
- put_reg (psw, val);
- break;
- case sim_rx_bpc_regnum:
- put_reg (bpc, val);
- break;
- case sim_rx_bpsw_regnum:
- put_reg (bpsw, val);
- break;
- case sim_rx_fintv_regnum:
- put_reg (fintv, val);
- break;
- case sim_rx_fpsw_regnum:
- put_reg (fpsw, val);
- break;
- case sim_rx_acc_regnum:
- put_reg (acclo, val & 0xffffffff);
- put_reg (acchi, (val >> 32) & 0xffffffff);
- break;
- default:
- fprintf (stderr, "rx minisim: unrecognized register number: %d\n",
- regno);
- return 0;
- }
- return size;
- }
- void
- sim_info (SIM_DESC sd, int verbose)
- {
- check_desc (sd);
- printf ("The rx minisim doesn't collect any statistics.\n");
- }
- static volatile int stop;
- static enum sim_stop reason;
- int siggnal;
- /* Given a signal number used by the RX bsp (that is, newlib),
- return a target signal number used by GDB. */
- static int
- rx_signal_to_gdb_signal (int rx)
- {
- switch (rx)
- {
- case 4:
- return GDB_SIGNAL_ILL;
- case 5:
- return GDB_SIGNAL_TRAP;
- case 10:
- return GDB_SIGNAL_BUS;
- case 11:
- return GDB_SIGNAL_SEGV;
- case 24:
- return GDB_SIGNAL_XCPU;
- case 2:
- return GDB_SIGNAL_INT;
- case 8:
- return GDB_SIGNAL_FPE;
- case 6:
- return GDB_SIGNAL_ABRT;
- }
- return 0;
- }
- /* Take a step return code RC and set up the variables consulted by
- sim_stop_reason appropriately. */
- static void
- handle_step (int rc)
- {
- if (execution_error_get_last_error () != SIM_ERR_NONE)
- {
- reason = sim_stopped;
- siggnal = GDB_SIGNAL_SEGV;
- }
- if (RX_STEPPED (rc) || RX_HIT_BREAK (rc))
- {
- reason = sim_stopped;
- siggnal = GDB_SIGNAL_TRAP;
- }
- else if (RX_STOPPED (rc))
- {
- reason = sim_stopped;
- siggnal = rx_signal_to_gdb_signal (RX_STOP_SIG (rc));
- }
- else
- {
- assert (RX_EXITED (rc));
- reason = sim_exited;
- siggnal = RX_EXIT_STATUS (rc);
- }
- }
- void
- sim_resume (SIM_DESC sd, int step, int sig_to_deliver)
- {
- int rc;
- check_desc (sd);
- if (sig_to_deliver != 0)
- {
- fprintf (stderr,
- "Warning: the rx minisim does not implement "
- "signal delivery yet.\n" "Resuming with no signal.\n");
- }
- execution_error_clear_last_error ();
- if (step)
- {
- rc = setjmp (decode_jmp_buf);
- if (rc == 0)
- rc = decode_opcode ();
- handle_step (rc);
- }
- else
- {
- /* We don't clear 'stop' here, because then we would miss
- interrupts that arrived on the way here. Instead, we clear
- the flag in sim_stop_reason, after GDB has disabled the
- interrupt signal handler. */
- for (;;)
- {
- if (stop)
- {
- stop = 0;
- reason = sim_stopped;
- siggnal = GDB_SIGNAL_INT;
- break;
- }
- rc = setjmp (decode_jmp_buf);
- if (rc == 0)
- rc = decode_opcode ();
- if (execution_error_get_last_error () != SIM_ERR_NONE)
- {
- reason = sim_stopped;
- siggnal = GDB_SIGNAL_SEGV;
- break;
- }
- if (!RX_STEPPED (rc))
- {
- handle_step (rc);
- break;
- }
- }
- }
- }
- int
- sim_stop (SIM_DESC sd)
- {
- stop = 1;
- return 1;
- }
- void
- sim_stop_reason (SIM_DESC sd, enum sim_stop *reason_p, int *sigrc_p)
- {
- check_desc (sd);
- *reason_p = reason;
- *sigrc_p = siggnal;
- }
- void
- sim_do_command (SIM_DESC sd, const char *cmd)
- {
- const char *arg;
- char **argv = buildargv (cmd);
- check_desc (sd);
- cmd = arg = "";
- if (argv != NULL)
- {
- if (argv[0] != NULL)
- cmd = argv[0];
- if (argv[1] != NULL)
- arg = argv[1];
- }
- if (strcmp (cmd, "trace") == 0)
- {
- if (strcmp (arg, "on") == 0)
- trace = 1;
- else if (strcmp (arg, "off") == 0)
- trace = 0;
- else
- printf ("The 'sim trace' command expects 'on' or 'off' "
- "as an argument.\n");
- }
- else if (strcmp (cmd, "verbose") == 0)
- {
- if (strcmp (arg, "on") == 0)
- verbose = 1;
- else if (strcmp (arg, "noisy") == 0)
- verbose = 2;
- else if (strcmp (arg, "off") == 0)
- verbose = 0;
- else
- printf ("The 'sim verbose' command expects 'on', 'noisy', or 'off'"
- " as an argument.\n");
- }
- else
- printf ("The 'sim' command expects either 'trace' or 'verbose'"
- " as a subcommand.\n");
- freeargv (argv);
- }
- char **
- sim_complete_command (SIM_DESC sd, const char *text, const char *word)
- {
- return NULL;
- }
- /* Stub this out for now. */
- char *
- sim_memory_map (SIM_DESC sd)
- {
- return NULL;
- }
|