diff options
author | Mike Frysinger <vapier@gentoo.org> | 2021-05-12 00:35:54 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2021-05-14 00:41:05 -0400 |
commit | df68e12b3b3eb91e54d6d888b73049562566e0b3 (patch) | |
tree | b60781365aba1b34bacad73f34987c22615438a4 /include/sim | |
parent | 183aaaf72a8c0643de1aab1018e23fe020e2ff79 (diff) | |
download | fsf-binutils-gdb-df68e12b3b3eb91e54d6d888b73049562566e0b3.zip fsf-binutils-gdb-df68e12b3b3eb91e54d6d888b73049562566e0b3.tar.gz fsf-binutils-gdb-df68e12b3b3eb91e54d6d888b73049562566e0b3.tar.bz2 |
sim: create header namespace
The gdb/callback.h & gdb/remote-sim.h headers have nothing to do with
gdb and are really definitions for the libsim API under the sim/ tree.
While gdb uses those headers as a client, it's not specific to it. So
create a new sim/ namespace and move the headers there.
Diffstat (limited to 'include/sim')
-rw-r--r-- | include/sim/ChangeLog | 4 | ||||
-rw-r--r-- | include/sim/callback.h | 347 | ||||
-rw-r--r-- | include/sim/sim.h | 299 |
3 files changed, 650 insertions, 0 deletions
diff --git a/include/sim/ChangeLog b/include/sim/ChangeLog new file mode 100644 index 0000000..f2aba1e --- /dev/null +++ b/include/sim/ChangeLog @@ -0,0 +1,4 @@ +2021-05-14 Mike Frysinger <vapier@gentoo.org> + + * callback.h: Moved from ../gdb/callback.h. + * sim.h: Moved from ../gdb/remote-sim.h. diff --git a/include/sim/callback.h b/include/sim/callback.h new file mode 100644 index 0000000..f021f4d --- /dev/null +++ b/include/sim/callback.h @@ -0,0 +1,347 @@ +/* Remote target system call callback support. + Copyright (C) 1997-2021 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + This file is part of GDB. + + 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 interface isn't intended to be specific to any particular kind + of remote (hardware, simulator, whatever). As such, support for it + (e.g. sim/common/callback.c) should *not* live in the simulator source + tree, nor should it live in the gdb source tree. */ + +/* There are various ways to handle system calls: + + 1) Have a simulator intercept the appropriate trap instruction and + directly perform the system call on behalf of the target program. + This is the typical way of handling system calls for embedded targets. + [Handling system calls for embedded targets isn't that much of an + oxymoron as running compiler testsuites make use of the capability.] + + This method of system call handling is done when STATE_ENVIRONMENT + is ENVIRONMENT_USER. + + 2) Have a simulator emulate the hardware as much as possible. + If the program running on the real hardware communicates with some sort + of target manager, one would want to be able to run this program on the + simulator as well. + + This method of system call handling is done when STATE_ENVIRONMENT + is ENVIRONMENT_OPERATING. +*/ + +#ifndef SIM_CALLBACK_H +#define SIM_CALLBACK_H + +/* ??? The reason why we check for va_start here should be documented. */ + +#ifndef va_start +#include <ansidecl.h> +#include <stdarg.h> +#endif +/* Needed for enum bfd_endian. */ +#include "bfd.h" + +/* Mapping of host/target values. */ +/* ??? For debugging purposes, one might want to add a string of the + name of the symbol. */ + +typedef struct { + const char *name; + int host_val; + int target_val; +} CB_TARGET_DEFS_MAP; + +#define MAX_CALLBACK_FDS 10 + +/* Forward decl for stat/fstat. */ +struct stat; + +typedef struct host_callback_struct host_callback; + +struct host_callback_struct +{ + int (*close) (host_callback *,int); + int (*get_errno) (host_callback *); + int (*isatty) (host_callback *, int); + int (*lseek) (host_callback *, int, long , int); + int (*open) (host_callback *, const char*, int mode); + int (*read) (host_callback *,int, char *, int); + int (*read_stdin) ( host_callback *, char *, int); + int (*rename) (host_callback *, const char *, const char *); + int (*system) (host_callback *, const char *); + long (*time) (host_callback *, long *); + int (*unlink) (host_callback *, const char *); + int (*write) (host_callback *,int, const char *, int); + int (*write_stdout) (host_callback *, const char *, int); + void (*flush_stdout) (host_callback *); + int (*write_stderr) (host_callback *, const char *, int); + void (*flush_stderr) (host_callback *); + int (*to_stat) (host_callback *, const char *, struct stat *); + int (*to_fstat) (host_callback *, int, struct stat *); + int (*to_lstat) (host_callback *, const char *, struct stat *); + int (*ftruncate) (host_callback *, int, long); + int (*truncate) (host_callback *, const char *, long); + int (*pipe) (host_callback *, int *); + + /* Called by the framework when a read call has emptied a pipe buffer. */ + void (*pipe_empty) (host_callback *, int read_fd, int write_fd); + + /* Called by the framework when a write call makes a pipe buffer + non-empty. */ + void (*pipe_nonempty) (host_callback *, int read_fd, int write_fd); + + /* When present, call to the client to give it the oportunity to + poll any io devices for a request to quit (indicated by a nonzero + return value). */ + int (*poll_quit) (host_callback *); + + /* Used when the target has gone away, so we can close open + handles and free memory etc etc. */ + int (*shutdown) (host_callback *); + int (*init) (host_callback *); + + /* depreciated, use vprintf_filtered - Talk to the user on a console. */ + void (*printf_filtered) (host_callback *, const char *, ...); + + /* Talk to the user on a console. */ + void (*vprintf_filtered) (host_callback *, const char *, va_list); + + /* Same as vprintf_filtered but to stderr. */ + void (*evprintf_filtered) (host_callback *, const char *, va_list); + + /* Print an error message and "exit". + In the case of gdb "exiting" means doing a longjmp back to the main + command loop. */ + void (*error) (host_callback *, const char *, ...) +#ifdef __GNUC__ + __attribute__ ((__noreturn__)) +#endif + ; + + int last_errno; /* host format */ + + int fdmap[MAX_CALLBACK_FDS]; + /* fd_buddy is used to contruct circular lists of target fds that point to + the same host fd. A uniquely mapped fd points to itself; for a closed + one, fd_buddy has the value -1. The host file descriptors for stdin / + stdout / stderr are never closed by the simulators, so they are put + in a special fd_buddy circular list which also has MAX_CALLBACK_FDS + as a member. */ + /* ??? We don't have a callback entry for dup, although it is trival to + implement now. */ + short fd_buddy[MAX_CALLBACK_FDS+1]; + + /* 0 = none, >0 = reader (index of writer), + <0 = writer (negative index of reader). + If abs (ispipe[N]) == N, then N is an end of a pipe whose other + end is closed. */ + short ispipe[MAX_CALLBACK_FDS]; + + /* A writer stores the buffer at its index. Consecutive writes + realloc the buffer and add to the size. The reader indicates the + read part in its .size, until it has consumed it all, at which + point it deallocates the buffer and zeroes out both sizes. */ + struct pipe_write_buffer + { + int size; + char *buffer; + } pipe_buffer[MAX_CALLBACK_FDS]; + + /* System call numbers. */ + CB_TARGET_DEFS_MAP *syscall_map; + /* Errno values. */ + CB_TARGET_DEFS_MAP *errno_map; + /* Flags to the open system call. */ + CB_TARGET_DEFS_MAP *open_map; + /* Signal numbers. */ + CB_TARGET_DEFS_MAP *signal_map; + /* Layout of `stat' struct. + The format is a series of "name,length" pairs separated by colons. + Empty space is indicated with a `name' of "space". + All padding must be explicitly mentioned. + Lengths are in bytes. If this needs to be extended to bits, + use "name.bits". + Example: "st_dev,4:st_ino,4:st_mode,4:..." */ + const char *stat_map; + + enum bfd_endian target_endian; + + /* Size of an "int" on the target (for syscalls whose ABI uses "int"). + This must include padding, and only padding-at-higher-address is + supported. For example, a 64-bit target with 32-bit int:s which + are padded to 64 bits when in an array, should supposedly set this + to 8. The default is 4 which matches ILP32 targets and 64-bit + targets with 32-bit ints and no padding. */ + int target_sizeof_int; + + /* Marker for those wanting to do sanity checks. + This should remain the last member of this struct to help catch + miscompilation errors. */ +#define HOST_CALLBACK_MAGIC 4705 /* teds constant */ + int magic; +}; + +extern host_callback default_callback; + +/* Canonical versions of system call numbers. + It's not intended to willy-nilly throw every system call ever heard + of in here. Only include those that have an important use. + ??? One can certainly start a discussion over the ones that are currently + here, but that will always be true. */ + +/* These are used by the ANSI C support of libc. */ +#define CB_SYS_exit 1 +#define CB_SYS_open 2 +#define CB_SYS_close 3 +#define CB_SYS_read 4 +#define CB_SYS_write 5 +#define CB_SYS_lseek 6 +#define CB_SYS_unlink 7 +#define CB_SYS_getpid 8 +#define CB_SYS_kill 9 +#define CB_SYS_fstat 10 +/*#define CB_SYS_sbrk 11 - not currently a system call, but reserved. */ + +/* ARGV support. */ +#define CB_SYS_argvlen 12 +#define CB_SYS_argv 13 + +/* These are extras added for one reason or another. */ +#define CB_SYS_chdir 14 +#define CB_SYS_stat 15 +#define CB_SYS_chmod 16 +#define CB_SYS_utime 17 +#define CB_SYS_time 18 + +/* More standard syscalls. */ +#define CB_SYS_lstat 19 +#define CB_SYS_rename 20 +#define CB_SYS_truncate 21 +#define CB_SYS_ftruncate 22 +#define CB_SYS_pipe 23 + +/* New ARGV support. */ +#define CB_SYS_argc 24 +#define CB_SYS_argnlen 25 +#define CB_SYS_argn 26 + +/* Struct use to pass and return information necessary to perform a + system call. */ +/* FIXME: Need to consider target word size. */ + +typedef struct cb_syscall { + /* The target's value of what system call to perform. */ + int func; + /* The arguments to the syscall. */ + long arg1, arg2, arg3, arg4; + + /* The result. */ + long result; + /* Some system calls have two results. */ + long result2; + /* The target's errno value, or 0 if success. + This is converted to the target's value with host_to_target_errno. */ + int errcode; + + /* Working space to be used by memory read/write callbacks. */ + PTR p1; + PTR p2; + long x1,x2; + + /* Callbacks for reading/writing memory (e.g. for read/write syscalls). + ??? long or unsigned long might be better to use for the `count' + argument here. We mimic sim_{read,write} for now. Be careful to + test any changes with -Wall -Werror, mixed signed comparisons + will get you. */ + int (*read_mem) (host_callback * /*cb*/, struct cb_syscall * /*sc*/, + unsigned long /*taddr*/, char * /*buf*/, + int /*bytes*/); + int (*write_mem) (host_callback * /*cb*/, struct cb_syscall * /*sc*/, + unsigned long /*taddr*/, const char * /*buf*/, + int /*bytes*/); + + /* For sanity checking, should be last entry. */ + int magic; +} CB_SYSCALL; + +/* Magic number sanity checker. */ +#define CB_SYSCALL_MAGIC 0x12344321 + +/* Macro to initialize CB_SYSCALL. Called first, before filling in + any fields. */ +#define CB_SYSCALL_INIT(sc) \ +do { \ + memset ((sc), 0, sizeof (*(sc))); \ + (sc)->magic = CB_SYSCALL_MAGIC; \ +} while (0) + +/* Return codes for various interface routines. */ + +typedef enum { + CB_RC_OK = 0, + /* generic error */ + CB_RC_ERR, + /* either file not found or no read access */ + CB_RC_ACCESS, + CB_RC_NO_MEM +} CB_RC; + +/* Read in target values for system call numbers, errno values, signals. */ +CB_RC cb_read_target_syscall_maps (host_callback *, const char *); + +/* Translate target to host syscall function numbers. */ +int cb_target_to_host_syscall (host_callback *, int); + +/* Translate host to target errno value. */ +int cb_host_to_target_errno (host_callback *, int); + +/* Translate target to host open flags. */ +int cb_target_to_host_open (host_callback *, int); + +/* Translate target signal number to host. */ +int cb_target_to_host_signal (host_callback *, int); + +/* Translate host signal number to target. */ +int cb_host_to_gdb_signal (host_callback *, int); + +/* Translate symbols into human readable strings. */ +const char *cb_host_str_syscall (host_callback *, int); +const char *cb_host_str_errno (host_callback *, int); +const char *cb_host_str_signal (host_callback *, int); +const char *cb_target_str_syscall (host_callback *, int); +const char *cb_target_str_errno (host_callback *, int); +const char *cb_target_str_signal (host_callback *, int); + +/* Translate host stat struct to target. + If stat struct ptr is NULL, just compute target stat struct size. + Result is size of target stat struct or 0 if error. */ +int cb_host_to_target_stat (host_callback *, const struct stat *, PTR); + +/* Translate a value to target endian. */ +void cb_store_target_endian (host_callback *, char *, int, long); + +/* Tests for special fds. */ +int cb_is_stdin (host_callback *, int); +int cb_is_stdout (host_callback *, int); +int cb_is_stderr (host_callback *, int); + +/* Read a string out of the target. */ +int cb_get_string (host_callback *, CB_SYSCALL *, char *, int, unsigned long); + +/* Perform a system call. */ +CB_RC cb_syscall (host_callback *, CB_SYSCALL *); + +#endif diff --git a/include/sim/sim.h b/include/sim/sim.h new file mode 100644 index 0000000..72d0a61 --- /dev/null +++ b/include/sim/sim.h @@ -0,0 +1,299 @@ +/* This file defines the interface between the simulator and gdb. + + Copyright (C) 1993-2021 Free Software Foundation, Inc. + + This file is part of GDB. + + 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/>. */ + +#ifndef SIM_SIM_H +#define SIM_SIM_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This file is used when building stand-alone simulators, so isolate this + file from gdb. */ + +/* Pick up CORE_ADDR_TYPE if defined (from gdb), otherwise use same value as + gdb does (unsigned int - from defs.h). */ + +#ifndef CORE_ADDR_TYPE +typedef unsigned int SIM_ADDR; +#else +typedef CORE_ADDR_TYPE SIM_ADDR; +#endif + + +/* Semi-opaque type used as result of sim_open and passed back to all + other routines. "desc" is short for "descriptor". + It is up to each simulator to define `sim_state'. */ + +typedef struct sim_state *SIM_DESC; + + +/* Values for `kind' arg to sim_open. */ + +typedef enum { + SIM_OPEN_STANDALONE, /* simulator used standalone (run.c) */ + SIM_OPEN_DEBUG /* simulator used by debugger (gdb) */ +} SIM_OPEN_KIND; + + +/* Return codes from various functions. */ + +typedef enum { + SIM_RC_FAIL = 0, + SIM_RC_OK = 1 +} SIM_RC; + + +/* Some structs, as opaque types. */ + +struct bfd; +struct host_callback_struct; + + +/* Main simulator entry points. */ + + +/* Create a fully initialized simulator instance. + + (This function is called when the simulator is selected from the + gdb command line.) + + KIND specifies how the simulator shall be used. Currently there + are only two kinds: stand-alone and debug. + + CALLBACK specifies a standard host callback (defined in callback.h). + + ABFD, when non NULL, designates a target program. The program is + not loaded. + + ARGV is a standard ARGV pointer such as that passed from the + command line. The syntax of the argument list is is assumed to be + ``SIM-PROG { SIM-OPTION } [ TARGET-PROGRAM { TARGET-OPTION } ]''. + The trailing TARGET-PROGRAM and args are only valid for a + stand-alone simulator. + + On success, the result is a non NULL descriptor that shall be + passed to the other sim_foo functions. While the simulator + configuration can be parameterized by (in decreasing precedence) + ARGV's SIM-OPTION, ARGV's TARGET-PROGRAM and the ABFD argument, the + successful creation of the simulator shall not dependent on the + presence of any of these arguments/options. + + Hardware simulator: The created simulator shall be sufficiently + initialized to handle, with out restrictions any client requests + (including memory reads/writes, register fetch/stores and a + resume). + + Process simulator: that process is not created until a call to + sim_create_inferior. FIXME: What should the state of the simulator + be? */ + +SIM_DESC sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *callback, + struct bfd *abfd, char * const *argv); + + +/* Destory a simulator instance. + + QUITTING is non-zero if we cannot hang on errors. + + This may involve freeing target memory and closing any open files + and mmap'd areas. You cannot assume sim_kill has already been + called. */ + +void sim_close (SIM_DESC sd, int quitting); + + +/* Load program PROG into the simulators memory. + + If ABFD is non-NULL, the bfd for the file has already been opened. + The result is a return code indicating success. + + Hardware simulator: Normally, each program section is written into + memory according to that sections LMA using physical (direct) + addressing. The exception being systems, such as PPC/CHRP, which + support more complicated program loaders. A call to this function + should not effect the state of the processor registers. Multiple + calls to this function are permitted and have an accumulative + effect. + + Process simulator: Calls to this function may be ignored. + + FIXME: Most hardware simulators load the image at the VMA using + virtual addressing. + + FIXME: For some hardware targets, before a loaded program can be + executed, it requires the manipulation of VM registers and tables. + Such manipulation should probably (?) occure in + sim_create_inferior. */ + +SIM_RC sim_load (SIM_DESC sd, const char *prog, struct bfd *abfd, int from_tty); + + +/* Prepare to run the simulated program. + + ABFD, if not NULL, provides initial processor state information. + ARGV and ENV, if non NULL, are NULL terminated lists of pointers. + + Hardware simulator: This function shall initialize the processor + registers to a known value. The program counter and possibly stack + pointer shall be set using information obtained from ABFD (or + hardware reset defaults). ARGV and ENV, dependant on the target + ABI, may be written to memory. + + Process simulator: After a call to this function, a new process + instance shall exist. The TEXT, DATA, BSS and stack regions shall + all be initialized, ARGV and ENV shall be written to process + address space (according to the applicable ABI) and the program + counter and stack pointer set accordingly. */ + +SIM_RC sim_create_inferior (SIM_DESC sd, struct bfd *abfd, + char * const *argv, char * const *env); + + +/* Fetch LENGTH bytes of the simulated program's memory. Start fetch + at virtual address MEM and store in BUF. Result is number of bytes + read, or zero if error. */ + +int sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length); + + +/* Store LENGTH bytes from BUF into the simulated program's + memory. Store bytes starting at virtual address MEM. Result is + number of bytes write, or zero if error. */ + +int sim_write (SIM_DESC sd, SIM_ADDR mem, const unsigned char *buf, int length); + + +/* Fetch register REGNO storing its raw (target endian) value in the + LENGTH byte buffer BUF. Return the actual size of the register or + zero if REGNO is not applicable. + + Legacy implementations ignore LENGTH and always return -1. + + If LENGTH does not match the size of REGNO no data is transfered + (the actual register size is still returned). */ + +int sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length); + + +/* Store register REGNO from the raw (target endian) value in BUF. + + Return the actual size of the register, any size not equal to + LENGTH indicates the register was not updated correctly. + + Return a LENGTH of -1 to indicate the register was not updated + and an error has occurred. + + Return a LENGTH of 0 to indicate the register was not updated + but no error has occurred. */ + +int sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length); + + +/* Print whatever statistics the simulator has collected. + + VERBOSE is currently unused and must always be zero. */ + +void sim_info (SIM_DESC sd, int verbose); + + +/* Return a memory map in XML format. + + The caller must free the returned string. + + For details on the format, see GDB's Memory Map Format documentation. */ + +char *sim_memory_map (SIM_DESC sd); + + +/* Run (or resume) the simulated program. + + STEP, when non-zero indicates that only a single simulator cycle + should be emulated. + + SIGGNAL, if non-zero is a (HOST) SIGRC value indicating the type of + event (hardware interrupt, signal) to be delivered to the simulated + program. + + Hardware simulator: If the SIGRC value returned by + sim_stop_reason() is passed back to the simulator via SIGGNAL then + the hardware simulator shall correctly deliver the hardware event + indicated by that signal. If a value of zero is passed in then the + simulation will continue as if there were no outstanding signal. + The effect of any other SIGGNAL value is is implementation + dependant. + + Process simulator: If SIGRC is non-zero then the corresponding + signal is delivered to the simulated program and execution is then + continued. A zero SIGRC value indicates that the program should + continue as normal. */ + +void sim_resume (SIM_DESC sd, int step, int siggnal); + + +/* Asynchronous request to stop the simulation. + A nonzero return indicates that the simulator is able to handle + the request */ + +int sim_stop (SIM_DESC sd); + + +/* Fetch the REASON why the program stopped. + + SIM_EXITED: The program has terminated. SIGRC indicates the target + dependant exit status. + + SIM_STOPPED: The program has stopped. SIGRC uses the host's signal + numbering as a way of identifying the reaon: program interrupted by + user via a sim_stop request (SIGINT); a breakpoint instruction + (SIGTRAP); a completed single step (SIGTRAP); an internal error + condition (SIGABRT); an illegal instruction (SIGILL); Access to an + undefined memory region (SIGSEGV); Mis-aligned memory access + (SIGBUS). For some signals information in addition to the signal + number may be retained by the simulator (e.g. offending address), + that information is not directly accessable via this interface. + + SIM_SIGNALLED: The program has been terminated by a signal. The + simulator has encountered target code that causes the program + to exit with signal SIGRC. + + SIM_RUNNING, SIM_POLLING: The return of one of these values + indicates a problem internal to the simulator. */ + +enum sim_stop { sim_running, sim_polling, sim_exited, sim_stopped, sim_signalled }; + +void sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc); + + +/* Passthru for other commands that the simulator might support. + Simulators should be prepared to deal with any combination of NULL + or empty CMD. */ + +void sim_do_command (SIM_DESC sd, const char *cmd); + +/* Complete a command based on the available sim commands. Returns an + array of possible matches. */ + +char **sim_complete_command (SIM_DESC sd, const char *text, const char *word); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined (SIM_SIM_H) */ |