This file was not part of the GDB 5.2.1 import and should have been
deleted from the vendor branch.
This commit is contained in:
parent
fdedc45ff6
commit
4d359ceaf0
@ -1,16 +0,0 @@
|
||||
echo Setting up the environment for debugging gdb.\n
|
||||
|
||||
set complaints 1
|
||||
|
||||
b fatal
|
||||
|
||||
b info_command
|
||||
commands
|
||||
silent
|
||||
return
|
||||
end
|
||||
|
||||
dir ../mmalloc
|
||||
dir ../libiberty
|
||||
dir ../bfd
|
||||
set prompt (top-gdb)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
/* OBSOLETE .text */
|
||||
/* OBSOLETE .global _convert_from_extended */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE _convert_from_extended: */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE ldfe f0,[a1] */
|
||||
/* OBSOLETE stfd f0,[a2] */
|
||||
/* OBSOLETE movs pc,lr */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE .global _convert_to_extended */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE _convert_to_extended: */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE ldfd f0,[a1] */
|
||||
/* OBSOLETE stfe f0,[a2] */
|
||||
/* OBSOLETE movs pc,lr */
|
@ -1,575 +0,0 @@
|
||||
/* OBSOLETE /* Acorn Risc Machine host machine support. */
|
||||
/* OBSOLETE Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE This file is part of GDB. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE This program is free software; you can redistribute it and/or modify */
|
||||
/* OBSOLETE it under the terms of the GNU General Public License as published by */
|
||||
/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */
|
||||
/* OBSOLETE (at your option) any later version. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE This program is distributed in the hope that it will be useful, */
|
||||
/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
||||
/* OBSOLETE GNU General Public License for more details. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE You should have received a copy of the GNU General Public License */
|
||||
/* OBSOLETE along with this program; if not, write to the Free Software */
|
||||
/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, */
|
||||
/* OBSOLETE Boston, MA 02111-1307, USA. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #include "defs.h" */
|
||||
/* OBSOLETE #include "frame.h" */
|
||||
/* OBSOLETE #include "inferior.h" */
|
||||
/* OBSOLETE #include "opcode/arm.h" */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #include <sys/param.h> */
|
||||
/* OBSOLETE #include <sys/dir.h> */
|
||||
/* OBSOLETE #include <signal.h> */
|
||||
/* OBSOLETE #include <sys/ioctl.h> */
|
||||
/* OBSOLETE #include <sys/ptrace.h> */
|
||||
/* OBSOLETE #include <machine/reg.h> */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #define N_TXTADDR(hdr) 0x8000 */
|
||||
/* OBSOLETE #define N_DATADDR(hdr) (hdr.a_text + 0x8000) */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #include "gdbcore.h" */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #include <sys/user.h> /* After a.out.h *x/ */
|
||||
/* OBSOLETE #include <sys/file.h> */
|
||||
/* OBSOLETE #include "gdb_stat.h" */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #include <errno.h> */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE void */
|
||||
/* OBSOLETE fetch_inferior_registers (regno) */
|
||||
/* OBSOLETE int regno; /* Original value discarded *x/ */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE register unsigned int regaddr; */
|
||||
/* OBSOLETE char buf[MAX_REGISTER_RAW_SIZE]; */
|
||||
/* OBSOLETE register int i; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE struct user u; */
|
||||
/* OBSOLETE unsigned int offset = (char *) &u.u_ar0 - (char *) &u; */
|
||||
/* OBSOLETE offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) */
|
||||
/* OBSOLETE - KERNEL_U_ADDR; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE registers_fetched (); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE for (regno = 0; regno < 16; regno++) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE regaddr = offset + regno * 4; */
|
||||
/* OBSOLETE *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, */
|
||||
/* OBSOLETE (PTRACE_ARG3_TYPE) regaddr, 0); */
|
||||
/* OBSOLETE if (regno == PC_REGNUM) */
|
||||
/* OBSOLETE *(int *) &buf[0] = GET_PC_PART (*(int *) &buf[0]); */
|
||||
/* OBSOLETE supply_register (regno, buf); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, */
|
||||
/* OBSOLETE (PTRACE_ARG3_TYPE) (offset + PC * 4), 0); */
|
||||
/* OBSOLETE supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* read the floating point registers *x/ */
|
||||
/* OBSOLETE offset = (char *) &u.u_fp_regs - (char *) &u; */
|
||||
/* OBSOLETE *(int *) buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0); */
|
||||
/* OBSOLETE supply_register (FPS_REGNUM, buf); */
|
||||
/* OBSOLETE for (regno = 16; regno < 24; regno++) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE regaddr = offset + 4 + 12 * (regno - 16); */
|
||||
/* OBSOLETE for (i = 0; i < 12; i += sizeof (int)) */
|
||||
/* OBSOLETE *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, */
|
||||
/* OBSOLETE (PTRACE_ARG3_TYPE) (regaddr + i), 0); */
|
||||
/* OBSOLETE supply_register (regno, buf); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Store our register values back into the inferior. */
|
||||
/* OBSOLETE If REGNO is -1, do this for all registers. */
|
||||
/* OBSOLETE Otherwise, REGNO specifies which register (so we can save time). *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE void */
|
||||
/* OBSOLETE store_inferior_registers (regno) */
|
||||
/* OBSOLETE int regno; */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE register unsigned int regaddr; */
|
||||
/* OBSOLETE char buf[80]; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE struct user u; */
|
||||
/* OBSOLETE unsigned long value; */
|
||||
/* OBSOLETE unsigned int offset = (char *) &u.u_ar0 - (char *) &u; */
|
||||
/* OBSOLETE offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) */
|
||||
/* OBSOLETE - KERNEL_U_ADDR; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (regno >= 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE if (regno >= 16) */
|
||||
/* OBSOLETE return; */
|
||||
/* OBSOLETE regaddr = offset + 4 * regno; */
|
||||
/* OBSOLETE errno = 0; */
|
||||
/* OBSOLETE value = read_register (regno); */
|
||||
/* OBSOLETE if (regno == PC_REGNUM) */
|
||||
/* OBSOLETE value = SET_PC_PART (read_register (PS_REGNUM), value); */
|
||||
/* OBSOLETE ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); */
|
||||
/* OBSOLETE if (errno != 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE sprintf (buf, "writing register number %d", regno); */
|
||||
/* OBSOLETE perror_with_name (buf); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE for (regno = 0; regno < 15; regno++) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE regaddr = offset + regno * 4; */
|
||||
/* OBSOLETE errno = 0; */
|
||||
/* OBSOLETE value = read_register (regno); */
|
||||
/* OBSOLETE if (regno == PC_REGNUM) */
|
||||
/* OBSOLETE value = SET_PC_PART (read_register (PS_REGNUM), value); */
|
||||
/* OBSOLETE ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); */
|
||||
/* OBSOLETE if (errno != 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE sprintf (buf, "writing all regs, number %d", regno); */
|
||||
/* OBSOLETE perror_with_name (buf); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Work with core dump and executable files, for GDB. */
|
||||
/* OBSOLETE This code would be in corefile.c if it weren't machine-dependent. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Structure to describe the chain of shared libraries used */
|
||||
/* OBSOLETE by the execfile. */
|
||||
/* OBSOLETE e.g. prog shares Xt which shares X11 which shares c. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE struct shared_library */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct exec_header header; */
|
||||
/* OBSOLETE char name[SHLIBLEN]; */
|
||||
/* OBSOLETE CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file *x/ */
|
||||
/* OBSOLETE long data_offset; /* offset of data section in file *x/ */
|
||||
/* OBSOLETE int chan; /* file descriptor for the file *x/ */
|
||||
/* OBSOLETE struct shared_library *shares; /* library this one shares *x/ */
|
||||
/* OBSOLETE }; */
|
||||
/* OBSOLETE static struct shared_library *shlib = 0; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Hook for `exec_file_command' command to call. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE extern void (*exec_file_display_hook) (); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE static CORE_ADDR unshared_text_start; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* extended header from exec file (for shared library info) *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE static struct exec_header exec_header; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE void */
|
||||
/* OBSOLETE core_file_command (filename, from_tty) */
|
||||
/* OBSOLETE char *filename; */
|
||||
/* OBSOLETE int from_tty; */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE int val; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Discard all vestiges of any previous core file */
|
||||
/* OBSOLETE and mark data and stack spaces as empty. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (corefile) */
|
||||
/* OBSOLETE free (corefile); */
|
||||
/* OBSOLETE corefile = 0; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (corechan >= 0) */
|
||||
/* OBSOLETE close (corechan); */
|
||||
/* OBSOLETE corechan = -1; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE data_start = 0; */
|
||||
/* OBSOLETE data_end = 0; */
|
||||
/* OBSOLETE stack_start = STACK_END_ADDR; */
|
||||
/* OBSOLETE stack_end = STACK_END_ADDR; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Now, if a new core file was specified, open it and digest it. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (filename) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE filename = tilde_expand (filename); */
|
||||
/* OBSOLETE make_cleanup (free, filename); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (have_inferior_p ()) */
|
||||
/* OBSOLETE error ("To look at a core file, you must kill the program with \"kill\"."); */
|
||||
/* OBSOLETE corechan = open (filename, O_RDONLY, 0); */
|
||||
/* OBSOLETE if (corechan < 0) */
|
||||
/* OBSOLETE perror_with_name (filename); */
|
||||
/* OBSOLETE /* 4.2-style (and perhaps also sysV-style) core dump file. *x/ */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct user u; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE unsigned int reg_offset, fp_reg_offset; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE val = myread (corechan, &u, sizeof u); */
|
||||
/* OBSOLETE if (val < 0) */
|
||||
/* OBSOLETE perror_with_name ("Not a core file: reading upage"); */
|
||||
/* OBSOLETE if (val != sizeof u) */
|
||||
/* OBSOLETE error ("Not a core file: could only read %d bytes", val); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* We are depending on exec_file_command having been called */
|
||||
/* OBSOLETE previously to set exec_data_start. Since the executable */
|
||||
/* OBSOLETE and the core file share the same text segment, the address */
|
||||
/* OBSOLETE of the data segment will be the same in both. *x/ */
|
||||
/* OBSOLETE data_start = exec_data_start; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE data_end = data_start + NBPG * u.u_dsize; */
|
||||
/* OBSOLETE stack_start = stack_end - NBPG * u.u_ssize; */
|
||||
/* OBSOLETE data_offset = NBPG * UPAGES; */
|
||||
/* OBSOLETE stack_offset = NBPG * (UPAGES + u.u_dsize); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Some machines put an absolute address in here and some put */
|
||||
/* OBSOLETE the offset in the upage of the regs. *x/ */
|
||||
/* OBSOLETE reg_offset = (int) u.u_ar0; */
|
||||
/* OBSOLETE if (reg_offset > NBPG * UPAGES) */
|
||||
/* OBSOLETE reg_offset -= KERNEL_U_ADDR; */
|
||||
/* OBSOLETE fp_reg_offset = (char *) &u.u_fp_regs - (char *) &u; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* I don't know where to find this info. */
|
||||
/* OBSOLETE So, for now, mark it as not available. *x/ */
|
||||
/* OBSOLETE N_SET_MAGIC (core_aouthdr, 0); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Read the register values out of the core file and store */
|
||||
/* OBSOLETE them where `read_register' will find them. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE register int regno; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE for (regno = 0; regno < NUM_REGS; regno++) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE char buf[MAX_REGISTER_RAW_SIZE]; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (regno < 16) */
|
||||
/* OBSOLETE val = lseek (corechan, reg_offset + 4 * regno, 0); */
|
||||
/* OBSOLETE else if (regno < 24) */
|
||||
/* OBSOLETE val = lseek (corechan, fp_reg_offset + 4 + 12 * (regno - 24), 0); */
|
||||
/* OBSOLETE else if (regno == 24) */
|
||||
/* OBSOLETE val = lseek (corechan, fp_reg_offset, 0); */
|
||||
/* OBSOLETE else if (regno == 25) */
|
||||
/* OBSOLETE val = lseek (corechan, reg_offset + 4 * PC, 0); */
|
||||
/* OBSOLETE if (val < 0 */
|
||||
/* OBSOLETE || (val = myread (corechan, buf, sizeof buf)) < 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE char *buffer = (char *) alloca (strlen (REGISTER_NAME (regno)) */
|
||||
/* OBSOLETE + 30); */
|
||||
/* OBSOLETE strcpy (buffer, "Reading register "); */
|
||||
/* OBSOLETE strcat (buffer, REGISTER_NAME (regno)); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE perror_with_name (buffer); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (regno == PC_REGNUM) */
|
||||
/* OBSOLETE *(int *) buf = GET_PC_PART (*(int *) buf); */
|
||||
/* OBSOLETE supply_register (regno, buf); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE if (filename[0] == '/') */
|
||||
/* OBSOLETE corefile = savestring (filename, strlen (filename)); */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE corefile = concat (current_directory, "/", filename, NULL); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE flush_cached_frames (); */
|
||||
/* OBSOLETE select_frame (get_current_frame (), 0); */
|
||||
/* OBSOLETE validate_files (); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (from_tty) */
|
||||
/* OBSOLETE printf ("No core file now.\n"); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #if 0 */
|
||||
/* OBSOLETE /* Work with core dump and executable files, for GDB. */
|
||||
/* OBSOLETE This code would be in corefile.c if it weren't machine-dependent. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Structure to describe the chain of shared libraries used */
|
||||
/* OBSOLETE by the execfile. */
|
||||
/* OBSOLETE e.g. prog shares Xt which shares X11 which shares c. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE struct shared_library */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct exec_header header; */
|
||||
/* OBSOLETE char name[SHLIBLEN]; */
|
||||
/* OBSOLETE CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file *x/ */
|
||||
/* OBSOLETE long data_offset; /* offset of data section in file *x/ */
|
||||
/* OBSOLETE int chan; /* file descriptor for the file *x/ */
|
||||
/* OBSOLETE struct shared_library *shares; /* library this one shares *x/ */
|
||||
/* OBSOLETE }; */
|
||||
/* OBSOLETE static struct shared_library *shlib = 0; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Hook for `exec_file_command' command to call. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE extern void (*exec_file_display_hook) (); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE static CORE_ADDR unshared_text_start; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* extended header from exec file (for shared library info) *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE static struct exec_header exec_header; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE void */
|
||||
/* OBSOLETE exec_file_command (filename, from_tty) */
|
||||
/* OBSOLETE char *filename; */
|
||||
/* OBSOLETE int from_tty; */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE int val; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Eliminate all traces of old exec file. */
|
||||
/* OBSOLETE Mark text segment as empty. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (execfile) */
|
||||
/* OBSOLETE free (execfile); */
|
||||
/* OBSOLETE execfile = 0; */
|
||||
/* OBSOLETE data_start = 0; */
|
||||
/* OBSOLETE data_end -= exec_data_start; */
|
||||
/* OBSOLETE text_start = 0; */
|
||||
/* OBSOLETE unshared_text_start = 0; */
|
||||
/* OBSOLETE text_end = 0; */
|
||||
/* OBSOLETE exec_data_start = 0; */
|
||||
/* OBSOLETE exec_data_end = 0; */
|
||||
/* OBSOLETE if (execchan >= 0) */
|
||||
/* OBSOLETE close (execchan); */
|
||||
/* OBSOLETE execchan = -1; */
|
||||
/* OBSOLETE if (shlib) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE close_shared_library (shlib); */
|
||||
/* OBSOLETE shlib = 0; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Now open and digest the file the user requested, if any. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (filename) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE filename = tilde_expand (filename); */
|
||||
/* OBSOLETE make_cleanup (free, filename); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, */
|
||||
/* OBSOLETE &execfile); */
|
||||
/* OBSOLETE if (execchan < 0) */
|
||||
/* OBSOLETE perror_with_name (filename); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct stat st_exec; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #ifdef HEADER_SEEK_FD */
|
||||
/* OBSOLETE HEADER_SEEK_FD (execchan); */
|
||||
/* OBSOLETE #endif */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE val = myread (execchan, &exec_header, sizeof exec_header); */
|
||||
/* OBSOLETE exec_aouthdr = exec_header.a_exec; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (val < 0) */
|
||||
/* OBSOLETE perror_with_name (filename); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE text_start = 0x8000; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Look for shared library if needed *x/ */
|
||||
/* OBSOLETE if (exec_header.a_exec.a_magic & MF_USES_SL) */
|
||||
/* OBSOLETE shlib = open_shared_library (exec_header.a_shlibname, text_start); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE text_offset = N_TXTOFF (exec_aouthdr); */
|
||||
/* OBSOLETE exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE if (shlib) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE unshared_text_start = shared_text_end (shlib) & ~0x7fff; */
|
||||
/* OBSOLETE stack_start = shlib->header.a_exec.a_sldatabase; */
|
||||
/* OBSOLETE stack_end = STACK_END_ADDR; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE unshared_text_start = 0x8000; */
|
||||
/* OBSOLETE text_end = unshared_text_start + exec_aouthdr.a_text; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE exec_data_start = unshared_text_start + exec_aouthdr.a_text; */
|
||||
/* OBSOLETE exec_data_end = exec_data_start + exec_aouthdr.a_data; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE data_start = exec_data_start; */
|
||||
/* OBSOLETE data_end += exec_data_start; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE fstat (execchan, &st_exec); */
|
||||
/* OBSOLETE exec_mtime = st_exec.st_mtime; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE validate_files (); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (from_tty) */
|
||||
/* OBSOLETE printf ("No executable file now.\n"); */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Tell display code (if any) about the changed file name. *x/ */
|
||||
/* OBSOLETE if (exec_file_display_hook) */
|
||||
/* OBSOLETE (*exec_file_display_hook) (filename); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE #endif */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE #if 0 */
|
||||
/* OBSOLETE /* Read from the program's memory (except for inferior processes). */
|
||||
/* OBSOLETE This function is misnamed, since it only reads, never writes; and */
|
||||
/* OBSOLETE since it will use the core file and/or executable file as necessary. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE It should be extended to write as well as read, FIXME, for patching files. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE Return 0 if address could be read, EIO if addresss out of bounds. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE int */
|
||||
/* OBSOLETE xfer_core_file (memaddr, myaddr, len) */
|
||||
/* OBSOLETE CORE_ADDR memaddr; */
|
||||
/* OBSOLETE char *myaddr; */
|
||||
/* OBSOLETE int len; */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE register int i; */
|
||||
/* OBSOLETE register int val; */
|
||||
/* OBSOLETE int xferchan; */
|
||||
/* OBSOLETE char **xferfile; */
|
||||
/* OBSOLETE int fileptr; */
|
||||
/* OBSOLETE int returnval = 0; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE while (len > 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE xferfile = 0; */
|
||||
/* OBSOLETE xferchan = 0; */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Determine which file the next bunch of addresses reside in, */
|
||||
/* OBSOLETE and where in the file. Set the file's read/write pointer */
|
||||
/* OBSOLETE to point at the proper place for the desired address */
|
||||
/* OBSOLETE and set xferfile and xferchan for the correct file. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE If desired address is nonexistent, leave them zero. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE i is set to the number of bytes that can be handled */
|
||||
/* OBSOLETE along with the next address. */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE We put the most likely tests first for efficiency. *x/ */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Note that if there is no core file */
|
||||
/* OBSOLETE data_start and data_end are equal. *x/ */
|
||||
/* OBSOLETE if (memaddr >= data_start && memaddr < data_end) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, data_end - memaddr); */
|
||||
/* OBSOLETE fileptr = memaddr - data_start + data_offset; */
|
||||
/* OBSOLETE xferfile = &corefile; */
|
||||
/* OBSOLETE xferchan = corechan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE /* Note that if there is no core file */
|
||||
/* OBSOLETE stack_start and stack_end define the shared library data. *x/ */
|
||||
/* OBSOLETE else if (memaddr >= stack_start && memaddr < stack_end) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE if (corechan < 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct shared_library *lib; */
|
||||
/* OBSOLETE for (lib = shlib; lib; lib = lib->shares) */
|
||||
/* OBSOLETE if (memaddr >= lib->header.a_exec.a_sldatabase && */
|
||||
/* OBSOLETE memaddr < lib->header.a_exec.a_sldatabase + */
|
||||
/* OBSOLETE lib->header.a_exec.a_data) */
|
||||
/* OBSOLETE break; */
|
||||
/* OBSOLETE if (lib) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, lib->header.a_exec.a_sldatabase + */
|
||||
/* OBSOLETE lib->header.a_exec.a_data - memaddr); */
|
||||
/* OBSOLETE fileptr = lib->data_offset + memaddr - */
|
||||
/* OBSOLETE lib->header.a_exec.a_sldatabase; */
|
||||
/* OBSOLETE xferfile = execfile; */
|
||||
/* OBSOLETE xferchan = lib->chan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, stack_end - memaddr); */
|
||||
/* OBSOLETE fileptr = memaddr - stack_start + stack_offset; */
|
||||
/* OBSOLETE xferfile = &corefile; */
|
||||
/* OBSOLETE xferchan = corechan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (corechan < 0 */
|
||||
/* OBSOLETE && memaddr >= exec_data_start && memaddr < exec_data_end) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, exec_data_end - memaddr); */
|
||||
/* OBSOLETE fileptr = memaddr - exec_data_start + exec_data_offset; */
|
||||
/* OBSOLETE xferfile = &execfile; */
|
||||
/* OBSOLETE xferchan = execchan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (memaddr >= text_start && memaddr < text_end) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE struct shared_library *lib; */
|
||||
/* OBSOLETE for (lib = shlib; lib; lib = lib->shares) */
|
||||
/* OBSOLETE if (memaddr >= lib->text_start && */
|
||||
/* OBSOLETE memaddr < lib->text_start + lib->header.a_exec.a_text) */
|
||||
/* OBSOLETE break; */
|
||||
/* OBSOLETE if (lib) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, lib->header.a_exec.a_text + */
|
||||
/* OBSOLETE lib->text_start - memaddr); */
|
||||
/* OBSOLETE fileptr = memaddr - lib->text_start + text_offset; */
|
||||
/* OBSOLETE xferfile = &execfile; */
|
||||
/* OBSOLETE xferchan = lib->chan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, text_end - memaddr); */
|
||||
/* OBSOLETE fileptr = memaddr - unshared_text_start + text_offset; */
|
||||
/* OBSOLETE xferfile = &execfile; */
|
||||
/* OBSOLETE xferchan = execchan; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (memaddr < text_start) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, text_start - memaddr); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (memaddr >= text_end */
|
||||
/* OBSOLETE && memaddr < (corechan >= 0 ? data_start : exec_data_start)) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, data_start - memaddr); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (corechan >= 0 */
|
||||
/* OBSOLETE && memaddr >= data_end && memaddr < stack_start) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, stack_start - memaddr); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (corechan < 0 && memaddr >= exec_data_end) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, -memaddr); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else if (memaddr >= stack_end && stack_end != 0) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE i = min (len, -memaddr); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE /* Address did not classify into one of the known ranges. */
|
||||
/* OBSOLETE This shouldn't happen; we catch the endpoints. *x/ */
|
||||
/* OBSOLETE internal_error ("Bad case logic in xfer_core_file."); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE /* Now we know which file to use. */
|
||||
/* OBSOLETE Set up its pointer and transfer the data. *x/ */
|
||||
/* OBSOLETE if (xferfile) */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE if (*xferfile == 0) */
|
||||
/* OBSOLETE if (xferfile == &execfile) */
|
||||
/* OBSOLETE error ("No program file to examine."); */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE error ("No core dump file or running program to examine."); */
|
||||
/* OBSOLETE val = lseek (xferchan, fileptr, 0); */
|
||||
/* OBSOLETE if (val < 0) */
|
||||
/* OBSOLETE perror_with_name (*xferfile); */
|
||||
/* OBSOLETE val = myread (xferchan, myaddr, i); */
|
||||
/* OBSOLETE if (val < 0) */
|
||||
/* OBSOLETE perror_with_name (*xferfile); */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE /* If this address is for nonexistent memory, */
|
||||
/* OBSOLETE read zeros if reading, or do nothing if writing. */
|
||||
/* OBSOLETE Actually, we never right. *x/ */
|
||||
/* OBSOLETE else */
|
||||
/* OBSOLETE { */
|
||||
/* OBSOLETE memset (myaddr, '\0', i); */
|
||||
/* OBSOLETE returnval = EIO; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE */
|
||||
/* OBSOLETE memaddr += i; */
|
||||
/* OBSOLETE myaddr += i; */
|
||||
/* OBSOLETE len -= i; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE return returnval; */
|
||||
/* OBSOLETE } */
|
||||
/* OBSOLETE #endif */
|
File diff suppressed because it is too large
Load Diff
@ -1,349 +0,0 @@
|
||||
/* Host callback routines for GDB.
|
||||
Copyright 1995 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
/* This file provides a standard way for targets to talk to the host OS
|
||||
level.
|
||||
|
||||
This interface will probably need a bit more banging to make it
|
||||
smooth. Currently the simulator uses this file to provide the
|
||||
callbacks for itself when it's built standalone, which is rather
|
||||
ugly. */
|
||||
|
||||
#ifndef INSIDE_SIMULATOR
|
||||
#include "defs.h"
|
||||
#endif
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "callback.h"
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
/* Set the callback copy of errno from what we see now. */
|
||||
static int
|
||||
wrap (p, val)
|
||||
host_callback *p;
|
||||
int val;
|
||||
{
|
||||
p->last_errno = errno;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Make sure the FD provided is ok. If not, return non-zero
|
||||
and set errno. */
|
||||
|
||||
static int
|
||||
fdbad (p, fd)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
{
|
||||
if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
|
||||
{
|
||||
p->last_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fdmap (p, fd)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
{
|
||||
return p->fdmap[fd];
|
||||
}
|
||||
|
||||
int
|
||||
os_close (p, fd)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
{
|
||||
int result;
|
||||
|
||||
result = fdbad (p, fd);
|
||||
if (result)
|
||||
return result;
|
||||
result = wrap (p, close (fdmap (p, fd)));
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
os_get_errno (p)
|
||||
host_callback *p;
|
||||
{
|
||||
/* !!! fixme, translate from host to taget errno value */
|
||||
return p->last_errno;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
os_isatty (p, fd)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
{
|
||||
int result;
|
||||
|
||||
result = fdbad (p, fd);
|
||||
if (result)
|
||||
return result;
|
||||
result = wrap (p, isatty (fdmap (fd)));
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
os_lseek (p, fd, off, way)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
long off;
|
||||
int way;
|
||||
{
|
||||
int result;
|
||||
|
||||
result = fdbad (p, fd);
|
||||
if (result)
|
||||
return result;
|
||||
result = lseek (fdmap (p, fd), off, way);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
os_open (p, name, flags)
|
||||
host_callback *p;
|
||||
const char *name;
|
||||
int flags;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_CALLBACK_FDS; i++)
|
||||
{
|
||||
if (!p->fdopen[i])
|
||||
{
|
||||
int f = open (name, flags);
|
||||
if (f < 0)
|
||||
{
|
||||
p->last_errno = errno;
|
||||
return f;
|
||||
}
|
||||
p->fdopen[i] = 1;
|
||||
p->fdmap[i] = f;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
p->last_errno = EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
os_read (p, fd, buf, len)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
int result;
|
||||
|
||||
result = fdbad (p, fd);
|
||||
if (result)
|
||||
return result;
|
||||
result = wrap (p, read (fdmap (p, fd), buf, len));
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
os_read_stdin (p, buf, len)
|
||||
host_callback *p;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
return wrap (p, read (0, buf, len));
|
||||
}
|
||||
|
||||
int
|
||||
os_write (p, fd, buf, len)
|
||||
host_callback *p;
|
||||
int fd;
|
||||
const char *buf;
|
||||
int len;
|
||||
{
|
||||
int result;
|
||||
|
||||
result = fdbad (p, fd);
|
||||
if (result)
|
||||
return result;
|
||||
result = wrap (p, write (fdmap (p, fd), buf, len));
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ignore the grossness of INSIDE_SIMULATOR, it will go away one day. */
|
||||
int
|
||||
os_write_stdout (p, buf, len)
|
||||
host_callback *p;
|
||||
const char *buf;
|
||||
int len;
|
||||
{
|
||||
#ifdef INSIDE_SIMULATOR
|
||||
return os_write (p, 1, buf, len);
|
||||
#else
|
||||
int i;
|
||||
char b[2];
|
||||
for (i = 0; i< len; i++)
|
||||
{
|
||||
b[0] = buf[i];
|
||||
b[1] = 0;
|
||||
if (target_output_hook)
|
||||
target_output_hook (b);
|
||||
else
|
||||
fputs_filtered (b, gdb_stdout);
|
||||
}
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
os_rename (p, f1, f2)
|
||||
host_callback *p;
|
||||
const char *f1;
|
||||
const char *f2;
|
||||
{
|
||||
return wrap (p, rename (f1, f2));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
os_system (p, s)
|
||||
host_callback *p;
|
||||
const char *s;
|
||||
{
|
||||
return wrap (p, system (s));
|
||||
}
|
||||
|
||||
long
|
||||
os_time (p, t)
|
||||
host_callback *p;
|
||||
long *t;
|
||||
{
|
||||
return wrap (p, time (t));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
os_unlink (p, f1)
|
||||
host_callback *p;
|
||||
const char *f1;
|
||||
{
|
||||
return wrap (p, unlink (f1));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
os_shutdown (p)
|
||||
host_callback *p;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_CALLBACK_FDS; i++)
|
||||
{
|
||||
if (p->fdopen[i] && !p->alwaysopen[i]) {
|
||||
close (p->fdmap[i]);
|
||||
p->fdopen[i] = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int os_init(p)
|
||||
host_callback *p;
|
||||
{
|
||||
int i;
|
||||
os_shutdown (p);
|
||||
for (i= 0; i < 3; i++)
|
||||
{
|
||||
p->fdmap[i] = i;
|
||||
p->fdopen[i] = 1;
|
||||
p->alwaysopen[i] = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* !!fixme!!
|
||||
This bit is ugly. When the interface has settled down I'll
|
||||
move the whole file into sim/common and remove this bit. */
|
||||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
os_printf_filtered (host_callback *p, const char *format, ...)
|
||||
#else
|
||||
os_printf_filtered (p, va_alist)
|
||||
host_callback *p;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
char *format;
|
||||
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
#ifdef INSIDE_SIMULATOR
|
||||
vprintf (format, args);
|
||||
#else
|
||||
vfprintf_filtered (stdout, format, args);
|
||||
#endif
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
host_callback default_callback =
|
||||
{
|
||||
os_close,
|
||||
os_get_errno,
|
||||
os_isatty,
|
||||
os_lseek,
|
||||
os_open,
|
||||
os_read,
|
||||
os_read_stdin,
|
||||
os_rename,
|
||||
os_system,
|
||||
os_time,
|
||||
os_unlink,
|
||||
os_write,
|
||||
os_write_stdout,
|
||||
|
||||
os_shutdown,
|
||||
os_init,
|
||||
|
||||
os_printf_filtered,
|
||||
|
||||
0, /* last errno */
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
#ifndef CALLBACK_H
|
||||
#define CALLBACK_H
|
||||
typedef struct host_callback_struct host_callback;
|
||||
|
||||
#define MAX_CALLBACK_FDS 10
|
||||
|
||||
struct host_callback_struct
|
||||
{
|
||||
int (*close) PARAMS ((host_callback *,int));
|
||||
int (*get_errno) PARAMS ((host_callback *));
|
||||
int (*isatty) PARAMS ((host_callback *, int));
|
||||
int (*lseek) PARAMS ((host_callback *, int, long , int));
|
||||
int (*open) PARAMS ((host_callback *, const char*, int mode));
|
||||
int (*read) PARAMS ((host_callback *,int, char *, int));
|
||||
int (*read_stdin) PARAMS (( host_callback *, char *, int));
|
||||
int (*rename) PARAMS ((host_callback *, const char *, const char *));
|
||||
int (*system) PARAMS ((host_callback *, const char *));
|
||||
long (*time) PARAMS ((host_callback *, long *));
|
||||
int (*unlink) PARAMS ((host_callback *, const char *));
|
||||
int (*write) PARAMS ((host_callback *,int, const char *, int));
|
||||
int (*write_stdout) PARAMS ((host_callback *, const char *, int));
|
||||
|
||||
|
||||
/* Used when the target has gone away, so we can close open
|
||||
handles and free memory etc etc. */
|
||||
int (*shutdown) PARAMS ((host_callback *));
|
||||
int (*init) PARAMS ((host_callback *));
|
||||
|
||||
/* Talk to the user on a console. */
|
||||
void (*printf_filtered) PARAMS ((host_callback *, const char *, ...));
|
||||
|
||||
int last_errno; /* host format */
|
||||
|
||||
int fdmap[MAX_CALLBACK_FDS];
|
||||
char fdopen[MAX_CALLBACK_FDS];
|
||||
char alwaysopen[MAX_CALLBACK_FDS];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
extern host_callback default_callback;
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
||||
MH_CFLAGS=
|
||||
XM_FILE=xm-cygwin32.h
|
||||
TERMCAP=
|
||||
NATDEPFILES=win32-nat.o
|
||||
XM_CLIBS=-lkernel32
|
||||
|
@ -1,6 +0,0 @@
|
||||
# Target: Intel 386 run win32
|
||||
TDEPFILES= i386-tdep.o i387-tdep.o
|
||||
TM_FILE= tm-cygwin32.h
|
||||
|
||||
|
||||
|
@ -1,27 +0,0 @@
|
||||
/* Native support for Sun 386i, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987, 1989, 1992 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Do implement the attach and detach commands. */
|
||||
|
||||
#define ATTACH_DETACH
|
||||
|
||||
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
|
||||
#define FETCH_INFERIOR_REGISTERS
|
||||
|
||||
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
|
@ -1,5 +0,0 @@
|
||||
# Host: Sun 386i
|
||||
XDEPFILES=
|
||||
XM_FILE= xm-sun386.h
|
||||
NAT_FILE= nm-sun386.h
|
||||
NATDEPFILES= infptrace.o inftarg.o fork-child.o sun386-nat.o
|
@ -1,3 +0,0 @@
|
||||
# Target: Sun 386i target configuration file.
|
||||
TDEPFILES= i386-tdep.o solib.o
|
||||
TM_FILE= tm-sun386.h
|
@ -1,125 +0,0 @@
|
||||
/* Macro definitions for i386 running under the win32 API Unix.
|
||||
Copyright 1995, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "i386/tm-i386v.h"
|
||||
|
||||
#undef MAX_REGISTER_RAW_SIZE
|
||||
#undef MAX_REGISTER_VIRTUAL_SIZE
|
||||
#undef NUM_REGS
|
||||
#undef REGISTER_BYTE
|
||||
#undef REGISTER_BYTES
|
||||
#undef REGISTER_CONVERTIBLE
|
||||
#undef REGISTER_CONVERT_TO_RAW
|
||||
#undef REGISTER_CONVERT_TO_VIRTUAL
|
||||
#undef REGISTER_NAMES
|
||||
#undef REGISTER_RAW_SIZE
|
||||
#undef REGISTER_VIRTUAL_SIZE
|
||||
#undef REGISTER_VIRTUAL_TYPE
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#define NUM_REGS 24
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
|
||||
/* the order of the first 8 registers must match the compiler's
|
||||
* numbering scheme (which is the same as the 386 scheme)
|
||||
* also, this table must match regmap in i386-pinsn.c.
|
||||
*/
|
||||
|
||||
#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
|
||||
"esp", "ebp", "esi", "edi", \
|
||||
"eip", "ps", "cs", "ss", \
|
||||
"ds", "es", "fs", "gs", \
|
||||
"st", "st(1)","st(2)","st(3)",\
|
||||
"st(4)","st(5)","st(6)","st(7)",}
|
||||
|
||||
#define FP0_REGNUM 16
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
|
||||
#define REGISTER_BYTES (16 * 4 + 8 * 10)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#define REGISTER_BYTE(N) (((N) < 16) ? (N) * 4 : (((N) - 16) * 10) + (16 * 4))
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. */
|
||||
|
||||
#define REGISTER_RAW_SIZE(N) (((N) < 16) ? 4 : 10)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((N) < 16) ? 4 : 10)
|
||||
|
||||
/* Largest value REGISTER_RAW_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_RAW_SIZE 10
|
||||
|
||||
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
|
||||
|
||||
#define MAX_REGISTER_VIRTUAL_SIZE 10
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#define REGISTER_CONVERTIBLE(N) \
|
||||
((N < FP0_REGNUM) ? 0 : 1)
|
||||
|
||||
/* Convert data from raw format for register REGNUM in buffer FROM
|
||||
to virtual format with type TYPE in buffer TO. */
|
||||
extern void
|
||||
i387_to_double PARAMS ((char *, char *));
|
||||
|
||||
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
|
||||
{ \
|
||||
double val; \
|
||||
i387_to_double ((FROM), (char *)&val); \
|
||||
store_floating ((TO), TYPE_LENGTH (TYPE), val); \
|
||||
}
|
||||
|
||||
extern void
|
||||
double_to_i387 PARAMS ((char *, char *));
|
||||
|
||||
#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
|
||||
{ \
|
||||
double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
|
||||
double_to_i387((char *)&val, (TO)); \
|
||||
}
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
((N < FP0_REGNUM) ? builtin_type_int : \
|
||||
builtin_type_double)
|
||||
|
||||
#define NAMES_HAVE_UNDERSCORE
|
||||
|
||||
|
||||
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, 0)
|
||||
extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR pc, char *name));
|
@ -1,205 +0,0 @@
|
||||
/* Parameters for a Sun 386i target machine, for GDB, the GNU debugger.
|
||||
Copyright 1986, 1987, 1991, 1992, 1993 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if !defined (TM_SUN386_H)
|
||||
#define TM_SUN386_H 1
|
||||
|
||||
#include "i386/tm-i386.h"
|
||||
|
||||
#ifndef sun386
|
||||
#define sun386
|
||||
#endif
|
||||
#define GDB_TARGET_IS_SUN386 1
|
||||
#define SUNOS4
|
||||
#define USE_MACHINE_REG_H
|
||||
|
||||
/* Perhaps some day this will work even without the following #define */
|
||||
#define COFF_ENCAPSULATE
|
||||
|
||||
#ifdef COFF_ENCAPSULATE
|
||||
/* Avoid conflicts between our include files and <sys/exec.h>
|
||||
(maybe not needed anymore). */
|
||||
#define _EXEC_
|
||||
#endif
|
||||
|
||||
/* sun386 ptrace seems unable to change the frame pointer */
|
||||
#define PTRACE_FP_BUG
|
||||
|
||||
/* Address of end of stack space. */
|
||||
|
||||
#define STACK_END_ADDR 0xfc000000
|
||||
|
||||
/* Number of machine registers */
|
||||
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS 35
|
||||
|
||||
/* Initializer for an array of names of registers. There should be NUM_REGS
|
||||
strings in this initializer. The order of the first 8 registers must match
|
||||
the compiler's numbering scheme (which is the same as the 386 scheme) also,
|
||||
this table must match regmap in i386-pinsn.c. */
|
||||
|
||||
#undef REGISTER_NAMES
|
||||
#define REGISTER_NAMES { "gs", "fs", "es", "ds", \
|
||||
"edi", "esi", "ebp", "esp", \
|
||||
"ebx", "edx", "ecx", "eax", \
|
||||
"retaddr", "trapnum", "errcode", "ip", \
|
||||
"cs", "ps", "sp", "ss", \
|
||||
"fst0", "fst1", "fst2", "fst3", \
|
||||
"fst4", "fst5", "fst6", "fst7", \
|
||||
"fctrl", "fstat", "ftag", "fip", \
|
||||
"fcs", "fopoff", "fopsel" \
|
||||
}
|
||||
|
||||
/* Register numbers of various important registers.
|
||||
Note that some of these values are "real" register numbers,
|
||||
and correspond to the general registers of the machine,
|
||||
and some are "phony" register numbers which are too large
|
||||
to be actual register numbers as far as the user is concerned
|
||||
but do serve to get the desired values when passed to read_register. */
|
||||
|
||||
#undef FP_REGNUM
|
||||
#define FP_REGNUM 6 /* (ebp) Contains address of executing stack frame */
|
||||
#undef SP_REGNUM
|
||||
#define SP_REGNUM 18 /* (usp) Contains address of top of stack */
|
||||
#undef PS_REGNUM
|
||||
#define PS_REGNUM 17 /* (ps) Contains processor status */
|
||||
#undef PC_REGNUM
|
||||
#define PC_REGNUM 15 /* (eip) Contains program counter */
|
||||
#undef FP0_REGNUM
|
||||
#define FP0_REGNUM 20 /* Floating point register 0 */
|
||||
#undef FPC_REGNUM
|
||||
#define FPC_REGNUM 28 /* 80387 control register */
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'. */
|
||||
|
||||
#undef REGISTER_BYTES
|
||||
#define REGISTER_BYTES (20*4+8*10+7*4)
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
#undef REGISTER_BYTE
|
||||
#define REGISTER_BYTE(N) \
|
||||
((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 160 \
|
||||
: (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 10) + 80 \
|
||||
: (N) * 4)
|
||||
|
||||
/* Number of bytes of storage in the actual machine representation
|
||||
for register N. */
|
||||
|
||||
#undef REGISTER_RAW_SIZE
|
||||
#define REGISTER_RAW_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 10 : 4)
|
||||
|
||||
/* Number of bytes of storage in the program's representation
|
||||
for register N. */
|
||||
|
||||
#undef REGISTER_VIRTUAL_SIZE
|
||||
#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 8 : 4)
|
||||
|
||||
/* Nonzero if register N requires conversion
|
||||
from raw format to virtual format. */
|
||||
|
||||
#undef REGISTER_CONVERTIBLE
|
||||
#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
|
||||
|
||||
/* Convert data from raw format for register REGNUM in buffer FROM
|
||||
to virtual format with type TYPE in buffer TO. */
|
||||
|
||||
#undef REGISTER_CONVERT_TO_VIRTUAL
|
||||
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
|
||||
{ \
|
||||
double val; \
|
||||
i387_to_double ((FROM), (char *)&val); \
|
||||
store_floating ((TO), TYPE_LENGTH (TYPE), val); \
|
||||
}
|
||||
extern void
|
||||
i387_to_double PARAMS ((char *, char *));
|
||||
|
||||
/* Convert data from virtual format with type TYPE in buffer FROM
|
||||
to raw format for register REGNUM in buffer TO. */
|
||||
|
||||
#undef REGISTER_CONVERT_TO_RAW
|
||||
#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
|
||||
{ \
|
||||
double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
|
||||
double_to_i387((char *)&val, (TO)); \
|
||||
}
|
||||
extern void
|
||||
double_to_i387 PARAMS ((char *, char *));
|
||||
|
||||
/* Return the GDB type object for the "standard" data type
|
||||
of data in register N. */
|
||||
|
||||
#undef REGISTER_VIRTUAL_TYPE
|
||||
#define REGISTER_VIRTUAL_TYPE(N) \
|
||||
(((unsigned)((N) - FP0_REGNUM)) < 8 ? builtin_type_double : builtin_type_int)
|
||||
|
||||
/* Extract from an array REGBUF containing the (raw) register state
|
||||
a function return value of type TYPE, and copy that, in virtual format,
|
||||
into VALBUF. */
|
||||
|
||||
#undef EXTRACT_RETURN_VALUE
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
memcpy (VALBUF, REGBUF + REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), TYPE_LENGTH (TYPE))
|
||||
|
||||
/* Write into appropriate registers a function return value
|
||||
of type TYPE, given in virtual format. */
|
||||
|
||||
#undef STORE_RETURN_VALUE
|
||||
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
|
||||
write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
|
||||
/* FRAME_CHAIN takes a frame's nominal address
|
||||
and produces the frame's chain-pointer. */
|
||||
|
||||
#undef FRAME_CHAIN
|
||||
#define FRAME_CHAIN(thisframe) \
|
||||
(!inside_entry_file ((thisframe)->pc) ? \
|
||||
read_memory_integer ((thisframe)->frame, 4) :\
|
||||
0)
|
||||
|
||||
/* Define other aspects of the stack frame. */
|
||||
|
||||
/* A macro that tells us whether the function invocation represented
|
||||
by FI does not have a frame on the stack associated with it. If it
|
||||
does not, FRAMELESS is set to 1, else 0. */
|
||||
|
||||
#undef FRAMELESS_FUNCTION_INVOCATION
|
||||
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
|
||||
{ (FRAMELESS) = frameless_look_for_prologue (FI); }
|
||||
|
||||
#undef FRAME_SAVED_PC
|
||||
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
|
||||
|
||||
/* Insert the specified number of args and function address
|
||||
into a call sequence of the above form stored at DUMMYNAME. */
|
||||
|
||||
#undef FIX_CALL_DUMMY
|
||||
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
|
||||
{ \
|
||||
*(int *)((char *)(dummyname) + 1) = (int)(fun) - (pc) - 5; \
|
||||
}
|
||||
|
||||
#endif /* !defined (TM_SUN386_H) */
|
||||
|
@ -1,17 +0,0 @@
|
||||
# gdbwin.o and ser-win32s.c have to be named because they have
|
||||
# _initialize functions that need to be found by init.c
|
||||
# gui.ores has to be named, or else msvc won't link it in.
|
||||
XDEPFILES = \
|
||||
mswin/gdbwin.o \
|
||||
mswin/ser-win32s.o \
|
||||
mswin/gui.ores \
|
||||
mswin/libwingdb.a
|
||||
|
||||
$(XDEPFILES):
|
||||
rootme=`pwd` ; export rootme ; \
|
||||
( cd mswin ; \
|
||||
$(MAKE) $(FLAGS_TO_PASS) all )
|
||||
|
||||
XM_FILE=xm-windows.h
|
||||
MMALLOC=
|
||||
SER_HARDWIRE =
|
@ -1,41 +0,0 @@
|
||||
/* Definitions for hosting on WIN32, for GDB.
|
||||
Copyright 1995, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define HOST_BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#include "fopen-bin.h"
|
||||
|
||||
#define GDBINIT_FILENAME "gdb.ini"
|
||||
|
||||
|
||||
#define SLASH_P(X) ((X)=='\\' || (X) == '/')
|
||||
#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
|
||||
#define SLASH_CHAR '/'
|
||||
#define SLASH_STRING "/"
|
||||
|
||||
|
||||
/* If we longjmp out of the signal handler we never get another one.
|
||||
So disable immediate_quit inside request_quit */
|
||||
#define REQUEST_QUIT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
/* Host-dependent definitions for Intel 386 running LynxOS.
|
||||
Copyright 1993 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define HOST_BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
/* Get generic LynxOS host definitions. */
|
||||
|
||||
#include "xm-lynx.h"
|
@ -1,36 +0,0 @@
|
||||
/* Native support for GNU/Linux, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987, 1989, 1992 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef XM_LINUX_H
|
||||
#define XM_LINUX_H
|
||||
|
||||
#define HOST_BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#define HAVE_TERMIOS
|
||||
|
||||
/* This is the amount to subtract from u.u_ar0
|
||||
to get the offset in the core file of the register values. */
|
||||
#define KERNEL_U_ADDR 0x0
|
||||
|
||||
#define NEED_POSIX_SETPGID
|
||||
|
||||
/* Need R_OK etc, but USG isn't defined. */
|
||||
#include <unistd.h>
|
||||
|
||||
#endif /* #ifndef XM_LINUX_H */
|
@ -1,20 +0,0 @@
|
||||
/* Host support for Sun 386i, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define HOST_BYTE_ORDER LITTLE_ENDIAN
|
@ -1,35 +0,0 @@
|
||||
/* Definitions for hosting on WIN32, built with Microsoft Visual C/C++, for GDB.
|
||||
Copyright 1996, 1998 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "i386/xm-cygwin.h"
|
||||
|
||||
#undef PRINTF_HAS_LONG_LONG
|
||||
#undef HAVE_UNISTD_H
|
||||
#undef HAVE_TERMIO_H
|
||||
#undef HAVE_TERMIOS_H
|
||||
#undef HAVE_SGTTY_H
|
||||
#undef HAVE_SBRK
|
||||
#define CANT_FORK
|
||||
|
||||
#define MALLOC_INCOMPATIBLE
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
#define SIGQUIT 3
|
||||
#define SIGTRAP 5
|
@ -1,2 +0,0 @@
|
||||
/* This is just a dummy file to symlink to when GDB is configured as a
|
||||
cross-only debugger. */
|
@ -1,43 +0,0 @@
|
||||
/* Common declarations for the GNU Hurd
|
||||
|
||||
Copyright 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>
|
||||
|
||||
The GNU Hurd 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 2, or (at
|
||||
your option) any later version.
|
||||
|
||||
The GNU Hurd 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef __NM_GNU_H__
|
||||
#define __NM_GNU_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <mach.h>
|
||||
#include <mach/exception.h>
|
||||
#include "regcache.h"
|
||||
|
||||
extern char *gnu_target_pid_to_str (int pid);
|
||||
|
||||
/* Before storing, we need to read all the registers. */
|
||||
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
|
||||
|
||||
/* Don't do wait_for_inferior on attach. */
|
||||
#define ATTACH_NO_WAIT
|
||||
|
||||
/* Use SVR4 style shared library support */
|
||||
#define SVR4_SHARED_LIBS
|
||||
#include "solib.h"
|
||||
#define NO_CORE_OPS
|
||||
|
||||
#endif /* __NM_GNU_H__ */
|
@ -1,85 +0,0 @@
|
||||
/* Native-dependent definitions for LynxOS.
|
||||
Copyright 1993, 1994, 1995, 1996, 1999, 2000
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef NM_LYNX_H
|
||||
#define NM_LYNX_H
|
||||
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
/* sys/kernel.h should define this, but doesn't always, sigh. */
|
||||
#ifndef __LYNXOS
|
||||
#define __LYNXOS
|
||||
#endif
|
||||
#include <sys/mem.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/itimer.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/proc.h>
|
||||
#include "gdbthread.h"
|
||||
|
||||
/* This is the amount to subtract from u.u_ar0 to get the offset in
|
||||
the core file of the register values. */
|
||||
|
||||
#define KERNEL_U_ADDR USRSTACK
|
||||
|
||||
#undef FLOAT_INFO /* No float info yet */
|
||||
|
||||
/* As of LynxOS 2.2.2 (beta 8/15/94), this is int. Previous versions seem to
|
||||
have had no prototype, so I'm not sure why GDB used to define this to
|
||||
char *. */
|
||||
#define PTRACE_ARG3_TYPE int
|
||||
|
||||
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
|
||||
|
||||
#define FETCH_INFERIOR_REGISTERS
|
||||
|
||||
/* Thread ID of stopped thread. */
|
||||
|
||||
#define WIFTID(x) (((union wait *)&x)->w_tid)
|
||||
|
||||
/* Override child_wait in inftarg.c */
|
||||
|
||||
#define CHILD_WAIT
|
||||
|
||||
/* Override child_resume in infptrace.c */
|
||||
|
||||
#define CHILD_RESUME
|
||||
|
||||
/* Override child_thread_alive in intarg.c */
|
||||
|
||||
#define CHILD_THREAD_ALIVE
|
||||
|
||||
#include "target.h"
|
||||
|
||||
extern ptid_t child_wait (ptid_t ptid,
|
||||
struct target_waitstatus *status);
|
||||
|
||||
/* Lynx needs a special definition of this so that we can
|
||||
print out the pid and thread number seperately. */
|
||||
|
||||
|
||||
/* override child_pid_to_str in inftarg.c */
|
||||
#define CHILD_PID_TO_STR
|
||||
extern char *lynx_pid_to_str (ptid_t ptid);
|
||||
|
||||
#endif /* NM_LYNX_H */
|
@ -1,126 +0,0 @@
|
||||
/* Mach 3.0 common definitions and global vars.
|
||||
|
||||
Copyright 1992, 1993, 1994, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef NM_M3_H
|
||||
#define NM_M3_H
|
||||
|
||||
#include <mach.h>
|
||||
#include "regcache.h"
|
||||
|
||||
/* Mach3 doesn't declare errno in <errno.h>. */
|
||||
extern int errno;
|
||||
|
||||
/* Task port of our debugged inferior. */
|
||||
|
||||
extern task_t inferior_task;
|
||||
|
||||
/* Thread port of the current thread in the inferior. */
|
||||
|
||||
extern thread_t current_thread;
|
||||
|
||||
/* If nonzero, we must suspend/abort && resume threads
|
||||
* when setting or getting the state.
|
||||
*/
|
||||
extern int must_suspend_thread;
|
||||
|
||||
#define PREPARE_TO_PROCEED(select_it) mach3_prepare_to_proceed(select_it)
|
||||
|
||||
/* Try to get the privileged host port for authentication to machid
|
||||
|
||||
* If you can get this, you may debug anything on this host.
|
||||
*
|
||||
* If you can't, gdb gives it's own task port as the
|
||||
* authentication port
|
||||
*/
|
||||
#define mach_privileged_host_port() task_by_pid(-1)
|
||||
|
||||
/*
|
||||
* This is the MIG ID number of the emulator/server bsd_execve() RPC call.
|
||||
*
|
||||
* It SHOULD never change, but if it does, gdb `run'
|
||||
* command won't work until you fix this define.
|
||||
*
|
||||
*/
|
||||
#define MIG_EXEC_SYSCALL_ID 101000
|
||||
|
||||
/* If our_message_port gets a msg with this ID,
|
||||
* GDB suspends it's inferior and enters command level.
|
||||
* (Useful at least if ^C does not work)
|
||||
*/
|
||||
#define GDB_MESSAGE_ID_STOP 0x41151
|
||||
|
||||
/* wait3 WNOHANG is defined in <sys/wait.h> but
|
||||
* for some reason gdb does not want to include
|
||||
* that file.
|
||||
*
|
||||
* If your system defines WNOHANG differently, this has to be changed.
|
||||
*/
|
||||
#define WNOHANG 1
|
||||
|
||||
/* Before storing, we need to read all the registers. */
|
||||
|
||||
#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
|
||||
|
||||
/* Check if the inferior exists */
|
||||
#define MACH_ERROR_NO_INFERIOR \
|
||||
do if (!MACH_PORT_VALID (inferior_task)) \
|
||||
error ("Inferior task does not exist."); while(0)
|
||||
|
||||
/* Error handler for mach calls */
|
||||
#define CHK(str,ret) \
|
||||
do if (ret != KERN_SUCCESS) \
|
||||
error ("Gdb %s [%d] %s : %s\n",__FILE__,__LINE__,str, \
|
||||
mach_error_string(ret)); while(0)
|
||||
|
||||
/* This is from POE9 emulator/emul_stack.h
|
||||
*/
|
||||
/*
|
||||
* Top of emulator stack holds link and reply port.
|
||||
*/
|
||||
struct emul_stack_top
|
||||
{
|
||||
struct emul_stack_top *link;
|
||||
mach_port_t reply_port;
|
||||
};
|
||||
|
||||
#define EMULATOR_STACK_SIZE (4096*4)
|
||||
|
||||
#define THREAD_ALLOWED_TO_BREAK(mid) mach_thread_for_breakpoint (mid)
|
||||
|
||||
#define THREAD_PARSE_ID(arg) mach_thread_parse_id (arg)
|
||||
|
||||
#define THREAD_OUTPUT_ID(mid) mach_thread_output_id (mid)
|
||||
|
||||
#define ATTACH_TO_THREAD attach_to_thread
|
||||
|
||||
/* Don't do wait_for_inferior on attach. */
|
||||
#define ATTACH_NO_WAIT
|
||||
|
||||
/* Do Mach 3 dependent operations when ^C or a STOP is requested */
|
||||
#define DO_QUIT() mach3_quit ()
|
||||
|
||||
#if 0
|
||||
/* This is bogus. It is NOT OK to quit out of target_wait. */
|
||||
/* If in mach_msg() and ^C is typed set immediate_quit */
|
||||
#define REQUEST_QUIT() mach3_request_quit ()
|
||||
#endif
|
||||
|
||||
#endif /* NM_M3_H */
|
@ -1,87 +0,0 @@
|
||||
/* Native-dependent definitions for NetBSD.
|
||||
Copyright 1994, 1996, 1999 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define PTRACE_ARG3_TYPE char*
|
||||
|
||||
#define FETCH_INFERIOR_REGISTERS
|
||||
|
||||
#define ATTACH_DETACH
|
||||
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#if defined (SVR4_SHARED_LIBS)
|
||||
#include "elf/common.h" /* Additional ELF shared library info. */
|
||||
#endif
|
||||
|
||||
#if !defined (SVR4_SHARED_LIBS)
|
||||
|
||||
/* make structure definitions match up with those expected in solib.c */
|
||||
#define link_object sod
|
||||
#define lo_name sod_name
|
||||
#define lo_library sod_library
|
||||
#define lo_unused sod_reserved
|
||||
#define lo_major sod_major
|
||||
#define lo_minor sod_minor
|
||||
#define lo_next sod_next
|
||||
|
||||
#define link_map so_map
|
||||
#define lm_addr som_addr
|
||||
#define lm_name som_path
|
||||
#define lm_next som_next
|
||||
#define lm_lop som_sod
|
||||
#define lm_lob som_sodbase
|
||||
#define lm_rwt som_write
|
||||
#define lm_ld som_dynamic
|
||||
#define lm_lpd som_spd
|
||||
|
||||
#define link_dynamic_2 section_dispatch_table
|
||||
#define ld_loaded sdt_loaded
|
||||
#define ld_need sdt_sods
|
||||
#define ld_rules sdt_filler1
|
||||
#define ld_got sdt_got
|
||||
#define ld_plt sdt_plt
|
||||
#define ld_rel sdt_rel
|
||||
#define ld_hash sdt_hash
|
||||
#define ld_stab sdt_nzlist
|
||||
#define ld_stab_hash sdt_filler2
|
||||
#define ld_buckets sdt_buckets
|
||||
#define ld_symbols sdt_strings
|
||||
#define ld_symb_size sdt_str_sz
|
||||
#define ld_text sdt_text_sz
|
||||
#define ld_plt_sz sdt_plt_sz
|
||||
|
||||
#define rtc_symb rt_symbol
|
||||
#define rtc_sp rt_sp
|
||||
#define rtc_next rt_next
|
||||
|
||||
#define ld_debug so_debug
|
||||
#define ldd_version dd_version
|
||||
#define ldd_in_debugger dd_in_debugger
|
||||
#define ldd_sym_loaded dd_sym_loaded
|
||||
#define ldd_bp_addr dd_bpt_addr
|
||||
#define ldd_bp_inst dd_bpt_shadow
|
||||
#define ldd_cp dd_cc
|
||||
|
||||
#define link_dynamic _dynamic
|
||||
#define ld_version d_version
|
||||
#define ldd d_debug
|
||||
#define ld_un d_un
|
||||
#define ld_2 d_sdt
|
||||
|
||||
#endif
|
@ -1,34 +0,0 @@
|
||||
/* Definitions for running gdb on a host machine running any flavor of SVR4.
|
||||
Copyright 1991, 1992, 1993, 1998 Free Software Foundation, Inc.
|
||||
Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Use SVR4 style shared library support */
|
||||
|
||||
#define SVR4_SHARED_LIBS
|
||||
#include "solib.h"
|
||||
|
||||
/* SVR4 has /proc support, so use it instead of ptrace. */
|
||||
|
||||
#define USE_PROC_FS
|
||||
|
||||
/* SVR4 machines can easily do attach and detach via /proc (procfs.c)
|
||||
support */
|
||||
|
||||
#define ATTACH_DETACH
|
@ -1,35 +0,0 @@
|
||||
/* Macro definitions for LynxOS targets.
|
||||
Copyright 1993, 1995 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef TM_LYNX_H
|
||||
#define TM_LYNX_H
|
||||
|
||||
/* Override number of expected traps from sysv. */
|
||||
#define START_INFERIOR_TRAPS_EXPECTED 2
|
||||
|
||||
#include "coff-solib.h" /* COFF shared library support */
|
||||
|
||||
/* Lynx's signal.h doesn't seem to have any macros for what signal numbers
|
||||
the real-time events are. */
|
||||
#define REALTIME_LO 33
|
||||
/* One more than the last one. */
|
||||
#define REALTIME_HI 64
|
||||
|
||||
#endif /* TM_LYNX_H */
|
@ -1,29 +0,0 @@
|
||||
/* Target machine sub-description for NetBSD.
|
||||
This is included by other tm-*.h files to specify NetBSD-specific stuff.
|
||||
Copyright 1993, 1994 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef SVR4_SHARED_LIBS
|
||||
|
||||
/* Return non-zero if we are in a shared library trampoline code stub. */
|
||||
|
||||
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
|
||||
(name && !strcmp(name, "_DYNAMIC"))
|
||||
|
||||
#endif /* !SVR4_SHARED_LIBS */
|
@ -1,32 +0,0 @@
|
||||
/* Target machine sub-description for SunOS version 4.
|
||||
This is included by other tm-*.h files to specify SunOS-specific stuff.
|
||||
Copyright 1990, 1991, 1992, 1993, 1994 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
|
||||
/* Return non-zero if we are in a shared library trampoline code stub. */
|
||||
|
||||
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
|
||||
lookup_solib_trampoline_symbol_by_pc (pc)
|
||||
|
||||
/* If PC is in a shared library trampoline code, return the PC
|
||||
where the function itself actually starts. If not, return 0. */
|
||||
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
|
@ -1,47 +0,0 @@
|
||||
/* Macro definitions for GDB on all SVR4 target systems.
|
||||
Copyright 1991, 1992, 1993, 1994, 1996, 1997, 2000
|
||||
Free Software Foundation, Inc.
|
||||
Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* For SVR4 shared libraries, each call to a library routine goes through
|
||||
a small piece of trampoline code in the ".plt" section.
|
||||
The horribly ugly wait_for_inferior() routine uses this macro to detect
|
||||
when we have stepped into one of these fragments.
|
||||
We do not use lookup_solib_trampoline_symbol_by_pc, because
|
||||
we cannot always find the shared library trampoline symbols
|
||||
(e.g. on Irix5). */
|
||||
|
||||
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) in_plt_section((pc), (name))
|
||||
extern int in_plt_section (CORE_ADDR, char *);
|
||||
|
||||
/* If PC is in a shared library trampoline code, return the PC
|
||||
where the function itself actually starts. If not, return 0. */
|
||||
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
|
||||
|
||||
/* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
|
||||
in identifiers. The default in G++ is to use dots instead, for all SVR4
|
||||
systems, so we make that our default also. FIXME: There should be some
|
||||
way to get G++ to tell us what CPLUS_MARKER it is using, perhaps by
|
||||
stashing it in the debugging information as part of the name of an
|
||||
invented symbol ("gcc_cplus_marker$" for example). */
|
||||
|
||||
#undef CPLUS_MARKER
|
||||
#define CPLUS_MARKER '.'
|
@ -1,91 +0,0 @@
|
||||
/* Parameters for hosting on an PowerPC, for GDB, the GNU debugger.
|
||||
Copyright 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Corporation.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The following text is taken from config/rs6000.mh:
|
||||
* # The IBM version of /usr/include/rpc/rpc.h has a bug -- it says
|
||||
* # `extern fd_set svc_fdset;' without ever defining the type fd_set.
|
||||
* # Unfortunately this occurs in the vx-share code, which is not configured
|
||||
* # like the rest of GDB (e.g. it doesn't include "defs.h").
|
||||
* # We circumvent this bug by #define-ing fd_set here, but undefining it in
|
||||
* # the xm-rs6000.h file before ordinary modules try to use it. FIXME, IBM!
|
||||
* MH_CFLAGS='-Dfd_set=int'
|
||||
* So, here we do the undefine...which has to occur before we include
|
||||
* <sys/select.h> below.
|
||||
*/
|
||||
#undef fd_set
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
/* At least as of AIX 3.2, we have termios. */
|
||||
#define HAVE_TERMIOS 1
|
||||
/* #define HAVE_TERMIO 1 */
|
||||
|
||||
#define USG 1
|
||||
|
||||
#define FIVE_ARG_PTRACE
|
||||
|
||||
/* This system requires that we open a terminal with O_NOCTTY for it to
|
||||
not become our controlling terminal. */
|
||||
|
||||
#define USE_O_NOCTTY
|
||||
|
||||
/* Brain death inherited from PC's pervades. */
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
|
||||
/* The IBM compiler requires this in order to properly compile alloca(). */
|
||||
#pragma alloca
|
||||
|
||||
/* There is no vfork. */
|
||||
|
||||
#define vfork fork
|
||||
|
||||
char *termdef ();
|
||||
|
||||
/* Signal handler for SIGWINCH `window size changed'. */
|
||||
|
||||
#define SIGWINCH_HANDLER aix_resizewindow
|
||||
extern void aix_resizewindow (int);
|
||||
|
||||
/* `lines_per_page' and `chars_per_line' are local to utils.c. Rectify this. */
|
||||
|
||||
#define SIGWINCH_HANDLER_BODY \
|
||||
\
|
||||
/* Respond to SIGWINCH `window size changed' signal, and reset GDB's \
|
||||
window settings appropriately. */ \
|
||||
\
|
||||
void \
|
||||
aix_resizewindow (signo) \
|
||||
int signo; \
|
||||
{ \
|
||||
int fd = fileno (stdout); \
|
||||
if (isatty (fd)) { \
|
||||
int val; \
|
||||
\
|
||||
val = atoi (termdef (fd, 'l')); \
|
||||
if (val > 0) \
|
||||
lines_per_page = val; \
|
||||
val = atoi (termdef (fd, 'c')); \
|
||||
if (val > 0) \
|
||||
chars_per_line = val; \
|
||||
} \
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* Host-dependent definitions for any CPU running LynxOS.
|
||||
Copyright 1993 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* for INT_MIN, to avoid "INT_MIN redefined" warnings from defs.h */
|
||||
|
||||
#include <limits.h>
|
@ -1,81 +0,0 @@
|
||||
/* Macro definitions for running GDB on Apple Macintoshes.
|
||||
Copyright (C) 1994, 1995 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "mpw.h"
|
||||
|
||||
#include "fopen-bin.h"
|
||||
|
||||
#include "spin.h"
|
||||
|
||||
#define CANT_FORK
|
||||
|
||||
/* Map these standard functions to versions that can do I/O in a console
|
||||
window. */
|
||||
|
||||
#define printf hacked_printf
|
||||
#define fprintf hacked_fprintf
|
||||
#define vprintf hacked_vfprintf
|
||||
#define fputs hacked_fputs
|
||||
#define fputc hacked_fputc
|
||||
#undef putc
|
||||
#define putc hacked_putc
|
||||
#define fflush hacked_fflush
|
||||
|
||||
#define fgetc hacked_fgetc
|
||||
|
||||
#define POSIX_UTIME
|
||||
|
||||
/* No declaration of strdup in MPW's string.h, oddly enough. */
|
||||
|
||||
char *strdup (char *s1);
|
||||
|
||||
/* '.' indicates drivers on the Mac, so we need a different filename. */
|
||||
|
||||
#define GDBINIT_FILENAME "_gdbinit"
|
||||
|
||||
/* Commas are more common to separate dirnames in a path on Macs. */
|
||||
|
||||
#define DIRNAME_SEPARATOR ','
|
||||
|
||||
/* This is a real crufty hack. */
|
||||
|
||||
#define HAVE_TERMIO
|
||||
|
||||
/* Addons to the basic MPW-supported signal list. */
|
||||
|
||||
#ifndef SIGQUIT
|
||||
#define SIGQUIT (1<<6)
|
||||
#endif
|
||||
#ifndef SIGHUP
|
||||
#define SIGHUP (1<<7)
|
||||
#endif
|
||||
|
||||
/* If __STDC__ is on, then this definition will be missing. */
|
||||
|
||||
#ifndef fileno
|
||||
#define fileno(p) (p)->_file
|
||||
#endif
|
||||
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif
|
||||
|
||||
extern int StandAlone;
|
||||
|
||||
extern int mac_app;
|
@ -1,26 +0,0 @@
|
||||
/* Host-dependent definitions for any CPU running NetBSD.
|
||||
Copyright 1993, 1994, 1995, 1996, 1999 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Include this to get things like NGROUPS which <limits.h> doesn't
|
||||
define on some systems. */
|
||||
#include <sys/param.h>
|
||||
|
||||
/* NetBSD has termios facilities. */
|
||||
#define HAVE_TERMIOS
|
@ -1,29 +0,0 @@
|
||||
/* Definitions for running gdb on a host machine running any flavor of SVR4.
|
||||
Copyright 1991, 1992, 1993, 1995, 1998 Free Software Foundation, Inc.
|
||||
Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* SVR4 has termios facilities. */
|
||||
|
||||
#undef HAVE_TERMIO
|
||||
#define HAVE_TERMIOS
|
||||
|
||||
/* SVR4 is a derivative of System V Release 3 (USG) */
|
||||
|
||||
#define USG
|
@ -1,165 +0,0 @@
|
||||
/* Remote debugging interface for CPU32Bug Rom monitor for GDB, the GNU debugger.
|
||||
Copyright 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Stu Grossman of Cygnus Support
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "regcache.h"
|
||||
|
||||
static void cpu32bug_open (char *args, int from_tty);
|
||||
|
||||
static void
|
||||
cpu32bug_supply_register (char *regname, int regnamelen, char *val, int vallen)
|
||||
{
|
||||
int regno;
|
||||
|
||||
if (regnamelen != 2)
|
||||
return;
|
||||
|
||||
switch (regname[0])
|
||||
{
|
||||
case 'S':
|
||||
if (regname[1] != 'R')
|
||||
return;
|
||||
regno = PS_REGNUM;
|
||||
break;
|
||||
case 'P':
|
||||
if (regname[1] != 'C')
|
||||
return;
|
||||
regno = PC_REGNUM;
|
||||
break;
|
||||
case 'D':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + D0_REGNUM;
|
||||
break;
|
||||
case 'A':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + A0_REGNUM;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_supply_register (regno, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This array of registers needs to match the indexes used by GDB. The
|
||||
* whole reason this exists is because the various ROM monitors use
|
||||
* different names than GDB does, and don't support all the
|
||||
* registers either. So, typing "info reg sp" becomes an "A7".
|
||||
*/
|
||||
|
||||
static char *cpu32bug_regnames[NUM_REGS] =
|
||||
{
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
|
||||
"SR", "PC",
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the monitor command strings. Since these are passed directly
|
||||
* through to a printf style function, we need can include formatting
|
||||
* strings. We also need a CR or LF on the end.
|
||||
*/
|
||||
|
||||
static struct target_ops cpu32bug_ops;
|
||||
|
||||
static char *cpu32bug_inits[] =
|
||||
{"\r", NULL};
|
||||
|
||||
static struct monitor_ops cpu32bug_cmds;
|
||||
|
||||
static void
|
||||
init_cpu32bug_cmds (void)
|
||||
{
|
||||
cpu32bug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
|
||||
cpu32bug_cmds.init = cpu32bug_inits; /* Init strings */
|
||||
cpu32bug_cmds.cont = "g\r"; /* continue command */
|
||||
cpu32bug_cmds.step = "t\r"; /* single step */
|
||||
cpu32bug_cmds.stop = NULL; /* interrupt command */
|
||||
cpu32bug_cmds.set_break = "br %x\r"; /* set a breakpoint */
|
||||
cpu32bug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
|
||||
cpu32bug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
|
||||
cpu32bug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
|
||||
cpu32bug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
|
||||
cpu32bug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
|
||||
cpu32bug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
|
||||
cpu32bug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
cpu32bug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
|
||||
cpu32bug_cmds.setmem.term = NULL; /* setreg.term */
|
||||
cpu32bug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
|
||||
cpu32bug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
|
||||
cpu32bug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
|
||||
cpu32bug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
|
||||
cpu32bug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
cpu32bug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
|
||||
cpu32bug_cmds.getmem.term = NULL; /* getmem.term */
|
||||
cpu32bug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
cpu32bug_cmds.setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
|
||||
cpu32bug_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
cpu32bug_cmds.setreg.term = NULL; /* setreg.term */
|
||||
cpu32bug_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
cpu32bug_cmds.getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
|
||||
cpu32bug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
|
||||
cpu32bug_cmds.getreg.term = NULL; /* getreg.term */
|
||||
cpu32bug_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
|
||||
cpu32bug_cmds.dump_registers = "rd\r"; /* dump_registers */
|
||||
cpu32bug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
|
||||
cpu32bug_cmds.supply_register = cpu32bug_supply_register; /* supply_register */
|
||||
cpu32bug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
cpu32bug_cmds.load = "lo\r"; /* download command */
|
||||
cpu32bug_cmds.loadresp = "\n"; /* load response */
|
||||
cpu32bug_cmds.prompt = "CPU32Bug>"; /* monitor command prompt */
|
||||
cpu32bug_cmds.line_term = "\r"; /* end-of-line terminator */
|
||||
cpu32bug_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
cpu32bug_cmds.target = &cpu32bug_ops; /* target operations */
|
||||
cpu32bug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
cpu32bug_cmds.regnames = cpu32bug_regnames; /* registers names */
|
||||
cpu32bug_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
}; /* init_cpu32bug_cmds */
|
||||
|
||||
static void
|
||||
cpu32bug_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &cpu32bug_cmds, from_tty);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_cpu32bug_rom (void)
|
||||
{
|
||||
init_cpu32bug_cmds ();
|
||||
init_monitor_ops (&cpu32bug_ops);
|
||||
|
||||
cpu32bug_ops.to_shortname = "cpu32bug";
|
||||
cpu32bug_ops.to_longname = "CPU32Bug monitor";
|
||||
cpu32bug_ops.to_doc = "Debug via the CPU32Bug monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
cpu32bug_ops.to_open = cpu32bug_open;
|
||||
|
||||
add_target (&cpu32bug_ops);
|
||||
}
|
@ -1,537 +0,0 @@
|
||||
/* Native support for Motorola 88k running Harris CX/UX.
|
||||
Copyright 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
|
||||
2001 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <signal.h>
|
||||
#include "gdbcore.h"
|
||||
#include <sys/user.h>
|
||||
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
#include "symtab.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#ifndef USER /* added to support BCS ptrace_user */
|
||||
#define USER ptrace_user
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include "gdb_stat.h"
|
||||
|
||||
#include "symtab.h"
|
||||
#include "setjmp.h"
|
||||
#include "value.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
/* CX/UX provides them already, but as word offsets instead of char offsets */
|
||||
#define SXIP_OFFSET (PT_SXIP * 4)
|
||||
#define SNIP_OFFSET (PT_SNIP * 4)
|
||||
#define SFIP_OFFSET (PT_SFIP * 4)
|
||||
#define PSR_OFFSET (PT_PSR * sizeof(int))
|
||||
#define FPSR_OFFSET (PT_FPSR * sizeof(int))
|
||||
#define FPCR_OFFSET (PT_FPCR * sizeof(int))
|
||||
|
||||
#define XREGADDR(r) (((char *)&u.pt_x0-(char *)&u) + \
|
||||
((r)-X0_REGNUM)*sizeof(X_REGISTER_RAW_TYPE))
|
||||
|
||||
extern int have_symbol_file_p ();
|
||||
|
||||
extern jmp_buf stack_jmp;
|
||||
|
||||
extern int errno;
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
|
||||
struct USER u;
|
||||
unsigned int offset;
|
||||
|
||||
offset = (char *) &u.pt_r0 - (char *) &u;
|
||||
regaddr = offset; /* byte offset to r0; */
|
||||
|
||||
/* offset = ptrace (3, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
|
||||
for (regno = 0; regno < PC_REGNUM; regno++)
|
||||
{
|
||||
/*regaddr = register_addr (regno, offset); */
|
||||
/* 88k enhancement */
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
*(int *) &buf[i] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
/* now load up registers 32-37; special pc registers */
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) PSR_OFFSET, 0);
|
||||
supply_register (PSR_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPSR_OFFSET, 0);
|
||||
supply_register (FPSR_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPCR_OFFSET, 0);
|
||||
supply_register (FPCR_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, 0);
|
||||
supply_register (SXIP_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, 0);
|
||||
supply_register (SNIP_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, 0);
|
||||
supply_register (SFIP_REGNUM, buf);
|
||||
|
||||
if (target_is_m88110)
|
||||
{
|
||||
for (regaddr = XREGADDR (X0_REGNUM), regno = X0_REGNUM;
|
||||
regno < NUM_REGS;
|
||||
regno++, regaddr += 16)
|
||||
{
|
||||
X_REGISTER_RAW_TYPE xval;
|
||||
|
||||
*(int *) &xval.w1 = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
*(int *) &xval.w2 = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) (regaddr + 4), 0);
|
||||
*(int *) &xval.w3 = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) (regaddr + 8), 0);
|
||||
*(int *) &xval.w4 = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) (regaddr + 12), 0);
|
||||
supply_register (regno, (void *) &xval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[80];
|
||||
|
||||
struct USER u;
|
||||
|
||||
unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
|
||||
|
||||
regaddr = offset;
|
||||
|
||||
/* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
|
||||
svr3 doesn't run on an 88110, or the kernel isolates the different (not
|
||||
completely sure this is true, but seems to be. */
|
||||
if (regno >= 0)
|
||||
{
|
||||
/* regaddr = register_addr (regno, offset); */
|
||||
if (regno < PC_REGNUM)
|
||||
{
|
||||
regaddr = offset + regno * sizeof (int);
|
||||
errno = 0;
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
else if (regno == PSR_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) PSR_OFFSET, read_register (regno));
|
||||
else if (regno == FPSR_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPSR_OFFSET, read_register (regno));
|
||||
else if (regno == FPCR_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPCR_OFFSET, read_register (regno));
|
||||
else if (regno == SXIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register (regno));
|
||||
else if (regno == SNIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register (regno));
|
||||
else if (regno == SFIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register (regno));
|
||||
else if (target_is_m88110 && regno < NUM_REGS)
|
||||
{
|
||||
X_REGISTER_RAW_TYPE xval;
|
||||
|
||||
read_register_bytes (REGISTER_BYTE (regno), (char *) &xval,
|
||||
sizeof (X_REGISTER_RAW_TYPE));
|
||||
regaddr = XREGADDR (regno);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr, xval.w1);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr + 4, xval.w2);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr + 8, xval.w3);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr + 12, xval.w4);
|
||||
}
|
||||
else
|
||||
printf_unfiltered ("Bad register number for store_inferior routine\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < PC_REGNUM; regno++)
|
||||
{
|
||||
/* regaddr = register_addr (regno, offset); */
|
||||
errno = 0;
|
||||
regaddr = offset + regno * sizeof (int);
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) PSR_OFFSET, read_register (regno));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPSR_OFFSET, read_register (regno));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) FPCR_OFFSET, read_register (regno));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register (SXIP_REGNUM));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register (SNIP_REGNUM));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register (SFIP_REGNUM));
|
||||
if (target_is_m88110)
|
||||
{
|
||||
for (regno = X0_REGNUM; regno < NUM_REGS; regno++)
|
||||
{
|
||||
X_REGISTER_RAW_TYPE xval;
|
||||
|
||||
read_register_bytes (REGISTER_BYTE (regno), (char *) &xval,
|
||||
sizeof (X_REGISTER_RAW_TYPE));
|
||||
regaddr = XREGADDR (regno);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr, xval.w1);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) (regaddr + 4), xval.w2);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) (regaddr + 8), xval.w3);
|
||||
ptrace (6, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) (regaddr + 12), xval.w4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* blockend is the address of the end of the user structure */
|
||||
|
||||
m88k_register_u_addr (int blockend, int regnum)
|
||||
{
|
||||
struct USER u;
|
||||
int ustart = blockend - sizeof (struct USER);
|
||||
|
||||
if (regnum < PSR_REGNUM)
|
||||
return (ustart + ((int) &u.pt_r0 - (int) &u) +
|
||||
REGISTER_SIZE * regnum);
|
||||
else if (regnum == PSR_REGNUM)
|
||||
return (ustart + ((int) &u.pt_psr) - (int) &u);
|
||||
else if (regnum == FPSR_REGNUM)
|
||||
return (ustart + ((int) &u.pt_fpsr) - (int) &u);
|
||||
else if (regnum == FPCR_REGNUM)
|
||||
return (ustart + ((int) &u.pt_fpcr) - (int) &u);
|
||||
else if (regnum == SXIP_REGNUM)
|
||||
return (ustart + SXIP_OFFSET);
|
||||
else if (regnum == SNIP_REGNUM)
|
||||
return (ustart + SNIP_OFFSET);
|
||||
else if (regnum == SFIP_REGNUM)
|
||||
return (ustart + SFIP_OFFSET);
|
||||
else if (target_is_m88110)
|
||||
return (ustart + ((int) &u.pt_x0 - (int) &u) + /* Must be X register */
|
||||
sizeof (u.pt_x0) * (regnum - X0_REGNUM));
|
||||
else
|
||||
return (blockend + REGISTER_SIZE * regnum);
|
||||
}
|
||||
|
||||
#ifdef USE_PROC_FS
|
||||
|
||||
#include <sys/procfs.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi <= SP_REGNUM; regi++)
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
|
||||
supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
|
||||
supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
|
||||
supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
|
||||
supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
|
||||
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
|
||||
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi <= R_R31; regi++)
|
||||
if ((regno == -1) || (regno == regi))
|
||||
*(regp + regi) = *(int *) ®isters[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == SXIP_REGNUM))
|
||||
*(regp + R_XIP) = *(int *) ®isters[REGISTER_BYTE (SXIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == SNIP_REGNUM))
|
||||
*(regp + R_NIP) = *(int *) ®isters[REGISTER_BYTE (SNIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == SFIP_REGNUM))
|
||||
*(regp + R_FIP) = *(int *) ®isters[REGISTER_BYTE (SFIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == PSR_REGNUM))
|
||||
*(regp + R_PSR) = *(int *) ®isters[REGISTER_BYTE (PSR_REGNUM)];
|
||||
if ((regno == -1) || (regno == FPSR_REGNUM))
|
||||
*(regp + R_FPSR) = *(int *) ®isters[REGISTER_BYTE (FPSR_REGNUM)];
|
||||
if ((regno == -1) || (regno == FPCR_REGNUM))
|
||||
*(regp + R_FPCR) = *(int *) ®isters[REGISTER_BYTE (FPCR_REGNUM)];
|
||||
}
|
||||
|
||||
#endif /* USE_PROC_FS */
|
||||
|
||||
/* This support adds the equivalent of adb's % command. When
|
||||
the `add-shared-symbol-files' command is given, this routine scans
|
||||
the dynamic linker's link map and reads the minimal symbols
|
||||
from each shared object file listed in the map. */
|
||||
|
||||
struct link_map
|
||||
{
|
||||
unsigned long l_addr; /* address at which object is mapped */
|
||||
char *l_name; /* full name of loaded object */
|
||||
void *l_ld; /* dynamic structure of object */
|
||||
struct link_map *l_next; /* next link object */
|
||||
struct link_map *l_prev; /* previous link object */
|
||||
};
|
||||
|
||||
#define LINKS_MAP_POINTER "_ld_tail"
|
||||
#define LIBC_FILE "/usr/lib/libc.so.1"
|
||||
#define SHARED_OFFSET 0xf0001000
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1023 /* maximum size of path name on OS */
|
||||
#endif
|
||||
|
||||
void
|
||||
add_shared_symbol_files (void)
|
||||
{
|
||||
void *desc;
|
||||
struct link_map *ld_map, *lm, lms;
|
||||
struct minimal_symbol *minsym;
|
||||
struct objfile *objfile;
|
||||
char *path_name;
|
||||
|
||||
if (ptid_equal (inferior_ptid, null_ptid))
|
||||
{
|
||||
warning ("The program has not yet been started.");
|
||||
return;
|
||||
}
|
||||
|
||||
objfile = symbol_file_add (LIBC_FILE, 0, NULL, 0, OBJF_READNOW);
|
||||
minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile);
|
||||
|
||||
ld_map = (struct link_map *)
|
||||
read_memory_integer (((int) SYMBOL_VALUE_ADDRESS (minsym) + SHARED_OFFSET), 4);
|
||||
lm = ld_map;
|
||||
while (lm)
|
||||
{
|
||||
int local_errno = 0;
|
||||
|
||||
read_memory ((CORE_ADDR) lm, (char *) &lms, sizeof (struct link_map));
|
||||
if (lms.l_name)
|
||||
{
|
||||
if (target_read_string ((CORE_ADDR) lms.l_name, &path_name,
|
||||
PATH_MAX, &local_errno))
|
||||
{
|
||||
struct section_addr_info section_addrs;
|
||||
memset (§ion_addrs, 0, sizeof (section_addrs));
|
||||
section_addrs.other[0].addr = lms.l_addr;
|
||||
section_addrs.other[0].name = ".text";
|
||||
symbol_file_add (path_name, 1, §ion_addrs, 0, 0);
|
||||
xfree (path_name);
|
||||
}
|
||||
}
|
||||
/* traverse links in reverse order so that we get the
|
||||
the symbols the user actually gets. */
|
||||
lm = lms.l_prev;
|
||||
}
|
||||
|
||||
/* Getting new symbols may change our opinion about what is
|
||||
frameless. */
|
||||
reinit_frame_cache ();
|
||||
}
|
||||
|
||||
#if defined(_ES_MP)
|
||||
|
||||
#include <sys/regset.h>
|
||||
|
||||
unsigned int
|
||||
m88k_harris_core_register_addr (int regno, int reg_ptr)
|
||||
{
|
||||
unsigned int word_offset;
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case PSR_REGNUM:
|
||||
word_offset = R_EPSR;
|
||||
break;
|
||||
case FPSR_REGNUM:
|
||||
word_offset = R_FPSR;
|
||||
break;
|
||||
case FPCR_REGNUM:
|
||||
word_offset = R_FPCR;
|
||||
break;
|
||||
case SXIP_REGNUM:
|
||||
word_offset = R_EXIP;
|
||||
break;
|
||||
case SNIP_REGNUM:
|
||||
word_offset = R_ENIP;
|
||||
break;
|
||||
case SFIP_REGNUM:
|
||||
word_offset = R_EFIP;
|
||||
break;
|
||||
default:
|
||||
if (regno <= FP_REGNUM)
|
||||
word_offset = regno;
|
||||
else
|
||||
word_offset = ((regno - X0_REGNUM) * 4);
|
||||
}
|
||||
return (word_offset * 4);
|
||||
}
|
||||
|
||||
#endif /* _ES_MP */
|
||||
|
||||
void
|
||||
_initialize_m88k_nat (void)
|
||||
{
|
||||
#ifdef _ES_MP
|
||||
/* Enable 88110 support, as we don't support the 88100 under ES/MP. */
|
||||
|
||||
target_is_m88110 = 1;
|
||||
#elif defined(_CX_UX)
|
||||
/* Determine whether we're running on an 88100 or an 88110. */
|
||||
target_is_m88110 = (sinfo (SYSMACHINE, 0) == SYS5800);
|
||||
#endif /* _CX_UX */
|
||||
}
|
||||
|
||||
#ifdef _ES_MP
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi < R_R31; regi++)
|
||||
{
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
}
|
||||
supply_register (PSR_REGNUM, (char *) (regp + R_EPSR));
|
||||
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
|
||||
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
|
||||
supply_register (SXIP_REGNUM, (char *) (regp + R_EXIP));
|
||||
supply_register (SNIP_REGNUM, (char *) (regp + R_ENIP));
|
||||
supply_register (SFIP_REGNUM, (char *) (regp + R_EFIP));
|
||||
}
|
||||
|
||||
/* Given a pointer to a floating point register set in /proc format
|
||||
(fpregset_t *), unpack the register contents and supply them as gdb's
|
||||
idea of the current floating point register values. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
register int regi;
|
||||
char *from;
|
||||
|
||||
for (regi = FP0_REGNUM; regi <= FPLAST_REGNUM; regi++)
|
||||
{
|
||||
from = (char *) &((*fpregsetp)[regi - FP0_REGNUM]);
|
||||
supply_register (regi, from);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _ES_MP */
|
||||
|
||||
#ifdef _CX_UX
|
||||
|
||||
#include <sys/regset.h>
|
||||
|
||||
unsigned int
|
||||
m88k_harris_core_register_addr (int regno, int reg_ptr)
|
||||
{
|
||||
unsigned int word_offset;
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case PSR_REGNUM:
|
||||
word_offset = R_PSR;
|
||||
break;
|
||||
case FPSR_REGNUM:
|
||||
word_offset = R_FPSR;
|
||||
break;
|
||||
case FPCR_REGNUM:
|
||||
word_offset = R_FPCR;
|
||||
break;
|
||||
case SXIP_REGNUM:
|
||||
word_offset = R_XIP;
|
||||
break;
|
||||
case SNIP_REGNUM:
|
||||
word_offset = R_NIP;
|
||||
break;
|
||||
case SFIP_REGNUM:
|
||||
word_offset = R_FIP;
|
||||
break;
|
||||
default:
|
||||
if (regno <= FP_REGNUM)
|
||||
word_offset = regno;
|
||||
else
|
||||
word_offset = ((regno - X0_REGNUM) * 4) + R_X0;
|
||||
}
|
||||
return (word_offset * 4);
|
||||
}
|
||||
|
||||
#endif /* _CX_UX */
|
@ -1,114 +0,0 @@
|
||||
@c GDB MANUAL configuration file.
|
||||
@c Copyright (c) 1993 Free Software Foundation, Inc.
|
||||
@c
|
||||
@c NOTE: While the GDB manual is configurable (by changing these
|
||||
@c switches), its configuration is ***NOT*** automatically tied in to
|
||||
@c source configuration---because the authors expect that, save in
|
||||
@c unusual cases, the most inclusive form of the manual is appropriate
|
||||
@c no matter how the program itself is configured.
|
||||
@c
|
||||
@c The only automatically-varying variable is the GDB version number,
|
||||
@c which the Makefile rewrites based on the VERSION variable from
|
||||
@c `../Makefile.in'.
|
||||
@c
|
||||
@c GDB version number is recorded in the variable GDBVN
|
||||
@include GDBvn.texi
|
||||
@c
|
||||
@c ----------------------------------------------------------------------
|
||||
@c PLATFORM FLAGS:
|
||||
@clear GENERIC
|
||||
@c
|
||||
@c HP PA-RISC target:
|
||||
@set HPPA
|
||||
@c
|
||||
@c Hitachi H8/300 target:
|
||||
@clear H8
|
||||
@c Hitachi H8/300 target ONLY:
|
||||
@clear H8EXCLUSIVE
|
||||
@c
|
||||
@c remote MIPS target:
|
||||
@clear MIPS
|
||||
@c
|
||||
@c SPARC target:
|
||||
@clear SPARC
|
||||
@c
|
||||
@c AMD 29000 target:
|
||||
@clear AMD29K
|
||||
@c
|
||||
@c Intel 960 target:
|
||||
@clear I960
|
||||
@c
|
||||
@c Tandem ST2000 (phone switch) target:
|
||||
@clear ST2000
|
||||
@c
|
||||
@c Zilog 8000 target:
|
||||
@clear Z8K
|
||||
@c
|
||||
@c Wind River Systems VxWorks environment:
|
||||
@clear VXWORKS
|
||||
@c
|
||||
@c ----------------------------------------------------------------------
|
||||
@c DOC FEATURE FLAGS:
|
||||
@c
|
||||
@c Bare-board target?
|
||||
@clear BARETARGET
|
||||
@c
|
||||
@c Restrict languages discussed to C?
|
||||
@c This is backward. As time permits, change this to language-specific
|
||||
@c switches for what to include.
|
||||
@clear CONLY
|
||||
@c Discuss Fortran?
|
||||
@clear FORTRAN
|
||||
@c
|
||||
@c Discuss Modula 2?
|
||||
@clear MOD2
|
||||
@c
|
||||
@c Specifically for host machine running DOS?
|
||||
@clear DOSHOST
|
||||
@c
|
||||
@c Talk about CPU simulator targets?
|
||||
@clear SIMS
|
||||
@c
|
||||
@c Remote serial line settings of interest?
|
||||
@set SERIAL
|
||||
@c
|
||||
@c Discuss features requiring Posix or similar OS environment?
|
||||
@set POSIX
|
||||
@c
|
||||
@c Discuss remote serial debugging stub?
|
||||
@clear REMOTESTUB
|
||||
@c
|
||||
@c Discuss gdbserver?
|
||||
@set GDBSERVER
|
||||
@c
|
||||
@c Discuss gdbserve.nlm?
|
||||
@set GDBSERVE
|
||||
@c
|
||||
@c Refrain from discussing how to configure sw and format doc?
|
||||
@clear PRECONFIGURED
|
||||
@c
|
||||
@c Refrain from referring to unfree publications?
|
||||
@set FSFDOC
|
||||
@c
|
||||
@c ----------------------------------------------------------------------
|
||||
@c STRINGS:
|
||||
@c
|
||||
@c Name of GDB program. Used also for (gdb) prompt string.
|
||||
@set GDBP gdb
|
||||
@c
|
||||
@c Name of GDB product. Used in running text.
|
||||
@set GDBN GDB
|
||||
@c
|
||||
@c Name of target.
|
||||
@set TARGET HP 9000 Systems
|
||||
@c
|
||||
@c Name of host. Should not be used in generic configs, but generic
|
||||
@c value may catch some flubs.
|
||||
@set HOST machine specific
|
||||
@c
|
||||
@c Name of GCC product
|
||||
@set NGCC GCC
|
||||
@c
|
||||
@c Name of GCC program
|
||||
@set GCC gcc
|
||||
|
@ -1,47 +0,0 @@
|
||||
@c GDB version number is recorded in the variable GDBVN
|
||||
@include GDBvn.texi
|
||||
@c
|
||||
@set AGGLOMERATION
|
||||
@clear AMD29K
|
||||
@set BARETARGET
|
||||
@clear CONLY
|
||||
@set DOSHOST
|
||||
@clear FORTRAN
|
||||
@clear FSFDOC
|
||||
@clear GDBSERVER
|
||||
@clear GENERIC
|
||||
@set H8
|
||||
@set H8EXCLUSIVE
|
||||
@clear HAVE-FLOAT
|
||||
@clear I960
|
||||
@clear MOD2
|
||||
@clear NOVEL
|
||||
@clear POSIX
|
||||
@set PRECONFIGURED
|
||||
@clear REMOTESTUB
|
||||
@set SIMS
|
||||
@clear SERIAL
|
||||
@clear SPARC
|
||||
@clear ST2000
|
||||
@clear VXWORKS
|
||||
@clear Z8K
|
||||
@c ----------------------------------------------------------------------
|
||||
@c STRINGS:
|
||||
@c
|
||||
@c Name of GDB program. Used also for (gdb) prompt string.
|
||||
@set GDBP gdb
|
||||
@c
|
||||
@c Name of GDB product. Used in running text.
|
||||
@set GDBN GDB
|
||||
@c
|
||||
@c Name of GDB initialization file.
|
||||
@set GDBINIT .gdbinit
|
||||
@c
|
||||
@c Name of target.
|
||||
@set TARGET Hitachi Microprocessors
|
||||
@c
|
||||
@c Name of GCC product
|
||||
@set NGCC GCC
|
||||
@c
|
||||
@c Name of GCC program
|
||||
@set GCC gcc
|
@ -1,878 +0,0 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename libgdb.info
|
||||
@settitle Libgdb
|
||||
@setchapternewpage off
|
||||
@c %**end of header
|
||||
|
||||
@ifinfo
|
||||
This file documents libgdb, the GNU symbolic debugger in a library.
|
||||
|
||||
This is Edition 0.3, Oct 1993, of @cite{Libgdb}.
|
||||
Copyright 1993 Cygnus Support
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through TeX and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
|
||||
@end ignore
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that the
|
||||
entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ifinfo
|
||||
|
||||
@c This title page illustrates only one of the
|
||||
@c two methods of forming a title page.
|
||||
|
||||
@titlepage
|
||||
@title Libgdb
|
||||
@subtitle Version 0.3
|
||||
@subtitle Oct 1993
|
||||
@author Thomas Lord
|
||||
|
||||
@c The following two commands
|
||||
@c start the copyright page.
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
Copyright @copyright{} 1993 Cygnus Support
|
||||
@end titlepage
|
||||
|
||||
@ifinfo
|
||||
@node Top, Overview, (dir), (dir)
|
||||
|
||||
This info file documents libgdb: an API for GDB, the GNU symbolic debugger.
|
||||
|
||||
@menu
|
||||
* Overview:: The basics of libgdb and this document.
|
||||
* Interpreter:: Libgdb is an Interpreter-Based Server.
|
||||
* Top Level:: You Provide the Top Level for the Libgdb
|
||||
Command Interpreter .
|
||||
* I/O:: How the Server's I/O Can be Used.
|
||||
* Invoking:: Invoking the Interpreter, Executing
|
||||
Commands.
|
||||
* Defining Commands:: How New Commands are Created.
|
||||
* Variables:: How Builtin Variables are Defined.
|
||||
* Asynchronous:: Scheduling Asynchronous Computations.
|
||||
* Commands:: Debugger Commands for Libgdb Applications
|
||||
@end menu
|
||||
|
||||
@end ifinfo
|
||||
@node Overview, Interpreter, top, top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Overview
|
||||
@cindex overview
|
||||
@cindex definitions
|
||||
|
||||
@heading Function and Purpose
|
||||
|
||||
Libgdb is a package which provides an API to the functionality of GDB,
|
||||
the GNU symbolic debugger. It is specifically intended to support the
|
||||
development of a symbolic debugger with a graphic interface.
|
||||
|
||||
|
||||
@heading This Document
|
||||
|
||||
This document is a specification of the libgdb API. It is written in
|
||||
the form of a programmer's manual. So the goal of this document is to
|
||||
explain what functions make up the API, and how they can be used in a
|
||||
running application.
|
||||
|
||||
|
||||
@heading Terminology
|
||||
|
||||
In this document, @dfn{libgdb} refers to a library containing the
|
||||
functions defined herein, @dfn{application} refers to any program built
|
||||
with that library.
|
||||
|
||||
|
||||
@heading Dependencies
|
||||
|
||||
Programs which are linked with libgdb must be linked with libbfd,
|
||||
libopcodes, libiberty, and libmmalloc.
|
||||
|
||||
@heading Acknowledgments
|
||||
|
||||
Essential contributions to this design were made by Stu Grossman, Jim
|
||||
Kingdon, and Rich Pixley.
|
||||
|
||||
@node Interpreter, Top Level, Overview, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Libgdb is an Interpreter Based Server
|
||||
@cindex interpreter
|
||||
@cindex server
|
||||
|
||||
To understand libgdb, it is necessary to understand how the library is
|
||||
structured. Historically, GDB is written as a small interpreter for a
|
||||
simple command language. The commands of the language perform useful
|
||||
debugging functions.
|
||||
|
||||
Libgdb is built from GDB by turning the interpreter into a debugging
|
||||
server. The server reads debugging commands from any source and
|
||||
interprets them, directing the output arbitrarily.
|
||||
|
||||
In addition to changing GDB from a tty-based program to a server, a
|
||||
number of new GDB commands have been added to make the server more
|
||||
useful for a program with a graphic interface.
|
||||
|
||||
Finally, libgdb includes provisions for asynchronous processing within
|
||||
the application.
|
||||
|
||||
Most operations that can be carried out with libgdb involve the GDB
|
||||
command interpreter. The usual mode of operation is that the operation
|
||||
is expressed as a string of GDB commands, which the interpreter is then
|
||||
invoked to carry out. The output from commands executed in this manner
|
||||
can be redirected in a variety of useful ways for further processing by
|
||||
the application.
|
||||
|
||||
The command interpreter provides an extensive system of hooks so an
|
||||
application can monitor any aspect of the debugging library's state. An
|
||||
application can set its own breakpoints and attach commands and
|
||||
conditions to those. It is possible to attach hooks to any debugger
|
||||
command; the hooks are invoked whenever that command is about to be
|
||||
invoked. By means of these, the displays of a graphical interface can
|
||||
be kept fully up to date at all times.
|
||||
|
||||
We show you how to define new primitives in the command language. By
|
||||
defining new primitives and using them in breakpoint scripts and command
|
||||
hooks, an application can schedule the execution of arbitrary C-code at
|
||||
almost any point of interest in the operation of libgdb.
|
||||
|
||||
We show you how to define new GDB convenience variables for which your
|
||||
code computes a value on demand. Referring to such variables in a
|
||||
breakpoint condition is a convenient way to conditionalize breakpoints
|
||||
in novel ways.
|
||||
|
||||
To summarize: in libgdb, the gdb command language is turned into a
|
||||
debugging server. The server takes commands as input, and the server's
|
||||
output is redirectable. An application uses libgdb by formatting
|
||||
debugging commands and invoking the interpreter. The application might
|
||||
maintain breakpoints, watchpoints and many kinds of hooks. An application
|
||||
can define new primitives for the interpreter.
|
||||
|
||||
@node Top Level, I/O, Interpreter, Top
|
||||
@chapter You Provide the Top Level for the Libgdb Command Interpreter
|
||||
@cindex {top level}
|
||||
|
||||
When you use libgdb, your code is providing a @dfn{top level} for the
|
||||
command language interpreter. The top level is significant because it
|
||||
provides commands for the the interpreter to execute. In addition, the
|
||||
top level is responsible for handling some kinds of errors, and
|
||||
performing certain cleanup operations on behalf of the interpreter.
|
||||
|
||||
@heading Initialization
|
||||
|
||||
Before calling any other libgdb functions, call this:
|
||||
|
||||
@deftypefun void gdb_init (void)
|
||||
Perform one-time initialization for libgdb.
|
||||
@end deftypefun
|
||||
|
||||
An application may wish to evaluate specific gdb commands as part of its
|
||||
own initialization. The details of how this can be accomplished are
|
||||
explained below.
|
||||
|
||||
@heading The Top-Level Loop
|
||||
|
||||
There is a strong presumption in libgdb that the application has
|
||||
the form of a loop. Here is what such a loop might look like:
|
||||
|
||||
@example
|
||||
while (gdb_still_going ())
|
||||
@{
|
||||
if (!GDB_TOP_LEVEL ())
|
||||
@{
|
||||
char * command;
|
||||
gdb_start_top_loop ();
|
||||
command = process_events ();
|
||||
gdb_execute_command (command);
|
||||
gdb_finish_top_loop ();
|
||||
@}
|
||||
@}
|
||||
@end example
|
||||
|
||||
The function @code{gdb_still_going} returns 1 until the gdb command
|
||||
`quit' is run.
|
||||
|
||||
The macro @code{GDB_TOP_LEVEL} invokes setjmp to set the top level error
|
||||
handler. When a command results in an error, the interpreter exits with
|
||||
a longjmp. There is nothing special libgdb requires of the top level
|
||||
error handler other than it be present and that it restart the top level
|
||||
loop. Errors are explained in detail in a later chapter.
|
||||
|
||||
Each time through the top level loop two important things happen: a
|
||||
debugger command is constructed on the basis of user input, and the
|
||||
interpreter is invoked to execute that command. In the sample code, the
|
||||
call to the imaginary function @code{process_events} represents the
|
||||
point at which a graphical interface should read input events until
|
||||
ready to execute a debugger command. The call to
|
||||
@code{gdb_execute_command} invokes the command interpreter (what happens
|
||||
to the output from the command will be explained later).
|
||||
|
||||
Libgdb manages some resources using the top-level loop. The primary
|
||||
reason for this is error-handling: even if a command terminates with an
|
||||
error, it may already have allocated resources which need to be freed.
|
||||
The freeing of such resources takes place at the top-level, regardless
|
||||
of how the the command exits. The calls to @code{gdb_start_top_loop}
|
||||
and @code{gdb_finish_top_loop} let libgdb know when it is safe to
|
||||
perform operations associated with these resources.
|
||||
|
||||
@heading Breakpoint Commands
|
||||
|
||||
Breakpoint commands are scripts of GDB operations associated with
|
||||
particular breakpoints. When a breakpoint is reached, its associated
|
||||
commands are executed.
|
||||
|
||||
Breakpoint commands are invoked by the libgdb function
|
||||
@code{gdb_finish_top_loop}.
|
||||
|
||||
Notice that if control returns to the top-level error handler, the
|
||||
execution of breakpoint commands is bypassed. This can happen as a
|
||||
result of errors during either @code{gdb_execute_command} or
|
||||
@code{gdb_finish_top_loop}.
|
||||
|
||||
@heading Application Initialization
|
||||
|
||||
Sometimes it is inconvenient to execute commands via a command loop for
|
||||
example, the commands an application uses to initialize itself. An
|
||||
alternative to @code{execute_command} is @code{execute_catching_errors}.
|
||||
When @code{execute_catching_errors} is used, no top level error handler
|
||||
need be in effect, and it is not necessary to call
|
||||
@code{gdb_start_top_loop} or @code{gdb_finish_top_loop}.
|
||||
|
||||
|
||||
@heading Cleanup
|
||||
|
||||
The debugger command ``quit'' performs all necessary cleanup for libgdb.
|
||||
After it has done so, it changes the return value of
|
||||
@code{gdb_still_going} to 0 and returns to the top level error handler.
|
||||
|
||||
|
||||
@node I/O, Invoking, Top Level, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter How the Server's I/O Can be Used
|
||||
@cindex I/O
|
||||
|
||||
In the last chapter it was pointed out that a libgdb application is
|
||||
responsible for providing commands for the interpreter to execute.
|
||||
However some commands require further input (for example, the ``quit''
|
||||
command might ask for confirmation). Almost all commands produce output
|
||||
of some kind. The purpose of this section is to explain how libgdb
|
||||
performs its I/O, and how an application can take advantage of
|
||||
this.
|
||||
|
||||
|
||||
@heading I/O Vectors
|
||||
|
||||
Libgdb has no fixed strategy for I/O. Instead, all operations are
|
||||
performed by functions called via structures of function pointers.
|
||||
Applications supply theses structures and can change them at any
|
||||
time.
|
||||
|
||||
@deftp Type {struct gdb_input_vector}
|
||||
@deftpx Type {struct gdb_output_vector}
|
||||
These structures contain a set of function pointers. Each function
|
||||
determines how a particular type of i/o is performed. The details of
|
||||
these strucutres are explained below.
|
||||
|
||||
The application allocates these structures, initializes them to all bits
|
||||
zero, fills in the function pointers, and then registers names for them
|
||||
them with libgdb.
|
||||
@end deftp
|
||||
|
||||
@deftypefun void gdb_name_input_vector (@var{name}, @var{vec})
|
||||
@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
|
||||
@deftypefunx void gdb_name_output_vector (@var{name}, @var{vec})
|
||||
@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
|
||||
@example
|
||||
char * @var{name};
|
||||
struct gdb_output_vector * @var{vec};
|
||||
@end example
|
||||
These functions are used to give and remove names to i/o vectors. Note
|
||||
that if a name is used twice, the most recent definition applies.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
|
||||
@subheading Output
|
||||
|
||||
An output vector is a structure with at least these fields:
|
||||
|
||||
@example
|
||||
struct gdb_output_vector
|
||||
@{
|
||||
/* output */
|
||||
void (*put_string) (struct gdb_output_vector *, char * str);
|
||||
@}
|
||||
@end example
|
||||
|
||||
Use the function @code{memset} or something equivalent to initialize an
|
||||
output vector to all bits zero. Then fill in the function pointer with
|
||||
your function.
|
||||
|
||||
A debugger command can produce three kinds of output: error messages
|
||||
(such as when trying to delete a non-existent breakpoint), informational
|
||||
messages (such as the notification printed when a breakpoint is hit),
|
||||
and the output specifically requested by a command (for example, the
|
||||
value printed by the ``print'' command). At any given time, then,
|
||||
libgdb has three output vectors. These are called the @dfn{error},
|
||||
@dfn{info}, @dfn{value} vector respectively.
|
||||
|
||||
@subheading Input
|
||||
|
||||
@example
|
||||
struct gdb_input_vector
|
||||
@{
|
||||
int (*query) (struct gdb_input_vector *,
|
||||
char * prompt,
|
||||
int quit_allowed);
|
||||
int * (*selection) (struct gdb_input_vector *,
|
||||
char * prompt,
|
||||
char ** choices);
|
||||
char * (*read_string) (struct gdb_input_vector *,
|
||||
char * prompt);
|
||||
char ** (*read_strings) (struct gdb_input_vector *,
|
||||
char * prompt);
|
||||
@}
|
||||
@end example
|
||||
|
||||
Use the function @code{memset} or something equivalent to initialize an
|
||||
input vector to all bits zero. Then fill in the function pointers with
|
||||
your functions.
|
||||
|
||||
There are four kinds of input requests explicitly made by libgdb.
|
||||
|
||||
A @dfn{query} is a yes or no question. The user can respond to a query
|
||||
with an affirmative or negative answer, or by telling gdb to abort the
|
||||
command (in some cases an abort is not permitted). Query should return
|
||||
'y' or 'n' or 0 to abort.
|
||||
|
||||
A @dfn{selection} is a list of options from which the user selects a subset.
|
||||
Selections should return a NULL terminated array of integers, which are
|
||||
indexes into the array of choices. It can return NULL instead to abort
|
||||
the command. The array returned by this function will be passed to
|
||||
@code{free} by libgdb.
|
||||
|
||||
A @dfn{read_string} asks the user to supply an arbitrary string. It may
|
||||
return NULL to abort the command. The string returned by @code{read_string}
|
||||
should be allocated by @code{malloc}; it will be freed by libgdb.
|
||||
|
||||
A @dfn{read_strings} asks the user to supply multiple lines of input
|
||||
(for example, the body of a command created using `define'). It, too,
|
||||
may return NULL to abort. The array and the strings returned by this
|
||||
function will be freed by libgdb.
|
||||
|
||||
@heading I/O Redirection from the Application Top-Level
|
||||
|
||||
@deftypefun struct gdb_io_vecs gdb_set_io (struct gdb_io_vecs *)
|
||||
@example
|
||||
|
||||
struct gdb_io_vecs
|
||||
@{
|
||||
struct gdb_input_vector * input;
|
||||
struct gdb_output_vector * error;
|
||||
struct gdb_output_vector * info;
|
||||
struct gdb_output_vector * value;
|
||||
@}
|
||||
@end example
|
||||
|
||||
This establishes a new set of i/o vectors, and returns the old setting.
|
||||
Any of the pointers in this structure may be NULL, indicating that the
|
||||
current value should be used.
|
||||
|
||||
This function is useful for setting up i/o vectors before any libgdb
|
||||
commands have been invoked (hence before any input or output has taken
|
||||
place).
|
||||
@end deftypefun
|
||||
|
||||
It is explained in a later chapter how to redirect output temporarily.
|
||||
(@xref{Invoking}.)
|
||||
|
||||
@heading I/O Redirection in Debugger Commands
|
||||
|
||||
A libgdb application creates input and output vectors and assigns them names.
|
||||
Which input and output vectors are used by libgdb is established by
|
||||
executing these debugger commands:
|
||||
|
||||
@defun {set input-vector} name
|
||||
@defunx {set error-output-vector} name
|
||||
@defunx {set info-output-vector} name
|
||||
@defunx {set value-output-vector} name
|
||||
Choose an I/O vector by name.
|
||||
@end defun
|
||||
|
||||
|
||||
A few debugger commands are for use only within commands defined using
|
||||
the debugger command `define' (they have no effect at other times).
|
||||
These commands exist so that an application can maintain hooks which
|
||||
redirect output without affecting the global I/O vectors.
|
||||
|
||||
@defun with-input-vector name
|
||||
@defunx with-error-output-vector name
|
||||
@defunx with-info-output-vector name
|
||||
@defunx with-value-output-vector name
|
||||
Set an I/O vector, but only temporarily. The setting has effect only
|
||||
within the command definition in which it occurs.
|
||||
@end defun
|
||||
|
||||
|
||||
@heading Initial Conditions
|
||||
|
||||
When libgdb is initialized, a set of default I/O vectors is put in
|
||||
place. The default vectors are called @code{default-input-vector},
|
||||
@code{default-output-vector}, &c.
|
||||
|
||||
The default query function always returns `y'. Other input functions
|
||||
always abort. The default output functions discard output silently.
|
||||
|
||||
|
||||
@node Invoking, Defining Commands, I/O, Top
|
||||
@chapter Invoking the Interpreter, Executing Commands
|
||||
@cindex {executing commands}
|
||||
@cindex {invoking the interpreter}
|
||||
|
||||
This section introduces the libgdb functions which invoke the command
|
||||
interpreter.
|
||||
|
||||
@deftypefun void gdb_execute_command (@var{command})
|
||||
@example
|
||||
char * @var{command};
|
||||
@end example
|
||||
Interpret the argument debugger command. An error handler must be set
|
||||
when this function is called. (@xref{Top Level}.)
|
||||
@end deftypefun
|
||||
|
||||
It is possible to override the current I/O vectors for the duration of a
|
||||
single command:
|
||||
|
||||
@deftypefun void gdb_execute_with_io (@var{command}, @var{vecs})
|
||||
@example
|
||||
char * @var{command};
|
||||
struct gdb_io_vecs * @var{vecs};
|
||||
|
||||
struct gdb_io_vecs
|
||||
@{
|
||||
struct gdb_input_vector * input;
|
||||
struct gdb_output_vector * error;
|
||||
struct gdb_output_vector * info;
|
||||
struct gdb_output_vector * value;
|
||||
@}
|
||||
@end example
|
||||
|
||||
Execute @var{command}, temporarily using the i/o vectors in @var{vecs}.
|
||||
|
||||
Any of the vectors may be NULL, indicating that the current value should
|
||||
be used. An error handler must be in place when this function is used.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {struct gdb_str_output} gdb_execute_for_strings (@var{cmd})
|
||||
@example
|
||||
char * cmd;
|
||||
@end example
|
||||
@deftypefunx {struct gdb_str_output} gdb_execute_for_strings2 (@var{cmd}, @var{input})
|
||||
@example
|
||||
char * cmd;
|
||||
struct gdb_input_vector * input;
|
||||
@end example
|
||||
@page
|
||||
@example
|
||||
struct gdb_str_output
|
||||
@{
|
||||
char * error;
|
||||
char * info;
|
||||
char * value;
|
||||
@};
|
||||
@end example
|
||||
|
||||
Execute @var{cmd}, collecting its output as strings. If no error
|
||||
occurs, all three strings will be present in the structure, the
|
||||
empty-string rather than NULL standing for no output of a particular
|
||||
kind.
|
||||
|
||||
If the command aborts with an error, then the @code{value} field will be
|
||||
NULL, though the other two strings will be present.
|
||||
|
||||
In all cases, the strings returned are allocated by malloc and should be
|
||||
freed by the caller.
|
||||
|
||||
The first form listed uses the current input vector, but overrides the
|
||||
current output vector. The second form additionally allows the input
|
||||
vector to be overridden.
|
||||
|
||||
This function does not require that an error handler be installed.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void execute_catching_errors (@var{command})
|
||||
@example
|
||||
char * @var{command};
|
||||
@end example
|
||||
Like @code{execute_command} except that no error handler is required.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun void execute_with_text (@var{command}, @var{text})
|
||||
@example
|
||||
char * @var{command};
|
||||
char ** @var{text};
|
||||
@end example
|
||||
Like @code{execute_catching_errors}, except that the input vector is
|
||||
overridden. The new input vector handles only calls to @code{query} (by
|
||||
returning 'y') and calls to @code{read_strings} by returning a copy of
|
||||
@var{text} and the strings it points to.
|
||||
|
||||
This form of execute_command is useful for commands like @code{define},
|
||||
@code{document}, and @code{commands}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
|
||||
@node Defining Commands, Variables, Invoking, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter How New Commands are Created
|
||||
@cindex {commands, defining}
|
||||
|
||||
Applications are, of course, free to take advantage of the existing GDB
|
||||
macro definition capability (the @code{define} and @code{document}
|
||||
functions).
|
||||
|
||||
In addition, an application can add new primitives to the GDB command
|
||||
language.
|
||||
|
||||
@deftypefun void gdb_define_app_command (@var{name}, @var{fn}, @var{doc})
|
||||
@example
|
||||
char * @var{name};
|
||||
gdb_cmd_fn @var{fn};
|
||||
char * @var{doc};
|
||||
|
||||
typedef void (*gdb_cmd_fn) (char * args);
|
||||
@end example
|
||||
|
||||
Create a new command call @var{name}. The new command is in the
|
||||
@code{application} help class. When invoked, the command-line arguments
|
||||
to the command are passed as a single string.
|
||||
|
||||
Calling this function twice with the same name replaces an earlier
|
||||
definition, but application commands can not replace builtin commands of
|
||||
the same name.
|
||||
|
||||
The documentation string of the command is set to a copy the string
|
||||
@var{doc}.
|
||||
@end deftypefun
|
||||
|
||||
@node Variables, Asynchronous, Defining Commands, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter How Builtin Variables are Defined
|
||||
@cindex {variables, defining}
|
||||
|
||||
Convenience variables provide a way for values maintained by libgdb to
|
||||
be referenced in expressions (e.g. @code{$bpnum}). Libgdb includes a
|
||||
means by which the application can define new, integer valued
|
||||
convenience variables:
|
||||
@page
|
||||
@deftypefun void gdb_define_int_var (@var{name}, @var{fn}, @var{fn_arg})
|
||||
@example
|
||||
char * @var{name};
|
||||
int (*@var{fn}) (void *);
|
||||
void * @var{fn_arg};
|
||||
@end example
|
||||
This function defines (or undefines) a convenience variable called @var{name}.
|
||||
If @var{fn} is NULL, the variable becomes undefined. Otherwise,
|
||||
@var{fn} is a function which, when passed @var{fn_arg} returns the value
|
||||
of the newly defined variable.
|
||||
|
||||
No libgdb functions should be called by @var{fn}.
|
||||
@end deftypefun
|
||||
|
||||
One use for this function is to create breakpoint conditions computed in
|
||||
novel ways. This is done by defining a convenience variable and
|
||||
referring to that variable in a breakpoint condition expression.
|
||||
|
||||
|
||||
@node Asynchronous, Commands, Variables, Top
|
||||
@chapter Scheduling Asynchronous Computations
|
||||
@cindex asynchronous
|
||||
|
||||
|
||||
A running libgdb function can take a long time. Libgdb includes a hook
|
||||
so that an application can run intermittently during long debugger
|
||||
operations.
|
||||
|
||||
@deftypefun void gdb_set_poll_fn (@var{fn}, @var{fn_arg})
|
||||
@example
|
||||
void (*@var{fn})(void * fn_arg, int (*gdb_poll)());
|
||||
void * @var{fn_arg};
|
||||
@end example
|
||||
Arrange to call @var{fn} periodically during lengthy debugger operations.
|
||||
If @var{fn} is NULL, polling is turned off. @var{fn} should take two
|
||||
arguments: an opaque pointer passed as @var{fn_arg} to
|
||||
@code{gdb_set_poll_fn}, and a function pointer. The function pointer
|
||||
passed to @var{fn} is provided by libgdb and points to a function that
|
||||
returns 0 when the poll function should return. That is, when
|
||||
@code{(*gdb_poll)()} returns 0, libgdb is ready to continue @var{fn}
|
||||
should return quickly.
|
||||
|
||||
It is possible that @code{(*gdb_poll)()} will return 0 the first time it
|
||||
is called, so it is reasonable for an application to do minimal processing
|
||||
before checking whether to return.
|
||||
|
||||
No libgdb functions should be called from an application's poll function,
|
||||
with one exception: @code{gdb_request_quit}.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@deftypefun void gdb_request_quit (void)
|
||||
This function, if called from a poll function, requests that the
|
||||
currently executing libgdb command be interrupted as soon as possible,
|
||||
and that control be returned to the top-level via an error.
|
||||
|
||||
The quit is not immediate. It will not occur until at least after the
|
||||
application's poll function returns.
|
||||
@end deftypefun
|
||||
|
||||
@node Commands, Top, Asynchronous, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Debugger Commands for Libgdb Applications
|
||||
|
||||
The debugger commands available to libgdb applications are the same commands
|
||||
available interactively via GDB. This section is an overview of the
|
||||
commands newly created as part of libgdb.
|
||||
|
||||
This section is not by any means a complete reference to the GDB command
|
||||
language. See the GDB manual for such a reference.
|
||||
|
||||
@menu
|
||||
* Command Hooks:: Setting Hooks to Execute With Debugger Commands.
|
||||
* View Commands:: View Commands Mirror Show Commands
|
||||
* Breakpoints:: The Application Can Have Its Own Breakpoints
|
||||
@end menu
|
||||
|
||||
@node Command Hooks, View Commands, Commands, Commands
|
||||
@comment node-name, next, previous, up
|
||||
@section Setting Hooks to Execute With Debugger Commands.
|
||||
|
||||
Debugger commands support hooks. A command hook is executed just before
|
||||
the interpreter invokes the hooked command.
|
||||
|
||||
There are two hooks allowed for every command. By convention, one hook
|
||||
is for use by users, the other is for use by the application.
|
||||
|
||||
A user hook is created for a command XYZZY by using
|
||||
@code{define-command} to create a command called @code{hook-XYZZY}.
|
||||
|
||||
An application hook is created for a command XYZZY by using
|
||||
@code{define-command} to create a command called @code{apphook-XYZZY}.
|
||||
|
||||
Application hooks are useful for interfaces which wish to continuously
|
||||
monitor certain aspects of debugger state. The application can set a
|
||||
hook on all commands that might modify the watched state. When the hook
|
||||
is executed, it can use i/o redirection to notify parts of the
|
||||
application that previous data may be out of date. After the top-level loop
|
||||
resumes, the application can recompute any values that may have changed.
|
||||
(@xref{I/O}.)
|
||||
|
||||
@node View Commands, Breakpoints, Command Hooks, Commands
|
||||
@comment node-name, next, previous, up
|
||||
@section View Commands Mirror Show Commands
|
||||
|
||||
The GDB command language contains many @code{set} and @code{show}
|
||||
commands. These commands are used to modify or examine parameters to
|
||||
the debugger.
|
||||
|
||||
It is difficult to get the current state of a parameter from the
|
||||
@code{show} command because @code{show} is very verbose.
|
||||
|
||||
@example
|
||||
(gdb) show check type
|
||||
Type checking is "auto; currently off".
|
||||
(gdb) show width
|
||||
Number of characters gdb thinks are in a line is 80.
|
||||
@end example
|
||||
|
||||
For every @code{show} command, libgdb includes a @code{view} command.
|
||||
@code{view} is like @code{show} without the verbose commentary:
|
||||
|
||||
@example
|
||||
(gdb) view check type
|
||||
auto; currently off
|
||||
(gdb) view width
|
||||
80
|
||||
@end example
|
||||
|
||||
(The precise format of the ouput from @code{view} is subject to change.
|
||||
In particular, @code{view} may one-day print values which can be used as
|
||||
arguments to the corresponding @code{set} command.)
|
||||
|
||||
@node Breakpoints, Structured Output, View Commands, Commands
|
||||
@comment node-name, next, previous, up
|
||||
@section The Application Can Have Its Own Breakpoints
|
||||
|
||||
The GDB breakpoint commands were written with a strong presumption that
|
||||
all breakpoints are managed by a human user. Therefore, the command
|
||||
language contains commands like `delete' which affect all breakpoints
|
||||
without discrimination.
|
||||
|
||||
In libgdb, there is added support for breakpoints and watchpoints which
|
||||
are set by the application and which should not be affected by ordinary,
|
||||
indiscriminate commands. These are called @dfn{protected} breakpoints.
|
||||
|
||||
@deffn {Debugger Command} break-protected ...
|
||||
@deffnx {Debugger Command} watch-protected ...
|
||||
These work like @code{break} and @code{watch} except that the resulting
|
||||
breakpoint is given a negative number. Negative numbered breakpoints do
|
||||
not appear in the output of @code{info breakpoints} but do in that of
|
||||
@code{info all-breakpoints}. Negative numbered breakpoints are not
|
||||
affected by commands which ordinarily affect `all' breakpoints (e.g.
|
||||
@code{delete} with no arguments).
|
||||
|
||||
Note that libgdb itself creates protected breakpoints, so programs
|
||||
should not rely on being able to allocate particular protected
|
||||
breakpoint numbers for themselves.
|
||||
@end deffn
|
||||
|
||||
More than one breakpoint may be set at a given location. Libgdb adds
|
||||
the concept of @dfn{priority} to breakpoints. A priority is an integer,
|
||||
assigned to each breakpoint. When a breakpoint is reached, the
|
||||
conditions of all breakpoints at the same location are evaluated in
|
||||
order of ascending priority. When breakpoint commands are executed,
|
||||
they are also executed in ascending priority (until all have been
|
||||
executed, an error occurs, or one set of commands continues the
|
||||
target).
|
||||
|
||||
@deffn {Debugger Command} priority n bplist
|
||||
Set the priority for breakpoints @var{bplist} to @var{n}.
|
||||
By default, breakpoints are assigned a priority of zero.
|
||||
@end deffn
|
||||
|
||||
@node Structured Output, Commands, Breakpoints, Commands
|
||||
@comment node-name, next, previous, up
|
||||
@section Structured Output, The @code{Explain} Command
|
||||
|
||||
(This section may be subject to considerable revision.)
|
||||
|
||||
When GDB prints a the value of an expression, the printed representation
|
||||
contains information that can be usefully fed back into future commands
|
||||
and expressions. For example,
|
||||
|
||||
@example
|
||||
(gdb) print foo
|
||||
$16 = @{v = 0x38ae0, v_length = 40@}
|
||||
@end example
|
||||
|
||||
On the basis of this output, a user knows, for example, that
|
||||
@code{$16.v} refers to a pointer valued @code{0x38ae0}
|
||||
|
||||
A new output command helps to make information like this available to
|
||||
the application.
|
||||
|
||||
@deffn {Debugger Command} explain expression
|
||||
@deffnx {Debugger Command} explain /format expression
|
||||
Print the value of @var{expression} in the manner of the @code{print}
|
||||
command, but embed that output in a list syntax containing information
|
||||
about the structure of the output.
|
||||
@end deffn
|
||||
|
||||
As an example, @code{explain argv} might produce this output:
|
||||
|
||||
@example
|
||||
(exp-attribute
|
||||
((expression "$19")
|
||||
(type "char **")
|
||||
(address "48560")
|
||||
(deref-expression "*$19"))
|
||||
"$19 = 0x3800\n")
|
||||
@end example
|
||||
|
||||
The syntax of output from @code{explain} is:
|
||||
|
||||
@example
|
||||
<explanation> := <quoted-string>
|
||||
| (exp-concat <explanation> <explanation>*)
|
||||
| (exp-attribute <property-list> <explanation>)
|
||||
|
||||
<property-list> := ( <property-pair>* )
|
||||
|
||||
<property-pair> := ( <property-name> <quoted-string> )
|
||||
@end example
|
||||
|
||||
The string-concatenation of all of the @code{<quoted-string>} (except
|
||||
those in property lists) yields the output generated by the equivalent
|
||||
@code{print} command. Quoted strings may contain quotes and backslashes
|
||||
if they are escaped by backslash. "\n" in a quoted string stands for
|
||||
newline; unescaped newlines do not occur within the strings output by
|
||||
@code{explain}.
|
||||
|
||||
Property names are made up of alphabetic characters, dashes, and
|
||||
underscores.
|
||||
|
||||
The set of properties is open-ended. As GDB acquires support for new
|
||||
source languages and other new capabilities, new property types may be
|
||||
added to the output of this command. Future commands may offer
|
||||
applications some selectivity concerning which properties are reported.
|
||||
|
||||
The initial set of properties defined includes:
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{expression}
|
||||
|
||||
This is an expression, such as @code{$42} or @code{$42.x}. The
|
||||
expression can be used to refer to the value printed in the attributed
|
||||
part of the string.
|
||||
|
||||
@item @code{type}
|
||||
|
||||
This is a user-readable name for the type of the attributed value.
|
||||
|
||||
@item @code{address}
|
||||
|
||||
If the value is stored in a target register, this is a register number.
|
||||
If the value is stored in a GDB convenience variable, this is an integer
|
||||
that is unique among all the convenience variables. Otherwise, this is
|
||||
the address in the target where the value is stored.
|
||||
|
||||
@item @code{deref-expression}
|
||||
|
||||
If the attributed value is a pointer type, this is an expression that
|
||||
refers to the dereferenced value.
|
||||
@end itemize
|
||||
|
||||
Here is a larger example, using the same object passed to @code{print}
|
||||
in an earlier example of this section.
|
||||
|
||||
@example
|
||||
(gdb) explain foo
|
||||
(exp-attribute
|
||||
( (expression "$16")
|
||||
(type "struct bytecode_vector")
|
||||
(address 14336) )
|
||||
(exp-concat
|
||||
"$16 = @{"
|
||||
(exp-attribute
|
||||
( (expression "$16.v")
|
||||
(type "char *")
|
||||
(address 14336)
|
||||
(deref-expression "*$16.v") )
|
||||
"v = 0x38ae0")
|
||||
(exp-attribute
|
||||
( (expression "$16.v_length")
|
||||
(type "int")
|
||||
(address 14340) )
|
||||
", v_length = 40")
|
||||
"@}\n"))
|
||||
@end example
|
||||
|
||||
It is undefined how libgdb will indent these lines of output or
|
||||
where newlines will be included.
|
||||
|
||||
@bye
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,451 +0,0 @@
|
||||
/* Low level interface to ptrace, for the remote server for GDB.
|
||||
Copyright (C) 1995, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include <sys/wait.h>
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/user.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if 0
|
||||
#include <sgtty.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
/***************Begin MY defs*********************/
|
||||
int quit_flag = 0;
|
||||
char registers[REGISTER_BYTES];
|
||||
|
||||
/* Index within `registers' of the first byte of the space for
|
||||
register N. */
|
||||
|
||||
|
||||
char buf2[MAX_REGISTER_RAW_SIZE];
|
||||
/***************End MY defs*********************/
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
|
||||
#include <sys/reg.h>
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
extern int errno;
|
||||
extern int inferior_pid;
|
||||
void quit (), perror_with_name ();
|
||||
int query ();
|
||||
|
||||
/* Start an inferior process and returns its pid.
|
||||
ALLARGS is a vector of program-name and args.
|
||||
ENV is the environment vector to pass. */
|
||||
|
||||
int
|
||||
create_inferior (program, allargs)
|
||||
char *program;
|
||||
char **allargs;
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = fork ();
|
||||
if (pid < 0)
|
||||
perror_with_name ("fork");
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
ptrace (PTRACE_TRACEME, 0, 0, 0);
|
||||
|
||||
execv (program, allargs);
|
||||
|
||||
fprintf (stderr, "Cannot exec %s: %s.\n", program,
|
||||
errno < sys_nerr ? sys_errlist[errno] : "unknown error");
|
||||
fflush (stderr);
|
||||
_exit (0177);
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* Kill the inferior process. Make us have no inferior. */
|
||||
|
||||
void
|
||||
kill_inferior ()
|
||||
{
|
||||
if (inferior_pid == 0)
|
||||
return;
|
||||
ptrace (PTRACE_KILL, inferior_pid, 0, 0);
|
||||
wait (0);
|
||||
/*************inferior_died ();****VK**************/
|
||||
}
|
||||
|
||||
/* Return nonzero if the given thread is still alive. */
|
||||
int
|
||||
mythread_alive (pid)
|
||||
int pid;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wait for process, returns status */
|
||||
|
||||
unsigned char
|
||||
mywait (status)
|
||||
char *status;
|
||||
{
|
||||
int pid;
|
||||
union wait w;
|
||||
|
||||
pid = wait (&w);
|
||||
if (pid != inferior_pid)
|
||||
perror_with_name ("wait");
|
||||
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
|
||||
*status = 'W';
|
||||
return ((unsigned char) WEXITSTATUS (w));
|
||||
}
|
||||
else if (!WIFSTOPPED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
|
||||
*status = 'X';
|
||||
return ((unsigned char) WTERMSIG (w));
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
*status = 'T';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
/* Resume execution of the inferior process.
|
||||
If STEP is nonzero, single-step it.
|
||||
If SIGNAL is nonzero, give it that signal. */
|
||||
|
||||
void
|
||||
myresume (step, signal)
|
||||
int step;
|
||||
int signal;
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace");
|
||||
}
|
||||
|
||||
|
||||
#if !defined (offsetof)
|
||||
#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
/* U_REGS_OFFSET is the offset of the registers within the u area. */
|
||||
#if !defined (U_REGS_OFFSET)
|
||||
#define U_REGS_OFFSET \
|
||||
ptrace (PT_READ_U, inferior_pid, \
|
||||
(PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
|
||||
- KERNEL_U_ADDR
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_M68K
|
||||
/* this table must line up with REGISTER_NAMES in tm-i386v.h */
|
||||
/* symbols like 'EAX' come from <sys/reg.h> */
|
||||
static int regmap[] =
|
||||
{
|
||||
EAX, ECX, EDX, EBX,
|
||||
UESP, EBP, ESI, EDI,
|
||||
EIP, EFL, CS, SS,
|
||||
DS, ES, FS, GS,
|
||||
};
|
||||
|
||||
int
|
||||
i386_register_u_addr (blockend, regnum)
|
||||
int blockend;
|
||||
int regnum;
|
||||
{
|
||||
#if 0
|
||||
/* this will be needed if fp registers are reinstated */
|
||||
/* for now, you can look at them with 'info float'
|
||||
* sys5 wont let you change them with ptrace anyway
|
||||
*/
|
||||
if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
|
||||
{
|
||||
int ubase, fpstate;
|
||||
struct user u;
|
||||
ubase = blockend + 4 * (SS + 1) - KSTKSZ;
|
||||
fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
|
||||
return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return (blockend + 4 * regmap[regnum]);
|
||||
|
||||
}
|
||||
#else /* TARGET_M68K */
|
||||
/* This table must line up with REGISTER_NAMES in tm-m68k.h */
|
||||
static int regmap[] =
|
||||
{
|
||||
#ifdef PT_D0
|
||||
PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
|
||||
PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
|
||||
PT_SR, PT_PC,
|
||||
#else
|
||||
14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15,
|
||||
17, 18,
|
||||
#endif
|
||||
#ifdef PT_FP0
|
||||
PT_FP0, PT_FP1, PT_FP2, PT_FP3, PT_FP4, PT_FP5, PT_FP6, PT_FP7,
|
||||
PT_FPCR, PT_FPSR, PT_FPIAR
|
||||
#else
|
||||
21, 24, 27, 30, 33, 36, 39, 42, 45, 46, 47
|
||||
#endif
|
||||
};
|
||||
|
||||
/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
|
||||
is stored. */
|
||||
|
||||
int
|
||||
m68k_linux_register_u_addr (blockend, regnum)
|
||||
int blockend;
|
||||
int regnum;
|
||||
{
|
||||
return (blockend + 4 * regmap[regnum]);
|
||||
}
|
||||
#endif
|
||||
|
||||
CORE_ADDR
|
||||
register_addr (regno, blockend)
|
||||
int regno;
|
||||
CORE_ADDR blockend;
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
|
||||
if (regno < 0 || regno >= ARCH_NUM_REGS)
|
||||
error ("Invalid register number %d.", regno);
|
||||
|
||||
REGISTER_U_ADDR (addr, blockend, regno);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Fetch one register. */
|
||||
|
||||
static void
|
||||
fetch_register (regno)
|
||||
int regno;
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
register int i;
|
||||
|
||||
/* Offset of registers within the u area. */
|
||||
unsigned int offset;
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
|
||||
regaddr = register_addr (regno, offset);
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
errno = 0;
|
||||
*(int *) ®isters[ regno * 4 + i] = ptrace (PTRACE_PEEKUSR, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
regaddr += sizeof (int);
|
||||
if (errno != 0)
|
||||
{
|
||||
/* Warning, not error, in case we are attached; sometimes the
|
||||
kernel doesn't let us at the registers. */
|
||||
char *err = strerror (errno);
|
||||
char *msg = alloca (strlen (err) + 128);
|
||||
sprintf (msg, "reading register %d: %s", regno, err);
|
||||
error (msg);
|
||||
goto error_exit;
|
||||
}
|
||||
}
|
||||
error_exit:;
|
||||
}
|
||||
|
||||
/* Fetch all registers, or just one, from the child process. */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (regno == -1 || regno == 0)
|
||||
for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
|
||||
fetch_register (regno);
|
||||
else
|
||||
fetch_register (regno);
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
register int i;
|
||||
unsigned int offset = U_REGS_OFFSET;
|
||||
|
||||
if (regno >= 0)
|
||||
{
|
||||
#if 0
|
||||
if (CANNOT_STORE_REGISTER (regno))
|
||||
return;
|
||||
#endif
|
||||
regaddr = register_addr (regno, offset);
|
||||
errno = 0;
|
||||
#if 0
|
||||
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
|
||||
{
|
||||
scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3;
|
||||
ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
scratch, 0);
|
||||
if (errno != 0)
|
||||
{
|
||||
/* Error, even if attached. Failing to write these two
|
||||
registers is pretty serious. */
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKEUSR, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
*(int *) ®isters[REGISTER_BYTE (regno) + i]);
|
||||
if (errno != 0)
|
||||
{
|
||||
/* Warning, not error, in case we are attached; sometimes the
|
||||
kernel doesn't let us at the registers. */
|
||||
char *err = strerror (errno);
|
||||
char *msg = alloca (strlen (err) + 128);
|
||||
sprintf (msg, "writing register %d: %s",
|
||||
regno, err);
|
||||
error (msg);
|
||||
return;
|
||||
}
|
||||
regaddr += sizeof(int);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
|
||||
store_inferior_registers (regno);
|
||||
}
|
||||
|
||||
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
|
||||
in the NEW_SUN_PTRACE case.
|
||||
It ought to be straightforward. But it appears that writing did
|
||||
not write the data that I specified. I cannot understand where
|
||||
it got the data that it actually did write. */
|
||||
|
||||
/* Copy LEN bytes from inferior's memory starting at MEMADDR
|
||||
to debugger memory starting at MYADDR. */
|
||||
|
||||
void
|
||||
read_inferior_memory (memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
{
|
||||
register int i;
|
||||
/* Round starting address down to longword boundary. */
|
||||
register CORE_ADDR addr = memaddr & -sizeof (int);
|
||||
/* Round ending address up; get number of longwords that makes. */
|
||||
register int count
|
||||
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
|
||||
/* Allocate buffer of that many longwords. */
|
||||
register int *buffer = (int *) alloca (count * sizeof (int));
|
||||
|
||||
/* Read all the longwords */
|
||||
for (i = 0; i < count; i++, addr += sizeof (int))
|
||||
{
|
||||
buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
|
||||
}
|
||||
|
||||
/* Copy appropriate bytes out of the buffer. */
|
||||
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
|
||||
}
|
||||
|
||||
/* Copy LEN bytes of data from debugger memory at MYADDR
|
||||
to inferior's memory at MEMADDR.
|
||||
On failure (cannot write the inferior)
|
||||
returns the value of errno. */
|
||||
|
||||
int
|
||||
write_inferior_memory (memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
{
|
||||
register int i;
|
||||
/* Round starting address down to longword boundary. */
|
||||
register CORE_ADDR addr = memaddr & -sizeof (int);
|
||||
/* Round ending address up; get number of longwords that makes. */
|
||||
register int count
|
||||
= (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
|
||||
/* Allocate buffer of that many longwords. */
|
||||
register int *buffer = (int *) alloca (count * sizeof (int));
|
||||
extern int errno;
|
||||
|
||||
/* Fill start and end extra bytes of buffer with existing memory data. */
|
||||
|
||||
buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
buffer[count - 1]
|
||||
= ptrace (PTRACE_PEEKTEXT, inferior_pid,
|
||||
addr + (count - 1) * sizeof (int), 0);
|
||||
}
|
||||
|
||||
/* Copy data to be written over corresponding part of buffer */
|
||||
|
||||
memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
|
||||
|
||||
/* Write the entire buffer. */
|
||||
|
||||
for (i = 0; i < count; i++, addr += sizeof (int))
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
|
||||
if (errno)
|
||||
return errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
initialize ()
|
||||
{
|
||||
inferior_pid = 0;
|
||||
}
|
||||
|
||||
int
|
||||
have_inferior_p ()
|
||||
{
|
||||
return inferior_pid != 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
/* Common things used by the various *gnu-nat.c files
|
||||
Copyright 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
Written by Miles Bader <miles@gnu.ai.mit.edu>
|
||||
|
||||
The GNU Hurd 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 2, or (at
|
||||
your option) any later version.
|
||||
|
||||
The GNU Hurd 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef __GNU_NAT_H__
|
||||
#define __GNU_NAT_H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <mach.h>
|
||||
|
||||
struct inf;
|
||||
|
||||
extern struct inf *current_inferior;
|
||||
|
||||
/* Converts a GDB pid to a struct proc. */
|
||||
struct proc *inf_tid_to_thread (struct inf *inf, int tid);
|
||||
|
||||
/* Makes sure that INF's thread list is synced with the actual process. */
|
||||
int inf_update_procs (struct inf *inf);
|
||||
|
||||
/* A proc is either a thread, or the task (there can only be one task proc
|
||||
because it always has the same TID, PROC_TID_TASK). */
|
||||
struct proc
|
||||
{
|
||||
thread_t port; /* The task or thread port. */
|
||||
int tid; /* The GDB pid (actually a thread id). */
|
||||
int num; /* An id number for threads, to print. */
|
||||
|
||||
mach_port_t saved_exc_port; /* The task/thread's real exception port. */
|
||||
mach_port_t exc_port; /* Our replacement, which for. */
|
||||
|
||||
int sc; /* Desired suspend count. */
|
||||
int cur_sc; /* Implemented suspend count. */
|
||||
int run_sc; /* Default sc when the program is running. */
|
||||
int pause_sc; /* Default sc when gdb has control. */
|
||||
int resume_sc; /* Sc resulting from the last resume. */
|
||||
int detach_sc; /* SC to leave around when detaching
|
||||
from program. */
|
||||
|
||||
thread_state_data_t state; /* Registers, &c. */
|
||||
int state_valid:1; /* True if STATE is up to date. */
|
||||
int state_changed:1;
|
||||
|
||||
int aborted:1; /* True if thread_abort has been called. */
|
||||
int dead:1; /* We happen to know it's actually dead. */
|
||||
|
||||
/* Bit mask of registers fetched by gdb. This is used when we re-fetch
|
||||
STATE after aborting the thread, to detect that gdb may have out-of-date
|
||||
information. */
|
||||
unsigned long fetched_regs;
|
||||
|
||||
struct inf *inf; /* Where we come from. */
|
||||
|
||||
struct proc *next;
|
||||
};
|
||||
|
||||
/* The task has a thread entry with this TID. */
|
||||
#define PROC_TID_TASK (-1)
|
||||
|
||||
#define proc_is_task(proc) ((proc)->tid == PROC_TID_TASK)
|
||||
#define proc_is_thread(proc) ((proc)->tid != PROC_TID_TASK)
|
||||
|
||||
extern int __proc_pid (struct proc *proc);
|
||||
|
||||
/* Make sure that the state field in PROC is up to date, and return a
|
||||
pointer to it, or 0 if something is wrong. If WILL_MODIFY is true,
|
||||
makes sure that the thread is stopped and aborted first, and sets
|
||||
the state_changed field in PROC to true. */
|
||||
extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
|
||||
|
||||
/* Return printable description of proc. */
|
||||
extern char *proc_string (struct proc *proc);
|
||||
|
||||
#define proc_debug(_proc, msg, args...) \
|
||||
do { struct proc *__proc = (_proc); \
|
||||
debug ("{proc %d/%d %p}: " msg, \
|
||||
__proc_pid (__proc), __proc->tid, __proc , ##args); } while (0)
|
||||
|
||||
extern int gnu_debug_flag;
|
||||
|
||||
#define debug(msg, args...) \
|
||||
do { if (gnu_debug_flag) \
|
||||
fprintf_unfiltered (gdb_stdlog, "%s: " msg "\r\n", __FUNCTION__ , ##args); } while (0)
|
||||
|
||||
#endif /* __GNU_NAT_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -1,576 +0,0 @@
|
||||
/* Definitions for data structures and routines for the regular
|
||||
expression library, version 0.12.
|
||||
Copyright (C) 1985,89,90,91,92,93,95,96,97,98 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the
|
||||
GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
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 2, 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, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _REGEX_H
|
||||
#define _REGEX_H 1
|
||||
|
||||
/* Allow the use in C++ code. */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* POSIX says that <sys/types.h> must be included (by the caller) before
|
||||
<regex.h>. */
|
||||
|
||||
#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS
|
||||
/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
|
||||
should be there. */
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
/* GDB LOCAL: define _REGEX_RE_COMP to get BSD style re_comp and re_exec */
|
||||
#ifndef _REGEX_RE_COMP
|
||||
#define _REGEX_RE_COMP
|
||||
#endif
|
||||
|
||||
/* The following two types have to be signed and unsigned integer type
|
||||
wide enough to hold a value of a pointer. For most ANSI compilers
|
||||
ptrdiff_t and size_t should be likely OK. Still size of these two
|
||||
types is 2 for Microsoft C. Ugh... */
|
||||
typedef long int s_reg_t;
|
||||
typedef unsigned long int active_reg_t;
|
||||
|
||||
/* The following bits are used to determine the regexp syntax we
|
||||
recognize. The set/not-set meanings are chosen so that Emacs syntax
|
||||
remains the value 0. The bits are given in alphabetical order, and
|
||||
the definitions shifted by one from the previous bit; thus, when we
|
||||
add or remove a bit, only one other definition need change. */
|
||||
typedef unsigned long int reg_syntax_t;
|
||||
|
||||
/* If this bit is not set, then \ inside a bracket expression is literal.
|
||||
If set, then such a \ quotes the following character. */
|
||||
#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
|
||||
|
||||
/* If this bit is not set, then + and ? are operators, and \+ and \? are
|
||||
literals.
|
||||
If set, then \+ and \? are operators and + and ? are literals. */
|
||||
#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
|
||||
|
||||
/* If this bit is set, then character classes are supported. They are:
|
||||
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
|
||||
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
|
||||
If not set, then character classes are not supported. */
|
||||
#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
|
||||
|
||||
/* If this bit is set, then ^ and $ are always anchors (outside bracket
|
||||
expressions, of course).
|
||||
If this bit is not set, then it depends:
|
||||
^ is an anchor if it is at the beginning of a regular
|
||||
expression or after an open-group or an alternation operator;
|
||||
$ is an anchor if it is at the end of a regular expression, or
|
||||
before a close-group or an alternation operator.
|
||||
|
||||
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
|
||||
POSIX draft 11.2 says that * etc. in leading positions is undefined.
|
||||
We already implemented a previous draft which made those constructs
|
||||
invalid, though, so we haven't changed the code back. */
|
||||
#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
|
||||
|
||||
/* If this bit is set, then special characters are always special
|
||||
regardless of where they are in the pattern.
|
||||
If this bit is not set, then special characters are special only in
|
||||
some contexts; otherwise they are ordinary. Specifically,
|
||||
* + ? and intervals are only special when not after the beginning,
|
||||
open-group, or alternation operator. */
|
||||
#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
|
||||
|
||||
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
|
||||
immediately after an alternation or begin-group operator. */
|
||||
#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . matches newline.
|
||||
If not set, then it doesn't. */
|
||||
#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
|
||||
|
||||
/* If this bit is set, then . doesn't match NUL.
|
||||
If not set, then it does. */
|
||||
#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, nonmatching lists [^...] do not match newline.
|
||||
If not set, they do. */
|
||||
#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
|
||||
|
||||
/* If this bit is set, either \{...\} or {...} defines an
|
||||
interval, depending on RE_NO_BK_BRACES.
|
||||
If not set, \{, \}, {, and } are literals. */
|
||||
#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
|
||||
|
||||
/* If this bit is set, +, ? and | aren't recognized as operators.
|
||||
If not set, they are. */
|
||||
#define RE_LIMITED_OPS (RE_INTERVALS << 1)
|
||||
|
||||
/* If this bit is set, newline is an alternation operator.
|
||||
If not set, newline is literal. */
|
||||
#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
|
||||
|
||||
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
|
||||
are literals.
|
||||
If not set, then `\{...\}' defines an interval. */
|
||||
#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
|
||||
|
||||
/* If this bit is set, (...) defines a group, and \( and \) are literals.
|
||||
If not set, \(...\) defines a group, and ( and ) are literals. */
|
||||
#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
|
||||
|
||||
/* If this bit is set, then \<digit> matches <digit>.
|
||||
If not set, then \<digit> is a back-reference. */
|
||||
#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
|
||||
|
||||
/* If this bit is set, then | is an alternation operator, and \| is literal.
|
||||
If not set, then \| is an alternation operator, and | is literal. */
|
||||
#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
|
||||
|
||||
/* If this bit is set, then an ending range point collating higher
|
||||
than the starting range point, as in [z-a], is invalid.
|
||||
If not set, then when ending range point collates higher than the
|
||||
starting range point, the range is ignored. */
|
||||
#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
|
||||
|
||||
/* If this bit is set, then an unmatched ) is ordinary.
|
||||
If not set, then an unmatched ) is invalid. */
|
||||
#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
|
||||
|
||||
/* If this bit is set, succeed as soon as we match the whole pattern,
|
||||
without further backtracking. */
|
||||
#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
|
||||
|
||||
/* If this bit is set, do not process the GNU regex operators.
|
||||
If not set, then the GNU regex operators are recognized. */
|
||||
#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
|
||||
|
||||
/* If this bit is set, turn on internal regex debugging.
|
||||
If not set, and debugging was on, turn it off.
|
||||
This only works if regex.c is compiled -DDEBUG.
|
||||
We define this bit always, so that all that's needed to turn on
|
||||
debugging is to recompile regex.c; the calling code can always have
|
||||
this bit set, and it won't affect anything in the normal case. */
|
||||
#define RE_DEBUG (RE_NO_GNU_OPS << 1)
|
||||
|
||||
/* This global variable defines the particular regexp syntax to use (for
|
||||
some interfaces). When a regexp is compiled, the syntax used is
|
||||
stored in the pattern buffer, so changing this does not affect
|
||||
already-compiled regexps. */
|
||||
extern reg_syntax_t re_syntax_options;
|
||||
|
||||
/* Define combinations of the above bits for the standard possibilities.
|
||||
(The [[[ comments delimit what gets put into the Texinfo file, so
|
||||
don't delete them!) */
|
||||
/* [[[begin syntaxes]]] */
|
||||
#define RE_SYNTAX_EMACS 0
|
||||
|
||||
#define RE_SYNTAX_AWK \
|
||||
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
|
||||
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
|
||||
|
||||
#define RE_SYNTAX_GNU_AWK \
|
||||
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
|
||||
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS))
|
||||
|
||||
#define RE_SYNTAX_POSIX_AWK \
|
||||
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
|
||||
| RE_INTERVALS | RE_NO_GNU_OPS)
|
||||
|
||||
#define RE_SYNTAX_GREP \
|
||||
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
|
||||
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
|
||||
| RE_NEWLINE_ALT)
|
||||
|
||||
#define RE_SYNTAX_EGREP \
|
||||
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
|
||||
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
|
||||
| RE_NO_BK_VBAR)
|
||||
|
||||
#define RE_SYNTAX_POSIX_EGREP \
|
||||
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
|
||||
|
||||
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
|
||||
#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
|
||||
|
||||
/* Syntax bits common to both basic and extended POSIX regex syntax. */
|
||||
#define _RE_SYNTAX_POSIX_COMMON \
|
||||
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
|
||||
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
|
||||
|
||||
#define RE_SYNTAX_POSIX_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
|
||||
|
||||
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
|
||||
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
|
||||
isn't minimal, since other operators, such as \`, aren't disabled. */
|
||||
#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
|
||||
|
||||
#define RE_SYNTAX_POSIX_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
|
||||
| RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
|
||||
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
|
||||
replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
|
||||
#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
|
||||
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
|
||||
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
|
||||
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
|
||||
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
|
||||
/* [[[end syntaxes]]] */
|
||||
|
||||
/* Maximum number of duplicates an interval can allow. Some systems
|
||||
(erroneously) define this in other header files, but we want our
|
||||
value, so remove any previous define. */
|
||||
#ifdef RE_DUP_MAX
|
||||
# undef RE_DUP_MAX
|
||||
#endif
|
||||
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
|
||||
#define RE_DUP_MAX (0x7fff)
|
||||
|
||||
|
||||
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
|
||||
|
||||
/* If this bit is set, then use extended regular expression syntax.
|
||||
If not set, then use basic regular expression syntax. */
|
||||
#define REG_EXTENDED 1
|
||||
|
||||
/* If this bit is set, then ignore case when matching.
|
||||
If not set, then case is significant. */
|
||||
#define REG_ICASE (REG_EXTENDED << 1)
|
||||
|
||||
/* If this bit is set, then anchors do not match at newline
|
||||
characters in the string.
|
||||
If not set, then anchors do match at newlines. */
|
||||
#define REG_NEWLINE (REG_ICASE << 1)
|
||||
|
||||
/* If this bit is set, then report only success or fail in regexec.
|
||||
If not set, then returns differ between not matching and errors. */
|
||||
#define REG_NOSUB (REG_NEWLINE << 1)
|
||||
|
||||
|
||||
/* POSIX `eflags' bits (i.e., information for regexec). */
|
||||
|
||||
/* If this bit is set, then the beginning-of-line operator doesn't match
|
||||
the beginning of the string (presumably because it's not the
|
||||
beginning of a line).
|
||||
If not set, then the beginning-of-line operator does match the
|
||||
beginning of the string. */
|
||||
#define REG_NOTBOL 1
|
||||
|
||||
/* Like REG_NOTBOL, except for the end-of-line. */
|
||||
#define REG_NOTEOL (1 << 1)
|
||||
|
||||
|
||||
/* If any error codes are removed, changed, or added, update the
|
||||
`re_error_msg' table in regex.c. */
|
||||
typedef enum
|
||||
{
|
||||
#if (_XOPEN_SOURCE - 0) == 500
|
||||
REG_NOSYS = -1, /* This will never happen for this implementation. */
|
||||
#endif
|
||||
|
||||
REG_NOERROR = 0, /* Success. */
|
||||
REG_NOMATCH, /* Didn't find a match (for regexec). */
|
||||
|
||||
/* POSIX regcomp return error codes. (In the order listed in the
|
||||
standard.) */
|
||||
REG_BADPAT, /* Invalid pattern. */
|
||||
REG_ECOLLATE, /* Not implemented. */
|
||||
REG_ECTYPE, /* Invalid character class name. */
|
||||
REG_EESCAPE, /* Trailing backslash. */
|
||||
REG_ESUBREG, /* Invalid back reference. */
|
||||
REG_EBRACK, /* Unmatched left bracket. */
|
||||
REG_EPAREN, /* Parenthesis imbalance. */
|
||||
REG_EBRACE, /* Unmatched \{. */
|
||||
REG_BADBR, /* Invalid contents of \{\}. */
|
||||
REG_ERANGE, /* Invalid range end. */
|
||||
REG_ESPACE, /* Ran out of memory. */
|
||||
REG_BADRPT, /* No preceding re for repetition op. */
|
||||
|
||||
/* Error codes we've added. */
|
||||
REG_EEND, /* Premature end. */
|
||||
REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
|
||||
REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
|
||||
} reg_errcode_t;
|
||||
|
||||
/* This data structure represents a compiled pattern. Before calling
|
||||
the pattern compiler, the fields `buffer', `allocated', `fastmap',
|
||||
`translate', and `no_sub' can be set. After the pattern has been
|
||||
compiled, the `re_nsub' field is available. All other fields are
|
||||
private to the regex routines. */
|
||||
|
||||
#ifndef RE_TRANSLATE_TYPE
|
||||
# define RE_TRANSLATE_TYPE char *
|
||||
#endif
|
||||
|
||||
struct re_pattern_buffer
|
||||
{
|
||||
/* [[[begin pattern_buffer]]] */
|
||||
/* Space that holds the compiled pattern. It is declared as
|
||||
`unsigned char *' because its elements are
|
||||
sometimes used as array indexes. */
|
||||
unsigned char *buffer;
|
||||
|
||||
/* Number of bytes to which `buffer' points. */
|
||||
unsigned long int allocated;
|
||||
|
||||
/* Number of bytes actually used in `buffer'. */
|
||||
unsigned long int used;
|
||||
|
||||
/* Syntax setting with which the pattern was compiled. */
|
||||
reg_syntax_t syntax;
|
||||
|
||||
/* Pointer to a fastmap, if any, otherwise zero. re_search uses
|
||||
the fastmap, if there is one, to skip over impossible
|
||||
starting points for matches. */
|
||||
char *fastmap;
|
||||
|
||||
/* Either a translate table to apply to all characters before
|
||||
comparing them, or zero for no translation. The translation
|
||||
is applied to a pattern when it is compiled and to a string
|
||||
when it is matched. */
|
||||
RE_TRANSLATE_TYPE translate;
|
||||
|
||||
/* Number of subexpressions found by the compiler. */
|
||||
size_t re_nsub;
|
||||
|
||||
/* Zero if this pattern cannot match the empty string, one else.
|
||||
Well, in truth it's used only in `re_search_2', to see
|
||||
whether or not we should use the fastmap, so we don't set
|
||||
this absolutely perfectly; see `re_compile_fastmap' (the
|
||||
`duplicate' case). */
|
||||
unsigned can_be_null : 1;
|
||||
|
||||
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
|
||||
for `max (RE_NREGS, re_nsub + 1)' groups.
|
||||
If REGS_REALLOCATE, reallocate space if necessary.
|
||||
If REGS_FIXED, use what's there. */
|
||||
#define REGS_UNALLOCATED 0
|
||||
#define REGS_REALLOCATE 1
|
||||
#define REGS_FIXED 2
|
||||
unsigned regs_allocated : 2;
|
||||
|
||||
/* Set to zero when `regex_compile' compiles a pattern; set to one
|
||||
by `re_compile_fastmap' if it updates the fastmap. */
|
||||
unsigned fastmap_accurate : 1;
|
||||
|
||||
/* If set, `re_match_2' does not return information about
|
||||
subexpressions. */
|
||||
unsigned no_sub : 1;
|
||||
|
||||
/* If set, a beginning-of-line anchor doesn't match at the
|
||||
beginning of the string. */
|
||||
unsigned not_bol : 1;
|
||||
|
||||
/* Similarly for an end-of-line anchor. */
|
||||
unsigned not_eol : 1;
|
||||
|
||||
/* If true, an anchor at a newline matches. */
|
||||
unsigned newline_anchor : 1;
|
||||
|
||||
/* [[[end pattern_buffer]]] */
|
||||
};
|
||||
|
||||
typedef struct re_pattern_buffer regex_t;
|
||||
|
||||
/* Type for byte offsets within the string. POSIX mandates this. */
|
||||
typedef int regoff_t;
|
||||
|
||||
|
||||
/* This is the structure we store register match data in. See
|
||||
regex.texinfo for a full description of what registers match. */
|
||||
struct re_registers
|
||||
{
|
||||
unsigned num_regs;
|
||||
regoff_t *start;
|
||||
regoff_t *end;
|
||||
};
|
||||
|
||||
|
||||
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
|
||||
`re_match_2' returns information about at least this many registers
|
||||
the first time a `regs' structure is passed. */
|
||||
#ifndef RE_NREGS
|
||||
# define RE_NREGS 30
|
||||
#endif
|
||||
|
||||
|
||||
/* POSIX specification for registers. Aside from the different names than
|
||||
`re_registers', POSIX uses an array of structures, instead of a
|
||||
structure of arrays. */
|
||||
typedef struct
|
||||
{
|
||||
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
|
||||
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
|
||||
} regmatch_t;
|
||||
|
||||
/* Declarations for routines. */
|
||||
|
||||
/* To avoid duplicating every routine declaration -- once with a
|
||||
prototype (if we are ANSI), and once without (if we aren't) -- we
|
||||
use the following macro to declare argument types. This
|
||||
unfortunately clutters up the declarations a bit, but I think it's
|
||||
worth it. */
|
||||
|
||||
#if __STDC__
|
||||
|
||||
# define _RE_ARGS(args) args
|
||||
|
||||
#else /* not __STDC__ */
|
||||
|
||||
# define _RE_ARGS(args) ()
|
||||
|
||||
#endif /* not __STDC__ */
|
||||
|
||||
/* Sets the current default syntax to SYNTAX, and return the old syntax.
|
||||
You can also simply assign to the `re_syntax_options' variable. */
|
||||
extern reg_syntax_t __re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
|
||||
extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
|
||||
|
||||
/* Compile the regular expression PATTERN, with length LENGTH
|
||||
and syntax given by the global `re_syntax_options', into the buffer
|
||||
BUFFER. Return NULL if successful, and an error string if not. */
|
||||
extern const char *__re_compile_pattern
|
||||
_RE_ARGS ((const char *pattern, size_t length,
|
||||
struct re_pattern_buffer *buffer));
|
||||
extern const char *re_compile_pattern
|
||||
_RE_ARGS ((const char *pattern, size_t length,
|
||||
struct re_pattern_buffer *buffer));
|
||||
|
||||
|
||||
/* Compile a fastmap for the compiled pattern in BUFFER; used to
|
||||
accelerate searches. Return 0 if successful and -2 if was an
|
||||
internal error. */
|
||||
extern int __re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
|
||||
extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
|
||||
|
||||
|
||||
/* Search in the string STRING (with length LENGTH) for the pattern
|
||||
compiled into BUFFER. Start searching at position START, for RANGE
|
||||
characters. Return the starting position of the match, -1 for no
|
||||
match, or -2 for an internal error. Also return register
|
||||
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
|
||||
extern int __re_search
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
|
||||
int length, int start, int range, struct re_registers *regs));
|
||||
extern int re_search
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
|
||||
int length, int start, int range, struct re_registers *regs));
|
||||
|
||||
|
||||
/* Like `re_search', but search in the concatenation of STRING1 and
|
||||
STRING2. Also, stop searching at index START + STOP. */
|
||||
extern int __re_search_2
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
|
||||
int length1, const char *string2, int length2,
|
||||
int start, int range, struct re_registers *regs, int stop));
|
||||
extern int re_search_2
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
|
||||
int length1, const char *string2, int length2,
|
||||
int start, int range, struct re_registers *regs, int stop));
|
||||
|
||||
|
||||
/* Like `re_search', but return how many characters in STRING the regexp
|
||||
in BUFFER matched, starting at position START. */
|
||||
extern int __re_match
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
|
||||
int length, int start, struct re_registers *regs));
|
||||
extern int re_match
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
|
||||
int length, int start, struct re_registers *regs));
|
||||
|
||||
|
||||
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
|
||||
extern int __re_match_2
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
|
||||
int length1, const char *string2, int length2,
|
||||
int start, struct re_registers *regs, int stop));
|
||||
extern int re_match_2
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
|
||||
int length1, const char *string2, int length2,
|
||||
int start, struct re_registers *regs, int stop));
|
||||
|
||||
|
||||
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
|
||||
ENDS. Subsequent matches using BUFFER and REGS will use this memory
|
||||
for recording register information. STARTS and ENDS must be
|
||||
allocated with malloc, and must each be at least `NUM_REGS * sizeof
|
||||
(regoff_t)' bytes long.
|
||||
|
||||
If NUM_REGS == 0, then subsequent matches should allocate their own
|
||||
register data.
|
||||
|
||||
Unless this function is called, the first search or match using
|
||||
PATTERN_BUFFER will allocate its own register data, without
|
||||
freeing the old data. */
|
||||
extern void __re_set_registers
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
|
||||
unsigned num_regs, regoff_t *starts, regoff_t *ends));
|
||||
extern void re_set_registers
|
||||
_RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
|
||||
unsigned num_regs, regoff_t *starts, regoff_t *ends));
|
||||
|
||||
#ifdef _REGEX_RE_COMP
|
||||
# ifndef _CRAY
|
||||
/* 4.2 bsd compatibility. */
|
||||
extern char *re_comp _RE_ARGS ((const char *));
|
||||
extern int re_exec _RE_ARGS ((const char *));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX compatibility. */
|
||||
extern int __regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
|
||||
int __cflags));
|
||||
extern int regcomp _RE_ARGS ((regex_t *__preg, const char *__pattern,
|
||||
int __cflags));
|
||||
|
||||
extern int __regexec _RE_ARGS ((const regex_t *__preg,
|
||||
const char *__string, size_t __nmatch,
|
||||
regmatch_t __pmatch[], int __eflags));
|
||||
extern int regexec _RE_ARGS ((const regex_t *__preg,
|
||||
const char *__string, size_t __nmatch,
|
||||
regmatch_t __pmatch[], int __eflags));
|
||||
|
||||
extern size_t __regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
|
||||
char *__errbuf, size_t __errbuf_size));
|
||||
extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg,
|
||||
char *__errbuf, size_t __errbuf_size));
|
||||
|
||||
extern void __regfree _RE_ARGS ((regex_t *__preg));
|
||||
extern void regfree _RE_ARGS ((regex_t *__preg));
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
#endif /* regex.h */
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
make-backup-files: t
|
||||
version-control: t
|
||||
trim-versions-without-asking: nil
|
||||
End:
|
||||
*/
|
@ -1,35 +0,0 @@
|
||||
/* Host-dependent code for dos running GO32 for GDB, the GNU debugger.
|
||||
Copyright 1992 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
sigsetmask (mask)
|
||||
int mask;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
strlwr (str)
|
||||
char *str;
|
||||
{
|
||||
for (; *str; str++)
|
||||
*str = tolower(*str);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,150 +0,0 @@
|
||||
/* hpread.h
|
||||
* Common include file for:
|
||||
* hp_symtab_read.c
|
||||
* hp_psymtab_read.c
|
||||
*/
|
||||
|
||||
/* Copyright 1993, 1996 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Written by the Center for Software Science at the University of Utah
|
||||
and by Cygnus Support. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "bfd.h"
|
||||
#include "gdb_string.h"
|
||||
#include "hp-symtab.h"
|
||||
#include "syms.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
#include "buildsym.h"
|
||||
#include "complaints.h"
|
||||
#include "gdb-stabs.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "demangle.h"
|
||||
|
||||
/* Private information attached to an objfile which we use to find
|
||||
and internalize the HP C debug symbols within that objfile. */
|
||||
|
||||
struct hpread_symfile_info
|
||||
{
|
||||
/* The contents of each of the debug sections (there are 4 of them). */
|
||||
char *gntt;
|
||||
char *lntt;
|
||||
char *slt;
|
||||
char *vt;
|
||||
|
||||
/* We keep the size of the $VT$ section for range checking. */
|
||||
unsigned int vt_size;
|
||||
|
||||
/* Some routines still need to know the number of symbols in the
|
||||
main debug sections ($LNTT$ and $GNTT$). */
|
||||
unsigned int lntt_symcount;
|
||||
unsigned int gntt_symcount;
|
||||
|
||||
/* To keep track of all the types we've processed. */
|
||||
struct type **type_vector;
|
||||
int type_vector_length;
|
||||
|
||||
/* Keeps track of the beginning of a range of source lines. */
|
||||
sltpointer sl_index;
|
||||
|
||||
/* Some state variables we'll need. */
|
||||
int within_function;
|
||||
|
||||
/* Keep track of the current function's address. We may need to look
|
||||
up something based on this address. */
|
||||
unsigned int current_function_value;
|
||||
};
|
||||
|
||||
/* Accessor macros to get at the fields. */
|
||||
#define HPUX_SYMFILE_INFO(o) \
|
||||
((struct hpread_symfile_info *)((o)->sym_private))
|
||||
#define GNTT(o) (HPUX_SYMFILE_INFO(o)->gntt)
|
||||
#define LNTT(o) (HPUX_SYMFILE_INFO(o)->lntt)
|
||||
#define SLT(o) (HPUX_SYMFILE_INFO(o)->slt)
|
||||
#define VT(o) (HPUX_SYMFILE_INFO(o)->vt)
|
||||
#define VT_SIZE(o) (HPUX_SYMFILE_INFO(o)->vt_size)
|
||||
#define LNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->lntt_symcount)
|
||||
#define GNTT_SYMCOUNT(o) (HPUX_SYMFILE_INFO(o)->gntt_symcount)
|
||||
#define TYPE_VECTOR(o) (HPUX_SYMFILE_INFO(o)->type_vector)
|
||||
#define TYPE_VECTOR_LENGTH(o) (HPUX_SYMFILE_INFO(o)->type_vector_length)
|
||||
#define SL_INDEX(o) (HPUX_SYMFILE_INFO(o)->sl_index)
|
||||
#define WITHIN_FUNCTION(o) (HPUX_SYMFILE_INFO(o)->within_function)
|
||||
#define CURRENT_FUNCTION_VALUE(o) (HPUX_SYMFILE_INFO(o)->current_function_value)
|
||||
|
||||
/* Given the native debug symbol SYM, set NAMEP to the name associated
|
||||
with the debug symbol. Note we may be called with a debug symbol which
|
||||
has no associated name, in that case we return an empty string.
|
||||
|
||||
Also note we "know" that the name for any symbol is always in the
|
||||
same place. Hence we don't have to conditionalize on the symbol type. */
|
||||
#define SET_NAMESTRING(SYM, NAMEP, OBJFILE) \
|
||||
if (! hpread_has_name ((SYM)->dblock.kind)) \
|
||||
*NAMEP = ""; \
|
||||
else if (((unsigned)(SYM)->dsfile.name) >= VT_SIZE (OBJFILE)) \
|
||||
{ \
|
||||
complain (&string_table_offset_complaint, (char *) symnum); \
|
||||
*NAMEP = ""; \
|
||||
} \
|
||||
else \
|
||||
*NAMEP = (SYM)->dsfile.name + VT (OBJFILE)
|
||||
|
||||
/* We put a pointer to this structure in the read_symtab_private field
|
||||
of the psymtab. */
|
||||
|
||||
struct symloc
|
||||
{
|
||||
/* The offset within the file symbol table of first local symbol for
|
||||
this file. */
|
||||
|
||||
int ldsymoff;
|
||||
|
||||
/* Length (in bytes) of the section of the symbol table devoted to
|
||||
this file's symbols (actually, the section bracketed may contain
|
||||
more than just this file's symbols). If ldsymlen is 0, the only
|
||||
reason for this thing's existence is the dependency list.
|
||||
Nothing else will happen when it is read in. */
|
||||
|
||||
int ldsymlen;
|
||||
};
|
||||
|
||||
#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
|
||||
#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
|
||||
#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
|
||||
|
||||
/* FIXME: Shouldn't this stuff be in a .h file somewhere? */
|
||||
/* Nonzero means give verbose info on gdb action. */
|
||||
extern int info_verbose;
|
||||
|
||||
/* Complaints about the symbols we have encountered. */
|
||||
extern struct complaint string_table_offset_complaint;
|
||||
extern struct complaint lbrac_unmatched_complaint;
|
||||
extern struct complaint lbrac_mismatch_complaint;
|
||||
|
||||
extern union sltentry *hpread_get_slt
|
||||
PARAMS ((int, struct objfile *));
|
||||
|
||||
extern union dnttentry *hpread_get_lntt
|
||||
PARAMS ((int, struct objfile *));
|
||||
|
||||
int hpread_has_name
|
||||
PARAMS ((enum dntt_entry_type));
|
||||
|
||||
/* end of hpread.h */
|
@ -1,271 +0,0 @@
|
||||
/* Low level interface to i386 running the GNU Hurd.
|
||||
Copyright 1992, 1995, 1996, 1998, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "floatformat.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mach.h>
|
||||
#include <mach_error.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/exception.h>
|
||||
|
||||
#include "i386-tdep.h"
|
||||
|
||||
#include "gnu-nat.h"
|
||||
#include "i387-nat.h"
|
||||
|
||||
|
||||
/* Offset to the thread_state_t location where REG is stored. */
|
||||
#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
|
||||
|
||||
/* At REG_OFFSET[N] is the offset to the thread_state_t location where
|
||||
the GDB register N is stored. */
|
||||
static int reg_offset[] =
|
||||
{
|
||||
REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
|
||||
REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
|
||||
REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
|
||||
REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
|
||||
};
|
||||
|
||||
#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
|
||||
|
||||
|
||||
/* Get the whole floating-point state of THREAD and record the
|
||||
values of the corresponding (pseudo) registers. */
|
||||
static void
|
||||
fetch_fpregs (struct proc *thread)
|
||||
{
|
||||
mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
|
||||
struct i386_float_state state;
|
||||
error_t err;
|
||||
|
||||
err = thread_get_state (thread->port, i386_FLOAT_STATE,
|
||||
(thread_state_t) &state, &count);
|
||||
if (err)
|
||||
{
|
||||
warning ("Couldn't fetch floating-point state from %s",
|
||||
proc_string (thread));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.initialized)
|
||||
/* The floating-point state isn't initialized. */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i <= FOP_REGNUM; i++)
|
||||
supply_register (i, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Supply the floating-point registers. */
|
||||
i387_supply_fsave (state.hw_state);
|
||||
}
|
||||
|
||||
/* Fetch register REGNO, or all regs if REGNO is -1. */
|
||||
void
|
||||
gnu_fetch_registers (int regno)
|
||||
{
|
||||
struct proc *thread;
|
||||
|
||||
/* Make sure we know about new threads. */
|
||||
inf_update_procs (current_inferior);
|
||||
|
||||
thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
|
||||
if (!thread)
|
||||
error ("Can't fetch registers from thread %d: No such thread",
|
||||
PIDGET (inferior_ptid));
|
||||
|
||||
if (regno < NUM_GREGS || regno == -1)
|
||||
{
|
||||
thread_state_t state;
|
||||
|
||||
/* This does the dirty work for us. */
|
||||
state = proc_get_state (thread, 0);
|
||||
if (!state)
|
||||
{
|
||||
warning ("Couldn't fetch registers from %s",
|
||||
proc_string (thread));
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
proc_debug (thread, "fetching all register");
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
supply_register (i, REG_ADDR (state, i));
|
||||
thread->fetched_regs = ~0;
|
||||
}
|
||||
else
|
||||
{
|
||||
proc_debug (thread, "fetching register %s", REGISTER_NAME (regno));
|
||||
|
||||
supply_register (regno, REG_ADDR (state, regno));
|
||||
thread->fetched_regs |= (1 << regno);
|
||||
}
|
||||
}
|
||||
|
||||
if (regno >= NUM_GREGS || regno == -1)
|
||||
{
|
||||
proc_debug (thread, "fetching floating-point registers");
|
||||
|
||||
fetch_fpregs (thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Store the whole floating-point state into THREAD using information
|
||||
from the corresponding (pseudo) registers. */
|
||||
static void
|
||||
store_fpregs (struct proc *thread, int regno)
|
||||
{
|
||||
mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
|
||||
struct i386_float_state state;
|
||||
error_t err;
|
||||
|
||||
err = thread_get_state (thread->port, i386_FLOAT_STATE,
|
||||
(thread_state_t) &state, &count);
|
||||
if (err)
|
||||
{
|
||||
warning ("Couldn't fetch floating-point state from %s",
|
||||
proc_string (thread));
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: kettenis/2001-07-15: Is this right? Should we somehow
|
||||
take into account REGISTER_VALID like the old code did? */
|
||||
i387_fill_fsave (state.hw_state, regno);
|
||||
|
||||
err = thread_set_state (thread->port, i386_FLOAT_STATE,
|
||||
(thread_state_t) &state, i386_FLOAT_STATE_COUNT);
|
||||
if (err)
|
||||
{
|
||||
warning ("Couldn't store floating-point state into %s",
|
||||
proc_string (thread));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store at least register REGNO, or all regs if REGNO == -1. */
|
||||
void
|
||||
gnu_store_registers (int regno)
|
||||
{
|
||||
struct proc *thread;
|
||||
|
||||
/* Make sure we know about new threads. */
|
||||
inf_update_procs (current_inferior);
|
||||
|
||||
thread = inf_tid_to_thread (current_inferior, PIDGET (inferior_ptid));
|
||||
if (!thread)
|
||||
error ("Couldn't store registers into thread %d: No such thread",
|
||||
PIDGET (inferior_ptid));
|
||||
|
||||
if (regno < NUM_GREGS || regno == -1)
|
||||
{
|
||||
thread_state_t state;
|
||||
thread_state_data_t old_state;
|
||||
int was_aborted = thread->aborted;
|
||||
int was_valid = thread->state_valid;
|
||||
int trace;
|
||||
|
||||
if (!was_aborted && was_valid)
|
||||
memcpy (&old_state, &thread->state, sizeof (old_state));
|
||||
|
||||
state = proc_get_state (thread, 1);
|
||||
if (!state)
|
||||
{
|
||||
warning ("Couldn't store registers into %s", proc_string (thread));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the T bit. We might try to restore the %eflags register
|
||||
below, but changing the T bit would seriously confuse GDB. */
|
||||
trace = ((struct i386_thread_state *)state)->efl & 0x100;
|
||||
|
||||
if (!was_aborted && was_valid)
|
||||
/* See which registers have changed after aborting the thread. */
|
||||
{
|
||||
int check_regno;
|
||||
|
||||
for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
|
||||
if ((thread->fetched_regs & (1 << check_regno))
|
||||
&& memcpy (REG_ADDR (&old_state, check_regno),
|
||||
REG_ADDR (state, check_regno),
|
||||
REGISTER_RAW_SIZE (check_regno)))
|
||||
/* Register CHECK_REGNO has changed! Ack! */
|
||||
{
|
||||
warning ("Register %s changed after the thread was aborted",
|
||||
REGISTER_NAME (check_regno));
|
||||
if (regno >= 0 && regno != check_regno)
|
||||
/* Update GDB's copy of the register. */
|
||||
supply_register (check_regno, REG_ADDR (state, check_regno));
|
||||
else
|
||||
warning ("... also writing this register! Suspicious...");
|
||||
}
|
||||
}
|
||||
|
||||
#define fill(state, regno) \
|
||||
memcpy (REG_ADDR(state, regno), ®isters[REGISTER_BYTE (regno)], \
|
||||
REGISTER_RAW_SIZE (regno))
|
||||
|
||||
if (regno == -1)
|
||||
{
|
||||
int i;
|
||||
|
||||
proc_debug (thread, "storing all registers");
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
if (register_valid[i])
|
||||
fill (state, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
proc_debug (thread, "storing register %s", REGISTER_NAME (regno));
|
||||
|
||||
gdb_assert (register_valid[regno]);
|
||||
fill (state, regno);
|
||||
}
|
||||
|
||||
/* Restore the T bit. */
|
||||
((struct i386_thread_state *)state)->efl &= ~0x100;
|
||||
((struct i386_thread_state *)state)->efl |= trace;
|
||||
}
|
||||
|
||||
#undef fill
|
||||
|
||||
if (regno >= NUM_GREGS || regno == -1)
|
||||
{
|
||||
proc_debug (thread, "storing floating-point registers");
|
||||
|
||||
store_fpregs (thread, regno);
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
/* Native support for the SGI Iris running IRIX version 4, for GDB.
|
||||
Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2000,
|
||||
2001 Free Software Foundation, Inc.
|
||||
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
|
||||
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
|
||||
Implemented for Irix 4.x by Garrett A. Wollman.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/procfs.h>
|
||||
#include <setjmp.h> /* For JB_XXX. */
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/* Size of elements in jmpbuf */
|
||||
|
||||
#define JB_ELEMENT_SIZE 4
|
||||
|
||||
typedef unsigned int greg_t; /* why isn't this defined? */
|
||||
|
||||
static void fetch_core_registers (char *, unsigned int, int, CORE_ADDR);
|
||||
|
||||
/*
|
||||
* See the comment in m68k-tdep.c regarding the utility of these functions.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) (gregsetp->gp_regs);
|
||||
static char zerobuf[MAX_REGISTER_RAW_SIZE] =
|
||||
{0};
|
||||
|
||||
/* FIXME: somewhere, there should be a #define for the meaning
|
||||
of this magic number 32; we should use that. */
|
||||
for (regi = 0; regi < 32; regi++)
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
|
||||
supply_register (PC_REGNUM, (char *) &(gregsetp->gp_pc));
|
||||
supply_register (HI_REGNUM, (char *) &(gregsetp->gp_mdhi));
|
||||
supply_register (LO_REGNUM, (char *) &(gregsetp->gp_mdlo));
|
||||
supply_register (CAUSE_REGNUM, (char *) &(gregsetp->gp_cause));
|
||||
|
||||
/* Fill inaccessible registers with zero. */
|
||||
supply_register (BADVADDR_REGNUM, zerobuf);
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
register greg_t *regp = (greg_t *) (gregsetp->gp_regs);
|
||||
|
||||
/* same FIXME as above wrt 32 */
|
||||
for (regi = 0; regi < 32; regi++)
|
||||
if ((regno == -1) || (regno == regi))
|
||||
*(regp + regi) = *(greg_t *) & registers[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == PC_REGNUM))
|
||||
gregsetp->gp_pc = *(greg_t *) & registers[REGISTER_BYTE (PC_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == CAUSE_REGNUM))
|
||||
gregsetp->gp_cause = *(greg_t *) & registers[REGISTER_BYTE (CAUSE_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == HI_REGNUM))
|
||||
gregsetp->gp_mdhi = *(greg_t *) & registers[REGISTER_BYTE (HI_REGNUM)];
|
||||
|
||||
if ((regno == -1) || (regno == LO_REGNUM))
|
||||
gregsetp->gp_mdlo = *(greg_t *) & registers[REGISTER_BYTE (LO_REGNUM)];
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we do the same thing for floating-point registers.
|
||||
* We don't bother to condition on FP0_REGNUM since any
|
||||
* reasonable MIPS configuration has an R3010 in it.
|
||||
*
|
||||
* Again, see the comments in m68k-tdep.c.
|
||||
*/
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
register int regi;
|
||||
static char zerobuf[MAX_REGISTER_RAW_SIZE] =
|
||||
{0};
|
||||
|
||||
for (regi = 0; regi < 32; regi++)
|
||||
supply_register (FP0_REGNUM + regi,
|
||||
(char *) &fpregsetp->fp_r.fp_regs[regi]);
|
||||
|
||||
supply_register (FCRCS_REGNUM, (char *) &fpregsetp->fp_csr);
|
||||
|
||||
/* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
|
||||
supply_register (FCRIR_REGNUM, zerobuf);
|
||||
}
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
char *from, *to;
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
from = (char *) ®isters[REGISTER_BYTE (regi)];
|
||||
to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
|
||||
memcpy (to, from, REGISTER_RAW_SIZE (regi));
|
||||
}
|
||||
}
|
||||
|
||||
if ((regno == -1) || (regno == FCRCS_REGNUM))
|
||||
fpregsetp->fp_csr = *(unsigned *) ®isters[REGISTER_BYTE (FCRCS_REGNUM)];
|
||||
}
|
||||
|
||||
|
||||
/* Figure out where the longjmp will land.
|
||||
We expect the first arg to be a pointer to the jmp_buf structure from which
|
||||
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
|
||||
This routine returns true on success. */
|
||||
|
||||
int
|
||||
get_longjmp_target (CORE_ADDR *pc)
|
||||
{
|
||||
char *buf;
|
||||
CORE_ADDR jb_addr;
|
||||
|
||||
buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
jb_addr = read_register (A0_REGNUM);
|
||||
|
||||
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Provide registers to GDB from a core file.
|
||||
|
||||
CORE_REG_SECT points to an array of bytes, which were obtained from
|
||||
a core file which BFD thinks might contain register contents.
|
||||
CORE_REG_SIZE is its size.
|
||||
|
||||
Normally, WHICH says which register set corelow suspects this is:
|
||||
0 --- the general-purpose register set
|
||||
2 --- the floating-point register set
|
||||
However, for Irix 4, WHICH isn't used.
|
||||
|
||||
REG_ADDR is also unused. */
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR reg_addr)
|
||||
{
|
||||
if (core_reg_size != REGISTER_BYTES)
|
||||
{
|
||||
warning ("wrong size gregset struct in core file");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy ((char *) registers, core_reg_sect, core_reg_size);
|
||||
}
|
||||
|
||||
|
||||
/* Register that we are able to handle irix4 core file formats.
|
||||
FIXME: is this really bfd_target_unknown_flavour? */
|
||||
|
||||
static struct core_fns irix4_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_core_irix4 (void)
|
||||
{
|
||||
add_core_fns (&irix4_core_fns);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,20 +0,0 @@
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <machine/reg.h>
|
||||
int rloc[] = {
|
||||
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, FP, SP, PS, PC
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,38 +0,0 @@
|
||||
/* Main loop for the standalone kernel debugger, for GDB, the GNU Debugger.
|
||||
Copyright 1989, 1991, 1992 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
static char *args[] =
|
||||
{"kdb", "kdb-symbols", 0};
|
||||
|
||||
static char *environment[] =
|
||||
{0};
|
||||
|
||||
char **environ;
|
||||
|
||||
start ()
|
||||
{
|
||||
INIT_STACK (kdb_stack_beg, kdb_stack_end);
|
||||
|
||||
environ = environment;
|
||||
|
||||
main (2, args, environment);
|
||||
}
|
@ -1,829 +0,0 @@
|
||||
/* Native-dependent code for LynxOS.
|
||||
Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "target.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/fpp.h>
|
||||
|
||||
static unsigned long registers_addr (int pid);
|
||||
static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
|
||||
|
||||
#define X(ENTRY)(offsetof(struct econtext, ENTRY))
|
||||
|
||||
#ifdef I386
|
||||
/* Mappings from tm-i386v.h */
|
||||
|
||||
static int regmap[] =
|
||||
{
|
||||
X (eax),
|
||||
X (ecx),
|
||||
X (edx),
|
||||
X (ebx),
|
||||
X (esp), /* sp */
|
||||
X (ebp), /* fp */
|
||||
X (esi),
|
||||
X (edi),
|
||||
X (eip), /* pc */
|
||||
X (flags), /* ps */
|
||||
X (cs),
|
||||
X (ss),
|
||||
X (ds),
|
||||
X (es),
|
||||
X (ecode), /* Lynx doesn't give us either fs or gs, so */
|
||||
X (fault), /* we just substitute these two in the hopes
|
||||
that they are useful. */
|
||||
};
|
||||
#endif /* I386 */
|
||||
|
||||
#ifdef M68K
|
||||
/* Mappings from tm-m68k.h */
|
||||
|
||||
static int regmap[] =
|
||||
{
|
||||
X (regs[0]), /* d0 */
|
||||
X (regs[1]), /* d1 */
|
||||
X (regs[2]), /* d2 */
|
||||
X (regs[3]), /* d3 */
|
||||
X (regs[4]), /* d4 */
|
||||
X (regs[5]), /* d5 */
|
||||
X (regs[6]), /* d6 */
|
||||
X (regs[7]), /* d7 */
|
||||
X (regs[8]), /* a0 */
|
||||
X (regs[9]), /* a1 */
|
||||
X (regs[10]), /* a2 */
|
||||
X (regs[11]), /* a3 */
|
||||
X (regs[12]), /* a4 */
|
||||
X (regs[13]), /* a5 */
|
||||
X (regs[14]), /* fp */
|
||||
offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
|
||||
X (status), /* ps */
|
||||
X (pc),
|
||||
|
||||
X (fregs[0 * 3]), /* fp0 */
|
||||
X (fregs[1 * 3]), /* fp1 */
|
||||
X (fregs[2 * 3]), /* fp2 */
|
||||
X (fregs[3 * 3]), /* fp3 */
|
||||
X (fregs[4 * 3]), /* fp4 */
|
||||
X (fregs[5 * 3]), /* fp5 */
|
||||
X (fregs[6 * 3]), /* fp6 */
|
||||
X (fregs[7 * 3]), /* fp7 */
|
||||
|
||||
X (fcregs[0]), /* fpcontrol */
|
||||
X (fcregs[1]), /* fpstatus */
|
||||
X (fcregs[2]), /* fpiaddr */
|
||||
X (ssw), /* fpcode */
|
||||
X (fault), /* fpflags */
|
||||
};
|
||||
#endif /* M68K */
|
||||
|
||||
#ifdef SPARC
|
||||
/* Mappings from tm-sparc.h */
|
||||
|
||||
#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
|
||||
|
||||
static int regmap[] =
|
||||
{
|
||||
-1, /* g0 */
|
||||
X (g1),
|
||||
X (g2),
|
||||
X (g3),
|
||||
X (g4),
|
||||
-1, /* g5->g7 aren't saved by Lynx */
|
||||
-1,
|
||||
-1,
|
||||
|
||||
X (o[0]),
|
||||
X (o[1]),
|
||||
X (o[2]),
|
||||
X (o[3]),
|
||||
X (o[4]),
|
||||
X (o[5]),
|
||||
X (o[6]), /* sp */
|
||||
X (o[7]), /* ra */
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, /* l0 -> l7 */
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, /* i0 -> i7 */
|
||||
|
||||
FX (f.fregs[0]), /* f0 */
|
||||
FX (f.fregs[1]),
|
||||
FX (f.fregs[2]),
|
||||
FX (f.fregs[3]),
|
||||
FX (f.fregs[4]),
|
||||
FX (f.fregs[5]),
|
||||
FX (f.fregs[6]),
|
||||
FX (f.fregs[7]),
|
||||
FX (f.fregs[8]),
|
||||
FX (f.fregs[9]),
|
||||
FX (f.fregs[10]),
|
||||
FX (f.fregs[11]),
|
||||
FX (f.fregs[12]),
|
||||
FX (f.fregs[13]),
|
||||
FX (f.fregs[14]),
|
||||
FX (f.fregs[15]),
|
||||
FX (f.fregs[16]),
|
||||
FX (f.fregs[17]),
|
||||
FX (f.fregs[18]),
|
||||
FX (f.fregs[19]),
|
||||
FX (f.fregs[20]),
|
||||
FX (f.fregs[21]),
|
||||
FX (f.fregs[22]),
|
||||
FX (f.fregs[23]),
|
||||
FX (f.fregs[24]),
|
||||
FX (f.fregs[25]),
|
||||
FX (f.fregs[26]),
|
||||
FX (f.fregs[27]),
|
||||
FX (f.fregs[28]),
|
||||
FX (f.fregs[29]),
|
||||
FX (f.fregs[30]),
|
||||
FX (f.fregs[31]),
|
||||
|
||||
X (y),
|
||||
X (psr),
|
||||
X (wim),
|
||||
X (tbr),
|
||||
X (pc),
|
||||
X (npc),
|
||||
FX (fsr), /* fpsr */
|
||||
-1, /* cpsr */
|
||||
};
|
||||
#endif /* SPARC */
|
||||
|
||||
#ifdef rs6000
|
||||
|
||||
static int regmap[] =
|
||||
{
|
||||
X (iregs[0]), /* r0 */
|
||||
X (iregs[1]),
|
||||
X (iregs[2]),
|
||||
X (iregs[3]),
|
||||
X (iregs[4]),
|
||||
X (iregs[5]),
|
||||
X (iregs[6]),
|
||||
X (iregs[7]),
|
||||
X (iregs[8]),
|
||||
X (iregs[9]),
|
||||
X (iregs[10]),
|
||||
X (iregs[11]),
|
||||
X (iregs[12]),
|
||||
X (iregs[13]),
|
||||
X (iregs[14]),
|
||||
X (iregs[15]),
|
||||
X (iregs[16]),
|
||||
X (iregs[17]),
|
||||
X (iregs[18]),
|
||||
X (iregs[19]),
|
||||
X (iregs[20]),
|
||||
X (iregs[21]),
|
||||
X (iregs[22]),
|
||||
X (iregs[23]),
|
||||
X (iregs[24]),
|
||||
X (iregs[25]),
|
||||
X (iregs[26]),
|
||||
X (iregs[27]),
|
||||
X (iregs[28]),
|
||||
X (iregs[29]),
|
||||
X (iregs[30]),
|
||||
X (iregs[31]),
|
||||
|
||||
X (fregs[0]), /* f0 */
|
||||
X (fregs[1]),
|
||||
X (fregs[2]),
|
||||
X (fregs[3]),
|
||||
X (fregs[4]),
|
||||
X (fregs[5]),
|
||||
X (fregs[6]),
|
||||
X (fregs[7]),
|
||||
X (fregs[8]),
|
||||
X (fregs[9]),
|
||||
X (fregs[10]),
|
||||
X (fregs[11]),
|
||||
X (fregs[12]),
|
||||
X (fregs[13]),
|
||||
X (fregs[14]),
|
||||
X (fregs[15]),
|
||||
X (fregs[16]),
|
||||
X (fregs[17]),
|
||||
X (fregs[18]),
|
||||
X (fregs[19]),
|
||||
X (fregs[20]),
|
||||
X (fregs[21]),
|
||||
X (fregs[22]),
|
||||
X (fregs[23]),
|
||||
X (fregs[24]),
|
||||
X (fregs[25]),
|
||||
X (fregs[26]),
|
||||
X (fregs[27]),
|
||||
X (fregs[28]),
|
||||
X (fregs[29]),
|
||||
X (fregs[30]),
|
||||
X (fregs[31]),
|
||||
|
||||
X (srr0), /* IAR (PC) */
|
||||
X (srr1), /* MSR (PS) */
|
||||
X (cr), /* CR */
|
||||
X (lr), /* LR */
|
||||
X (ctr), /* CTR */
|
||||
X (xer), /* XER */
|
||||
X (mq) /* MQ */
|
||||
};
|
||||
|
||||
#endif /* rs6000 */
|
||||
|
||||
#ifdef SPARC
|
||||
|
||||
/* This routine handles some oddball cases for Sparc registers and LynxOS.
|
||||
In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
|
||||
It also handles knows where to find the I & L regs on the stack. */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
int whatregs = 0;
|
||||
|
||||
#define WHATREGS_FLOAT 1
|
||||
#define WHATREGS_GEN 2
|
||||
#define WHATREGS_STACK 4
|
||||
|
||||
if (regno == -1)
|
||||
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
|
||||
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||
whatregs = WHATREGS_STACK;
|
||||
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
|
||||
whatregs = WHATREGS_FLOAT;
|
||||
else
|
||||
whatregs = WHATREGS_GEN;
|
||||
|
||||
if (whatregs & WHATREGS_GEN)
|
||||
{
|
||||
struct econtext ec; /* general regs */
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & ec, 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_GETREGS)");
|
||||
|
||||
memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
|
||||
supply_register (G0_REGNUM, buf);
|
||||
supply_register (TBR_REGNUM, (char *) &ec.tbr);
|
||||
|
||||
memcpy (®isters[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
|
||||
4 * REGISTER_RAW_SIZE (G1_REGNUM));
|
||||
for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
|
||||
register_valid[i] = 1;
|
||||
|
||||
supply_register (PS_REGNUM, (char *) &ec.psr);
|
||||
supply_register (Y_REGNUM, (char *) &ec.y);
|
||||
supply_register (PC_REGNUM, (char *) &ec.pc);
|
||||
supply_register (NPC_REGNUM, (char *) &ec.npc);
|
||||
supply_register (WIM_REGNUM, (char *) &ec.wim);
|
||||
|
||||
memcpy (®isters[REGISTER_BYTE (O0_REGNUM)], ec.o,
|
||||
8 * REGISTER_RAW_SIZE (O0_REGNUM));
|
||||
for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
|
||||
register_valid[i] = 1;
|
||||
}
|
||||
|
||||
if (whatregs & WHATREGS_STACK)
|
||||
{
|
||||
CORE_ADDR sp;
|
||||
int i;
|
||||
|
||||
sp = read_register (SP_REGNUM);
|
||||
|
||||
target_read_memory (sp + FRAME_SAVED_I0,
|
||||
®isters[REGISTER_BYTE (I0_REGNUM)],
|
||||
8 * REGISTER_RAW_SIZE (I0_REGNUM));
|
||||
for (i = I0_REGNUM; i <= I7_REGNUM; i++)
|
||||
register_valid[i] = 1;
|
||||
|
||||
target_read_memory (sp + FRAME_SAVED_L0,
|
||||
®isters[REGISTER_BYTE (L0_REGNUM)],
|
||||
8 * REGISTER_RAW_SIZE (L0_REGNUM));
|
||||
for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
|
||||
register_valid[i] = 1;
|
||||
}
|
||||
|
||||
if (whatregs & WHATREGS_FLOAT)
|
||||
{
|
||||
struct fcontext fc; /* fp regs */
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & fc, 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_GETFPREGS)");
|
||||
|
||||
memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
|
||||
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
||||
for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
|
||||
register_valid[i] = 1;
|
||||
|
||||
supply_register (FPS_REGNUM, (char *) &fc.fsr);
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine handles storing of the I & L regs for the Sparc. The trick
|
||||
here is that they actually live on the stack. The really tricky part is
|
||||
that when changing the stack pointer, the I & L regs must be written to
|
||||
where the new SP points, otherwise the regs will be incorrect when the
|
||||
process is started up again. We assume that the I & L regs are valid at
|
||||
this point. */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
int whatregs = 0;
|
||||
|
||||
if (regno == -1)
|
||||
whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
|
||||
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||
whatregs = WHATREGS_STACK;
|
||||
else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
|
||||
whatregs = WHATREGS_FLOAT;
|
||||
else if (regno == SP_REGNUM)
|
||||
whatregs = WHATREGS_STACK | WHATREGS_GEN;
|
||||
else
|
||||
whatregs = WHATREGS_GEN;
|
||||
|
||||
if (whatregs & WHATREGS_GEN)
|
||||
{
|
||||
struct econtext ec; /* general regs */
|
||||
int retval;
|
||||
|
||||
ec.tbr = read_register (TBR_REGNUM);
|
||||
memcpy (&ec.g1, ®isters[REGISTER_BYTE (G1_REGNUM)],
|
||||
4 * REGISTER_RAW_SIZE (G1_REGNUM));
|
||||
|
||||
ec.psr = read_register (PS_REGNUM);
|
||||
ec.y = read_register (Y_REGNUM);
|
||||
ec.pc = read_register (PC_REGNUM);
|
||||
ec.npc = read_register (NPC_REGNUM);
|
||||
ec.wim = read_register (WIM_REGNUM);
|
||||
|
||||
memcpy (ec.o, ®isters[REGISTER_BYTE (O0_REGNUM)],
|
||||
8 * REGISTER_RAW_SIZE (O0_REGNUM));
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & ec, 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_SETREGS)");
|
||||
}
|
||||
|
||||
if (whatregs & WHATREGS_STACK)
|
||||
{
|
||||
int regoffset;
|
||||
CORE_ADDR sp;
|
||||
|
||||
sp = read_register (SP_REGNUM);
|
||||
|
||||
if (regno == -1 || regno == SP_REGNUM)
|
||||
{
|
||||
if (!register_valid[L0_REGNUM + 5])
|
||||
internal_error (__FILE__, __LINE__, "failed internal consistency check");
|
||||
target_write_memory (sp + FRAME_SAVED_I0,
|
||||
®isters[REGISTER_BYTE (I0_REGNUM)],
|
||||
8 * REGISTER_RAW_SIZE (I0_REGNUM));
|
||||
|
||||
target_write_memory (sp + FRAME_SAVED_L0,
|
||||
®isters[REGISTER_BYTE (L0_REGNUM)],
|
||||
8 * REGISTER_RAW_SIZE (L0_REGNUM));
|
||||
}
|
||||
else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
|
||||
{
|
||||
if (!register_valid[regno])
|
||||
internal_error (__FILE__, __LINE__, "failed internal consistency check");
|
||||
if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
|
||||
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
|
||||
+ FRAME_SAVED_L0;
|
||||
else
|
||||
regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
|
||||
+ FRAME_SAVED_I0;
|
||||
target_write_memory (sp + regoffset,
|
||||
®isters[REGISTER_BYTE (regno)],
|
||||
REGISTER_RAW_SIZE (regno));
|
||||
}
|
||||
}
|
||||
|
||||
if (whatregs & WHATREGS_FLOAT)
|
||||
{
|
||||
struct fcontext fc; /* fp regs */
|
||||
int retval;
|
||||
|
||||
/* We read fcontext first so that we can get good values for fq_t... */
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & fc, 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_GETFPREGS)");
|
||||
|
||||
memcpy (fc.f.fregs, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
32 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
||||
|
||||
fc.fsr = read_register (FPS_REGNUM);
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & fc, 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_SETFPREGS)");
|
||||
}
|
||||
}
|
||||
#endif /* SPARC */
|
||||
|
||||
#if defined (I386) || defined (M68K) || defined (rs6000)
|
||||
|
||||
/* Return the offset relative to the start of the per-thread data to the
|
||||
saved context block. */
|
||||
|
||||
static unsigned long
|
||||
registers_addr (int pid)
|
||||
{
|
||||
CORE_ADDR stblock;
|
||||
int ecpoff = offsetof (st_t, ecp);
|
||||
CORE_ADDR ecp;
|
||||
|
||||
errno = 0;
|
||||
stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_THREADUSER)");
|
||||
|
||||
ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) ecpoff,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
|
||||
|
||||
return ecp - stblock;
|
||||
}
|
||||
|
||||
/* Fetch one or more registers from the inferior. REGNO == -1 to get
|
||||
them all. We actually fetch more than requested, when convenient,
|
||||
marking them as valid so we won't fetch them again. */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
int reglo, reghi;
|
||||
int i;
|
||||
unsigned long ecp;
|
||||
|
||||
if (regno == -1)
|
||||
{
|
||||
reglo = 0;
|
||||
reghi = NUM_REGS - 1;
|
||||
}
|
||||
else
|
||||
reglo = reghi = regno;
|
||||
|
||||
ecp = registers_addr (PIDGET (inferior_ptid));
|
||||
|
||||
for (regno = reglo; regno <= reghi; regno++)
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
int ptrace_fun = PTRACE_PEEKTHREAD;
|
||||
|
||||
#ifdef M68K
|
||||
ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
errno = 0;
|
||||
reg = ptrace (ptrace_fun, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_PEEKUSP)");
|
||||
|
||||
*(int *) &buf[i] = reg;
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
int reglo, reghi;
|
||||
int i;
|
||||
unsigned long ecp;
|
||||
|
||||
if (regno == -1)
|
||||
{
|
||||
reglo = 0;
|
||||
reghi = NUM_REGS - 1;
|
||||
}
|
||||
else
|
||||
reglo = reghi = regno;
|
||||
|
||||
ecp = registers_addr (PIDGET (inferior_ptid));
|
||||
|
||||
for (regno = reglo; regno <= reghi; regno++)
|
||||
{
|
||||
int ptrace_fun = PTRACE_POKEUSER;
|
||||
|
||||
if (CANNOT_STORE_REGISTER (regno))
|
||||
continue;
|
||||
|
||||
#ifdef M68K
|
||||
ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = *(unsigned int *) ®isters[REGISTER_BYTE (regno) + i];
|
||||
|
||||
errno = 0;
|
||||
ptrace (ptrace_fun, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace(PTRACE_POKEUSP)");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
|
||||
|
||||
/* Wait for child to do something. Return pid of child, or -1 in case
|
||||
of error; store status through argument pointer OURSTATUS. */
|
||||
|
||||
ptid_t
|
||||
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
||||
{
|
||||
int save_errno;
|
||||
int thread;
|
||||
union wait status;
|
||||
int pid;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int sig;
|
||||
|
||||
set_sigint_trap (); /* Causes SIGINT to be passed on to the
|
||||
attached process. */
|
||||
pid = wait (&status);
|
||||
|
||||
save_errno = errno;
|
||||
|
||||
clear_sigint_trap ();
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
if (save_errno == EINTR)
|
||||
continue;
|
||||
fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
|
||||
safe_strerror (save_errno));
|
||||
/* Claim it exited with unknown signal. */
|
||||
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
||||
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid != PIDGET (inferior_ptid)) /* Some other process?!? */
|
||||
continue;
|
||||
|
||||
thread = status.w_tid; /* Get thread id from status */
|
||||
|
||||
/* Initial thread value can only be acquired via wait, so we have to
|
||||
resort to this hack. */
|
||||
|
||||
if (TIDGET (inferior_ptid) == 0 && thread != 0)
|
||||
{
|
||||
inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread);
|
||||
add_thread (inferior_ptid);
|
||||
}
|
||||
|
||||
ptid = BUILDPID (pid, thread);
|
||||
|
||||
/* We've become a single threaded process again. */
|
||||
if (thread == 0)
|
||||
inferior_ptid = ptid;
|
||||
|
||||
/* Check for thread creation. */
|
||||
if (WIFSTOPPED (status)
|
||||
&& WSTOPSIG (status) == SIGTRAP
|
||||
&& !in_thread_list (ptid))
|
||||
{
|
||||
int realsig;
|
||||
|
||||
realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
|
||||
(PTRACE_ARG3_TYPE) 0, 0);
|
||||
|
||||
if (realsig == SIGNEWTHREAD)
|
||||
{
|
||||
/* It's a new thread notification. We don't want to much with
|
||||
realsig -- the code in wait_for_inferior expects SIGTRAP. */
|
||||
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
|
||||
ourstatus->value.sig = TARGET_SIGNAL_0;
|
||||
return ptid;
|
||||
}
|
||||
else
|
||||
error ("Signal for unknown thread was not SIGNEWTHREAD");
|
||||
}
|
||||
|
||||
/* Check for thread termination. */
|
||||
else if (WIFSTOPPED (status)
|
||||
&& WSTOPSIG (status) == SIGTRAP
|
||||
&& in_thread_list (ptid))
|
||||
{
|
||||
int realsig;
|
||||
|
||||
realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
|
||||
(PTRACE_ARG3_TYPE) 0, 0);
|
||||
|
||||
if (realsig == SIGTHREADEXIT)
|
||||
{
|
||||
ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SPARC
|
||||
/* SPARC Lynx uses an byte reversed wait status; we must use the
|
||||
host macros to access it. These lines just a copy of
|
||||
store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
|
||||
because target.c can't include the Lynx <sys/wait.h>. */
|
||||
if (WIFEXITED (status))
|
||||
{
|
||||
ourstatus->kind = TARGET_WAITKIND_EXITED;
|
||||
ourstatus->value.integer = WEXITSTATUS (status);
|
||||
}
|
||||
else if (!WIFSTOPPED (status))
|
||||
{
|
||||
ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
|
||||
ourstatus->value.sig =
|
||||
target_signal_from_host (WTERMSIG (status));
|
||||
}
|
||||
else
|
||||
{
|
||||
ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
||||
ourstatus->value.sig =
|
||||
target_signal_from_host (WSTOPSIG (status));
|
||||
}
|
||||
#else
|
||||
store_waitstatus (ourstatus, status.w_status);
|
||||
#endif
|
||||
|
||||
return ptid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return nonzero if the given thread is still alive. */
|
||||
int
|
||||
child_thread_alive (ptid_t ptid)
|
||||
{
|
||||
int pid = PIDGET (ptid);
|
||||
|
||||
/* Arggh. Apparently pthread_kill only works for threads within
|
||||
the process that calls pthread_kill.
|
||||
|
||||
We want to avoid the lynx signal extensions as they simply don't
|
||||
map well to the generic gdb interface we want to keep.
|
||||
|
||||
All we want to do is determine if a particular thread is alive;
|
||||
it appears as if we can just make a harmless thread specific
|
||||
ptrace call to do that. */
|
||||
return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
|
||||
}
|
||||
|
||||
/* Resume execution of the inferior process.
|
||||
If STEP is nonzero, single-step it.
|
||||
If SIGNAL is nonzero, give it that signal. */
|
||||
|
||||
void
|
||||
child_resume (ptid_t ptid, int step, enum target_signal signal)
|
||||
{
|
||||
int func;
|
||||
int pid = PIDGET (ptid);
|
||||
|
||||
errno = 0;
|
||||
|
||||
/* If pid == -1, then we want to step/continue all threads, else
|
||||
we only want to step/continue a single thread. */
|
||||
if (pid == -1)
|
||||
{
|
||||
pid = PIDGET (inferior_ptid);
|
||||
func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
|
||||
}
|
||||
else
|
||||
func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
|
||||
|
||||
|
||||
/* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
|
||||
it was. (If GDB wanted it to start some other way, we have already
|
||||
written a new PC value to the child.)
|
||||
|
||||
If this system does not support PT_STEP, a higher level function will
|
||||
have called single_step() to transmute the step request into a
|
||||
continue request (by setting breakpoints on all possible successor
|
||||
instructions), so we don't have to worry about that here. */
|
||||
|
||||
ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
|
||||
|
||||
if (errno)
|
||||
perror_with_name ("ptrace");
|
||||
}
|
||||
|
||||
/* Convert a Lynx process ID to a string. Returns the string in a static
|
||||
buffer. */
|
||||
|
||||
char *
|
||||
child_pid_to_str (ptid_t ptid)
|
||||
{
|
||||
static char buf[40];
|
||||
|
||||
sprintf (buf, "process %d thread %d", PIDGET (ptid), TIDGET (ptid));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Extract the register values out of the core file and store
|
||||
them where `read_register' will find them.
|
||||
|
||||
CORE_REG_SECT points to the register values themselves, read into memory.
|
||||
CORE_REG_SIZE is the size of that area.
|
||||
WHICH says which set of registers we are handling (0 = int, 2 = float
|
||||
on machines where they are discontiguous).
|
||||
REG_ADDR is the offset from u.u_ar0 to the register values relative to
|
||||
core_reg_sect. This is used with old-fashioned core files to
|
||||
locate the registers in a large upage-plus-stack ".reg" section.
|
||||
Original upage address X is at location core_reg_sect+x+reg_addr.
|
||||
*/
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR reg_addr)
|
||||
{
|
||||
struct st_entry s;
|
||||
unsigned int regno;
|
||||
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
if (regmap[regno] != -1)
|
||||
supply_register (regno, core_reg_sect + offsetof (st_t, ec)
|
||||
+ regmap[regno]);
|
||||
|
||||
#ifdef SPARC
|
||||
/* Fetching this register causes all of the I & L regs to be read from the
|
||||
stack and validated. */
|
||||
|
||||
fetch_inferior_registers (I0_REGNUM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Register that we are able to handle lynx core file formats.
|
||||
FIXME: is this really bfd_target_unknown_flavour? */
|
||||
|
||||
static struct core_fns lynx_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_core_lynx (void)
|
||||
{
|
||||
add_core_fns (&lynx_core_fns);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,626 +0,0 @@
|
||||
/* Remote debugging interface to m32r and mon2000 ROM monitors for GDB,
|
||||
the GNU debugger.
|
||||
Copyright 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Adapted by Michael Snyder of Cygnus Support.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This module defines communication with the Mitsubishi m32r monitor */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "symtab.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "symfile.h" /* for generic load */
|
||||
#include <time.h> /* for time_t */
|
||||
#include "gdb_string.h"
|
||||
#include "objfiles.h" /* for ALL_OBJFILES etc. */
|
||||
#include "inferior.h" /* for write_pc() */
|
||||
#include <ctype.h>
|
||||
#include "regcache.h"
|
||||
|
||||
extern void report_transfer_performance (unsigned long, time_t, time_t);
|
||||
|
||||
/*
|
||||
* All this stuff just to get my host computer's IP address!
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h> /* for hostent */
|
||||
#include <netinet/in.h> /* for struct in_addr */
|
||||
#if 1
|
||||
#include <arpa/inet.h> /* for inet_ntoa */
|
||||
#endif
|
||||
|
||||
static char *board_addr; /* user-settable IP address for M32R-EVA */
|
||||
static char *server_addr; /* user-settable IP address for gdb host */
|
||||
static char *download_path; /* user-settable path for SREC files */
|
||||
|
||||
|
||||
/*
|
||||
* Function: m32r_load_1 (helper function)
|
||||
*/
|
||||
|
||||
static void
|
||||
m32r_load_section (bfd *abfd, asection *s, void *obj)
|
||||
{
|
||||
unsigned int *data_count = obj;
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
bfd_size_type section_size = bfd_section_size (abfd, s);
|
||||
bfd_vma section_base = bfd_section_lma (abfd, s);
|
||||
unsigned int buffer, i;
|
||||
|
||||
*data_count += section_size;
|
||||
|
||||
printf_filtered ("Loading section %s, size 0x%lx lma ",
|
||||
bfd_section_name (abfd, s), section_size);
|
||||
print_address_numeric (section_base, 1, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
monitor_printf ("%s mw\r", paddr_nz (section_base));
|
||||
for (i = 0; i < section_size; i += 4)
|
||||
{
|
||||
QUIT;
|
||||
monitor_expect (" -> ", NULL, 0);
|
||||
bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
|
||||
monitor_printf ("%x\n", buffer);
|
||||
}
|
||||
monitor_expect (" -> ", NULL, 0);
|
||||
monitor_printf ("q\n");
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
m32r_load_1 (void *dummy)
|
||||
{
|
||||
int data_count = 0;
|
||||
|
||||
bfd_map_over_sections ((bfd *) dummy, m32r_load_section, &data_count);
|
||||
return data_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: m32r_load (an alternate way to load)
|
||||
*/
|
||||
|
||||
static void
|
||||
m32r_load (char *filename, int from_tty)
|
||||
{
|
||||
bfd *abfd;
|
||||
asection *s;
|
||||
unsigned int i, data_count = 0;
|
||||
time_t start_time, end_time; /* for timing of download */
|
||||
|
||||
if (filename == NULL || filename[0] == 0)
|
||||
filename = get_exec_file (1);
|
||||
|
||||
abfd = bfd_openr (filename, 0);
|
||||
if (!abfd)
|
||||
error ("Unable to open file %s\n", filename);
|
||||
if (bfd_check_format (abfd, bfd_object) == 0)
|
||||
error ("File is not an object file\n");
|
||||
start_time = time (NULL);
|
||||
#if 0
|
||||
for (s = abfd->sections; s; s = s->next)
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
bfd_size_type section_size = bfd_section_size (abfd, s);
|
||||
bfd_vma section_base = bfd_section_vma (abfd, s);
|
||||
unsigned int buffer;
|
||||
|
||||
data_count += section_size;
|
||||
|
||||
printf_filtered ("Loading section %s, size 0x%lx vma ",
|
||||
bfd_section_name (abfd, s), section_size);
|
||||
print_address_numeric (section_base, 1, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
monitor_printf ("%x mw\r", section_base);
|
||||
for (i = 0; i < section_size; i += 4)
|
||||
{
|
||||
monitor_expect (" -> ", NULL, 0);
|
||||
bfd_get_section_contents (abfd, s, (char *) &buffer, i, 4);
|
||||
monitor_printf ("%x\n", buffer);
|
||||
}
|
||||
monitor_expect (" -> ", NULL, 0);
|
||||
monitor_printf ("q\n");
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
}
|
||||
#else
|
||||
if (!(catch_errors (m32r_load_1, abfd, "Load aborted!\n", RETURN_MASK_ALL)))
|
||||
{
|
||||
monitor_printf ("q\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
end_time = time (NULL);
|
||||
printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
|
||||
report_transfer_performance (data_count, start_time, end_time);
|
||||
|
||||
/* Finally, make the PC point at the start address */
|
||||
if (exec_bfd)
|
||||
write_pc (bfd_get_start_address (exec_bfd));
|
||||
|
||||
inferior_ptid = null_ptid; /* No process now */
|
||||
|
||||
/* This is necessary because many things were based on the PC at the
|
||||
time that we attached to the monitor, which is no longer valid
|
||||
now that we have loaded new code (and just changed the PC).
|
||||
Another way to do this might be to call normal_stop, except that
|
||||
the stack may not be valid, and things would get horribly
|
||||
confused... */
|
||||
|
||||
clear_symtab_users ();
|
||||
}
|
||||
|
||||
static void
|
||||
m32r_load_gen (char *filename, int from_tty)
|
||||
{
|
||||
generic_load (filename, from_tty);
|
||||
}
|
||||
|
||||
static void m32r_open (char *args, int from_tty);
|
||||
static void mon2000_open (char *args, int from_tty);
|
||||
|
||||
/* This array of registers needs to match the indexes used by GDB. The
|
||||
whole reason this exists is because the various ROM monitors use
|
||||
different names than GDB does, and don't support all the registers
|
||||
either. So, typing "info reg sp" becomes an "A7". */
|
||||
|
||||
static char *m32r_regnames[] =
|
||||
{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"psw", "cbr", "spi", "spu", "bpc", "pc", "accl", "acch",
|
||||
};
|
||||
|
||||
static void
|
||||
m32r_supply_register (char *regname, int regnamelen, char *val, int vallen)
|
||||
{
|
||||
int regno;
|
||||
int num_regs = sizeof (m32r_regnames) / sizeof (m32r_regnames[0]);
|
||||
|
||||
for (regno = 0; regno < num_regs; regno++)
|
||||
if (strncmp (regname, m32r_regnames[regno], regnamelen) == 0)
|
||||
break;
|
||||
|
||||
if (regno >= num_regs)
|
||||
return; /* no match */
|
||||
|
||||
if (regno == ACCL_REGNUM)
|
||||
{ /* special handling for 64-bit acc reg */
|
||||
monitor_supply_register (ACCH_REGNUM, val);
|
||||
val = strchr (val, ':'); /* skip past ':' to get 2nd word */
|
||||
if (val != NULL)
|
||||
monitor_supply_register (ACCL_REGNUM, val + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
monitor_supply_register (regno, val);
|
||||
if (regno == PSW_REGNUM)
|
||||
{
|
||||
unsigned long psw = strtoul (val, NULL, 16);
|
||||
char *zero = "00000000", *one = "00000001";
|
||||
|
||||
#ifdef SM_REGNUM
|
||||
/* Stack mode bit */
|
||||
monitor_supply_register (SM_REGNUM, (psw & 0x80) ? one : zero);
|
||||
#endif
|
||||
#ifdef BSM_REGNUM
|
||||
/* Backup stack mode bit */
|
||||
monitor_supply_register (BSM_REGNUM, (psw & 0x8000) ? one : zero);
|
||||
#endif
|
||||
#ifdef IE_REGNUM
|
||||
/* Interrupt enable bit */
|
||||
monitor_supply_register (IE_REGNUM, (psw & 0x40) ? one : zero);
|
||||
#endif
|
||||
#ifdef BIE_REGNUM
|
||||
/* Backup interrupt enable bit */
|
||||
monitor_supply_register (BIE_REGNUM, (psw & 0x4000) ? one : zero);
|
||||
#endif
|
||||
#ifdef COND_REGNUM
|
||||
/* Condition bit (carry etc.) */
|
||||
monitor_supply_register (COND_REGNUM, (psw & 0x1) ? one : zero);
|
||||
#endif
|
||||
#ifdef CBR_REGNUM
|
||||
monitor_supply_register (CBR_REGNUM, (psw & 0x1) ? one : zero);
|
||||
#endif
|
||||
#ifdef BPC_REGNUM
|
||||
monitor_supply_register (BPC_REGNUM, zero); /* KLUDGE: (???????) */
|
||||
#endif
|
||||
#ifdef BCARRY_REGNUM
|
||||
monitor_supply_register (BCARRY_REGNUM, zero); /* KLUDGE: (??????) */
|
||||
#endif
|
||||
}
|
||||
|
||||
if (regno == SPI_REGNUM || regno == SPU_REGNUM)
|
||||
{ /* special handling for stack pointer (spu or spi) */
|
||||
unsigned long stackmode = read_register (PSW_REGNUM) & 0x80;
|
||||
|
||||
if (regno == SPI_REGNUM && !stackmode) /* SP == SPI */
|
||||
monitor_supply_register (SP_REGNUM, val);
|
||||
else if (regno == SPU_REGNUM && stackmode) /* SP == SPU */
|
||||
monitor_supply_register (SP_REGNUM, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* m32r RevC board monitor */
|
||||
|
||||
static struct target_ops m32r_ops;
|
||||
|
||||
static char *m32r_inits[] =
|
||||
{"\r", NULL};
|
||||
|
||||
static struct monitor_ops m32r_cmds;
|
||||
|
||||
static void
|
||||
init_m32r_cmds (void)
|
||||
{
|
||||
m32r_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST;
|
||||
m32r_cmds.init = m32r_inits; /* Init strings */
|
||||
m32r_cmds.cont = "go\r"; /* continue command */
|
||||
m32r_cmds.step = "step\r"; /* single step */
|
||||
m32r_cmds.stop = NULL; /* interrupt command */
|
||||
m32r_cmds.set_break = "%x +bp\r"; /* set a breakpoint */
|
||||
m32r_cmds.clr_break = "%x -bp\r"; /* clear a breakpoint */
|
||||
m32r_cmds.clr_all_break = "bpoff\r"; /* clear all breakpoints */
|
||||
m32r_cmds.fill = "%x %x %x fill\r"; /* fill (start length val) */
|
||||
m32r_cmds.setmem.cmdb = "%x 1 %x fill\r"; /* setmem.cmdb (addr, value) */
|
||||
m32r_cmds.setmem.cmdw = "%x 1 %x fillh\r"; /* setmem.cmdw (addr, value) */
|
||||
m32r_cmds.setmem.cmdl = "%x 1 %x fillw\r"; /* setmem.cmdl (addr, value) */
|
||||
m32r_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
m32r_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
|
||||
m32r_cmds.setmem.term = NULL; /* setmem.term */
|
||||
m32r_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
|
||||
m32r_cmds.getmem.cmdb = "%x %x dump\r"; /* getmem.cmdb (addr, len) */
|
||||
m32r_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
|
||||
m32r_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
|
||||
m32r_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
m32r_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
|
||||
m32r_cmds.getmem.term = NULL; /* getmem.term */
|
||||
m32r_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
m32r_cmds.setreg.cmd = "%x to %%%s\r"; /* setreg.cmd (name, value) */
|
||||
m32r_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
m32r_cmds.setreg.term = NULL; /* setreg.term */
|
||||
m32r_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
m32r_cmds.getreg.cmd = NULL; /* getreg.cmd (name) */
|
||||
m32r_cmds.getreg.resp_delim = NULL; /* getreg.resp_delim */
|
||||
m32r_cmds.getreg.term = NULL; /* getreg.term */
|
||||
m32r_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
|
||||
m32r_cmds.dump_registers = ".reg\r"; /* dump_registers */
|
||||
m32r_cmds.register_pattern = "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
|
||||
m32r_cmds.supply_register = m32r_supply_register; /* supply_register */
|
||||
m32r_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
m32r_cmds.load = NULL; /* download command */
|
||||
m32r_cmds.loadresp = NULL; /* load response */
|
||||
m32r_cmds.prompt = "ok "; /* monitor command prompt */
|
||||
m32r_cmds.line_term = "\r"; /* end-of-line terminator */
|
||||
m32r_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
m32r_cmds.target = &m32r_ops; /* target operations */
|
||||
m32r_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
m32r_cmds.regnames = m32r_regnames; /* registers names */
|
||||
m32r_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
} /* init_m32r_cmds */
|
||||
|
||||
static void
|
||||
m32r_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &m32r_cmds, from_tty);
|
||||
}
|
||||
|
||||
/* Mon2000 monitor (MSA2000 board) */
|
||||
|
||||
static struct target_ops mon2000_ops;
|
||||
static struct monitor_ops mon2000_cmds;
|
||||
|
||||
static void
|
||||
init_mon2000_cmds (void)
|
||||
{
|
||||
mon2000_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_REGISTER_VALUE_FIRST;
|
||||
mon2000_cmds.init = m32r_inits; /* Init strings */
|
||||
mon2000_cmds.cont = "go\r"; /* continue command */
|
||||
mon2000_cmds.step = "step\r"; /* single step */
|
||||
mon2000_cmds.stop = NULL; /* interrupt command */
|
||||
mon2000_cmds.set_break = "%x +bp\r"; /* set a breakpoint */
|
||||
mon2000_cmds.clr_break = "%x -bp\r"; /* clear a breakpoint */
|
||||
mon2000_cmds.clr_all_break = "bpoff\r"; /* clear all breakpoints */
|
||||
mon2000_cmds.fill = "%x %x %x fill\r"; /* fill (start length val) */
|
||||
mon2000_cmds.setmem.cmdb = "%x 1 %x fill\r"; /* setmem.cmdb (addr, value) */
|
||||
mon2000_cmds.setmem.cmdw = "%x 1 %x fillh\r"; /* setmem.cmdw (addr, value) */
|
||||
mon2000_cmds.setmem.cmdl = "%x 1 %x fillw\r"; /* setmem.cmdl (addr, value) */
|
||||
mon2000_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
mon2000_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
|
||||
mon2000_cmds.setmem.term = NULL; /* setmem.term */
|
||||
mon2000_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
|
||||
mon2000_cmds.getmem.cmdb = "%x %x dump\r"; /* getmem.cmdb (addr, len) */
|
||||
mon2000_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
|
||||
mon2000_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
|
||||
mon2000_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
mon2000_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
|
||||
mon2000_cmds.getmem.term = NULL; /* getmem.term */
|
||||
mon2000_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
mon2000_cmds.setreg.cmd = "%x to %%%s\r"; /* setreg.cmd (name, value) */
|
||||
mon2000_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
mon2000_cmds.setreg.term = NULL; /* setreg.term */
|
||||
mon2000_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
mon2000_cmds.getreg.cmd = NULL; /* getreg.cmd (name) */
|
||||
mon2000_cmds.getreg.resp_delim = NULL; /* getreg.resp_delim */
|
||||
mon2000_cmds.getreg.term = NULL; /* getreg.term */
|
||||
mon2000_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
|
||||
mon2000_cmds.dump_registers = ".reg\r"; /* dump_registers */
|
||||
mon2000_cmds.register_pattern = "\\(\\w+\\) += \\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
|
||||
mon2000_cmds.supply_register = m32r_supply_register; /* supply_register */
|
||||
mon2000_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
mon2000_cmds.load = NULL; /* download command */
|
||||
mon2000_cmds.loadresp = NULL; /* load response */
|
||||
mon2000_cmds.prompt = "Mon2000>"; /* monitor command prompt */
|
||||
mon2000_cmds.line_term = "\r"; /* end-of-line terminator */
|
||||
mon2000_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
mon2000_cmds.target = &mon2000_ops; /* target operations */
|
||||
mon2000_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
mon2000_cmds.regnames = m32r_regnames; /* registers names */
|
||||
mon2000_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
} /* init_mon2000_cmds */
|
||||
|
||||
static void
|
||||
mon2000_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &mon2000_cmds, from_tty);
|
||||
}
|
||||
|
||||
/* Function: set_board_address
|
||||
Tell the BootOne monitor what it's ethernet IP address is. */
|
||||
|
||||
static void
|
||||
m32r_set_board_address (char *args, int from_tty)
|
||||
{
|
||||
int resp_len;
|
||||
char buf[1024];
|
||||
|
||||
if (args && *args)
|
||||
{
|
||||
monitor_printf ("ulip %s\n", args);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
/* now parse the result for success */
|
||||
}
|
||||
else
|
||||
error ("Requires argument (IP address for M32R-EVA board)");
|
||||
}
|
||||
|
||||
/* Function: set_server_address
|
||||
Tell the BootOne monitor what gdb's ethernet IP address is. */
|
||||
|
||||
static void
|
||||
m32r_set_server_address (char *args, int from_tty)
|
||||
{
|
||||
int resp_len;
|
||||
char buf[1024];
|
||||
|
||||
if (args && *args)
|
||||
{
|
||||
monitor_printf ("uhip %s\n", args);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
/* now parse the result for success */
|
||||
}
|
||||
else
|
||||
error ("Requires argument (IP address of GDB's host computer)");
|
||||
}
|
||||
|
||||
/* Function: set_download_path
|
||||
Tell the BootOne monitor the default path for downloadable SREC files. */
|
||||
|
||||
static void
|
||||
m32r_set_download_path (char *args, int from_tty)
|
||||
{
|
||||
int resp_len;
|
||||
char buf[1024];
|
||||
|
||||
if (args && *args)
|
||||
{
|
||||
monitor_printf ("up %s\n", args);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
/* now parse the result for success */
|
||||
}
|
||||
else
|
||||
error ("Requires argument (default path for downloadable SREC files)");
|
||||
}
|
||||
|
||||
static void
|
||||
m32r_upload_command (char *args, int from_tty)
|
||||
{
|
||||
bfd *abfd;
|
||||
asection *s;
|
||||
time_t start_time, end_time; /* for timing of download */
|
||||
int resp_len, data_count = 0;
|
||||
char buf[1024];
|
||||
struct hostent *hostent;
|
||||
struct in_addr inet_addr;
|
||||
|
||||
/* first check to see if there's an ethernet port! */
|
||||
monitor_printf ("ust\r");
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
if (!strchr (buf, ':'))
|
||||
error ("No ethernet connection!");
|
||||
|
||||
if (board_addr == 0)
|
||||
{
|
||||
/* scan second colon in the output from the "ust" command */
|
||||
char *myIPaddress = strchr (strchr (buf, ':') + 1, ':') + 1;
|
||||
|
||||
while (isspace (*myIPaddress))
|
||||
myIPaddress++;
|
||||
|
||||
if (!strncmp (myIPaddress, "0.0.", 4)) /* empty */
|
||||
error ("Please use 'set board-address' to set the M32R-EVA board's IP address.");
|
||||
if (strchr (myIPaddress, '('))
|
||||
*(strchr (myIPaddress, '(')) = '\0'; /* delete trailing junk */
|
||||
board_addr = xstrdup (myIPaddress);
|
||||
}
|
||||
if (server_addr == 0)
|
||||
{
|
||||
buf[0] = 0;
|
||||
gethostname (buf, sizeof (buf));
|
||||
if (buf[0] != 0)
|
||||
hostent = gethostbyname (buf);
|
||||
if (hostent != 0)
|
||||
{
|
||||
#if 1
|
||||
memcpy (&inet_addr.s_addr, hostent->h_addr,
|
||||
sizeof (inet_addr.s_addr));
|
||||
server_addr = (char *) inet_ntoa (inet_addr);
|
||||
#else
|
||||
server_addr = (char *) inet_ntoa (hostent->h_addr);
|
||||
#endif
|
||||
}
|
||||
if (server_addr == 0) /* failed? */
|
||||
error ("Need to know gdb host computer's IP address (use 'set server-address')");
|
||||
}
|
||||
|
||||
if (args == 0 || args[0] == 0) /* no args: upload the current file */
|
||||
args = get_exec_file (1);
|
||||
|
||||
if (args[0] != '/' && download_path == 0)
|
||||
{
|
||||
if (current_directory)
|
||||
download_path = xstrdup (current_directory);
|
||||
else
|
||||
error ("Need to know default download path (use 'set download-path')");
|
||||
}
|
||||
|
||||
start_time = time (NULL);
|
||||
monitor_printf ("uhip %s\r", server_addr);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf)); /* parse result? */
|
||||
monitor_printf ("ulip %s\r", board_addr);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf)); /* parse result? */
|
||||
if (args[0] != '/')
|
||||
monitor_printf ("up %s\r", download_path); /* use default path */
|
||||
else
|
||||
monitor_printf ("up\r"); /* rooted filename/path */
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf)); /* parse result? */
|
||||
|
||||
if (strrchr (args, '.') && !strcmp (strrchr (args, '.'), ".srec"))
|
||||
monitor_printf ("ul %s\r", args);
|
||||
else /* add ".srec" suffix */
|
||||
monitor_printf ("ul %s.srec\r", args);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf)); /* parse result? */
|
||||
|
||||
if (buf[0] == 0 || strstr (buf, "complete") == 0)
|
||||
error ("Upload file not found: %s.srec\nCheck IP addresses and download path.", args);
|
||||
else
|
||||
printf_filtered (" -- Ethernet load complete.\n");
|
||||
|
||||
end_time = time (NULL);
|
||||
abfd = bfd_openr (args, 0);
|
||||
if (abfd != NULL)
|
||||
{ /* Download is done -- print section statistics */
|
||||
if (bfd_check_format (abfd, bfd_object) == 0)
|
||||
{
|
||||
printf_filtered ("File is not an object file\n");
|
||||
}
|
||||
for (s = abfd->sections; s; s = s->next)
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
bfd_size_type section_size = bfd_section_size (abfd, s);
|
||||
bfd_vma section_base = bfd_section_lma (abfd, s);
|
||||
unsigned int buffer;
|
||||
|
||||
data_count += section_size;
|
||||
|
||||
printf_filtered ("Loading section %s, size 0x%lx lma ",
|
||||
bfd_section_name (abfd, s), section_size);
|
||||
print_address_numeric (section_base, 1, gdb_stdout);
|
||||
printf_filtered ("\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
/* Finally, make the PC point at the start address */
|
||||
write_pc (bfd_get_start_address (abfd));
|
||||
report_transfer_performance (data_count, start_time, end_time);
|
||||
printf_filtered ("Start address 0x%lx\n", bfd_get_start_address (abfd));
|
||||
}
|
||||
inferior_ptid = null_ptid; /* No process now */
|
||||
|
||||
/* This is necessary because many things were based on the PC at the
|
||||
time that we attached to the monitor, which is no longer valid
|
||||
now that we have loaded new code (and just changed the PC).
|
||||
Another way to do this might be to call normal_stop, except that
|
||||
the stack may not be valid, and things would get horribly
|
||||
confused... */
|
||||
|
||||
clear_symtab_users ();
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_m32r_rom (void)
|
||||
{
|
||||
/* Initialize m32r RevC monitor target */
|
||||
init_m32r_cmds ();
|
||||
init_monitor_ops (&m32r_ops);
|
||||
|
||||
m32r_ops.to_shortname = "m32r";
|
||||
m32r_ops.to_longname = "m32r monitor";
|
||||
m32r_ops.to_load = m32r_load_gen; /* monitor lacks a download command */
|
||||
m32r_ops.to_doc = "Debug via the m32r monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
m32r_ops.to_open = m32r_open;
|
||||
add_target (&m32r_ops);
|
||||
|
||||
/* Initialize mon2000 monitor target */
|
||||
init_mon2000_cmds ();
|
||||
init_monitor_ops (&mon2000_ops);
|
||||
|
||||
mon2000_ops.to_shortname = "mon2000";
|
||||
mon2000_ops.to_longname = "Mon2000 monitor";
|
||||
mon2000_ops.to_load = m32r_load_gen; /* monitor lacks a download command */
|
||||
mon2000_ops.to_doc = "Debug via the Mon2000 monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
mon2000_ops.to_open = mon2000_open;
|
||||
add_target (&mon2000_ops);
|
||||
|
||||
add_show_from_set
|
||||
(add_set_cmd ("download-path", class_obscure, var_string,
|
||||
(char *) &download_path,
|
||||
"Set the default path for downloadable SREC files.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
|
||||
add_show_from_set
|
||||
(add_set_cmd ("board-address", class_obscure, var_string,
|
||||
(char *) &board_addr,
|
||||
"Set IP address for M32R-EVA target board.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
|
||||
add_show_from_set
|
||||
(add_set_cmd ("server-address", class_obscure, var_string,
|
||||
(char *) &server_addr,
|
||||
"Set IP address for download server (GDB's host computer).",
|
||||
&setlist),
|
||||
&showlist);
|
||||
|
||||
add_com ("upload", class_obscure, m32r_upload_command,
|
||||
"Upload the srec file via the monitor's Ethernet upload capability.");
|
||||
|
||||
add_com ("tload", class_obscure, m32r_load, "test upload command.");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,705 +0,0 @@
|
||||
/* Target-dependent code for the Mitsubishi m32r for GDB, the GNU debugger.
|
||||
Copyright 1996, 1998, 1999, 2000, 2001 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "obstack.h"
|
||||
#include "target.h"
|
||||
#include "value.h"
|
||||
#include "bfd.h"
|
||||
#include "gdb_string.h"
|
||||
#include "gdbcore.h"
|
||||
#include "symfile.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* Function: m32r_use_struct_convention
|
||||
Return nonzero if call_function should allocate stack space for a
|
||||
struct return? */
|
||||
int
|
||||
m32r_use_struct_convention (int gcc_p, struct type *type)
|
||||
{
|
||||
return (TYPE_LENGTH (type) > 8);
|
||||
}
|
||||
|
||||
/* Function: frame_find_saved_regs
|
||||
Return the frame_saved_regs structure for the frame.
|
||||
Doesn't really work for dummy frames, but it does pass back
|
||||
an empty frame_saved_regs, so I guess that's better than total failure */
|
||||
|
||||
void
|
||||
m32r_frame_find_saved_regs (struct frame_info *fi,
|
||||
struct frame_saved_regs *regaddr)
|
||||
{
|
||||
memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs));
|
||||
}
|
||||
|
||||
/* Turn this on if you want to see just how much instruction decoding
|
||||
if being done, its quite a lot
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
dump_insn (char *commnt, CORE_ADDR pc, int insn)
|
||||
{
|
||||
printf_filtered (" %s %08x %08x ",
|
||||
commnt, (unsigned int) pc, (unsigned int) insn);
|
||||
TARGET_PRINT_INSN (pc, &tm_print_insn_info);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
#define insn_debug(args) { printf_filtered args; }
|
||||
#else
|
||||
#define dump_insn(a,b,c) {}
|
||||
#define insn_debug(args) {}
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SEARCH_LIMIT 44
|
||||
|
||||
/* Function: scan_prologue
|
||||
This function decodes the target function prologue to determine
|
||||
1) the size of the stack frame, and 2) which registers are saved on it.
|
||||
It saves the offsets of saved regs in the frame_saved_regs argument,
|
||||
and returns the frame size. */
|
||||
|
||||
/*
|
||||
The sequence it currently generates is:
|
||||
|
||||
if (varargs function) { ddi sp,#n }
|
||||
push registers
|
||||
if (additional stack <= 256) { addi sp,#-stack }
|
||||
else if (additional stack < 65k) { add3 sp,sp,#-stack
|
||||
|
||||
} else if (additional stack) {
|
||||
seth sp,#(stack & 0xffff0000)
|
||||
or3 sp,sp,#(stack & 0x0000ffff)
|
||||
sub sp,r4
|
||||
}
|
||||
if (frame pointer) {
|
||||
mv sp,fp
|
||||
}
|
||||
|
||||
These instructions are scheduled like everything else, so you should stop at
|
||||
the first branch instruction.
|
||||
|
||||
*/
|
||||
|
||||
/* This is required by skip prologue and by m32r_init_extra_frame_info.
|
||||
The results of decoding a prologue should be cached because this
|
||||
thrashing is getting nuts.
|
||||
I am thinking of making a container class with two indexes, name and
|
||||
address. It may be better to extend the symbol table.
|
||||
*/
|
||||
|
||||
static void
|
||||
decode_prologue (CORE_ADDR start_pc, CORE_ADDR scan_limit, CORE_ADDR *pl_endptr, /* var parameter */
|
||||
unsigned long *framelength, struct frame_info *fi,
|
||||
struct frame_saved_regs *fsr)
|
||||
{
|
||||
unsigned long framesize;
|
||||
int insn;
|
||||
int op1;
|
||||
int maybe_one_more = 0;
|
||||
CORE_ADDR after_prologue = 0;
|
||||
CORE_ADDR after_stack_adjust = 0;
|
||||
CORE_ADDR current_pc;
|
||||
|
||||
|
||||
framesize = 0;
|
||||
after_prologue = 0;
|
||||
insn_debug (("rd prolog l(%d)\n", scan_limit - current_pc));
|
||||
|
||||
for (current_pc = start_pc; current_pc < scan_limit; current_pc += 2)
|
||||
{
|
||||
|
||||
insn = read_memory_unsigned_integer (current_pc, 2);
|
||||
dump_insn ("insn-1", current_pc, insn); /* MTZ */
|
||||
|
||||
/* If this is a 32 bit instruction, we dont want to examine its
|
||||
immediate data as though it were an instruction */
|
||||
if (current_pc & 0x02)
|
||||
{ /* Clear the parallel execution bit from 16 bit instruction */
|
||||
if (maybe_one_more)
|
||||
{ /* The last instruction was a branch, usually terminates
|
||||
the series, but if this is a parallel instruction,
|
||||
it may be a stack framing instruction */
|
||||
if (!(insn & 0x8000))
|
||||
{
|
||||
insn_debug (("Really done"));
|
||||
break; /* nope, we are really done */
|
||||
}
|
||||
}
|
||||
insn &= 0x7fff; /* decode this instruction further */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maybe_one_more)
|
||||
break; /* This isnt the one more */
|
||||
if (insn & 0x8000)
|
||||
{
|
||||
insn_debug (("32 bit insn\n"));
|
||||
if (current_pc == scan_limit)
|
||||
scan_limit += 2; /* extend the search */
|
||||
current_pc += 2; /* skip the immediate data */
|
||||
if (insn == 0x8faf) /* add3 sp, sp, xxxx */
|
||||
/* add 16 bit sign-extended offset */
|
||||
{
|
||||
insn_debug (("stack increment\n"));
|
||||
framesize += -((short) read_memory_unsigned_integer (current_pc, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((insn >> 8) == 0xe4) && /* ld24 r4, xxxxxx; sub sp, r4 */
|
||||
read_memory_unsigned_integer (current_pc + 2, 2) == 0x0f24)
|
||||
{ /* subtract 24 bit sign-extended negative-offset */
|
||||
dump_insn ("insn-2", current_pc + 2, insn);
|
||||
insn = read_memory_unsigned_integer (current_pc - 2, 4);
|
||||
dump_insn ("insn-3(l4)", current_pc - 2, insn);
|
||||
if (insn & 0x00800000) /* sign extend */
|
||||
insn |= 0xff000000; /* negative */
|
||||
else
|
||||
insn &= 0x00ffffff; /* positive */
|
||||
framesize += insn;
|
||||
}
|
||||
}
|
||||
after_prologue = current_pc;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
op1 = insn & 0xf000; /* isolate just the first nibble */
|
||||
|
||||
if ((insn & 0xf0ff) == 0x207f)
|
||||
{ /* st reg, @-sp */
|
||||
int regno;
|
||||
insn_debug (("push\n"));
|
||||
#if 0 /* No, PUSH FP is not an indication that we will use a frame pointer. */
|
||||
if (((insn & 0xffff) == 0x2d7f) && fi)
|
||||
fi->using_frame_pointer = 1;
|
||||
#endif
|
||||
framesize += 4;
|
||||
#if 0
|
||||
/* Why should we increase the scan limit, just because we did a push?
|
||||
And if there is a reason, surely we would only want to do it if we
|
||||
had already reached the scan limit... */
|
||||
if (current_pc == scan_limit)
|
||||
scan_limit += 2;
|
||||
#endif
|
||||
regno = ((insn >> 8) & 0xf);
|
||||
if (fsr) /* save_regs offset */
|
||||
fsr->regs[regno] = framesize;
|
||||
after_prologue = 0;
|
||||
continue;
|
||||
}
|
||||
if ((insn >> 8) == 0x4f) /* addi sp, xx */
|
||||
/* add 8 bit sign-extended offset */
|
||||
{
|
||||
int stack_adjust = (char) (insn & 0xff);
|
||||
|
||||
/* there are probably two of these stack adjustments:
|
||||
1) A negative one in the prologue, and
|
||||
2) A positive one in the epilogue.
|
||||
We are only interested in the first one. */
|
||||
|
||||
if (stack_adjust < 0)
|
||||
{
|
||||
framesize -= stack_adjust;
|
||||
after_prologue = 0;
|
||||
/* A frameless function may have no "mv fp, sp".
|
||||
In that case, this is the end of the prologue. */
|
||||
after_stack_adjust = current_pc + 2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (insn == 0x1d8f)
|
||||
{ /* mv fp, sp */
|
||||
if (fi)
|
||||
fi->using_frame_pointer = 1; /* fp is now valid */
|
||||
insn_debug (("done fp found\n"));
|
||||
after_prologue = current_pc + 2;
|
||||
break; /* end of stack adjustments */
|
||||
}
|
||||
if (insn == 0x7000) /* Nop looks like a branch, continue explicitly */
|
||||
{
|
||||
insn_debug (("nop\n"));
|
||||
after_prologue = current_pc + 2;
|
||||
continue; /* nop occurs between pushes */
|
||||
}
|
||||
/* End of prolog if any of these are branch instructions */
|
||||
if ((op1 == 0x7000)
|
||||
|| (op1 == 0xb000)
|
||||
|| (op1 == 0xf000))
|
||||
{
|
||||
after_prologue = current_pc;
|
||||
insn_debug (("Done: branch\n"));
|
||||
maybe_one_more = 1;
|
||||
continue;
|
||||
}
|
||||
/* Some of the branch instructions are mixed with other types */
|
||||
if (op1 == 0x1000)
|
||||
{
|
||||
int subop = insn & 0x0ff0;
|
||||
if ((subop == 0x0ec0) || (subop == 0x0fc0))
|
||||
{
|
||||
insn_debug (("done: jmp\n"));
|
||||
after_prologue = current_pc;
|
||||
maybe_one_more = 1;
|
||||
continue; /* jmp , jl */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_pc >= scan_limit)
|
||||
{
|
||||
if (pl_endptr)
|
||||
{
|
||||
#if 1
|
||||
if (after_stack_adjust != 0)
|
||||
/* We did not find a "mv fp,sp", but we DID find
|
||||
a stack_adjust. Is it safe to use that as the
|
||||
end of the prologue? I just don't know. */
|
||||
{
|
||||
*pl_endptr = after_stack_adjust;
|
||||
if (framelength)
|
||||
*framelength = framesize;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* We reached the end of the loop without finding the end
|
||||
of the prologue. No way to win -- we should report failure.
|
||||
The way we do that is to return the original start_pc.
|
||||
GDB will set a breakpoint at the start of the function (etc.) */
|
||||
*pl_endptr = start_pc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (after_prologue == 0)
|
||||
after_prologue = current_pc;
|
||||
|
||||
insn_debug ((" framesize %d, firstline %08x\n", framesize, after_prologue));
|
||||
if (framelength)
|
||||
*framelength = framesize;
|
||||
if (pl_endptr)
|
||||
*pl_endptr = after_prologue;
|
||||
} /* decode_prologue */
|
||||
|
||||
/* Function: skip_prologue
|
||||
Find end of function prologue */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_skip_prologue (CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR func_addr, func_end;
|
||||
struct symtab_and_line sal;
|
||||
|
||||
/* See what the symbol table says */
|
||||
|
||||
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
|
||||
{
|
||||
sal = find_pc_line (func_addr, 0);
|
||||
|
||||
if (sal.line != 0 && sal.end <= func_end)
|
||||
{
|
||||
|
||||
insn_debug (("BP after prologue %08x\n", sal.end));
|
||||
func_end = sal.end;
|
||||
}
|
||||
else
|
||||
/* Either there's no line info, or the line after the prologue is after
|
||||
the end of the function. In this case, there probably isn't a
|
||||
prologue. */
|
||||
{
|
||||
insn_debug (("No line info, line(%x) sal_end(%x) funcend(%x)\n",
|
||||
sal.line, sal.end, func_end));
|
||||
func_end = min (func_end, func_addr + DEFAULT_SEARCH_LIMIT);
|
||||
}
|
||||
}
|
||||
else
|
||||
func_end = pc + DEFAULT_SEARCH_LIMIT;
|
||||
decode_prologue (pc, func_end, &sal.end, 0, 0, 0);
|
||||
return sal.end;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
m32r_scan_prologue (struct frame_info *fi, struct frame_saved_regs *fsr)
|
||||
{
|
||||
struct symtab_and_line sal;
|
||||
CORE_ADDR prologue_start, prologue_end, current_pc;
|
||||
unsigned long framesize = 0;
|
||||
|
||||
/* this code essentially duplicates skip_prologue,
|
||||
but we need the start address below. */
|
||||
|
||||
if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
|
||||
{
|
||||
sal = find_pc_line (prologue_start, 0);
|
||||
|
||||
if (sal.line == 0) /* no line info, use current PC */
|
||||
if (prologue_start == entry_point_address ())
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
prologue_start = fi->pc;
|
||||
prologue_end = prologue_start + 48; /* We're in the boondocks:
|
||||
allow for 16 pushes, an add,
|
||||
and "mv fp,sp" */
|
||||
}
|
||||
#if 0
|
||||
prologue_end = min (prologue_end, fi->pc);
|
||||
#endif
|
||||
insn_debug (("fipc(%08x) start(%08x) end(%08x)\n",
|
||||
fi->pc, prologue_start, prologue_end));
|
||||
prologue_end = min (prologue_end, prologue_start + DEFAULT_SEARCH_LIMIT);
|
||||
decode_prologue (prologue_start, prologue_end, &prologue_end, &framesize,
|
||||
fi, fsr);
|
||||
return framesize;
|
||||
}
|
||||
|
||||
/* Function: init_extra_frame_info
|
||||
This function actually figures out the frame address for a given pc and
|
||||
sp. This is tricky on the m32r because we sometimes don't use an explicit
|
||||
frame pointer, and the previous stack pointer isn't necessarily recorded
|
||||
on the stack. The only reliable way to get this info is to
|
||||
examine the prologue. */
|
||||
|
||||
void
|
||||
m32r_init_extra_frame_info (struct frame_info *fi)
|
||||
{
|
||||
int reg;
|
||||
|
||||
if (fi->next)
|
||||
fi->pc = FRAME_SAVED_PC (fi->next);
|
||||
|
||||
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
|
||||
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
|
||||
{
|
||||
/* We need to setup fi->frame here because run_stack_dummy gets it wrong
|
||||
by assuming it's always FP. */
|
||||
fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
|
||||
fi->framesize = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fi->using_frame_pointer = 0;
|
||||
fi->framesize = m32r_scan_prologue (fi, &fi->fsr);
|
||||
|
||||
if (!fi->next)
|
||||
if (fi->using_frame_pointer)
|
||||
{
|
||||
fi->frame = read_register (FP_REGNUM);
|
||||
}
|
||||
else
|
||||
fi->frame = read_register (SP_REGNUM);
|
||||
else
|
||||
/* fi->next means this is not the innermost frame */ if (fi->using_frame_pointer)
|
||||
/* we have an FP */
|
||||
if (fi->next->fsr.regs[FP_REGNUM] != 0) /* caller saved our FP */
|
||||
fi->frame = read_memory_integer (fi->next->fsr.regs[FP_REGNUM], 4);
|
||||
for (reg = 0; reg < NUM_REGS; reg++)
|
||||
if (fi->fsr.regs[reg] != 0)
|
||||
fi->fsr.regs[reg] = fi->frame + fi->framesize - fi->fsr.regs[reg];
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: m32r_virtual_frame_pointer
|
||||
Return the register that the function uses for a frame pointer,
|
||||
plus any necessary offset to be applied to the register before
|
||||
any frame pointer offsets. */
|
||||
|
||||
void
|
||||
m32r_virtual_frame_pointer (CORE_ADDR pc, long *reg, long *offset)
|
||||
{
|
||||
struct frame_info fi;
|
||||
|
||||
/* Set up a dummy frame_info. */
|
||||
fi.next = NULL;
|
||||
fi.prev = NULL;
|
||||
fi.frame = 0;
|
||||
fi.pc = pc;
|
||||
|
||||
/* Analyze the prolog and fill in the extra info. */
|
||||
m32r_init_extra_frame_info (&fi);
|
||||
|
||||
|
||||
/* Results will tell us which type of frame it uses. */
|
||||
if (fi.using_frame_pointer)
|
||||
{
|
||||
*reg = FP_REGNUM;
|
||||
*offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*reg = SP_REGNUM;
|
||||
*offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: find_callers_reg
|
||||
Find REGNUM on the stack. Otherwise, it's in an active register. One thing
|
||||
we might want to do here is to check REGNUM against the clobber mask, and
|
||||
somehow flag it as invalid if it isn't saved on the stack somewhere. This
|
||||
would provide a graceful failure mode when trying to get the value of
|
||||
caller-saves registers for an inner frame. */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_find_callers_reg (struct frame_info *fi, int regnum)
|
||||
{
|
||||
for (; fi; fi = fi->next)
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
|
||||
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
|
||||
else if (fi->fsr.regs[regnum] != 0)
|
||||
return read_memory_integer (fi->fsr.regs[regnum],
|
||||
REGISTER_RAW_SIZE (regnum));
|
||||
return read_register (regnum);
|
||||
}
|
||||
|
||||
/* Function: frame_chain
|
||||
Given a GDB frame, determine the address of the calling function's frame.
|
||||
This will be used to create a new GDB frame struct, and then
|
||||
INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
|
||||
For m32r, we save the frame size when we initialize the frame_info. */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_frame_chain (struct frame_info *fi)
|
||||
{
|
||||
CORE_ADDR fn_start, callers_pc, fp;
|
||||
|
||||
/* is this a dummy frame? */
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
|
||||
return fi->frame; /* dummy frame same as caller's frame */
|
||||
|
||||
/* is caller-of-this a dummy frame? */
|
||||
callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
|
||||
fp = m32r_find_callers_reg (fi, FP_REGNUM);
|
||||
if (PC_IN_CALL_DUMMY (callers_pc, fp, fp))
|
||||
return fp; /* dummy frame's frame may bear no relation to ours */
|
||||
|
||||
if (find_pc_partial_function (fi->pc, 0, &fn_start, 0))
|
||||
if (fn_start == entry_point_address ())
|
||||
return 0; /* in _start fn, don't chain further */
|
||||
if (fi->framesize == 0)
|
||||
{
|
||||
printf_filtered ("cannot determine frame size @ %s , pc(%s)\n",
|
||||
paddr (fi->frame),
|
||||
paddr (fi->pc));
|
||||
return 0;
|
||||
}
|
||||
insn_debug (("m32rx frame %08x\n", fi->frame + fi->framesize));
|
||||
return fi->frame + fi->framesize;
|
||||
}
|
||||
|
||||
/* Function: push_return_address (pc)
|
||||
Set up the return address for the inferior function call.
|
||||
Necessary for targets that don't actually execute a JSR/BSR instruction
|
||||
(ie. when using an empty CALL_DUMMY) */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
|
||||
{
|
||||
write_register (RP_REGNUM, CALL_DUMMY_ADDRESS ());
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
||||
/* Function: pop_frame
|
||||
Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
struct frame_info *
|
||||
m32r_pop_frame (struct frame_info *frame)
|
||||
{
|
||||
int regnum;
|
||||
|
||||
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
|
||||
generic_pop_dummy_frame ();
|
||||
else
|
||||
{
|
||||
for (regnum = 0; regnum < NUM_REGS; regnum++)
|
||||
if (frame->fsr.regs[regnum] != 0)
|
||||
write_register (regnum,
|
||||
read_memory_integer (frame->fsr.regs[regnum], 4));
|
||||
|
||||
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
|
||||
write_register (SP_REGNUM, read_register (FP_REGNUM));
|
||||
if (read_register (PSW_REGNUM) & 0x80)
|
||||
write_register (SPU_REGNUM, read_register (SP_REGNUM));
|
||||
else
|
||||
write_register (SPI_REGNUM, read_register (SP_REGNUM));
|
||||
}
|
||||
flush_cached_frames ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Function: frame_saved_pc
|
||||
Find the caller of this frame. We do this by seeing if RP_REGNUM is saved
|
||||
in the stack anywhere, otherwise we get it from the registers. */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_frame_saved_pc (struct frame_info *fi)
|
||||
{
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
|
||||
return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
|
||||
else
|
||||
return m32r_find_callers_reg (fi, RP_REGNUM);
|
||||
}
|
||||
|
||||
/* Function: push_arguments
|
||||
Setup the function arguments for calling a function in the inferior.
|
||||
|
||||
On the Mitsubishi M32R architecture, there are four registers (R0 to R3)
|
||||
which are dedicated for passing function arguments. Up to the first
|
||||
four arguments (depending on size) may go into these registers.
|
||||
The rest go on the stack.
|
||||
|
||||
Arguments that are smaller than 4 bytes will still take up a whole
|
||||
register or a whole 32-bit word on the stack, and will be
|
||||
right-justified in the register or the stack word. This includes
|
||||
chars, shorts, and small aggregate types.
|
||||
|
||||
Arguments of 8 bytes size are split between two registers, if
|
||||
available. If only one register is available, the argument will
|
||||
be split between the register and the stack. Otherwise it is
|
||||
passed entirely on the stack. Aggregate types with sizes between
|
||||
4 and 8 bytes are passed entirely on the stack, and are left-justified
|
||||
within the double-word (as opposed to aggregates smaller than 4 bytes
|
||||
which are right-justified).
|
||||
|
||||
Aggregates of greater than 8 bytes are first copied onto the stack,
|
||||
and then a pointer to the copy is passed in the place of the normal
|
||||
argument (either in a register if available, or on the stack).
|
||||
|
||||
Functions that must return an aggregate type can return it in the
|
||||
normal return value registers (R0 and R1) if its size is 8 bytes or
|
||||
less. For larger return values, the caller must allocate space for
|
||||
the callee to copy the return value to. A pointer to this space is
|
||||
passed as an implicit first argument, always in R0. */
|
||||
|
||||
CORE_ADDR
|
||||
m32r_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
|
||||
unsigned char struct_return, CORE_ADDR struct_addr)
|
||||
{
|
||||
int stack_offset, stack_alloc;
|
||||
int argreg;
|
||||
int argnum;
|
||||
struct type *type;
|
||||
CORE_ADDR regval;
|
||||
char *val;
|
||||
char valbuf[4];
|
||||
int len;
|
||||
int odd_sized_struct;
|
||||
|
||||
/* first force sp to a 4-byte alignment */
|
||||
sp = sp & ~3;
|
||||
|
||||
argreg = ARG0_REGNUM;
|
||||
/* The "struct return pointer" pseudo-argument goes in R0 */
|
||||
if (struct_return)
|
||||
write_register (argreg++, struct_addr);
|
||||
|
||||
/* Now make sure there's space on the stack */
|
||||
for (argnum = 0, stack_alloc = 0;
|
||||
argnum < nargs; argnum++)
|
||||
stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + 3) & ~3);
|
||||
sp -= stack_alloc; /* make room on stack for args */
|
||||
|
||||
|
||||
/* Now load as many as possible of the first arguments into
|
||||
registers, and push the rest onto the stack. There are 16 bytes
|
||||
in four registers available. Loop thru args from first to last. */
|
||||
|
||||
argreg = ARG0_REGNUM;
|
||||
for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
|
||||
{
|
||||
type = VALUE_TYPE (args[argnum]);
|
||||
len = TYPE_LENGTH (type);
|
||||
memset (valbuf, 0, sizeof (valbuf));
|
||||
if (len < 4)
|
||||
{ /* value gets right-justified in the register or stack word */
|
||||
memcpy (valbuf + (4 - len),
|
||||
(char *) VALUE_CONTENTS (args[argnum]), len);
|
||||
val = valbuf;
|
||||
}
|
||||
else
|
||||
val = (char *) VALUE_CONTENTS (args[argnum]);
|
||||
|
||||
if (len > 4 && (len & 3) != 0)
|
||||
odd_sized_struct = 1; /* such structs go entirely on stack */
|
||||
else
|
||||
odd_sized_struct = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
if (argreg > ARGLAST_REGNUM || odd_sized_struct)
|
||||
{ /* must go on the stack */
|
||||
write_memory (sp + stack_offset, val, 4);
|
||||
stack_offset += 4;
|
||||
}
|
||||
/* NOTE WELL!!!!! This is not an "else if" clause!!!
|
||||
That's because some *&^%$ things get passed on the stack
|
||||
AND in the registers! */
|
||||
if (argreg <= ARGLAST_REGNUM)
|
||||
{ /* there's room in a register */
|
||||
regval = extract_address (val, REGISTER_RAW_SIZE (argreg));
|
||||
write_register (argreg++, regval);
|
||||
}
|
||||
/* Store the value 4 bytes at a time. This means that things
|
||||
larger than 4 bytes may go partly in registers and partly
|
||||
on the stack. */
|
||||
len -= REGISTER_RAW_SIZE (argreg);
|
||||
val += REGISTER_RAW_SIZE (argreg);
|
||||
}
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
/* Function: fix_call_dummy
|
||||
If there is real CALL_DUMMY code (eg. on the stack), this function
|
||||
has the responsability to insert the address of the actual code that
|
||||
is the target of the target function call. */
|
||||
|
||||
void
|
||||
m32r_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
|
||||
struct value **args, struct type *type, int gcc_p)
|
||||
{
|
||||
/* ld24 r8, <(imm24) fun> */
|
||||
*(unsigned long *) (dummy) = (fun & 0x00ffffff) | 0xe8000000;
|
||||
}
|
||||
|
||||
|
||||
/* Function: m32r_write_sp
|
||||
Because SP is really a read-only register that mirrors either SPU or SPI,
|
||||
we must actually write one of those two as well, depending on PSW. */
|
||||
|
||||
void
|
||||
m32r_write_sp (CORE_ADDR val)
|
||||
{
|
||||
unsigned long psw = read_register (PSW_REGNUM);
|
||||
|
||||
if (psw & 0x80) /* stack mode: user or interrupt */
|
||||
write_register (SPU_REGNUM, val);
|
||||
else
|
||||
write_register (SPI_REGNUM, val);
|
||||
write_register (SP_REGNUM, val);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_m32r_tdep (void)
|
||||
{
|
||||
tm_print_insn = print_insn_m32r;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,685 +0,0 @@
|
||||
/* Target dependent code for the Motorola 68000 series.
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbcore.h"
|
||||
#include "value.h"
|
||||
#include "gdb_string.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
|
||||
#define P_LINKL_FP 0x480e
|
||||
#define P_LINKW_FP 0x4e56
|
||||
#define P_PEA_FP 0x4856
|
||||
#define P_MOVL_SP_FP 0x2c4f
|
||||
#define P_MOVL 0x207c
|
||||
#define P_JSR 0x4eb9
|
||||
#define P_BSR 0x61ff
|
||||
#define P_LEAL 0x43fb
|
||||
#define P_MOVML 0x48ef
|
||||
#define P_FMOVM 0xf237
|
||||
#define P_TRAP 0x4e40
|
||||
|
||||
/* The only reason this is here is the tm-altos.h reference below. It
|
||||
was moved back here from tm-m68k.h. FIXME? */
|
||||
|
||||
extern CORE_ADDR
|
||||
altos_skip_prologue (CORE_ADDR pc)
|
||||
{
|
||||
register int op = read_memory_integer (pc, 2);
|
||||
if (op == P_LINKW_FP)
|
||||
pc += 4; /* Skip link #word */
|
||||
else if (op == P_LINKL_FP)
|
||||
pc += 6; /* Skip link #long */
|
||||
/* Not sure why branches are here. */
|
||||
/* From tm-altos.h */
|
||||
else if (op == 0060000)
|
||||
pc += 4; /* Skip bra #word */
|
||||
else if (op == 00600377)
|
||||
pc += 6; /* skip bra #long */
|
||||
else if ((op & 0177400) == 0060000)
|
||||
pc += 2; /* skip bra #char */
|
||||
return pc;
|
||||
}
|
||||
|
||||
int
|
||||
delta68_in_sigtramp (CORE_ADDR pc, char *name)
|
||||
{
|
||||
if (name != NULL)
|
||||
return strcmp (name, "_sigcode") == 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
delta68_frame_args_address (struct frame_info *frame_info)
|
||||
{
|
||||
/* we assume here that the only frameless functions are the system calls
|
||||
or other functions who do not put anything on the stack. */
|
||||
if (frame_info->signal_handler_caller)
|
||||
return frame_info->frame + 12;
|
||||
else if (frameless_look_for_prologue (frame_info))
|
||||
{
|
||||
/* Check for an interrupted system call */
|
||||
if (frame_info->next && frame_info->next->signal_handler_caller)
|
||||
return frame_info->next->frame + 16;
|
||||
else
|
||||
return frame_info->frame + 4;
|
||||
}
|
||||
else
|
||||
return frame_info->frame;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
delta68_frame_saved_pc (struct frame_info *frame_info)
|
||||
{
|
||||
return read_memory_integer (delta68_frame_args_address (frame_info) + 4, 4);
|
||||
}
|
||||
|
||||
/* Return number of args passed to a frame.
|
||||
Can return -1, meaning no way to tell. */
|
||||
|
||||
int
|
||||
isi_frame_num_args (struct frame_info *fi)
|
||||
{
|
||||
int val;
|
||||
CORE_ADDR pc = FRAME_SAVED_PC (fi);
|
||||
int insn = 0177777 & read_memory_integer (pc, 2);
|
||||
val = 0;
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */
|
||||
val = read_memory_integer (pc + 2, 2);
|
||||
else if ((insn & 0170777) == 0050217 /* addql #N, sp */
|
||||
|| (insn & 0170777) == 0050117) /* addqw */
|
||||
{
|
||||
val = (insn >> 9) & 7;
|
||||
if (val == 0)
|
||||
val = 8;
|
||||
}
|
||||
else if (insn == 0157774) /* addal #WW, sp */
|
||||
val = read_memory_integer (pc + 2, 4);
|
||||
val >>= 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
delta68_frame_num_args (struct frame_info *fi)
|
||||
{
|
||||
int val;
|
||||
CORE_ADDR pc = FRAME_SAVED_PC (fi);
|
||||
int insn = 0177777 & read_memory_integer (pc, 2);
|
||||
val = 0;
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */
|
||||
val = read_memory_integer (pc + 2, 2);
|
||||
else if ((insn & 0170777) == 0050217 /* addql #N, sp */
|
||||
|| (insn & 0170777) == 0050117) /* addqw */
|
||||
{
|
||||
val = (insn >> 9) & 7;
|
||||
if (val == 0)
|
||||
val = 8;
|
||||
}
|
||||
else if (insn == 0157774) /* addal #WW, sp */
|
||||
val = read_memory_integer (pc + 2, 4);
|
||||
val >>= 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
news_frame_num_args (struct frame_info *fi)
|
||||
{
|
||||
int val;
|
||||
CORE_ADDR pc = FRAME_SAVED_PC (fi);
|
||||
int insn = 0177777 & read_memory_integer (pc, 2);
|
||||
val = 0;
|
||||
if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */
|
||||
val = read_memory_integer (pc + 2, 2);
|
||||
else if ((insn & 0170777) == 0050217 /* addql #N, sp */
|
||||
|| (insn & 0170777) == 0050117) /* addqw */
|
||||
{
|
||||
val = (insn >> 9) & 7;
|
||||
if (val == 0)
|
||||
val = 8;
|
||||
}
|
||||
else if (insn == 0157774) /* addal #WW, sp */
|
||||
val = read_memory_integer (pc + 2, 4);
|
||||
val >>= 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Push an empty stack frame, to record the current PC, etc. */
|
||||
|
||||
void
|
||||
m68k_push_dummy_frame (void)
|
||||
{
|
||||
register CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
register int regnum;
|
||||
char raw_buffer[12];
|
||||
|
||||
sp = push_word (sp, read_register (PC_REGNUM));
|
||||
sp = push_word (sp, read_register (FP_REGNUM));
|
||||
write_register (FP_REGNUM, sp);
|
||||
|
||||
/* Always save the floating-point registers, whether they exist on
|
||||
this target or not. */
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
|
||||
{
|
||||
read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
|
||||
sp = push_bytes (sp, raw_buffer, 12);
|
||||
}
|
||||
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
|
||||
{
|
||||
sp = push_word (sp, read_register (regnum));
|
||||
}
|
||||
sp = push_word (sp, read_register (PS_REGNUM));
|
||||
write_register (SP_REGNUM, sp);
|
||||
}
|
||||
|
||||
/* Discard from the stack the innermost frame,
|
||||
restoring all saved registers. */
|
||||
|
||||
void
|
||||
m68k_pop_frame (void)
|
||||
{
|
||||
register struct frame_info *frame = get_current_frame ();
|
||||
register CORE_ADDR fp;
|
||||
register int regnum;
|
||||
struct frame_saved_regs fsr;
|
||||
char raw_buffer[12];
|
||||
|
||||
fp = FRAME_FP (frame);
|
||||
get_frame_saved_regs (frame, &fsr);
|
||||
for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
|
||||
{
|
||||
if (fsr.regs[regnum])
|
||||
{
|
||||
read_memory (fsr.regs[regnum], raw_buffer, 12);
|
||||
write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
|
||||
}
|
||||
}
|
||||
for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
|
||||
{
|
||||
if (fsr.regs[regnum])
|
||||
{
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
|
||||
}
|
||||
}
|
||||
if (fsr.regs[PS_REGNUM])
|
||||
{
|
||||
write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
|
||||
}
|
||||
write_register (FP_REGNUM, read_memory_integer (fp, 4));
|
||||
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
|
||||
write_register (SP_REGNUM, fp + 8);
|
||||
flush_cached_frames ();
|
||||
}
|
||||
|
||||
|
||||
/* Given an ip value corresponding to the start of a function,
|
||||
return the ip of the first instruction after the function
|
||||
prologue. This is the generic m68k support. Machines which
|
||||
require something different can override the SKIP_PROLOGUE
|
||||
macro to point elsewhere.
|
||||
|
||||
Some instructions which typically may appear in a function
|
||||
prologue include:
|
||||
|
||||
A link instruction, word form:
|
||||
|
||||
link.w %a6,&0 4e56 XXXX
|
||||
|
||||
A link instruction, long form:
|
||||
|
||||
link.l %fp,&F%1 480e XXXX XXXX
|
||||
|
||||
A movm instruction to preserve integer regs:
|
||||
|
||||
movm.l &M%1,(4,%sp) 48ef XXXX XXXX
|
||||
|
||||
A fmovm instruction to preserve float regs:
|
||||
|
||||
fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
|
||||
|
||||
Some profiling setup code (FIXME, not recognized yet):
|
||||
|
||||
lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
|
||||
bsr _mcount 61ff XXXX XXXX
|
||||
|
||||
*/
|
||||
|
||||
CORE_ADDR
|
||||
m68k_skip_prologue (CORE_ADDR ip)
|
||||
{
|
||||
register CORE_ADDR limit;
|
||||
struct symtab_and_line sal;
|
||||
register int op;
|
||||
|
||||
/* Find out if there is a known limit for the extent of the prologue.
|
||||
If so, ensure we don't go past it. If not, assume "infinity". */
|
||||
|
||||
sal = find_pc_line (ip, 0);
|
||||
limit = (sal.end) ? sal.end : (CORE_ADDR) ~ 0;
|
||||
|
||||
while (ip < limit)
|
||||
{
|
||||
op = read_memory_integer (ip, 2);
|
||||
op &= 0xFFFF;
|
||||
|
||||
if (op == P_LINKW_FP)
|
||||
ip += 4; /* Skip link.w */
|
||||
else if (op == P_PEA_FP)
|
||||
ip += 2; /* Skip pea %fp */
|
||||
else if (op == P_MOVL_SP_FP)
|
||||
ip += 2; /* Skip move.l %sp, %fp */
|
||||
else if (op == P_LINKL_FP)
|
||||
ip += 6; /* Skip link.l */
|
||||
else if (op == P_MOVML)
|
||||
ip += 6; /* Skip movm.l */
|
||||
else if (op == P_FMOVM)
|
||||
ip += 10; /* Skip fmovm */
|
||||
else
|
||||
break; /* Found unknown code, bail out. */
|
||||
}
|
||||
return (ip);
|
||||
}
|
||||
|
||||
void
|
||||
m68k_find_saved_regs (struct frame_info *frame_info,
|
||||
struct frame_saved_regs *saved_regs)
|
||||
{
|
||||
register int regnum;
|
||||
register int regmask;
|
||||
register CORE_ADDR next_addr;
|
||||
register CORE_ADDR pc;
|
||||
|
||||
/* First possible address for a pc in a call dummy for this frame. */
|
||||
CORE_ADDR possible_call_dummy_start =
|
||||
(frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4 - 8 * 12;
|
||||
|
||||
int nextinsn;
|
||||
memset (saved_regs, 0, sizeof (*saved_regs));
|
||||
if ((frame_info)->pc >= possible_call_dummy_start
|
||||
&& (frame_info)->pc <= (frame_info)->frame)
|
||||
{
|
||||
|
||||
/* It is a call dummy. We could just stop now, since we know
|
||||
what the call dummy saves and where. But this code proceeds
|
||||
to parse the "prologue" which is part of the call dummy.
|
||||
This is needlessly complex and confusing. FIXME. */
|
||||
|
||||
next_addr = (frame_info)->frame;
|
||||
pc = possible_call_dummy_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
pc = get_pc_function_start ((frame_info)->pc);
|
||||
|
||||
nextinsn = read_memory_integer (pc, 2);
|
||||
if (P_PEA_FP == nextinsn
|
||||
&& P_MOVL_SP_FP == read_memory_integer (pc + 2, 2))
|
||||
{
|
||||
/* pea %fp
|
||||
move.l %sp, %fp */
|
||||
next_addr = frame_info->frame;
|
||||
pc += 4;
|
||||
}
|
||||
else if (P_LINKL_FP == nextinsn)
|
||||
/* link.l %fp */
|
||||
/* Find the address above the saved
|
||||
regs using the amount of storage from the link instruction. */
|
||||
{
|
||||
next_addr = (frame_info)->frame + read_memory_integer (pc + 2, 4);
|
||||
pc += 6;
|
||||
}
|
||||
else if (P_LINKW_FP == nextinsn)
|
||||
/* link.w %fp */
|
||||
/* Find the address above the saved
|
||||
regs using the amount of storage from the link instruction. */
|
||||
{
|
||||
next_addr = (frame_info)->frame + read_memory_integer (pc + 2, 2);
|
||||
pc += 4;
|
||||
}
|
||||
else
|
||||
goto lose;
|
||||
|
||||
/* If have an addal #-n, sp next, adjust next_addr. */
|
||||
if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
|
||||
next_addr += read_memory_integer (pc += 2, 4), pc += 4;
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
nextinsn = 0xffff & read_memory_integer (pc, 2);
|
||||
regmask = read_memory_integer (pc + 2, 2);
|
||||
/* fmovemx to -(sp) */
|
||||
if (0xf227 == nextinsn && (regmask & 0xff00) == 0xe000)
|
||||
{
|
||||
/* Regmask's low bit is for register fp7, the first pushed */
|
||||
for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
saved_regs->regs[regnum] = (next_addr -= 12);
|
||||
pc += 4;
|
||||
}
|
||||
/* fmovemx to (fp + displacement) */
|
||||
else if (0171056 == nextinsn && (regmask & 0xff00) == 0xf000)
|
||||
{
|
||||
register CORE_ADDR addr;
|
||||
|
||||
addr = (frame_info)->frame + read_memory_integer (pc + 4, 2);
|
||||
/* Regmask's low bit is for register fp7, the first pushed */
|
||||
for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
{
|
||||
saved_regs->regs[regnum] = addr;
|
||||
addr += 12;
|
||||
}
|
||||
pc += 6;
|
||||
}
|
||||
/* moveml to (sp) */
|
||||
else if (0044327 == nextinsn)
|
||||
{
|
||||
/* Regmask's low bit is for register 0, the first written */
|
||||
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
{
|
||||
saved_regs->regs[regnum] = next_addr;
|
||||
next_addr += 4;
|
||||
}
|
||||
pc += 4;
|
||||
}
|
||||
/* moveml to (fp + displacement) */
|
||||
else if (0044356 == nextinsn)
|
||||
{
|
||||
register CORE_ADDR addr;
|
||||
|
||||
addr = (frame_info)->frame + read_memory_integer (pc + 4, 2);
|
||||
/* Regmask's low bit is for register 0, the first written */
|
||||
for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
{
|
||||
saved_regs->regs[regnum] = addr;
|
||||
addr += 4;
|
||||
}
|
||||
pc += 6;
|
||||
}
|
||||
/* moveml to -(sp) */
|
||||
else if (0044347 == nextinsn)
|
||||
{
|
||||
/* Regmask's low bit is for register 15, the first pushed */
|
||||
for (regnum = 16; --regnum >= 0; regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
saved_regs->regs[regnum] = (next_addr -= 4);
|
||||
pc += 4;
|
||||
}
|
||||
/* movl r,-(sp) */
|
||||
else if (0x2f00 == (0xfff0 & nextinsn))
|
||||
{
|
||||
regnum = 0xf & nextinsn;
|
||||
saved_regs->regs[regnum] = (next_addr -= 4);
|
||||
pc += 2;
|
||||
}
|
||||
/* fmovemx to index of sp */
|
||||
else if (0xf236 == nextinsn && (regmask & 0xff00) == 0xf000)
|
||||
{
|
||||
/* Regmask's low bit is for register fp0, the first written */
|
||||
for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
|
||||
if (regmask & 1)
|
||||
{
|
||||
saved_regs->regs[regnum] = next_addr;
|
||||
next_addr += 12;
|
||||
}
|
||||
pc += 10;
|
||||
}
|
||||
/* clrw -(sp); movw ccr,-(sp) */
|
||||
else if (0x4267 == nextinsn && 0x42e7 == regmask)
|
||||
{
|
||||
saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
|
||||
pc += 4;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
lose:;
|
||||
saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
|
||||
saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
|
||||
saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
|
||||
#ifdef SIG_SP_FP_OFFSET
|
||||
/* Adjust saved SP_REGNUM for fake _sigtramp frames. */
|
||||
if (frame_info->signal_handler_caller && frame_info->next)
|
||||
saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_PROC_FS /* Target dependent support for /proc */
|
||||
|
||||
#include <sys/procfs.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/* The /proc interface divides the target machine's register set up into
|
||||
two different sets, the general register set (gregset) and the floating
|
||||
point register set (fpregset). For each set, there is an ioctl to get
|
||||
the current register set and another ioctl to set the current values.
|
||||
|
||||
The actual structure passed through the ioctl interface is, of course,
|
||||
naturally machine dependent, and is different for each set of registers.
|
||||
For the m68k for example, the general register set is typically defined
|
||||
by:
|
||||
|
||||
typedef int gregset_t[18];
|
||||
|
||||
#define R_D0 0
|
||||
...
|
||||
#define R_PS 17
|
||||
|
||||
and the floating point set by:
|
||||
|
||||
typedef struct fpregset {
|
||||
int f_pcr;
|
||||
int f_psr;
|
||||
int f_fpiaddr;
|
||||
int f_fpregs[8][3]; (8 regs, 96 bits each)
|
||||
} fpregset_t;
|
||||
|
||||
These routines provide the packing and unpacking of gregset_t and
|
||||
fpregset_t formatted data.
|
||||
|
||||
*/
|
||||
|
||||
/* Atari SVR4 has R_SR but not R_PS */
|
||||
|
||||
#if !defined (R_PS) && defined (R_SR)
|
||||
#define R_PS R_SR
|
||||
#endif
|
||||
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi < R_PC; regi++)
|
||||
{
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
}
|
||||
supply_register (PS_REGNUM, (char *) (regp + R_PS));
|
||||
supply_register (PC_REGNUM, (char *) (regp + R_PC));
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi < R_PC; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
*(regp + regi) = *(int *) ®isters[REGISTER_BYTE (regi)];
|
||||
}
|
||||
}
|
||||
if ((regno == -1) || (regno == PS_REGNUM))
|
||||
{
|
||||
*(regp + R_PS) = *(int *) ®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||
}
|
||||
if ((regno == -1) || (regno == PC_REGNUM))
|
||||
{
|
||||
*(regp + R_PC) = *(int *) ®isters[REGISTER_BYTE (PC_REGNUM)];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (FP0_REGNUM)
|
||||
|
||||
/* Given a pointer to a floating point register set in /proc format
|
||||
(fpregset_t *), unpack the register contents and supply them as gdb's
|
||||
idea of the current floating point register values. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
register int regi;
|
||||
char *from;
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
|
||||
{
|
||||
from = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
|
||||
supply_register (regi, from);
|
||||
}
|
||||
supply_register (FPC_REGNUM, (char *) &(fpregsetp->f_pcr));
|
||||
supply_register (FPS_REGNUM, (char *) &(fpregsetp->f_psr));
|
||||
supply_register (FPI_REGNUM, (char *) &(fpregsetp->f_fpiaddr));
|
||||
}
|
||||
|
||||
/* Given a pointer to a floating point register set in /proc format
|
||||
(fpregset_t *), update the register specified by REGNO from gdb's idea
|
||||
of the current floating point register set. If REGNO is -1, update
|
||||
them all. */
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
char *to;
|
||||
char *from;
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
from = (char *) ®isters[REGISTER_BYTE (regi)];
|
||||
to = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
|
||||
memcpy (to, from, REGISTER_RAW_SIZE (regi));
|
||||
}
|
||||
}
|
||||
if ((regno == -1) || (regno == FPC_REGNUM))
|
||||
{
|
||||
fpregsetp->f_pcr = *(int *) ®isters[REGISTER_BYTE (FPC_REGNUM)];
|
||||
}
|
||||
if ((regno == -1) || (regno == FPS_REGNUM))
|
||||
{
|
||||
fpregsetp->f_psr = *(int *) ®isters[REGISTER_BYTE (FPS_REGNUM)];
|
||||
}
|
||||
if ((regno == -1) || (regno == FPI_REGNUM))
|
||||
{
|
||||
fpregsetp->f_fpiaddr = *(int *) ®isters[REGISTER_BYTE (FPI_REGNUM)];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined (FP0_REGNUM) */
|
||||
|
||||
#endif /* USE_PROC_FS */
|
||||
|
||||
/* Figure out where the longjmp will land. Slurp the args out of the stack.
|
||||
We expect the first arg to be a pointer to the jmp_buf structure from which
|
||||
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
|
||||
This routine returns true on success. */
|
||||
|
||||
/* NOTE: cagney/2000-11-08: For this function to be fully multi-arched
|
||||
the macro's JB_PC and JB_ELEMENT_SIZE would need to be moved into
|
||||
the ``struct gdbarch_tdep'' object and then set on a target ISA/ABI
|
||||
dependant basis. */
|
||||
|
||||
int
|
||||
m68k_get_longjmp_target (CORE_ADDR *pc)
|
||||
{
|
||||
#if defined (JB_PC) && defined (JB_ELEMENT_SIZE)
|
||||
char *buf;
|
||||
CORE_ADDR sp, jb_addr;
|
||||
|
||||
buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
sp = read_register (SP_REGNUM);
|
||||
|
||||
if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
|
||||
buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
TARGET_PTR_BIT / TARGET_CHAR_BIT))
|
||||
return 0;
|
||||
|
||||
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
|
||||
|
||||
return 1;
|
||||
#else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"m68k_get_longjmp_target: not implemented");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Immediately after a function call, return the saved pc before the frame
|
||||
is setup. For sun3's, we check for the common case of being inside of a
|
||||
system call, and if so, we know that Sun pushes the call # on the stack
|
||||
prior to doing the trap. */
|
||||
|
||||
CORE_ADDR
|
||||
m68k_saved_pc_after_call (struct frame_info *frame)
|
||||
{
|
||||
#ifdef SYSCALL_TRAP
|
||||
int op;
|
||||
|
||||
op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
|
||||
|
||||
if (op == SYSCALL_TRAP)
|
||||
return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
|
||||
else
|
||||
#endif /* SYSCALL_TRAP */
|
||||
return read_memory_integer (read_register (SP_REGNUM), 4);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_initialize_m68k_tdep (void)
|
||||
{
|
||||
tm_print_insn = print_insn_m68k;
|
||||
}
|
@ -1,710 +0,0 @@
|
||||
/* Motorola m68k native support for GNU/Linux.
|
||||
|
||||
Copyright 1996, 1998, 2000, 2001, 2002 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "language.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#ifdef USG
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
#ifdef HAVE_SYS_REG_H
|
||||
#include <sys/reg.h>
|
||||
#endif
|
||||
|
||||
#include <sys/file.h>
|
||||
#include "gdb_stat.h"
|
||||
|
||||
#include "floatformat.h"
|
||||
|
||||
#include "target.h"
|
||||
|
||||
|
||||
/* This table must line up with REGISTER_NAMES in tm-m68k.h */
|
||||
static const int regmap[] =
|
||||
{
|
||||
PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
|
||||
PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
|
||||
PT_SR, PT_PC,
|
||||
/* PT_FP0, ..., PT_FP7 */
|
||||
21, 24, 27, 30, 33, 36, 39, 42,
|
||||
/* PT_FPCR, PT_FPSR, PT_FPIAR */
|
||||
45, 46, 47
|
||||
};
|
||||
|
||||
/* Which ptrace request retrieves which registers?
|
||||
These apply to the corresponding SET requests as well. */
|
||||
#define NUM_GREGS (18)
|
||||
#define MAX_NUM_REGS (NUM_GREGS + 11)
|
||||
|
||||
int
|
||||
getregs_supplies (int regno)
|
||||
{
|
||||
return 0 <= regno && regno < NUM_GREGS;
|
||||
}
|
||||
|
||||
int
|
||||
getfpregs_supplies (int regno)
|
||||
{
|
||||
return FP0_REGNUM <= regno && regno <= FPI_REGNUM;
|
||||
}
|
||||
|
||||
/* Does the current host support the GETREGS request? */
|
||||
int have_ptrace_getregs =
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
|
||||
/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
|
||||
is stored. */
|
||||
|
||||
int
|
||||
m68k_linux_register_u_addr (int blockend, int regnum)
|
||||
{
|
||||
return (blockend + 4 * regmap[regnum]);
|
||||
}
|
||||
|
||||
|
||||
/* Fetching registers directly from the U area, one at a time. */
|
||||
|
||||
/* FIXME: This duplicates code from `inptrace.c'. The problem is that we
|
||||
define FETCH_INFERIOR_REGISTERS since we want to use our own versions
|
||||
of {fetch,store}_inferior_registers that use the GETREGS request. This
|
||||
means that the code in `infptrace.c' is #ifdef'd out. But we need to
|
||||
fall back on that code when GDB is running on top of a kernel that
|
||||
doesn't support the GETREGS request. */
|
||||
|
||||
#ifndef PT_READ_U
|
||||
#define PT_READ_U PTRACE_PEEKUSR
|
||||
#endif
|
||||
#ifndef PT_WRITE_U
|
||||
#define PT_WRITE_U PTRACE_POKEUSR
|
||||
#endif
|
||||
|
||||
/* Default the type of the ptrace transfer to int. */
|
||||
#ifndef PTRACE_XFER_TYPE
|
||||
#define PTRACE_XFER_TYPE int
|
||||
#endif
|
||||
|
||||
/* Fetch one register. */
|
||||
|
||||
static void
|
||||
fetch_register (int regno)
|
||||
{
|
||||
/* This isn't really an address. But ptrace thinks of it as one. */
|
||||
CORE_ADDR regaddr;
|
||||
char mess[128]; /* For messages */
|
||||
register int i;
|
||||
unsigned int offset; /* Offset of registers within the u area. */
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
int tid;
|
||||
|
||||
if (CANNOT_FETCH_REGISTER (regno))
|
||||
{
|
||||
memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
|
||||
supply_register (regno, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
|
||||
regaddr = register_addr (regno, offset);
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
|
||||
{
|
||||
errno = 0;
|
||||
*(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
regaddr += sizeof (PTRACE_XFER_TYPE);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (mess, "reading register %s (#%d)",
|
||||
REGISTER_NAME (regno), regno);
|
||||
perror_with_name (mess);
|
||||
}
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
|
||||
/* Fetch register values from the inferior.
|
||||
If REGNO is negative, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
old_fetch_inferior_registers (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store one register. */
|
||||
|
||||
static void
|
||||
store_register (int regno)
|
||||
{
|
||||
/* This isn't really an address. But ptrace thinks of it as one. */
|
||||
CORE_ADDR regaddr;
|
||||
char mess[128]; /* For messages */
|
||||
register int i;
|
||||
unsigned int offset; /* Offset of registers within the u area. */
|
||||
int tid;
|
||||
char *buf = alloca (MAX_REGISTER_RAW_SIZE);
|
||||
|
||||
if (CANNOT_STORE_REGISTER (regno))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
|
||||
regaddr = register_addr (regno, offset);
|
||||
|
||||
/* Put the contents of regno into a local buffer */
|
||||
regcache_collect (regno, buf);
|
||||
|
||||
/* Store the local buffer into the inferior a chunk at the time. */
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
*(PTRACE_XFER_TYPE *) (buf + i));
|
||||
regaddr += sizeof (PTRACE_XFER_TYPE);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (mess, "writing register %s (#%d)",
|
||||
REGISTER_NAME (regno), regno);
|
||||
perror_with_name (mess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is negative, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
old_store_inferior_registers (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a pointer to a general register set in /proc format
|
||||
(elf_gregset_t *), unpack the register contents and supply
|
||||
them as gdb's idea of the current register values. */
|
||||
|
||||
|
||||
/* Note both m68k-tdep.c and m68klinux-nat.c contain definitions
|
||||
for supply_gregset and supply_fpregset. The definitions
|
||||
in m68k-tdep.c are valid if USE_PROC_FS is defined. Otherwise,
|
||||
the definitions in m68klinux-nat.c will be used. This is a
|
||||
bit of a hack. The supply_* routines do not belong in
|
||||
*_tdep.c files. But, there are several lynx ports that currently
|
||||
depend on these definitions. */
|
||||
|
||||
#ifndef USE_PROC_FS
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
void
|
||||
supply_gregset (elf_gregset_t *gregsetp)
|
||||
{
|
||||
elf_greg_t *regp = (elf_greg_t *) gregsetp;
|
||||
int regi;
|
||||
|
||||
for (regi = D0_REGNUM; regi <= SP_REGNUM; regi++)
|
||||
supply_register (regi, (char *) ®p[regmap[regi]]);
|
||||
supply_register (PS_REGNUM, (char *) ®p[PT_SR]);
|
||||
supply_register (PC_REGNUM, (char *) ®p[PT_PC]);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a general-purpose register) in
|
||||
*GREGSETPS with the value in GDB's register array. If REGNO is -1,
|
||||
do this for all registers. */
|
||||
void
|
||||
fill_gregset (elf_gregset_t *gregsetp, int regno)
|
||||
{
|
||||
elf_greg_t *regp = (elf_greg_t *) gregsetp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
if ((regno == -1 || regno == i))
|
||||
regcache_collect (i, regp + regmap[i]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Fetch all general-purpose registers from process/thread TID and
|
||||
store their values in GDB's register array. */
|
||||
|
||||
static void
|
||||
fetch_regs (int tid)
|
||||
{
|
||||
elf_gregset_t regs;
|
||||
|
||||
if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0)
|
||||
{
|
||||
if (errno == EIO)
|
||||
{
|
||||
/* The kernel we're running on doesn't support the GETREGS
|
||||
request. Reset `have_ptrace_getregs'. */
|
||||
have_ptrace_getregs = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
perror_with_name ("Couldn't get registers");
|
||||
}
|
||||
|
||||
supply_gregset (®s);
|
||||
}
|
||||
|
||||
/* Store all valid general-purpose registers in GDB's register array
|
||||
into the process/thread specified by TID. */
|
||||
|
||||
static void
|
||||
store_regs (int tid, int regno)
|
||||
{
|
||||
elf_gregset_t regs;
|
||||
|
||||
if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
fill_gregset (®s, regno);
|
||||
|
||||
if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0)
|
||||
perror_with_name ("Couldn't write registers");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void fetch_regs (int tid) {}
|
||||
static void store_regs (int tid, int regno) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Transfering floating-point registers between GDB, inferiors and cores. */
|
||||
|
||||
/* What is the address of fpN within the floating-point register set F? */
|
||||
#define FPREG_ADDR(f, n) ((char *) &(f)->fpregs[(n) * 3])
|
||||
|
||||
/* Fill GDB's register array with the floating-point register values in
|
||||
*FPREGSETP. */
|
||||
|
||||
void
|
||||
supply_fpregset (elf_fpregset_t *fpregsetp)
|
||||
{
|
||||
int regi;
|
||||
|
||||
for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
|
||||
supply_register (regi, FPREG_ADDR (fpregsetp, regi - FP0_REGNUM));
|
||||
supply_register (FPC_REGNUM, (char *) &fpregsetp->fpcntl[0]);
|
||||
supply_register (FPS_REGNUM, (char *) &fpregsetp->fpcntl[1]);
|
||||
supply_register (FPI_REGNUM, (char *) &fpregsetp->fpcntl[2]);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a floating-point register) in
|
||||
*FPREGSETP with the value in GDB's register array. If REGNO is -1,
|
||||
do this for all registers. */
|
||||
|
||||
void
|
||||
fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Fill in the floating-point registers. */
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + 8; i++)
|
||||
if (regno == -1 || regno == i)
|
||||
regcache_collect (regno, FPREG_ADDR (fpregsetp, regno - FP0_REGNUM));
|
||||
|
||||
/* Fill in the floating-point control registers. */
|
||||
for (i = FPC_REGNUM; i <= FPI_REGNUM; i++)
|
||||
if (regno == -1 || regno == i)
|
||||
regcache_collect (regno, (char *) &fpregsetp->fpcntl[regno - FPC_REGNUM]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Fetch all floating-point registers from process/thread TID and store
|
||||
thier values in GDB's register array. */
|
||||
|
||||
static void
|
||||
fetch_fpregs (int tid)
|
||||
{
|
||||
elf_fpregset_t fpregs;
|
||||
|
||||
if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
supply_fpregset (&fpregs);
|
||||
}
|
||||
|
||||
/* Store all valid floating-point registers in GDB's register array
|
||||
into the process/thread specified by TID. */
|
||||
|
||||
static void
|
||||
store_fpregs (int tid, int regno)
|
||||
{
|
||||
elf_fpregset_t fpregs;
|
||||
|
||||
if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
fill_fpregset (&fpregs, regno);
|
||||
|
||||
if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0)
|
||||
perror_with_name ("Couldn't write floating point status");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void fetch_fpregs (int tid) {}
|
||||
static void store_fpregs (int tid, int regno) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Transferring arbitrary registers between GDB and inferior. */
|
||||
|
||||
/* Fetch register REGNO from the child process. If REGNO is -1, do
|
||||
this for all registers (including the floating point and SSE
|
||||
registers). */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
int tid;
|
||||
|
||||
/* Use the old method of peeking around in `struct user' if the
|
||||
GETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
||||
|
||||
/* Use the PTRACE_GETFPXREGS request whenever possible, since it
|
||||
transfers more registers in one system call, and we'll cache the
|
||||
results. But remember that fetch_fpxregs can fail, and return
|
||||
zero. */
|
||||
if (regno == -1)
|
||||
{
|
||||
fetch_regs (tid);
|
||||
|
||||
/* The call above might reset `have_ptrace_getregs'. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (-1);
|
||||
return;
|
||||
}
|
||||
|
||||
fetch_fpregs (tid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getregs_supplies (regno))
|
||||
{
|
||||
fetch_regs (tid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getfpregs_supplies (regno))
|
||||
{
|
||||
fetch_fpregs (tid);
|
||||
return;
|
||||
}
|
||||
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"Got request for bad register number %d.", regno);
|
||||
}
|
||||
|
||||
/* Store register REGNO back into the child process. If REGNO is -1,
|
||||
do this for all registers (including the floating point and SSE
|
||||
registers). */
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
int tid;
|
||||
|
||||
/* Use the old method of poking around in `struct user' if the
|
||||
SETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_store_inferior_registers (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
||||
|
||||
/* Use the PTRACE_SETFPREGS requests whenever possible, since it
|
||||
transfers more registers in one system call. But remember that
|
||||
store_fpregs can fail, and return zero. */
|
||||
if (regno == -1)
|
||||
{
|
||||
store_regs (tid, regno);
|
||||
store_fpregs (tid, regno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getregs_supplies (regno))
|
||||
{
|
||||
store_regs (tid, regno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getfpregs_supplies (regno))
|
||||
{
|
||||
store_fpregs (tid, regno);
|
||||
return;
|
||||
}
|
||||
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"Got request to store bad register number %d.", regno);
|
||||
}
|
||||
|
||||
/* Interpreting register set info found in core files. */
|
||||
|
||||
/* Provide registers to GDB from a core file.
|
||||
|
||||
(We can't use the generic version of this function in
|
||||
core-regset.c, because we need to use elf_gregset_t instead of
|
||||
gregset_t.)
|
||||
|
||||
CORE_REG_SECT points to an array of bytes, which are the contents
|
||||
of a `note' from a core file which BFD thinks might contain
|
||||
register contents. CORE_REG_SIZE is its size.
|
||||
|
||||
WHICH says which register set corelow suspects this is:
|
||||
0 --- the general-purpose register set, in elf_gregset_t format
|
||||
2 --- the floating-point register set, in elf_fpregset_t format
|
||||
|
||||
REG_ADDR isn't used on GNU/Linux. */
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
|
||||
int which, CORE_ADDR reg_addr)
|
||||
{
|
||||
elf_gregset_t gregset;
|
||||
elf_fpregset_t fpregset;
|
||||
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
if (core_reg_size != sizeof (gregset))
|
||||
warning ("Wrong size gregset in core file.");
|
||||
else
|
||||
{
|
||||
memcpy (&gregset, core_reg_sect, sizeof (gregset));
|
||||
supply_gregset (&gregset);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (core_reg_size != sizeof (fpregset))
|
||||
warning ("Wrong size fpregset in core file.");
|
||||
else
|
||||
{
|
||||
memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
|
||||
supply_fpregset (&fpregset);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* We've covered all the kinds of registers we know about here,
|
||||
so this must be something we wouldn't know what to do with
|
||||
anyway. Just ignore it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
kernel_u_size (void)
|
||||
{
|
||||
return (sizeof (struct user));
|
||||
}
|
||||
|
||||
/* Check whether insn1 and insn2 are parts of a signal trampoline. */
|
||||
|
||||
#define IS_SIGTRAMP(insn1, insn2) \
|
||||
(/* addaw #20,sp; moveq #119,d0; trap #0 */ \
|
||||
(insn1 == 0xdefc0014 && insn2 == 0x70774e40) \
|
||||
/* moveq #119,d0; trap #0 */ \
|
||||
|| insn1 == 0x70774e40)
|
||||
|
||||
#define IS_RT_SIGTRAMP(insn1, insn2) \
|
||||
(/* movel #173,d0; trap #0 */ \
|
||||
(insn1 == 0x203c0000 && insn2 == 0x00ad4e40) \
|
||||
/* moveq #82,d0; notb d0; trap #0 */ \
|
||||
|| (insn1 == 0x70524600 && (insn2 >> 16) == 0x4e40))
|
||||
|
||||
/* Return non-zero if PC points into the signal trampoline. For the sake
|
||||
of m68k_linux_frame_saved_pc we also distinguish between non-RT and RT
|
||||
signal trampolines. */
|
||||
|
||||
int
|
||||
m68k_linux_in_sigtramp (CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR sp;
|
||||
char buf[12];
|
||||
unsigned long insn0, insn1, insn2;
|
||||
|
||||
if (read_memory_nobpt (pc - 4, buf, sizeof (buf)))
|
||||
return 0;
|
||||
insn1 = extract_unsigned_integer (buf + 4, 4);
|
||||
insn2 = extract_unsigned_integer (buf + 8, 4);
|
||||
if (IS_SIGTRAMP (insn1, insn2))
|
||||
return 1;
|
||||
if (IS_RT_SIGTRAMP (insn1, insn2))
|
||||
return 2;
|
||||
|
||||
insn0 = extract_unsigned_integer (buf, 4);
|
||||
if (IS_SIGTRAMP (insn0, insn1))
|
||||
return 1;
|
||||
if (IS_RT_SIGTRAMP (insn0, insn1))
|
||||
return 2;
|
||||
|
||||
insn0 = (insn0 << 16) | (insn1 >> 16);
|
||||
insn1 = (insn1 << 16) | (insn2 >> 16);
|
||||
if (IS_SIGTRAMP (insn0, insn1))
|
||||
return 1;
|
||||
if (IS_RT_SIGTRAMP (insn0, insn1))
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
|
||||
#define SIGCONTEXT_PC_OFFSET 26
|
||||
|
||||
/* Offset to saved PC in ucontext, from <asm/ucontext.h>. */
|
||||
#define UCONTEXT_PC_OFFSET 88
|
||||
|
||||
/* Get saved user PC for sigtramp from sigcontext or ucontext. */
|
||||
|
||||
static CORE_ADDR
|
||||
m68k_linux_sigtramp_saved_pc (struct frame_info *frame)
|
||||
{
|
||||
CORE_ADDR sigcontext_addr;
|
||||
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
|
||||
int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
|
||||
int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
|
||||
|
||||
/* Get sigcontext address, it is the third parameter on the stack. */
|
||||
if (frame->next)
|
||||
sigcontext_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
|
||||
+ FRAME_ARGS_SKIP
|
||||
+ sigcontext_offs,
|
||||
ptrbytes);
|
||||
else
|
||||
sigcontext_addr = read_memory_integer (read_register (SP_REGNUM)
|
||||
+ sigcontext_offs,
|
||||
ptrbytes);
|
||||
|
||||
/* Don't cause a memory_error when accessing sigcontext in case the
|
||||
stack layout has changed or the stack is corrupt. */
|
||||
if (m68k_linux_in_sigtramp (frame->pc) == 2)
|
||||
target_read_memory (sigcontext_addr + UCONTEXT_PC_OFFSET, buf, ptrbytes);
|
||||
else
|
||||
target_read_memory (sigcontext_addr + SIGCONTEXT_PC_OFFSET, buf, ptrbytes);
|
||||
return extract_unsigned_integer (buf, ptrbytes);
|
||||
}
|
||||
|
||||
/* Return the saved program counter for FRAME. */
|
||||
|
||||
CORE_ADDR
|
||||
m68k_linux_frame_saved_pc (struct frame_info *frame)
|
||||
{
|
||||
if (frame->signal_handler_caller)
|
||||
return m68k_linux_sigtramp_saved_pc (frame);
|
||||
|
||||
return read_memory_integer (frame->frame + 4, 4);
|
||||
}
|
||||
|
||||
/* Register that we are able to handle GNU/Linux ELF core file
|
||||
formats. */
|
||||
|
||||
static struct core_fns linux_elf_core_fns =
|
||||
{
|
||||
bfd_target_elf_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_m68k_linux_nat ()
|
||||
{
|
||||
add_core_fns (&linux_elf_core_fns);
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/* Native-dependent code for Motorola m68k's running NetBSD, for GDB.
|
||||
Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/frame.h>
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
struct fpreg inferior_fp_registers;
|
||||
|
||||
ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers, 0);
|
||||
memcpy (®isters[REGISTER_BYTE (0)], &inferior_registers,
|
||||
sizeof (inferior_registers));
|
||||
|
||||
ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers, 0);
|
||||
memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
|
||||
sizeof (inferior_fp_registers));
|
||||
|
||||
registers_fetched ();
|
||||
}
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
struct fpreg inferior_fp_registers;
|
||||
|
||||
memcpy (&inferior_registers, ®isters[REGISTER_BYTE (0)],
|
||||
sizeof (inferior_registers));
|
||||
ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers, 0);
|
||||
|
||||
memcpy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
sizeof (inferior_fp_registers));
|
||||
ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fp_registers, 0);
|
||||
}
|
||||
|
||||
struct md_core
|
||||
{
|
||||
struct reg intreg;
|
||||
struct fpreg freg;
|
||||
};
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR ignore)
|
||||
{
|
||||
struct md_core *core_reg = (struct md_core *) core_reg_sect;
|
||||
|
||||
/* Integer registers */
|
||||
memcpy (®isters[REGISTER_BYTE (0)],
|
||||
&core_reg->intreg, sizeof (struct reg));
|
||||
/* Floating point registers */
|
||||
memcpy (®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||
&core_reg->freg, sizeof (struct fpreg));
|
||||
}
|
||||
|
||||
/* Register that we are able to handle m68knbsd core file formats.
|
||||
FIXME: is this really bfd_target_unknown_flavour? */
|
||||
|
||||
static struct core_fns m68knbsd_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_m68knbsd_nat (void)
|
||||
{
|
||||
add_core_fns (&m68knbsd_core_fns);
|
||||
}
|
@ -1,290 +0,0 @@
|
||||
/* Native-dependent Motorola 88xxx support for GDB, the GNU Debugger.
|
||||
Copyright 1988, 1990, 1991, 1992, 1993, 1995, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <signal.h>
|
||||
#include "gdbcore.h"
|
||||
#include <sys/user.h>
|
||||
|
||||
#ifndef USER /* added to support BCS ptrace_user */
|
||||
#define USER ptrace_user
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include "gdb_stat.h"
|
||||
|
||||
#include "symtab.h"
|
||||
#include "setjmp.h"
|
||||
#include "value.h"
|
||||
|
||||
#ifdef DELTA88
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
/* define offsets to the pc instruction offsets in ptrace_user struct */
|
||||
#define SXIP_OFFSET ((char *)&u.pt_sigframe.sig_sxip - (char *)&u)
|
||||
#define SNIP_OFFSET ((char *)&u.pt_sigframe.sig_snip - (char *)&u)
|
||||
#define SFIP_OFFSET ((char *)&u.pt_sigframe.sig_sfip - (char *)&u)
|
||||
#else
|
||||
/* define offsets to the pc instruction offsets in ptrace_user struct */
|
||||
#define SXIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u)
|
||||
#define SNIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u)
|
||||
#define SFIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u)
|
||||
#endif
|
||||
|
||||
extern int have_symbol_file_p ();
|
||||
|
||||
extern jmp_buf stack_jmp;
|
||||
|
||||
extern int errno;
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
register int i;
|
||||
|
||||
struct USER u;
|
||||
unsigned int offset;
|
||||
|
||||
offset = (char *) &u.pt_r0 - (char *) &u;
|
||||
regaddr = offset; /* byte offset to r0; */
|
||||
|
||||
/* offset = ptrace (3, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
/*regaddr = register_addr (regno, offset); */
|
||||
/* 88k enhancement */
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
|
||||
{
|
||||
*(int *) &buf[i] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
regaddr += sizeof (int);
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
/* now load up registers 36 - 38; special pc registers */
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, 0);
|
||||
supply_register (SXIP_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, 0);
|
||||
supply_register (SNIP_REGNUM, buf);
|
||||
*(int *) &buf[0] = ptrace (3, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, 0);
|
||||
supply_register (SFIP_REGNUM, buf);
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[80];
|
||||
|
||||
struct USER u;
|
||||
|
||||
unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
|
||||
|
||||
regaddr = offset;
|
||||
|
||||
/* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
|
||||
svr3 doesn't run on an 88110, or the kernel isolates the different (not
|
||||
completely sure this is true, but seems to be. */
|
||||
if (regno >= 0)
|
||||
{
|
||||
/* regaddr = register_addr (regno, offset); */
|
||||
if (regno < PC_REGNUM)
|
||||
{
|
||||
regaddr = offset + regno * sizeof (int);
|
||||
errno = 0;
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
else if (regno == SXIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register (regno));
|
||||
else if (regno == SNIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register (regno));
|
||||
else if (regno == SFIP_REGNUM)
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register (regno));
|
||||
else
|
||||
printf_unfiltered ("Bad register number for store_inferior routine\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < PC_REGNUM; regno++)
|
||||
{
|
||||
/* regaddr = register_addr (regno, offset); */
|
||||
errno = 0;
|
||||
regaddr = offset + regno * sizeof (int);
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) regaddr, read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register (SXIP_REGNUM));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register (SNIP_REGNUM));
|
||||
ptrace (6, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register (SFIP_REGNUM));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* blockend is the address of the end of the user structure */
|
||||
m88k_register_u_addr (int blockend, int regnum)
|
||||
{
|
||||
struct USER u;
|
||||
int ustart = blockend - sizeof (struct USER);
|
||||
switch (regnum)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
return (ustart + ((int) &u.pt_r0 - (int) &u) + REGISTER_SIZE * regnum);
|
||||
case PSR_REGNUM:
|
||||
return (ustart + ((int) &u.pt_psr - (int) &u));
|
||||
case FPSR_REGNUM:
|
||||
return (ustart + ((int) &u.pt_fpsr - (int) &u));
|
||||
case FPCR_REGNUM:
|
||||
return (ustart + ((int) &u.pt_fpcr - (int) &u));
|
||||
case SXIP_REGNUM:
|
||||
return (ustart + SXIP_OFFSET);
|
||||
case SNIP_REGNUM:
|
||||
return (ustart + SNIP_OFFSET);
|
||||
case SFIP_REGNUM:
|
||||
return (ustart + SFIP_OFFSET);
|
||||
default:
|
||||
if (regnum < NUM_REGS)
|
||||
/* The register is one of those which is not defined...
|
||||
give it zero */
|
||||
return (ustart + ((int) &u.pt_r0 - (int) &u));
|
||||
else
|
||||
return (blockend + REGISTER_SIZE * regnum);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PROC_FS
|
||||
|
||||
#include <sys/procfs.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
register int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi <= SP_REGNUM; regi++)
|
||||
supply_register (regi, (char *) (regp + regi));
|
||||
|
||||
supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
|
||||
supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
|
||||
supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
|
||||
supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
|
||||
supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
|
||||
supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
register greg_t *regp = (greg_t *) gregsetp;
|
||||
|
||||
for (regi = 0; regi <= R_R31; regi++)
|
||||
if ((regno == -1) || (regno == regi))
|
||||
*(regp + regi) = *(int *) ®isters[REGISTER_BYTE (regi)];
|
||||
|
||||
if ((regno == -1) || (regno == SXIP_REGNUM))
|
||||
*(regp + R_XIP) = *(int *) ®isters[REGISTER_BYTE (SXIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == SNIP_REGNUM))
|
||||
*(regp + R_NIP) = *(int *) ®isters[REGISTER_BYTE (SNIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == SFIP_REGNUM))
|
||||
*(regp + R_FIP) = *(int *) ®isters[REGISTER_BYTE (SFIP_REGNUM)];
|
||||
if ((regno == -1) || (regno == PSR_REGNUM))
|
||||
*(regp + R_PSR) = *(int *) ®isters[REGISTER_BYTE (PSR_REGNUM)];
|
||||
if ((regno == -1) || (regno == FPSR_REGNUM))
|
||||
*(regp + R_FPSR) = *(int *) ®isters[REGISTER_BYTE (FPSR_REGNUM)];
|
||||
if ((regno == -1) || (regno == FPCR_REGNUM))
|
||||
*(regp + R_FPCR) = *(int *) ®isters[REGISTER_BYTE (FPCR_REGNUM)];
|
||||
}
|
||||
|
||||
#endif /* USE_PROC_FS */
|
@ -1,634 +0,0 @@
|
||||
/* Target-machine dependent code for Motorola 88000 series, for GDB.
|
||||
Copyright 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000,
|
||||
2001 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "symtab.h"
|
||||
#include "setjmp.h"
|
||||
#include "value.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* Size of an instruction */
|
||||
#define BYTES_PER_88K_INSN 4
|
||||
|
||||
void frame_find_saved_regs ();
|
||||
|
||||
/* Is this target an m88110? Otherwise assume m88100. This has
|
||||
relevance for the ways in which we screw with instruction pointers. */
|
||||
|
||||
int target_is_m88110 = 0;
|
||||
|
||||
/* The type of a register. */
|
||||
struct type *
|
||||
m88k_register_type (int regnum)
|
||||
{
|
||||
if (regnum >= XFP_REGNUM)
|
||||
return builtin_type_m88110_ext;
|
||||
else if (regnum == PC_REGNUM || regnum == FP_REGNUM || regnum == SP_REGNUM)
|
||||
return builtin_type_void_func_ptr;
|
||||
else
|
||||
return builtin_type_int32;
|
||||
}
|
||||
|
||||
|
||||
/* The m88k kernel aligns all instructions on 4-byte boundaries. The
|
||||
kernel also uses the least significant two bits for its own hocus
|
||||
pocus. When gdb receives an address from the kernel, it needs to
|
||||
preserve those right-most two bits, but gdb also needs to be careful
|
||||
to realize that those two bits are not really a part of the address
|
||||
of an instruction. Shrug. */
|
||||
|
||||
CORE_ADDR
|
||||
m88k_addr_bits_remove (CORE_ADDR addr)
|
||||
{
|
||||
return ((addr) & ~3);
|
||||
}
|
||||
|
||||
|
||||
/* Given a GDB frame, determine the address of the calling function's frame.
|
||||
This will be used to create a new GDB frame struct, and then
|
||||
INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
|
||||
|
||||
For us, the frame address is its stack pointer value, so we look up
|
||||
the function prologue to determine the caller's sp value, and return it. */
|
||||
|
||||
CORE_ADDR
|
||||
frame_chain (struct frame_info *thisframe)
|
||||
{
|
||||
|
||||
frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
|
||||
/* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
|
||||
the ADDRESS, of SP_REGNUM. It also depends on the cache of
|
||||
frame_find_saved_regs results. */
|
||||
if (thisframe->fsr->regs[SP_REGNUM])
|
||||
return thisframe->fsr->regs[SP_REGNUM];
|
||||
else
|
||||
return thisframe->frame; /* Leaf fn -- next frame up has same SP. */
|
||||
}
|
||||
|
||||
int
|
||||
frameless_function_invocation (struct frame_info *frame)
|
||||
{
|
||||
|
||||
frame_find_saved_regs (frame, (struct frame_saved_regs *) 0);
|
||||
/* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
|
||||
the ADDRESS, of SP_REGNUM. It also depends on the cache of
|
||||
frame_find_saved_regs results. */
|
||||
if (frame->fsr->regs[SP_REGNUM])
|
||||
return 0; /* Frameful -- return addr saved somewhere */
|
||||
else
|
||||
return 1; /* Frameless -- no saved return address */
|
||||
}
|
||||
|
||||
void
|
||||
init_extra_frame_info (int fromleaf, struct frame_info *frame)
|
||||
{
|
||||
frame->fsr = 0; /* Not yet allocated */
|
||||
frame->args_pointer = 0; /* Unknown */
|
||||
frame->locals_pointer = 0; /* Unknown */
|
||||
}
|
||||
|
||||
/* Examine an m88k function prologue, recording the addresses at which
|
||||
registers are saved explicitly by the prologue code, and returning
|
||||
the address of the first instruction after the prologue (but not
|
||||
after the instruction at address LIMIT, as explained below).
|
||||
|
||||
LIMIT places an upper bound on addresses of the instructions to be
|
||||
examined. If the prologue code scan reaches LIMIT, the scan is
|
||||
aborted and LIMIT is returned. This is used, when examining the
|
||||
prologue for the current frame, to keep examine_prologue () from
|
||||
claiming that a given register has been saved when in fact the
|
||||
instruction that saves it has not yet been executed. LIMIT is used
|
||||
at other times to stop the scan when we hit code after the true
|
||||
function prologue (e.g. for the first source line) which might
|
||||
otherwise be mistaken for function prologue.
|
||||
|
||||
The format of the function prologue matched by this routine is
|
||||
derived from examination of the source to gcc 1.95, particularly
|
||||
the routine output_prologue () in config/out-m88k.c.
|
||||
|
||||
subu r31,r31,n # stack pointer update
|
||||
|
||||
(st rn,r31,offset)? # save incoming regs
|
||||
(st.d rn,r31,offset)?
|
||||
|
||||
(addu r30,r31,n)? # frame pointer update
|
||||
|
||||
(pic sequence)? # PIC code prologue
|
||||
|
||||
(or rn,rm,0)? # Move parameters to other regs
|
||||
*/
|
||||
|
||||
/* Macros for extracting fields from instructions. */
|
||||
|
||||
#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
|
||||
#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
|
||||
#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF))
|
||||
#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF))
|
||||
#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5)
|
||||
#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF))
|
||||
|
||||
/*
|
||||
* prologue_insn_tbl is a table of instructions which may comprise a
|
||||
* function prologue. Associated with each table entry (corresponding
|
||||
* to a single instruction or group of instructions), is an action.
|
||||
* This action is used by examine_prologue (below) to determine
|
||||
* the state of certain machine registers and where the stack frame lives.
|
||||
*/
|
||||
|
||||
enum prologue_insn_action
|
||||
{
|
||||
PIA_SKIP, /* don't care what the instruction does */
|
||||
PIA_NOTE_ST, /* note register stored and where */
|
||||
PIA_NOTE_STD, /* note pair of registers stored and where */
|
||||
PIA_NOTE_SP_ADJUSTMENT, /* note stack pointer adjustment */
|
||||
PIA_NOTE_FP_ASSIGNMENT, /* note frame pointer assignment */
|
||||
PIA_NOTE_PROLOGUE_END, /* no more prologue */
|
||||
};
|
||||
|
||||
struct prologue_insns
|
||||
{
|
||||
unsigned long insn;
|
||||
unsigned long mask;
|
||||
enum prologue_insn_action action;
|
||||
};
|
||||
|
||||
struct prologue_insns prologue_insn_tbl[] =
|
||||
{
|
||||
/* Various register move instructions */
|
||||
{0x58000000, 0xf800ffff, PIA_SKIP}, /* or/or.u with immed of 0 */
|
||||
{0xf4005800, 0xfc1fffe0, PIA_SKIP}, /* or rd, r0, rs */
|
||||
{0xf4005800, 0xfc00ffff, PIA_SKIP}, /* or rd, rs, r0 */
|
||||
|
||||
/* Stack pointer setup: "subu sp, sp, n" where n is a multiple of 8 */
|
||||
{0x67ff0000, 0xffff0007, PIA_NOTE_SP_ADJUSTMENT},
|
||||
|
||||
/* Frame pointer assignment: "addu r30, r31, n" */
|
||||
{0x63df0000, 0xffff0000, PIA_NOTE_FP_ASSIGNMENT},
|
||||
|
||||
/* Store to stack instructions; either "st rx, sp, n" or "st.d rx, sp, n" */
|
||||
{0x241f0000, 0xfc1f0000, PIA_NOTE_ST}, /* st rx, sp, n */
|
||||
{0x201f0000, 0xfc1f0000, PIA_NOTE_STD}, /* st.d rs, sp, n */
|
||||
|
||||
/* Instructions needed for setting up r25 for pic code. */
|
||||
{0x5f200000, 0xffff0000, PIA_SKIP}, /* or.u r25, r0, offset_high */
|
||||
{0xcc000002, 0xffffffff, PIA_SKIP}, /* bsr.n Lab */
|
||||
{0x5b390000, 0xffff0000, PIA_SKIP}, /* or r25, r25, offset_low */
|
||||
{0xf7396001, 0xffffffff, PIA_SKIP}, /* Lab: addu r25, r25, r1 */
|
||||
|
||||
/* Various branch or jump instructions which have a delay slot -- these
|
||||
do not form part of the prologue, but the instruction in the delay
|
||||
slot might be a store instruction which should be noted. */
|
||||
{0xc4000000, 0xe4000000, PIA_NOTE_PROLOGUE_END},
|
||||
/* br.n, bsr.n, bb0.n, or bb1.n */
|
||||
{0xec000000, 0xfc000000, PIA_NOTE_PROLOGUE_END}, /* bcnd.n */
|
||||
{0xf400c400, 0xfffff7e0, PIA_NOTE_PROLOGUE_END} /* jmp.n or jsr.n */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
|
||||
is not the address of a valid instruction, the address of the next
|
||||
instruction beyond ADDR otherwise. *PWORD1 receives the first word
|
||||
of the instruction. */
|
||||
|
||||
#define NEXT_PROLOGUE_INSN(addr, lim, pword1) \
|
||||
(((addr) < (lim)) ? next_insn (addr, pword1) : 0)
|
||||
|
||||
/* Read the m88k instruction at 'memaddr' and return the address of
|
||||
the next instruction after that, or 0 if 'memaddr' is not the
|
||||
address of a valid instruction. The instruction
|
||||
is stored at 'pword1'. */
|
||||
|
||||
CORE_ADDR
|
||||
next_insn (CORE_ADDR memaddr, unsigned long *pword1)
|
||||
{
|
||||
*pword1 = read_memory_integer (memaddr, BYTES_PER_88K_INSN);
|
||||
return memaddr + BYTES_PER_88K_INSN;
|
||||
}
|
||||
|
||||
/* Read a register from frames called by us (or from the hardware regs). */
|
||||
|
||||
static int
|
||||
read_next_frame_reg (struct frame_info *frame, int regno)
|
||||
{
|
||||
for (; frame; frame = frame->next)
|
||||
{
|
||||
if (regno == SP_REGNUM)
|
||||
return FRAME_FP (frame);
|
||||
else if (frame->fsr->regs[regno])
|
||||
return read_memory_integer (frame->fsr->regs[regno], 4);
|
||||
}
|
||||
return read_register (regno);
|
||||
}
|
||||
|
||||
/* Examine the prologue of a function. `ip' points to the first instruction.
|
||||
`limit' is the limit of the prologue (e.g. the addr of the first
|
||||
linenumber, or perhaps the program counter if we're stepping through).
|
||||
`frame_sp' is the stack pointer value in use in this frame.
|
||||
`fsr' is a pointer to a frame_saved_regs structure into which we put
|
||||
info about the registers saved by this frame.
|
||||
`fi' is a struct frame_info pointer; we fill in various fields in it
|
||||
to reflect the offsets of the arg pointer and the locals pointer. */
|
||||
|
||||
static CORE_ADDR
|
||||
examine_prologue (register CORE_ADDR ip, register CORE_ADDR limit,
|
||||
CORE_ADDR frame_sp, struct frame_saved_regs *fsr,
|
||||
struct frame_info *fi)
|
||||
{
|
||||
register CORE_ADDR next_ip;
|
||||
register int src;
|
||||
unsigned long insn;
|
||||
int size, offset;
|
||||
char must_adjust[32]; /* If set, must adjust offsets in fsr */
|
||||
int sp_offset = -1; /* -1 means not set (valid must be mult of 8) */
|
||||
int fp_offset = -1; /* -1 means not set */
|
||||
CORE_ADDR frame_fp;
|
||||
CORE_ADDR prologue_end = 0;
|
||||
|
||||
memset (must_adjust, '\0', sizeof (must_adjust));
|
||||
next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
|
||||
|
||||
while (next_ip)
|
||||
{
|
||||
struct prologue_insns *pip;
|
||||
|
||||
for (pip = prologue_insn_tbl; (insn & pip->mask) != pip->insn;)
|
||||
if (++pip >= prologue_insn_tbl + sizeof prologue_insn_tbl)
|
||||
goto end_of_prologue_found; /* not a prologue insn */
|
||||
|
||||
switch (pip->action)
|
||||
{
|
||||
case PIA_NOTE_ST:
|
||||
case PIA_NOTE_STD:
|
||||
if (sp_offset != -1)
|
||||
{
|
||||
src = ST_SRC (insn);
|
||||
offset = ST_OFFSET (insn);
|
||||
must_adjust[src] = 1;
|
||||
fsr->regs[src++] = offset; /* Will be adjusted later */
|
||||
if (pip->action == PIA_NOTE_STD && src < 32)
|
||||
{
|
||||
offset += 4;
|
||||
must_adjust[src] = 1;
|
||||
fsr->regs[src++] = offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto end_of_prologue_found;
|
||||
break;
|
||||
case PIA_NOTE_SP_ADJUSTMENT:
|
||||
if (sp_offset == -1)
|
||||
sp_offset = -SUBU_OFFSET (insn);
|
||||
else
|
||||
goto end_of_prologue_found;
|
||||
break;
|
||||
case PIA_NOTE_FP_ASSIGNMENT:
|
||||
if (fp_offset == -1)
|
||||
fp_offset = ADDU_OFFSET (insn);
|
||||
else
|
||||
goto end_of_prologue_found;
|
||||
break;
|
||||
case PIA_NOTE_PROLOGUE_END:
|
||||
if (!prologue_end)
|
||||
prologue_end = ip;
|
||||
break;
|
||||
case PIA_SKIP:
|
||||
default:
|
||||
/* Do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
ip = next_ip;
|
||||
next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
|
||||
}
|
||||
|
||||
end_of_prologue_found:
|
||||
|
||||
if (prologue_end)
|
||||
ip = prologue_end;
|
||||
|
||||
/* We're done with the prologue. If we don't care about the stack
|
||||
frame itself, just return. (Note that fsr->regs has been trashed,
|
||||
but the one caller who calls with fi==0 passes a dummy there.) */
|
||||
|
||||
if (fi == 0)
|
||||
return ip;
|
||||
|
||||
/*
|
||||
OK, now we have:
|
||||
|
||||
sp_offset original (before any alloca calls) displacement of SP
|
||||
(will be negative).
|
||||
|
||||
fp_offset displacement from original SP to the FP for this frame
|
||||
or -1.
|
||||
|
||||
fsr->regs[0..31] displacement from original SP to the stack
|
||||
location where reg[0..31] is stored.
|
||||
|
||||
must_adjust[0..31] set if corresponding offset was set.
|
||||
|
||||
If alloca has been called between the function prologue and the current
|
||||
IP, then the current SP (frame_sp) will not be the original SP as set by
|
||||
the function prologue. If the current SP is not the original SP, then the
|
||||
compiler will have allocated an FP for this frame, fp_offset will be set,
|
||||
and we can use it to calculate the original SP.
|
||||
|
||||
Then, we figure out where the arguments and locals are, and relocate the
|
||||
offsets in fsr->regs to absolute addresses. */
|
||||
|
||||
if (fp_offset != -1)
|
||||
{
|
||||
/* We have a frame pointer, so get it, and base our calc's on it. */
|
||||
frame_fp = (CORE_ADDR) read_next_frame_reg (fi->next, ACTUAL_FP_REGNUM);
|
||||
frame_sp = frame_fp - fp_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have no frame pointer, therefore frame_sp is still the same value
|
||||
as set by prologue. But where is the frame itself? */
|
||||
if (must_adjust[SRP_REGNUM])
|
||||
{
|
||||
/* Function header saved SRP (r1), the return address. Frame starts
|
||||
4 bytes down from where it was saved. */
|
||||
frame_fp = frame_sp + fsr->regs[SRP_REGNUM] - 4;
|
||||
fi->locals_pointer = frame_fp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Function header didn't save SRP (r1), so we are in a leaf fn or
|
||||
are otherwise confused. */
|
||||
frame_fp = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The locals are relative to the FP (whether it exists as an allocated
|
||||
register, or just as an assumed offset from the SP) */
|
||||
fi->locals_pointer = frame_fp;
|
||||
|
||||
/* The arguments are just above the SP as it was before we adjusted it
|
||||
on entry. */
|
||||
fi->args_pointer = frame_sp - sp_offset;
|
||||
|
||||
/* Now that we know the SP value used by the prologue, we know where
|
||||
it saved all the registers. */
|
||||
for (src = 0; src < 32; src++)
|
||||
if (must_adjust[src])
|
||||
fsr->regs[src] += frame_sp;
|
||||
|
||||
/* The saved value of the SP is always known. */
|
||||
/* (we hope...) */
|
||||
if (fsr->regs[SP_REGNUM] != 0
|
||||
&& fsr->regs[SP_REGNUM] != frame_sp - sp_offset)
|
||||
fprintf_unfiltered (gdb_stderr, "Bad saved SP value %lx != %lx, offset %x!\n",
|
||||
fsr->regs[SP_REGNUM],
|
||||
frame_sp - sp_offset, sp_offset);
|
||||
|
||||
fsr->regs[SP_REGNUM] = frame_sp - sp_offset;
|
||||
|
||||
return (ip);
|
||||
}
|
||||
|
||||
/* Given an ip value corresponding to the start of a function,
|
||||
return the ip of the first instruction after the function
|
||||
prologue. */
|
||||
|
||||
CORE_ADDR
|
||||
m88k_skip_prologue (CORE_ADDR ip)
|
||||
{
|
||||
struct frame_saved_regs saved_regs_dummy;
|
||||
struct symtab_and_line sal;
|
||||
CORE_ADDR limit;
|
||||
|
||||
sal = find_pc_line (ip, 0);
|
||||
limit = (sal.end) ? sal.end : 0xffffffff;
|
||||
|
||||
return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy,
|
||||
(struct frame_info *) 0));
|
||||
}
|
||||
|
||||
/* Put here the code to store, into a struct frame_saved_regs,
|
||||
the addresses of the saved registers of frame described by FRAME_INFO.
|
||||
This includes special registers such as pc and fp saved in special
|
||||
ways in the stack frame. sp is even more special:
|
||||
the address we return for it IS the sp for the next frame.
|
||||
|
||||
We cache the result of doing this in the frame_obstack, since it is
|
||||
fairly expensive. */
|
||||
|
||||
void
|
||||
frame_find_saved_regs (struct frame_info *fi, struct frame_saved_regs *fsr)
|
||||
{
|
||||
register struct frame_saved_regs *cache_fsr;
|
||||
CORE_ADDR ip;
|
||||
struct symtab_and_line sal;
|
||||
CORE_ADDR limit;
|
||||
|
||||
if (!fi->fsr)
|
||||
{
|
||||
cache_fsr = (struct frame_saved_regs *)
|
||||
frame_obstack_alloc (sizeof (struct frame_saved_regs));
|
||||
memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
|
||||
fi->fsr = cache_fsr;
|
||||
|
||||
/* Find the start and end of the function prologue. If the PC
|
||||
is in the function prologue, we only consider the part that
|
||||
has executed already. In the case where the PC is not in
|
||||
the function prologue, we set limit to two instructions beyond
|
||||
where the prologue ends in case if any of the prologue instructions
|
||||
were moved into a delay slot of a branch instruction. */
|
||||
|
||||
ip = get_pc_function_start (fi->pc);
|
||||
sal = find_pc_line (ip, 0);
|
||||
limit = (sal.end && sal.end < fi->pc) ? sal.end + 2 * BYTES_PER_88K_INSN
|
||||
: fi->pc;
|
||||
|
||||
/* This will fill in fields in *fi as well as in cache_fsr. */
|
||||
#ifdef SIGTRAMP_FRAME_FIXUP
|
||||
if (fi->signal_handler_caller)
|
||||
SIGTRAMP_FRAME_FIXUP (fi->frame);
|
||||
#endif
|
||||
examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
|
||||
#ifdef SIGTRAMP_SP_FIXUP
|
||||
if (fi->signal_handler_caller && fi->fsr->regs[SP_REGNUM])
|
||||
SIGTRAMP_SP_FIXUP (fi->fsr->regs[SP_REGNUM]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fsr)
|
||||
*fsr = *fi->fsr;
|
||||
}
|
||||
|
||||
/* Return the address of the locals block for the frame
|
||||
described by FI. Returns 0 if the address is unknown.
|
||||
NOTE! Frame locals are referred to by negative offsets from the
|
||||
argument pointer, so this is the same as frame_args_address(). */
|
||||
|
||||
CORE_ADDR
|
||||
frame_locals_address (struct frame_info *fi)
|
||||
{
|
||||
struct frame_saved_regs fsr;
|
||||
|
||||
if (fi->args_pointer) /* Cached value is likely there. */
|
||||
return fi->args_pointer;
|
||||
|
||||
/* Nope, generate it. */
|
||||
|
||||
get_frame_saved_regs (fi, &fsr);
|
||||
|
||||
return fi->args_pointer;
|
||||
}
|
||||
|
||||
/* Return the address of the argument block for the frame
|
||||
described by FI. Returns 0 if the address is unknown. */
|
||||
|
||||
CORE_ADDR
|
||||
frame_args_address (struct frame_info *fi)
|
||||
{
|
||||
struct frame_saved_regs fsr;
|
||||
|
||||
if (fi->args_pointer) /* Cached value is likely there. */
|
||||
return fi->args_pointer;
|
||||
|
||||
/* Nope, generate it. */
|
||||
|
||||
get_frame_saved_regs (fi, &fsr);
|
||||
|
||||
return fi->args_pointer;
|
||||
}
|
||||
|
||||
/* Return the saved PC from this frame.
|
||||
|
||||
If the frame has a memory copy of SRP_REGNUM, use that. If not,
|
||||
just use the register SRP_REGNUM itself. */
|
||||
|
||||
CORE_ADDR
|
||||
frame_saved_pc (struct frame_info *frame)
|
||||
{
|
||||
return read_next_frame_reg (frame, SRP_REGNUM);
|
||||
}
|
||||
|
||||
|
||||
#define DUMMY_FRAME_SIZE 192
|
||||
|
||||
static void
|
||||
write_word (CORE_ADDR sp, ULONGEST word)
|
||||
{
|
||||
register int len = REGISTER_SIZE;
|
||||
char buffer[MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
store_unsigned_integer (buffer, len, word);
|
||||
write_memory (sp, buffer, len);
|
||||
}
|
||||
|
||||
void
|
||||
m88k_push_dummy_frame (void)
|
||||
{
|
||||
register CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
register int rn;
|
||||
int offset;
|
||||
|
||||
sp -= DUMMY_FRAME_SIZE; /* allocate a bunch of space */
|
||||
|
||||
for (rn = 0, offset = 0; rn <= SP_REGNUM; rn++, offset += 4)
|
||||
write_word (sp + offset, read_register (rn));
|
||||
|
||||
write_word (sp + offset, read_register (SXIP_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_word (sp + offset, read_register (SNIP_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_word (sp + offset, read_register (SFIP_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_word (sp + offset, read_register (PSR_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_word (sp + offset, read_register (FPSR_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_word (sp + offset, read_register (FPCR_REGNUM));
|
||||
offset += 4;
|
||||
|
||||
write_register (SP_REGNUM, sp);
|
||||
write_register (ACTUAL_FP_REGNUM, sp);
|
||||
}
|
||||
|
||||
void
|
||||
pop_frame (void)
|
||||
{
|
||||
register struct frame_info *frame = get_current_frame ();
|
||||
register int regnum;
|
||||
struct frame_saved_regs fsr;
|
||||
|
||||
get_frame_saved_regs (frame, &fsr);
|
||||
|
||||
if (PC_IN_CALL_DUMMY (read_pc (), read_register (SP_REGNUM), frame->frame))
|
||||
{
|
||||
/* FIXME: I think get_frame_saved_regs should be handling this so
|
||||
that we can deal with the saved registers properly (e.g. frame
|
||||
1 is a call dummy, the user types "frame 2" and then "print $ps"). */
|
||||
register CORE_ADDR sp = read_register (ACTUAL_FP_REGNUM);
|
||||
int offset;
|
||||
|
||||
for (regnum = 0, offset = 0; regnum <= SP_REGNUM; regnum++, offset += 4)
|
||||
(void) write_register (regnum, read_memory_integer (sp + offset, 4));
|
||||
|
||||
write_register (SXIP_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
write_register (SNIP_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
write_register (SFIP_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
write_register (PSR_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
write_register (FPSR_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
write_register (FPCR_REGNUM, read_memory_integer (sp + offset, 4));
|
||||
offset += 4;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regnum = FP_REGNUM; regnum > 0; regnum--)
|
||||
if (fsr.regs[regnum])
|
||||
write_register (regnum,
|
||||
read_memory_integer (fsr.regs[regnum], 4));
|
||||
write_pc (frame_saved_pc (frame));
|
||||
}
|
||||
reinit_frame_cache ();
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_m88k_tdep (void)
|
||||
{
|
||||
tm_print_insn = print_insn_m88k;
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
/* Remote target glue for the Intel 960 MON960 ROM monitor.
|
||||
Copyright 1995, 1996, 1997, 1998, 1999, 2000
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "srec.h"
|
||||
#include "xmodem.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h" /* for generic_load */
|
||||
#include "inferior.h" /* for write_pc() */
|
||||
|
||||
#define USE_GENERIC_LOAD
|
||||
|
||||
static struct target_ops mon960_ops;
|
||||
|
||||
static void mon960_open (char *args, int from_tty);
|
||||
|
||||
#ifdef USE_GENERIC_LOAD
|
||||
|
||||
static void
|
||||
mon960_load_gen (char *filename, int from_tty)
|
||||
{
|
||||
generic_load (filename, from_tty);
|
||||
/* Finally, make the PC point at the start address */
|
||||
if (exec_bfd)
|
||||
write_pc (bfd_get_start_address (exec_bfd));
|
||||
|
||||
inferior_ptid = null_ptid; /* No process now */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
mon960_load (struct serial *desc, char *file, int hashmark)
|
||||
{
|
||||
bfd *abfd;
|
||||
asection *s;
|
||||
char *buffer;
|
||||
int i;
|
||||
|
||||
buffer = alloca (XMODEM_PACKETSIZE);
|
||||
abfd = bfd_openr (file, 0);
|
||||
if (!abfd)
|
||||
{
|
||||
printf_filtered ("Unable to open file %s\n", file);
|
||||
return;
|
||||
}
|
||||
if (bfd_check_format (abfd, bfd_object) == 0)
|
||||
{
|
||||
printf_filtered ("File is not an object file\n");
|
||||
return;
|
||||
}
|
||||
for (s = abfd->sections; s; s = s->next)
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
bfd_size_type section_size;
|
||||
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
|
||||
s->vma + s->_raw_size);
|
||||
gdb_flush (gdb_stdout);
|
||||
monitor_printf (current_monitor->load, s->vma);
|
||||
if (current_monitor->loadresp)
|
||||
monitor_expect (current_monitor->loadresp, NULL, 0);
|
||||
xmodem_init_xfer (desc);
|
||||
section_size = bfd_section_size (abfd, s);
|
||||
for (i = 0; i < section_size; i += XMODEM_DATASIZE)
|
||||
{
|
||||
int numbytes;
|
||||
numbytes = min (XMODEM_DATASIZE, section_size - i);
|
||||
bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
|
||||
numbytes);
|
||||
xmodem_send_packet (desc, buffer, numbytes, hashmark);
|
||||
if (hashmark)
|
||||
{
|
||||
putchar_unfiltered ('#');
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
} /* Per-packet (or S-record) loop */
|
||||
xmodem_finish_xfer (desc);
|
||||
monitor_expect_prompt (NULL, 0);
|
||||
putchar_unfiltered ('\n');
|
||||
} /* Loadable sections */
|
||||
if (hashmark)
|
||||
putchar_unfiltered ('\n');
|
||||
}
|
||||
|
||||
#endif /* USE_GENERIC_LOAD */
|
||||
|
||||
/* This array of registers need to match the indexes used by GDB.
|
||||
This exists because the various ROM monitors use different strings
|
||||
than does GDB, and don't necessarily support all the registers
|
||||
either. So, typing "info reg sp" becomes a "r30". */
|
||||
|
||||
/* these correspond to the offsets from tm-* files from config directories */
|
||||
/* g0-g14, fp, pfp, sp, rip,r3-15, pc, ac, tc, fp0-3 */
|
||||
/* NOTE: "ip" is documented as "ir" in the Mon960 UG. */
|
||||
/* NOTE: "ir" can't be accessed... but there's an ip and rip. */
|
||||
static char *full_regnames[NUM_REGS] =
|
||||
{
|
||||
/* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7",
|
||||
/* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
/* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
|
||||
/* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp",
|
||||
/* 32 */ "pc", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",
|
||||
};
|
||||
|
||||
static char *mon960_regnames[NUM_REGS];
|
||||
|
||||
/* Define the monitor command strings. Since these are passed directly
|
||||
through to a printf style function, we may include formatting
|
||||
strings. We also need a CR or LF on the end. */
|
||||
|
||||
/* need to pause the monitor for timing reasons, so slow it down */
|
||||
|
||||
#if 0
|
||||
/* FIXME: this extremely long init string causes MON960 to return two NAKS
|
||||
instead of performing the autobaud recognition, at least when gdb
|
||||
is running on GNU/Linux. The short string below works on Linux, and on
|
||||
SunOS using a tcp serial connection. Must retest on SunOS using a
|
||||
direct serial connection; if that works, get rid of the long string. */
|
||||
static char *mon960_inits[] =
|
||||
{"\n\r\r\r\r\r\r\r\r\r\r\r\r\r\r\n\r\n\r\n", NULL};
|
||||
#else
|
||||
static char *mon960_inits[] =
|
||||
{"\r", NULL};
|
||||
#endif
|
||||
|
||||
static struct monitor_ops mon960_cmds;
|
||||
|
||||
static void
|
||||
init_mon960_cmds (void)
|
||||
{
|
||||
mon960_cmds.flags = MO_CLR_BREAK_USES_ADDR
|
||||
| MO_NO_ECHO_ON_OPEN | MO_SEND_BREAK_ON_STOP | MO_GETMEM_READ_SINGLE; /* flags */
|
||||
mon960_cmds.init = mon960_inits; /* Init strings */
|
||||
mon960_cmds.cont = "go\n\r"; /* continue command */
|
||||
mon960_cmds.step = "st\n\r"; /* single step */
|
||||
mon960_cmds.stop = NULL; /* break interrupts the program */
|
||||
mon960_cmds.set_break = NULL; /* set a breakpoint */
|
||||
mon960_cmds.clr_break = /* can't use "br" because only 2 hw bps are supported */
|
||||
mon960_cmds.clr_all_break = NULL; /* clear a breakpoint - "de" is for hw bps */
|
||||
NULL, /* clear all breakpoints */
|
||||
mon960_cmds.fill = NULL; /* fill (start end val) */
|
||||
/* can't use "fi" because it takes words, not bytes */
|
||||
/* can't use "mb", "md" or "mo" because they require interaction */
|
||||
mon960_cmds.setmem.cmdb = NULL; /* setmem.cmdb (addr, value) */
|
||||
mon960_cmds.setmem.cmdw = NULL; /* setmem.cmdw (addr, value) */
|
||||
mon960_cmds.setmem.cmdl = "md %x %x\n\r"; /* setmem.cmdl (addr, value) */
|
||||
mon960_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
mon960_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
|
||||
mon960_cmds.setmem.term = NULL; /* setmem.term */
|
||||
mon960_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
|
||||
/* since the parsing of multiple bytes is difficult due to
|
||||
interspersed addresses, we'll only read 1 value at a time,
|
||||
even tho these can handle a count */
|
||||
mon960_cmds.getmem.cmdb = "db %x\n\r"; /* getmem.cmdb (addr, #bytes) */
|
||||
mon960_cmds.getmem.cmdw = "ds %x\n\r"; /* getmem.cmdw (addr, #swords) */
|
||||
mon960_cmds.getmem.cmdl = "di %x\n\r"; /* getmem.cmdl (addr, #words) */
|
||||
mon960_cmds.getmem.cmdll = "dd %x\n\r"; /* getmem.cmdll (addr, #dwords) */
|
||||
mon960_cmds.getmem.resp_delim = " : "; /* getmem.resp_delim */
|
||||
mon960_cmds.getmem.term = NULL; /* getmem.term */
|
||||
mon960_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
mon960_cmds.setreg.cmd = "md %s %x\n\r"; /* setreg.cmd (name, value) */
|
||||
mon960_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
mon960_cmds.setreg.term = NULL; /* setreg.term */
|
||||
mon960_cmds.setreg.term_cmd = NULL, /* setreg.term_cmd */
|
||||
mon960_cmds.getreg.cmd = "di %s\n\r"; /* getreg.cmd (name) */
|
||||
mon960_cmds.getreg.resp_delim = " : "; /* getreg.resp_delim */
|
||||
mon960_cmds.getreg.term = NULL; /* getreg.term */
|
||||
mon960_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
|
||||
mon960_cmds.dump_registers = "re\n\r"; /* dump_registers */
|
||||
mon960_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
|
||||
mon960_cmds.supply_register = NULL; /* supply_register */
|
||||
#ifdef USE_GENERIC_LOAD
|
||||
mon960_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
mon960_cmds.load = NULL; /* download command */
|
||||
mon960_cmds.loadresp = NULL; /* load response */
|
||||
#else
|
||||
mon960_cmds.load_routine = mon960_load; /* load_routine (defaults to SRECs) */
|
||||
mon960_cmds.load = "do\n\r"; /* download command */
|
||||
mon960_cmds.loadresp = "Downloading\n\r"; /* load response */
|
||||
#endif
|
||||
mon960_cmds.prompt = "=>"; /* monitor command prompt */
|
||||
mon960_cmds.line_term = "\n\r"; /* end-of-command delimitor */
|
||||
mon960_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
mon960_cmds.target = &mon960_ops; /* target operations */
|
||||
mon960_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
mon960_cmds.regnames = mon960_regnames; /* registers names */
|
||||
mon960_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
};
|
||||
|
||||
static void
|
||||
mon960_open (char *args, int from_tty)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
monitor_open (args, &mon960_cmds, from_tty);
|
||||
|
||||
/* Attempt to fetch the value of the first floating point register (fp0).
|
||||
If the monitor returns a string containing the word "Bad" we'll assume
|
||||
this processor has no floating point registers, and nullify the
|
||||
regnames entries that refer to FP registers. */
|
||||
|
||||
monitor_printf (mon960_cmds.getreg.cmd, full_regnames[FP0_REGNUM]); /* di fp0 */
|
||||
if (monitor_expect_prompt (buf, sizeof (buf)) != -1)
|
||||
if (strstr (buf, "Bad") != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + 4; i++)
|
||||
mon960_regnames[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_mon960 (void)
|
||||
{
|
||||
memcpy (mon960_regnames, full_regnames, sizeof (full_regnames));
|
||||
|
||||
init_mon960_cmds ();
|
||||
|
||||
init_monitor_ops (&mon960_ops);
|
||||
|
||||
mon960_ops.to_shortname = "mon960"; /* for the target command */
|
||||
mon960_ops.to_longname = "Intel 960 MON960 monitor";
|
||||
#ifdef USE_GENERIC_LOAD
|
||||
mon960_ops.to_load = mon960_load_gen; /* FIXME - should go back and try "do" */
|
||||
#endif
|
||||
/* use SW breaks; target only supports 2 HW breakpoints */
|
||||
mon960_ops.to_insert_breakpoint = memory_insert_breakpoint;
|
||||
mon960_ops.to_remove_breakpoint = memory_remove_breakpoint;
|
||||
|
||||
mon960_ops.to_doc =
|
||||
"Use an Intel 960 board running the MON960 debug monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
|
||||
mon960_ops.to_open = mon960_open;
|
||||
add_target (&mon960_ops);
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
# Configuration fragment for GDB.
|
||||
|
||||
If "{host_canonical}" =~ /m68k-apple-mpw/
|
||||
forward-include "{srcdir}"config:m68k:xm-mpw.h xm.h
|
||||
Set siow_lib '"{Libraries}"SIOW.o'
|
||||
|
||||
Else If "{host_canonical}" =~ /powerpc-apple-mpw/
|
||||
forward-include "{srcdir}"config:powerpc:xm-mpw.h xm.h
|
||||
Set siow_lib '"{PPCLibraries}"PPCSIOW.o'
|
||||
|
||||
End If
|
||||
|
||||
Set xdepfiles '"{o}"mac-xdep.c.o'
|
||||
|
||||
Set enable_cflags ""
|
||||
|
||||
# Make a copy of this file and give it a different name, so it
|
||||
# won't be confused with GDB's serial.h.
|
||||
|
||||
Duplicate -y "{CIncludes}"Serial.h MacSerial.h
|
||||
|
||||
Echo "/* dummy */" >termio.h
|
||||
|
||||
If "{target_canonical}" =~ /m68k-apple-macos/
|
||||
forward-include "{srcdir}"config:m68k:tm-mac.h tm.h
|
||||
forward-include "{srcdir}"config:m68k:tm-m68k.h 'm68k/tm-m68k.h'
|
||||
Set tdepfiles '"{o}"m68k-tdep.c.o'
|
||||
|
||||
Else If "{target_canonical}" =~ /powerpc-apple-macos/
|
||||
forward-include "{srcdir}"config:powerpc:tm-macos.h tm.h
|
||||
forward-include "{srcdir}"config:rs6000:tm-rs6000.h 'rs6000/tm-rs6000.h'
|
||||
Set tdepfiles '"{o}"rs6000-tdep.c.o "{o}"xcoffread.c.o'
|
||||
|
||||
Else If "{target_canonical}" =~ /i386-unknown-go32/
|
||||
forward-include "{srcdir}"config:i386:tm-i386v.h tm.h
|
||||
Set tdepfiles '"{o}"i386-tdep.c.o'
|
||||
|
||||
Else If "{target_canonical}" =~ /mips-idt-ecoff/
|
||||
forward-include "{srcdir}"config:mips:tm-embed.h tm.h
|
||||
forward-include "{srcdir}"config:mips:tm-bigmips.h 'mips/tm-bigmips.h'
|
||||
forward-include "{srcdir}"config:mips:tm-mips.h 'mips/tm-mips.h'
|
||||
Set tdepfiles '"{o}"mips-tdep.c.o "{o}"remote-mips.c.o'
|
||||
|
||||
Else If "{target_canonical}" =~ /sh-hitachi-hms/
|
||||
forward-include "{srcdir}"config:sh:tm-sh.h tm.h
|
||||
Set tdepfiles '"{o}"sh-tdep.c.o'
|
||||
|
||||
End If
|
||||
|
||||
If "{target_canonical}" =~ /m68k-apple-macos/
|
||||
forward-include "{srcdir}"config:m68k:nm-macos.h nm.h
|
||||
Set natdepfiles '"{o}"mac-nat.c.o'
|
||||
|
||||
Else If "{target_canonical}" =~ /powerpc-apple-macos/
|
||||
forward-include "{srcdir}"config:powerpc:nm-macos.h nm.h
|
||||
Set natdepfiles '"{o}"mac-nat.c.o'
|
||||
|
||||
Else
|
||||
forward-include "{srcdir}"config:nm-empty.h nm.h
|
||||
Set natdepfiles ' '
|
||||
|
||||
End If
|
||||
|
||||
Echo '# From mpw-config.in' > "{o}"mk.tmp
|
||||
Echo "TDEPFILES = " {tdepfiles} >> "{o}"mk.tmp
|
||||
Echo "XDEPFILES = " {xdepfiles} >> "{o}"mk.tmp
|
||||
Echo "NATDEPFILES = " {natdepfiles} >> "{o}"mk.tmp
|
||||
Echo "XM_ADD_FILES = " >> "{o}"mk.tmp
|
||||
Echo "TM_ADD_FILES = " >> "{o}"mk.tmp
|
||||
Echo "NAT_ADD_FILES = " >> "{o}"mk.tmp
|
||||
Echo "XM_CDEPS = " >> "{o}"mk.tmp
|
||||
Echo "TM_CDEPS = " >> "{o}"mk.tmp
|
||||
Echo "NAT_CDEPS = " >> "{o}"mk.tmp
|
||||
Echo "SIOW_LIB = " {siow_lib} >> "{o}"mk.tmp
|
||||
Echo "ENABLE_CFLAGS = " {enable_cflags} >> "{o}"mk.tmp
|
||||
Echo '# End from mpw-config.in' >> "{o}"mk.tmp
|
||||
|
||||
Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
|
||||
Echo '#include "mpw.h"' >> "{o}"config.new
|
||||
|
||||
MoveIfChange "{o}"config.new "{o}"config.h
|
@ -1,178 +0,0 @@
|
||||
# Sed commands that finish translating the GDB Unix Makefile to MPW syntax.
|
||||
|
||||
/^host_alias =/s/^/#/
|
||||
/^target_alias =/s/^/#/
|
||||
|
||||
/^host_makefile_frag@$/d
|
||||
/^target_makefile_frag@$/d
|
||||
|
||||
/@ENABLE_CFLAGS@/s/@ENABLE_CFLAGS@/{ENABLE_CFLAGS}/g
|
||||
/^ENABLE_CFLAGS=/s/^/#/
|
||||
|
||||
# Edit all the symbolic definitions pointing to various libraries and such.
|
||||
|
||||
/^INCLUDE_DIR = /s/"{srcdir}":include/"{topsrcdir}"include:/
|
||||
|
||||
/^MMALLOC_DIR = /s/::mmalloc/mmalloc:/
|
||||
/^MMALLOC_SRC = /s/"{srcdir}"/"{topsrcdir}"/
|
||||
/^MMALLOC =/s/=.*$/=/
|
||||
/MMALLOC_CFLAGS =/s/=.*$/= -u USE_MMALLOC/
|
||||
|
||||
/^BFD_DIR = /s/::bfd/bfd:/
|
||||
/^BFD = /s/{BFD_DIR}:libbfd/{BFD_DIR}libbfd/
|
||||
/^BFD_SRC = /s/"{srcdir}"/"{topsrcdir}"/
|
||||
|
||||
/^READLINE_DIR = /s/::readline/readline:/
|
||||
/^READLINE =/s/=.*$/=/
|
||||
/^READLINE_SRC = /s/"{srcdir}"/"{topsrcdir}"/
|
||||
|
||||
/^INCLUDE_CFLAGS = /s/$/ -i "{topsrcdir}"include:mpw: -i ::extra-include:/
|
||||
|
||||
/^SER_HARDWIRE =/s/ser-unix/ser-mac/
|
||||
|
||||
/^TERMCAP =/s/ =.*$/ =/
|
||||
|
||||
# Whack out various autoconf vars that we don't need.
|
||||
/@CONFIG_LDFLAGS@/s/@CONFIG_LDFLAGS@//g
|
||||
/@HLDFLAGS@/s/@HLDFLAGS@//g
|
||||
/@DEFS@/s/@DEFS@//g
|
||||
/@YACC@/s/@YACC@/byacc/g
|
||||
/@ENABLE_OBS@/s/@ENABLE_OBS@//g
|
||||
/@ENABLE_CLIBS@/s/@ENABLE_CLIBS@//g
|
||||
/@LIBS@/s/@LIBS@//g
|
||||
|
||||
# Whack out autoconf hook for thread debugging.
|
||||
/@THREAD_DB_OBS@/s/@THREAD_DB_OBS@//g
|
||||
|
||||
# Fix up paths to include directories.
|
||||
/INCLUDE_DIR/s/"{s}"{INCLUDE_DIR}/{INCLUDE_DIR}/g
|
||||
/INCLUDE_DIR/s/{INCLUDE_DIR}:/{INCLUDE_DIR}/g
|
||||
/INCLUDE_DIR/s/"{INCLUDE_DIR}":/"{INCLUDE_DIR}"/g
|
||||
|
||||
/{BFD_DIR}/s/"{BFD_DIR}":/"{BFD_DIR}"/g
|
||||
/{BFD_DIR}/s/\([ ]\){BFD_DIR}/\1::{BFD_DIR}/g
|
||||
/{BFD_DIR}/s/\([ ]\)"{BFD_DIR}"/\1::"{BFD_DIR}"/g
|
||||
|
||||
/{BFD_SRC}/s/"{s}"{BFD_SRC}/{BFD_SRC}/g
|
||||
/{BFD_SRC}/s/{BFD_SRC}:/{BFD_SRC}/g
|
||||
|
||||
/{READLINE_SRC}/s/"{s}"{READLINE_SRC}/{READLINE_SRC}/g
|
||||
|
||||
/^readline_headers =/,/^$/c\
|
||||
readline_headers =\
|
||||
|
||||
|
||||
# This isn't really useful, and seems to cause nonsensical complaints.
|
||||
/{ALLDEPFILES}/s/{ALLDEPFILES}//g
|
||||
|
||||
/^copying.c \\Option-f /,/^$/d
|
||||
|
||||
# Fix the syntax of bits of C code that go into version.c.
|
||||
/char /s/'char .Option-x/'char */
|
||||
|
||||
# Point at files in the obj dir rather than src dir.
|
||||
/version/s/"{s}"version\.c/"{o}"version.c/g
|
||||
/version/s/^version\.c/"{o}"version.c/
|
||||
/config/s/"{s}"config\.h/"{o}"config.h/g
|
||||
/config/s/^config\.h/"{o}"config.h/
|
||||
/xm/s/"{s}"xm\.h/"{o}"xm.h/g
|
||||
/xm/s/^xm\.h/"{o}"xm.h/
|
||||
/tm/s/"{s}"tm\.h/"{o}"tm.h/g
|
||||
/tm/s/^tm\.h/"{o}"tm.h/
|
||||
/nm/s/"{s}"nm\.h/"{o}"nm.h/g
|
||||
/nm/s/^nm\.h/"{o}"nm.h/
|
||||
|
||||
/exp.tab.c/s/"{s}"\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/g
|
||||
/exp.tab.c/s/^\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/
|
||||
|
||||
/y.tab/s/"{s}"y.tab\.c/"{o}"y.tab.c/g
|
||||
/y.tab/s/^y.tab\.c/"{o}"y.tab.c/
|
||||
|
||||
/init/s/"{s}"init\.c-tmp/"{o}"init.c-tmp/g
|
||||
/init/s/^init\.c-tmp/"{o}"init.c-tmp/
|
||||
/init/s/"{s}"init\.c/"{o}"init.c/g
|
||||
/init/s/^init\.c/"{o}"init.c/
|
||||
|
||||
# Fix up the generation of version.c.
|
||||
/"{o}"version.c \\Option-f Makefile/,/^$/c\
|
||||
"{o}"version.c \\Option-f Makefile\
|
||||
echo -n 'char *version = "' >"{o}"version.c\
|
||||
echo -n "{VERSION}" >>"{o}"version.c\
|
||||
echo '";' >>"{o}"version.c\
|
||||
echo -n 'char *host_name = "' >>"{o}"version.c\
|
||||
echo -n "{host_alias}" >>"{o}"version.c\
|
||||
echo '";' >>"{o}"version.c\
|
||||
echo -n 'char *target_name = "' >>"{o}"version.c\
|
||||
echo -n "{target_alias}" >>"{o}"version.c\
|
||||
echo '";' >>"{o}"version.c\
|
||||
|
||||
|
||||
/ansidecl/s/include "{s}""ansidecl.h"/include "ansidecl.h"/
|
||||
|
||||
# Open-brace in a command causes much confusion; replace with the
|
||||
# result from a script.
|
||||
/initialize_all_files ()/c\
|
||||
Echo -n 'void initialize_all_files () ' >> "{o}"init.c-tmp\
|
||||
open-brace >> "{o}"init.c-tmp
|
||||
|
||||
# Replace the whole sed bit for init.c; it's simpler that way...
|
||||
/echo {OBS} {TSOBS}/,/echo '}'/c\
|
||||
For i in {OBS} {TSOBS}\
|
||||
Set filename "`Echo {i} | sed \\Option-d\
|
||||
-e '/^Onindy.c.o/d' \\Option-d\
|
||||
-e '/^nindy.c.o/d' \\Option-d\
|
||||
-e '/ttyflush.c.o/d' \\Option-d\
|
||||
-e '/xdr_ld.c.o/d' \\Option-d\
|
||||
-e '/xdr_ptrace.c.o/d' \\Option-d\
|
||||
-e '/xdr_rdb.c.o/d' \\Option-d\
|
||||
-e '/udr.c.o/d' \\Option-d\
|
||||
-e '/udip2soc.c.o/d' \\Option-d\
|
||||
-e '/udi2go32.c.o/d' \\Option-d\
|
||||
-e '/version.c.o/d' \\Option-d\
|
||||
-e '/[a-z0-9A-Z_]*-exp.tab.c.o/d' \\Option-d\
|
||||
-e 's/\\.c\\.o/.c/' \\Option-d\
|
||||
-e 's/^://'`"\
|
||||
If "{filename}" != ""\
|
||||
sed <"{s}""{filename}" >>"{o}"init.c-tmp -n \\Option-d\
|
||||
-e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\\([a-z_0-9A-Z]*\\).*/ {extern void \\1 (); \\1 ();}/p'\
|
||||
End If\
|
||||
End For\
|
||||
Echo '}' >>"{o}"init.c-tmp
|
||||
|
||||
# Fix the main compile/link command.
|
||||
/{CC_LD} {INTERNAL_LDFLAGS} -o gdb/,/"{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES}/c\
|
||||
{CC_LD} {INTERNAL_LDFLAGS} -o gdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES} {EXTRALIBS}\
|
||||
{MAKEPEF} gdb{PROG_EXT} -o gdb {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
|
||||
{REZ} "{s}"mac-gdb.r -o gdb -append -d PROG_NAME='"'gdb'"' -d VERSION_STRING='"'{version}'"'\
|
||||
|
||||
# Replace the install actions with MPW-friendly script.
|
||||
/^install \\Option-f /,/^$/c\
|
||||
install \\Option-f all install-only\
|
||||
\
|
||||
install-only \\Option-f \
|
||||
NewFolderRecursive "{bindir}"\
|
||||
Duplicate -y gdb "{bindir}"gdb\
|
||||
If "`Exists SiowGDB`" != ""\
|
||||
Duplicate -y SiowGDB "{bindir}"SiowGDB\
|
||||
End If\
|
||||
|
||||
|
||||
# Don't do any recursive subdir stuff.
|
||||
/ subdir_do/s/{MAKE}/null-command/
|
||||
|
||||
# Edit out actions that only confuse MPW Make.
|
||||
/^config.status \\Option-f/,/^$/d
|
||||
/^Makefile \\Option-f/,/^$/d
|
||||
|
||||
# Don't test config.h dependencies.
|
||||
/^"{o}"config.h \\Option-f/s/^/#/
|
||||
|
||||
# Add an action to build SIOWgdb.
|
||||
$a\
|
||||
SIOWgdb \\Option-f {OBS} {TSOBS} {ADD_DEPS} {CDEPS} "{o}"init.c.o\
|
||||
Delete -i -y SIOWgdb\
|
||||
{CC_LD} {INTERNAL_LDFLAGS} -t 'APPL' -c 'gdb ' -o SIOWgdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {SIOW_LIB} {LOADLIBES} {EXTRALIBS}\
|
||||
{MAKEPEF} SIOWgdb{PROG_EXT} -o SIOWgdb -ft 'APPL' -fc 'gdb ' {MAKEPEF_FLAGS} \
|
||||
{REZ} -o SIOWgdb "{RIncludes}"siow.r -append -d __kPrefSize=5000 -d __kMinSize=2000 -d APPNAME='"'SIOWgdb'"' \
|
||||
{REZ} "{s}"mac-gdb.r -o SIOWgdb -append -d VERSION_STRING='"'{version}'"'\
|
||||
|
@ -1,65 +0,0 @@
|
||||
/* Low level interface to ptrace, for GDB when running under Unix.
|
||||
Copyright (C) 1986, 1987, 1989 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Bad implement execle(3). It's depend for "/bin/cc".
|
||||
|
||||
main()
|
||||
{
|
||||
printf("execle:\n");
|
||||
execle(FILE, ARGS, envp);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
GCC:
|
||||
link a6,#0
|
||||
pea LC5 ; call printf
|
||||
jbsr _printf
|
||||
; ; (not popd stack)
|
||||
pea _envp ; call execle
|
||||
clrl sp@-
|
||||
pea LC4
|
||||
pea LC4
|
||||
pea LC4
|
||||
pea LC3
|
||||
pea LC6
|
||||
jbsr _execle
|
||||
addw #32,sp ; delayed pop !!
|
||||
|
||||
/bin/cc:
|
||||
link.l fp,#L23
|
||||
movem.l #L24,(sp)
|
||||
pea L26 ; call printf
|
||||
jbsr _printf
|
||||
addq.l #4,sp ; <--- popd stack !!
|
||||
pea _envp ; call execle
|
||||
clr.l -(sp)
|
||||
pea L32
|
||||
|
||||
*/
|
||||
|
||||
execle(name, args)
|
||||
char *name, *args;
|
||||
{
|
||||
register char **env = &args;
|
||||
while (*env++)
|
||||
;
|
||||
execve(name, (char **)&args, (char **)*env);
|
||||
}
|
||||
#endif
|
@ -1,78 +0,0 @@
|
||||
/* Target-machine dependent code for the NINDY monitor running on the Intel 960
|
||||
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 2000
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Intel Corporation.
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Miscellaneous NINDY-dependent routines.
|
||||
Some replace macros normally defined in "tm.h". */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
/* 'start_frame' is a variable in the NINDY runtime startup routine
|
||||
that contains the frame pointer of the 'start' routine (the routine
|
||||
that calls 'main'). By reading its contents out of remote memory,
|
||||
we can tell where the frame chain ends: backtraces should halt before
|
||||
they display this frame. */
|
||||
|
||||
int
|
||||
nindy_frame_chain_valid (CORE_ADDR chain, struct frame_info *curframe)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
/* crtnindy.o is an assembler module that is assumed to be linked
|
||||
* first in an i80960 executable. It contains the true entry point;
|
||||
* it performs startup up initialization and then calls 'main'.
|
||||
*
|
||||
* 'sf' is the name of a variable in crtnindy.o that is set
|
||||
* during startup to the address of the first frame.
|
||||
*
|
||||
* 'a' is the address of that variable in 80960 memory.
|
||||
*/
|
||||
static char sf[] = "start_frame";
|
||||
CORE_ADDR a;
|
||||
|
||||
|
||||
chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
|
||||
contain return status info in them. */
|
||||
if (chain == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sym = lookup_symbol (sf, 0, VAR_NAMESPACE, (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
if (sym != 0)
|
||||
{
|
||||
a = SYMBOL_VALUE (sym);
|
||||
}
|
||||
else
|
||||
{
|
||||
msymbol = lookup_minimal_symbol (sf, NULL, NULL);
|
||||
if (msymbol == NULL)
|
||||
return 0;
|
||||
a = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
}
|
||||
|
||||
return (chain != read_memory_integer (a, 4));
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
/* Print NS 32000 instructions for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1991, 1992, 1994, 1995, 1998, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
static int sign_extend (int value, int bits);
|
||||
|
||||
void
|
||||
_initialize_ns32k_tdep (void)
|
||||
{
|
||||
tm_print_insn = print_insn_ns32k;
|
||||
}
|
||||
|
||||
/* Advance PC across any function entry prologue instructions
|
||||
to reach some "real" code. */
|
||||
|
||||
CORE_ADDR
|
||||
umax_skip_prologue (CORE_ADDR pc)
|
||||
{
|
||||
register unsigned char op = read_memory_integer (pc, 1);
|
||||
if (op == 0x82)
|
||||
{
|
||||
op = read_memory_integer (pc + 2, 1);
|
||||
if ((op & 0x80) == 0)
|
||||
pc += 3;
|
||||
else if ((op & 0xc0) == 0x80)
|
||||
pc += 4;
|
||||
else
|
||||
pc += 6;
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* Return number of args passed to a frame.
|
||||
Can return -1, meaning no way to tell.
|
||||
Encore's C compiler often reuses same area on stack for args,
|
||||
so this will often not work properly. If the arg names
|
||||
are known, it's likely most of them will be printed. */
|
||||
|
||||
int
|
||||
umax_frame_num_args (struct frame_info *fi)
|
||||
{
|
||||
int numargs;
|
||||
CORE_ADDR pc;
|
||||
CORE_ADDR enter_addr;
|
||||
unsigned int insn;
|
||||
unsigned int addr_mode;
|
||||
int width;
|
||||
|
||||
numargs = -1;
|
||||
enter_addr = ns32k_get_enter_addr ((fi)->pc);
|
||||
if (enter_addr > 0)
|
||||
{
|
||||
pc = ((enter_addr == 1)
|
||||
? SAVED_PC_AFTER_CALL (fi)
|
||||
: FRAME_SAVED_PC (fi));
|
||||
insn = read_memory_integer (pc, 2);
|
||||
addr_mode = (insn >> 11) & 0x1f;
|
||||
insn = insn & 0x7ff;
|
||||
if ((insn & 0x7fc) == 0x57c
|
||||
&& addr_mode == 0x14) /* immediate */
|
||||
{
|
||||
if (insn == 0x57c) /* adjspb */
|
||||
width = 1;
|
||||
else if (insn == 0x57d) /* adjspw */
|
||||
width = 2;
|
||||
else if (insn == 0x57f) /* adjspd */
|
||||
width = 4;
|
||||
else
|
||||
internal_error (__FILE__, __LINE__, "bad else");
|
||||
numargs = read_memory_integer (pc + 2, width);
|
||||
if (width > 1)
|
||||
flip_bytes (&numargs, width);
|
||||
numargs = -sign_extend (numargs, width * 8) / 4;
|
||||
}
|
||||
}
|
||||
return numargs;
|
||||
}
|
||||
|
||||
static int
|
||||
sign_extend (int value, int bits)
|
||||
{
|
||||
value = value & ((1 << bits) - 1);
|
||||
return (value & (1 << (bits - 1))
|
||||
? value | (~((1 << bits) - 1))
|
||||
: value);
|
||||
}
|
||||
|
||||
void
|
||||
flip_bytes (void *p, int count)
|
||||
{
|
||||
char tmp;
|
||||
char *ptr = 0;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
tmp = *ptr;
|
||||
ptr[0] = ptr[count - 1];
|
||||
ptr[count - 1] = tmp;
|
||||
ptr++;
|
||||
count -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of locals in the current frame given a pc
|
||||
pointing to the enter instruction. This is used in the macro
|
||||
FRAME_FIND_SAVED_REGS. */
|
||||
|
||||
int
|
||||
ns32k_localcount (CORE_ADDR enter_pc)
|
||||
{
|
||||
unsigned char localtype;
|
||||
int localcount;
|
||||
|
||||
localtype = read_memory_integer (enter_pc + 2, 1);
|
||||
if ((localtype & 0x80) == 0)
|
||||
localcount = localtype;
|
||||
else if ((localtype & 0xc0) == 0x80)
|
||||
localcount = (((localtype & 0x3f) << 8)
|
||||
| (read_memory_integer (enter_pc + 3, 1) & 0xff));
|
||||
else
|
||||
localcount = (((localtype & 0x3f) << 24)
|
||||
| ((read_memory_integer (enter_pc + 3, 1) & 0xff) << 16)
|
||||
| ((read_memory_integer (enter_pc + 4, 1) & 0xff) << 8)
|
||||
| (read_memory_integer (enter_pc + 5, 1) & 0xff));
|
||||
return localcount;
|
||||
}
|
||||
|
||||
|
||||
/* Nonzero if instruction at PC is a return instruction. */
|
||||
|
||||
static int
|
||||
ns32k_about_to_return (CORE_ADDR pc)
|
||||
{
|
||||
return (read_memory_integer (pc, 1) == 0x12);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the address of the enter opcode for the function
|
||||
* containing PC, if there is an enter for the function,
|
||||
* and if the pc is between the enter and exit.
|
||||
* Returns positive address if pc is between enter/exit,
|
||||
* 1 if pc before enter or after exit, 0 otherwise.
|
||||
*/
|
||||
|
||||
CORE_ADDR
|
||||
ns32k_get_enter_addr (CORE_ADDR pc)
|
||||
{
|
||||
CORE_ADDR enter_addr;
|
||||
unsigned char op;
|
||||
|
||||
if (pc == 0)
|
||||
return 0;
|
||||
|
||||
if (ns32k_about_to_return (pc))
|
||||
return 1; /* after exit */
|
||||
|
||||
enter_addr = get_pc_function_start (pc);
|
||||
|
||||
if (pc == enter_addr)
|
||||
return 1; /* before enter */
|
||||
|
||||
op = read_memory_integer (enter_addr, 1);
|
||||
|
||||
if (op != 0x82)
|
||||
return 0; /* function has no enter/exit */
|
||||
|
||||
return enter_addr; /* pc is between enter and exit */
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
/* Low level interface to ns532 running mach 3.0.
|
||||
Copyright (C) 1992 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mach.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/exception.h>
|
||||
#include <mach_error.h>
|
||||
|
||||
#define private static
|
||||
|
||||
|
||||
/* Find offsets to thread states at compile time.
|
||||
* If your compiler does not grok this, calculate offsets
|
||||
* offsets yourself and use them (or get a compatible compiler :-)
|
||||
*/
|
||||
|
||||
#define REG_N_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->ts.reg)
|
||||
#define REG_F_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->fs.reg)
|
||||
|
||||
/* at reg_offset[i] is the offset to the ns532_combined_state
|
||||
* location where the gdb registers[i] is stored.
|
||||
*/
|
||||
|
||||
static int reg_offset[] =
|
||||
{
|
||||
REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3),
|
||||
REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7),
|
||||
REG_F_OFFSET(l0a), REG_F_OFFSET(l0b),REG_F_OFFSET(l2a),REG_F_OFFSET(l2b),
|
||||
REG_F_OFFSET(l4a), REG_F_OFFSET(l4b),REG_F_OFFSET(l6a),REG_F_OFFSET(l6b),
|
||||
REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr),
|
||||
REG_F_OFFSET(fsr),
|
||||
REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a),
|
||||
REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a),
|
||||
};
|
||||
|
||||
#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
|
||||
|
||||
/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
|
||||
* Caller knows that the regs handled in one transaction are of same size.
|
||||
*/
|
||||
#define FETCH_REGS(state, regnum, count) \
|
||||
memcpy (®isters[REGISTER_BYTE (regnum)], \
|
||||
(char *)state+reg_offset[ regnum ], \
|
||||
count*REGISTER_SIZE)
|
||||
|
||||
/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
|
||||
#define STORE_REGS(state, regnum, count) \
|
||||
memcpy ((char *)state+reg_offset[ regnum ], \
|
||||
®isters[REGISTER_BYTE (regnum)], \
|
||||
count*REGISTER_SIZE)
|
||||
|
||||
/*
|
||||
* Fetch inferiors registers for gdb.
|
||||
* REGNO specifies which (as gdb views it) register, -1 for all.
|
||||
*/
|
||||
|
||||
void
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
kern_return_t ret;
|
||||
thread_state_data_t state;
|
||||
unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
|
||||
int index;
|
||||
|
||||
if (! MACH_PORT_VALID (current_thread))
|
||||
error ("fetch inferior registers: Invalid thread");
|
||||
|
||||
if (must_suspend_thread)
|
||||
setup_thread (current_thread, 1);
|
||||
|
||||
ret = thread_get_state (current_thread,
|
||||
NS532_COMBINED_STATE,
|
||||
state,
|
||||
&stateCnt);
|
||||
|
||||
if (ret != KERN_SUCCESS)
|
||||
warning ("fetch_inferior_registers: %s ",
|
||||
mach_error_string (ret));
|
||||
#if 0
|
||||
/* It may be more effective to store validate all of them,
|
||||
* since we fetched them all anyway
|
||||
*/
|
||||
else if (regno != -1)
|
||||
supply_register (regno, (char *)state+reg_offset[regno]);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
for (index = 0; index < NUM_REGS; index++)
|
||||
supply_register (index, (char *)state+reg_offset[index]);
|
||||
}
|
||||
|
||||
if (must_suspend_thread)
|
||||
setup_thread (current_thread, 0);
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
* If REGNO is -1, do this for all registers.
|
||||
* Otherwise, REGNO specifies which register
|
||||
*
|
||||
* On mach3 all registers are always saved in one call.
|
||||
*/
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
kern_return_t ret;
|
||||
thread_state_data_t state;
|
||||
unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
|
||||
register int index;
|
||||
|
||||
if (! MACH_PORT_VALID (current_thread))
|
||||
error ("store inferior registers: Invalid thread");
|
||||
|
||||
if (must_suspend_thread)
|
||||
setup_thread (current_thread, 1);
|
||||
|
||||
/* Fetch the state of the current thread */
|
||||
ret = thread_get_state (current_thread,
|
||||
NS532_COMBINED_STATE,
|
||||
state,
|
||||
&stateCnt);
|
||||
|
||||
if (ret != KERN_SUCCESS)
|
||||
{
|
||||
warning ("store_inferior_registers (get): %s",
|
||||
mach_error_string (ret));
|
||||
if (must_suspend_thread)
|
||||
setup_thread (current_thread, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* move gdb's registers to thread's state
|
||||
*
|
||||
* Since we save all registers anyway, save the ones
|
||||
* that gdb thinks are valid (e.g. ignore the regno
|
||||
* parameter)
|
||||
*/
|
||||
#if 0
|
||||
if (regno != -1)
|
||||
STORE_REGS (state, regno, 1);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (index = 0; index < NUM_REGS; index++)
|
||||
STORE_REGS (state, index, 1);
|
||||
}
|
||||
|
||||
/* Write gdb's current view of register to the thread
|
||||
*/
|
||||
ret = thread_set_state (current_thread,
|
||||
NS532_COMBINED_STATE,
|
||||
state,
|
||||
NS532_COMBINED_STATE_COUNT);
|
||||
|
||||
if (ret != KERN_SUCCESS)
|
||||
warning ("store_inferior_registers (set): %s",
|
||||
mach_error_string (ret));
|
||||
|
||||
if (must_suspend_thread)
|
||||
setup_thread (current_thread, 0);
|
||||
}
|
@ -1,364 +0,0 @@
|
||||
/* Functions specific to running gdb native on an ns32k running NetBSD
|
||||
Copyright 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/pcb.h>
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "target.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#define RF(dst, src) \
|
||||
memcpy(®isters[REGISTER_BYTE(dst)], &src, sizeof(src))
|
||||
|
||||
#define RS(src, dst) \
|
||||
memcpy(&dst, ®isters[REGISTER_BYTE(src)], sizeof(dst))
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
struct fpreg inferior_fpregisters;
|
||||
|
||||
ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers, 0);
|
||||
ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fpregisters, 0);
|
||||
|
||||
RF (R0_REGNUM + 0, inferior_registers.r_r0);
|
||||
RF (R0_REGNUM + 1, inferior_registers.r_r1);
|
||||
RF (R0_REGNUM + 2, inferior_registers.r_r2);
|
||||
RF (R0_REGNUM + 3, inferior_registers.r_r3);
|
||||
RF (R0_REGNUM + 4, inferior_registers.r_r4);
|
||||
RF (R0_REGNUM + 5, inferior_registers.r_r5);
|
||||
RF (R0_REGNUM + 6, inferior_registers.r_r6);
|
||||
RF (R0_REGNUM + 7, inferior_registers.r_r7);
|
||||
|
||||
RF (SP_REGNUM, inferior_registers.r_sp);
|
||||
RF (FP_REGNUM, inferior_registers.r_fp);
|
||||
RF (PC_REGNUM, inferior_registers.r_pc);
|
||||
RF (PS_REGNUM, inferior_registers.r_psr);
|
||||
|
||||
RF (FPS_REGNUM, inferior_fpregisters.r_fsr);
|
||||
RF (FP0_REGNUM + 0, inferior_fpregisters.r_freg[0]);
|
||||
RF (FP0_REGNUM + 2, inferior_fpregisters.r_freg[2]);
|
||||
RF (FP0_REGNUM + 4, inferior_fpregisters.r_freg[4]);
|
||||
RF (FP0_REGNUM + 6, inferior_fpregisters.r_freg[6]);
|
||||
RF (LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
|
||||
RF (LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
|
||||
RF (LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
|
||||
RF (LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
|
||||
registers_fetched ();
|
||||
}
|
||||
|
||||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
struct reg inferior_registers;
|
||||
struct fpreg inferior_fpregisters;
|
||||
|
||||
RS (R0_REGNUM + 0, inferior_registers.r_r0);
|
||||
RS (R0_REGNUM + 1, inferior_registers.r_r1);
|
||||
RS (R0_REGNUM + 2, inferior_registers.r_r2);
|
||||
RS (R0_REGNUM + 3, inferior_registers.r_r3);
|
||||
RS (R0_REGNUM + 4, inferior_registers.r_r4);
|
||||
RS (R0_REGNUM + 5, inferior_registers.r_r5);
|
||||
RS (R0_REGNUM + 6, inferior_registers.r_r6);
|
||||
RS (R0_REGNUM + 7, inferior_registers.r_r7);
|
||||
|
||||
RS (SP_REGNUM, inferior_registers.r_sp);
|
||||
RS (FP_REGNUM, inferior_registers.r_fp);
|
||||
RS (PC_REGNUM, inferior_registers.r_pc);
|
||||
RS (PS_REGNUM, inferior_registers.r_psr);
|
||||
|
||||
RS (FPS_REGNUM, inferior_fpregisters.r_fsr);
|
||||
RS (FP0_REGNUM + 0, inferior_fpregisters.r_freg[0]);
|
||||
RS (FP0_REGNUM + 2, inferior_fpregisters.r_freg[2]);
|
||||
RS (FP0_REGNUM + 4, inferior_fpregisters.r_freg[4]);
|
||||
RS (FP0_REGNUM + 6, inferior_fpregisters.r_freg[6]);
|
||||
RS (LP0_REGNUM + 1, inferior_fpregisters.r_freg[1]);
|
||||
RS (LP0_REGNUM + 3, inferior_fpregisters.r_freg[3]);
|
||||
RS (LP0_REGNUM + 5, inferior_fpregisters.r_freg[5]);
|
||||
RS (LP0_REGNUM + 7, inferior_fpregisters.r_freg[7]);
|
||||
|
||||
ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_registers, 0);
|
||||
ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) & inferior_fpregisters, 0);
|
||||
}
|
||||
|
||||
|
||||
/* XXX - Add this to machine/regs.h instead? */
|
||||
struct coreregs
|
||||
{
|
||||
struct reg intreg;
|
||||
struct fpreg freg;
|
||||
};
|
||||
|
||||
/* Get registers from a core file. REG_ADDR is unused. */
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
unsigned int reg_addr)
|
||||
{
|
||||
struct coreregs *core_reg;
|
||||
|
||||
core_reg = (struct coreregs *) core_reg_sect;
|
||||
|
||||
/*
|
||||
* We have *all* registers
|
||||
* in the first core section.
|
||||
* Ignore which.
|
||||
*/
|
||||
|
||||
if (core_reg_size < sizeof (*core_reg))
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "Couldn't read regs from core file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer registers */
|
||||
RF (R0_REGNUM + 0, core_reg->intreg.r_r0);
|
||||
RF (R0_REGNUM + 1, core_reg->intreg.r_r1);
|
||||
RF (R0_REGNUM + 2, core_reg->intreg.r_r2);
|
||||
RF (R0_REGNUM + 3, core_reg->intreg.r_r3);
|
||||
RF (R0_REGNUM + 4, core_reg->intreg.r_r4);
|
||||
RF (R0_REGNUM + 5, core_reg->intreg.r_r5);
|
||||
RF (R0_REGNUM + 6, core_reg->intreg.r_r6);
|
||||
RF (R0_REGNUM + 7, core_reg->intreg.r_r7);
|
||||
|
||||
RF (SP_REGNUM, core_reg->intreg.r_sp);
|
||||
RF (FP_REGNUM, core_reg->intreg.r_fp);
|
||||
RF (PC_REGNUM, core_reg->intreg.r_pc);
|
||||
RF (PS_REGNUM, core_reg->intreg.r_psr);
|
||||
|
||||
/* Floating point registers */
|
||||
RF (FPS_REGNUM, core_reg->freg.r_fsr);
|
||||
RF (FP0_REGNUM + 0, core_reg->freg.r_freg[0]);
|
||||
RF (FP0_REGNUM + 2, core_reg->freg.r_freg[2]);
|
||||
RF (FP0_REGNUM + 4, core_reg->freg.r_freg[4]);
|
||||
RF (FP0_REGNUM + 6, core_reg->freg.r_freg[6]);
|
||||
RF (LP0_REGNUM + 1, core_reg->freg.r_freg[1]);
|
||||
RF (LP0_REGNUM + 3, core_reg->freg.r_freg[3]);
|
||||
RF (LP0_REGNUM + 5, core_reg->freg.r_freg[5]);
|
||||
RF (LP0_REGNUM + 7, core_reg->freg.r_freg[7]);
|
||||
registers_fetched ();
|
||||
}
|
||||
|
||||
/* Register that we are able to handle ns32knbsd core file formats.
|
||||
FIXME: is this really bfd_target_unknown_flavour? */
|
||||
|
||||
static struct core_fns nat_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_ns32knbsd_nat (void)
|
||||
{
|
||||
add_core_fns (&nat_core_fns);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kernel_u_size() is not helpful on NetBSD because
|
||||
* the "u" struct is NOT in the core dump file.
|
||||
*/
|
||||
|
||||
#ifdef FETCH_KCORE_REGISTERS
|
||||
/*
|
||||
* Get registers from a kernel crash dump or live kernel.
|
||||
* Called by kcore-nbsd.c:get_kcore_registers().
|
||||
*/
|
||||
void
|
||||
fetch_kcore_registers (struct pcb *pcb)
|
||||
{
|
||||
struct switchframe sf;
|
||||
struct reg intreg;
|
||||
int dummy;
|
||||
|
||||
/* Integer registers */
|
||||
if (target_read_memory ((CORE_ADDR) pcb->pcb_ksp, (char *) &sf, sizeof sf))
|
||||
error ("Cannot read integer registers.");
|
||||
|
||||
/* We use the psr at kernel entry */
|
||||
if (target_read_memory ((CORE_ADDR) pcb->pcb_onstack, (char *) &intreg, sizeof intreg))
|
||||
error ("Cannot read processor status register.");
|
||||
|
||||
dummy = 0;
|
||||
RF (R0_REGNUM + 0, dummy);
|
||||
RF (R0_REGNUM + 1, dummy);
|
||||
RF (R0_REGNUM + 2, dummy);
|
||||
RF (R0_REGNUM + 3, sf.sf_r3);
|
||||
RF (R0_REGNUM + 4, sf.sf_r4);
|
||||
RF (R0_REGNUM + 5, sf.sf_r5);
|
||||
RF (R0_REGNUM + 6, sf.sf_r6);
|
||||
RF (R0_REGNUM + 7, sf.sf_r7);
|
||||
|
||||
dummy = pcb->pcb_kfp + 8;
|
||||
RF (SP_REGNUM, dummy);
|
||||
RF (FP_REGNUM, sf.sf_fp);
|
||||
RF (PC_REGNUM, sf.sf_pc);
|
||||
RF (PS_REGNUM, intreg.r_psr);
|
||||
|
||||
/* Floating point registers */
|
||||
RF (FPS_REGNUM, pcb->pcb_fsr);
|
||||
RF (FP0_REGNUM + 0, pcb->pcb_freg[0]);
|
||||
RF (FP0_REGNUM + 2, pcb->pcb_freg[2]);
|
||||
RF (FP0_REGNUM + 4, pcb->pcb_freg[4]);
|
||||
RF (FP0_REGNUM + 6, pcb->pcb_freg[6]);
|
||||
RF (LP0_REGNUM + 1, pcb->pcb_freg[1]);
|
||||
RF (LP0_REGNUM + 3, pcb->pcb_freg[3]);
|
||||
RF (LP0_REGNUM + 5, pcb->pcb_freg[5]);
|
||||
RF (LP0_REGNUM + 7, pcb->pcb_freg[7]);
|
||||
registers_fetched ();
|
||||
}
|
||||
#endif /* FETCH_KCORE_REGISTERS */
|
||||
|
||||
void
|
||||
clear_regs (void)
|
||||
{
|
||||
double zero = 0.0;
|
||||
int null = 0;
|
||||
|
||||
/* Integer registers */
|
||||
RF (R0_REGNUM + 0, null);
|
||||
RF (R0_REGNUM + 1, null);
|
||||
RF (R0_REGNUM + 2, null);
|
||||
RF (R0_REGNUM + 3, null);
|
||||
RF (R0_REGNUM + 4, null);
|
||||
RF (R0_REGNUM + 5, null);
|
||||
RF (R0_REGNUM + 6, null);
|
||||
RF (R0_REGNUM + 7, null);
|
||||
|
||||
RF (SP_REGNUM, null);
|
||||
RF (FP_REGNUM, null);
|
||||
RF (PC_REGNUM, null);
|
||||
RF (PS_REGNUM, null);
|
||||
|
||||
/* Floating point registers */
|
||||
RF (FPS_REGNUM, zero);
|
||||
RF (FP0_REGNUM + 0, zero);
|
||||
RF (FP0_REGNUM + 2, zero);
|
||||
RF (FP0_REGNUM + 4, zero);
|
||||
RF (FP0_REGNUM + 6, zero);
|
||||
RF (LP0_REGNUM + 0, zero);
|
||||
RF (LP0_REGNUM + 1, zero);
|
||||
RF (LP0_REGNUM + 2, zero);
|
||||
RF (LP0_REGNUM + 3, zero);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Return number of args passed to a frame.
|
||||
Can return -1, meaning no way to tell. */
|
||||
|
||||
int
|
||||
frame_num_args (struct frame_info *fi)
|
||||
{
|
||||
CORE_ADDR enter_addr;
|
||||
CORE_ADDR argp;
|
||||
int inst;
|
||||
int args;
|
||||
int i;
|
||||
|
||||
if (read_memory_integer (fi->frame, 4) == 0 && fi->pc < 0x10000)
|
||||
{
|
||||
/* main is always called with three args */
|
||||
return (3);
|
||||
}
|
||||
enter_addr = ns32k_get_enter_addr (fi->pc);
|
||||
if (enter_addr = 0)
|
||||
return (-1);
|
||||
argp = enter_addr == 1 ? SAVED_PC_AFTER_CALL (fi) : FRAME_SAVED_PC (fi);
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
/*
|
||||
* After a bsr gcc may emit the following instructions
|
||||
* to remove the arguments from the stack:
|
||||
* cmpqd 0,tos - to remove 4 bytes from the stack
|
||||
* cmpd tos,tos - to remove 8 bytes from the stack
|
||||
* adjsp[bwd] -n - to remove n bytes from the stack
|
||||
* Gcc sometimes delays emitting these instructions and
|
||||
* may even throw a branch between our feet.
|
||||
*/
|
||||
inst = read_memory_integer (argp, 4);
|
||||
args = read_memory_integer (argp + 2, 4);
|
||||
if ((inst & 0xff) == 0xea)
|
||||
{ /* br */
|
||||
args = ((inst >> 8) & 0xffffff) | (args << 24);
|
||||
if (args & 0x80)
|
||||
{
|
||||
if (args & 0x40)
|
||||
{
|
||||
args = ntohl (args);
|
||||
}
|
||||
else
|
||||
{
|
||||
args = ntohs (args & 0xffff);
|
||||
if (args & 0x2000)
|
||||
args |= 0xc000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args = args & 0xff;
|
||||
if (args & 0x40)
|
||||
args |= 0x80;
|
||||
}
|
||||
argp += args;
|
||||
continue;
|
||||
}
|
||||
if ((inst & 0xffff) == 0xb81f) /* cmpqd 0,tos */
|
||||
return (1);
|
||||
else if ((inst & 0xffff) == 0xbdc7) /* cmpd tos,tos */
|
||||
return (2);
|
||||
else if ((inst & 0xfffc) == 0xa57c)
|
||||
{ /* adjsp[bwd] */
|
||||
switch (inst & 3)
|
||||
{
|
||||
case 0:
|
||||
args = ((args & 0xff) + 0x80);
|
||||
break;
|
||||
case 1:
|
||||
args = ((ntohs (args) & 0xffff) + 0x8000);
|
||||
break;
|
||||
case 3:
|
||||
args = -ntohl (args);
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
if (args / 4 > 10 || (args & 3) != 0)
|
||||
continue;
|
||||
return (args / 4);
|
||||
}
|
||||
argp += 1;
|
||||
}
|
||||
return (-1);
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
/* Remote target glue for the Oki op50n based eval board.
|
||||
|
||||
Copyright 1995, 1998, 1999, 2000 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
|
||||
static void op50n_open (char *args, int from_tty);
|
||||
|
||||
/*
|
||||
* this array of registers need to match the indexes used by GDB. The
|
||||
* whole reason this exists is cause the various ROM monitors use
|
||||
* different strings than GDB does, and doesn't support all the
|
||||
* registers either. So, typing "info reg sp" becomes a "r30".
|
||||
*/
|
||||
|
||||
static char *op50n_regnames[NUM_REGS] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
||||
"cr11", "p", NULL, NULL, NULL, "cr15", "cr19", "cr20",
|
||||
"cr21", "cr22", NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, "cr0", "cr8", "cr9", "cr10", "cr12",
|
||||
"cr13", "cr24", "cr25", "cr26",
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the monitor command strings. Since these are passed directly
|
||||
* through to a printf style function, we need can include formatting
|
||||
* strings. We also need a CR or LF on the end.
|
||||
*/
|
||||
|
||||
static struct target_ops op50n_ops;
|
||||
|
||||
static char *op50n_inits[] =
|
||||
{".\r", NULL};
|
||||
|
||||
static struct monitor_ops op50n_cmds;
|
||||
|
||||
static void
|
||||
init_op50n_cmds (void)
|
||||
{
|
||||
op50n_cmds.flags = MO_CLR_BREAK_USES_ADDR /*| MO_GETMEM_READ_SINGLE */ ; /* flags */
|
||||
op50n_cmds.init = op50n_inits; /* Init strings */
|
||||
op50n_cmds.cont = "g\r"; /* continue command */
|
||||
op50n_cmds.step = "t\r"; /* single step */
|
||||
op50n_cmds.stop = "\003.\r"; /* Interrupt char */
|
||||
op50n_cmds.set_break = "b %x\r"; /* set a breakpoint */
|
||||
op50n_cmds.clr_break = "b %x;0\r"; /* clear breakpoint at addr */
|
||||
op50n_cmds.clr_all_break = "bx\r"; /* clear all breakpoints */
|
||||
op50n_cmds.fill = "fx %x s%x %x\r"; /* memory fill cmd (addr, len, val) */
|
||||
op50n_cmds.setmem.cmdb = "sx %x %x\r"; /* setmem.cmdb (addr, value) */
|
||||
op50n_cmds.setmem.cmdw = "sh %x %x\r"; /* setmem.cmdw (addr, value) */
|
||||
op50n_cmds.setmem.cmdl = "s %x %x\r"; /* setmem.cmdl (addr, value) */
|
||||
op50n_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
op50n_cmds.setmem.resp_delim = NULL; /* setmem.resp_delim */
|
||||
op50n_cmds.setmem.term = NULL; /* setmem.term */
|
||||
op50n_cmds.setmem.term_cmd = NULL; /* setmem.term_cmd */
|
||||
#if 0
|
||||
{
|
||||
"sx %x\r", /* getmem.cmdb (addr, len) */
|
||||
"sh %x\r", /* getmem.cmdw (addr, len) */
|
||||
"s %x\r", /* getmem.cmdl (addr, len) */
|
||||
NULL, /* getmem.cmdll (addr, len) */
|
||||
" : ", /* getmem.resp_delim */
|
||||
" ", /* getmem.term */
|
||||
".\r", /* getmem.term_cmd */
|
||||
};
|
||||
#else
|
||||
op50n_cmds.getmem.cmdb = "dx %x s%x\r"; /* getmem.cmdb (addr, len) */
|
||||
op50n_cmds.getmem.cmdw = NULL; /* getmem.cmdw (addr, len) */
|
||||
op50n_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, len) */
|
||||
op50n_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
op50n_cmds.getmem.resp_delim = " : "; /* getmem.resp_delim */
|
||||
op50n_cmds.getmem.term = NULL; /* getmem.term */
|
||||
op50n_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
#endif
|
||||
op50n_cmds.setreg.cmd = "x %s %x\r"; /* setreg.cmd (name, value) */
|
||||
op50n_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
op50n_cmds.setreg.term = NULL; /* setreg.term */
|
||||
op50n_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
op50n_cmds.getreg.cmd = "x %s\r"; /* getreg.cmd (name) */
|
||||
op50n_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
|
||||
op50n_cmds.getreg.term = " "; /* getreg.term */
|
||||
op50n_cmds.getreg.term_cmd = ".\r"; /* getreg.term_cmd */
|
||||
op50n_cmds.dump_registers = NULL; /* dump_registers */
|
||||
op50n_cmds.register_pattern = NULL; /* register_pattern */
|
||||
op50n_cmds.supply_register = NULL; /* supply_register */
|
||||
op50n_cmds.load_routine = NULL; /* load routine */
|
||||
op50n_cmds.load = "r 0\r"; /* download command */
|
||||
op50n_cmds.loadresp = NULL; /* load response */
|
||||
op50n_cmds.prompt = "\n#"; /* monitor command prompt */
|
||||
op50n_cmds.line_term = "\r"; /* end-of-command delimitor */
|
||||
op50n_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
op50n_cmds.target = &op50n_ops; /* target operations */
|
||||
op50n_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
op50n_cmds.regnames = op50n_regnames; /* register names */
|
||||
op50n_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
};
|
||||
|
||||
static void
|
||||
op50n_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &op50n_cmds, from_tty);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_op50n (void)
|
||||
{
|
||||
init_op50n_cmds ();
|
||||
init_monitor_ops (&op50n_ops);
|
||||
|
||||
op50n_ops.to_shortname = "op50n";
|
||||
op50n_ops.to_longname = "Oki's debug monitor for the Op50n Eval board";
|
||||
op50n_ops.to_doc = "Debug on a Oki OP50N eval board.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
op50n_ops.to_open = op50n_open;
|
||||
|
||||
add_target (&op50n_ops);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,812 +0,0 @@
|
||||
/* Shared code to pre-read a stab (dbx-style), when building a psymtab.
|
||||
Copyright 1986, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 1998
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The following need to be defined:
|
||||
SET_NAMESTRING() --Set namestring to name of symbol.
|
||||
CUR_SYMBOL_TYPE --Type code of current symbol.
|
||||
CUR_SYMBOL_VALUE --Value field of current symbol. May be adjusted here.
|
||||
namestring - variable pointing to the name of the stab.
|
||||
section_offsets - variable pointing to the section offsets.
|
||||
pst - the partial symbol table being built.
|
||||
|
||||
psymtab_include_list, includes_used, includes_allocated - list of include
|
||||
file names (N_SOL) seen so far.
|
||||
dependency_list, dependencies_used, dependencies_allocated - list of
|
||||
N_EXCL stabs seen so far.
|
||||
|
||||
END_PSYMTAB -- end a partial symbol table.
|
||||
START_PSYMTAB -- start a partial symbol table.
|
||||
*/
|
||||
|
||||
/* End of macro definitions, now let's handle them symbols! */
|
||||
|
||||
switch (CUR_SYMBOL_TYPE)
|
||||
{
|
||||
char *p;
|
||||
/*
|
||||
* Standard, external, non-debugger, symbols
|
||||
*/
|
||||
|
||||
case N_TEXT | N_EXT:
|
||||
case N_NBTEXT | N_EXT:
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
goto record_it;
|
||||
|
||||
case N_DATA | N_EXT:
|
||||
case N_NBDATA | N_EXT:
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
goto record_it;
|
||||
|
||||
case N_BSS:
|
||||
case N_BSS | N_EXT:
|
||||
case N_NBBSS | N_EXT:
|
||||
case N_SETV | N_EXT: /* FIXME, is this in BSS? */
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_BSS);
|
||||
goto record_it;
|
||||
|
||||
case N_ABS | N_EXT:
|
||||
record_it:
|
||||
#ifdef DBXREAD_ONLY
|
||||
SET_NAMESTRING();
|
||||
|
||||
bss_ext_symbol:
|
||||
record_minimal_symbol (namestring, CUR_SYMBOL_VALUE,
|
||||
CUR_SYMBOL_TYPE, objfile); /* Always */
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
|
||||
/* Standard, local, non-debugger, symbols */
|
||||
|
||||
case N_NBTEXT:
|
||||
|
||||
/* We need to be able to deal with both N_FN or N_TEXT,
|
||||
because we have no way of knowing whether the sys-supplied ld
|
||||
or GNU ld was used to make the executable. Sequents throw
|
||||
in another wrinkle -- they renumbered N_FN. */
|
||||
|
||||
case N_FN:
|
||||
case N_FN_SEQ:
|
||||
case N_TEXT:
|
||||
#ifdef DBXREAD_ONLY
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
SET_NAMESTRING();
|
||||
if ((namestring[0] == '-' && namestring[1] == 'l')
|
||||
|| (namestring [(nsl = strlen (namestring)) - 1] == 'o'
|
||||
&& namestring [nsl - 2] == '.'))
|
||||
{
|
||||
if (objfile -> ei.entry_point < CUR_SYMBOL_VALUE &&
|
||||
objfile -> ei.entry_point >= last_o_file_start)
|
||||
{
|
||||
objfile -> ei.entry_file_lowpc = last_o_file_start;
|
||||
objfile -> ei.entry_file_highpc = CUR_SYMBOL_VALUE;
|
||||
}
|
||||
if (past_first_source_file && pst
|
||||
/* The gould NP1 uses low values for .o and -l symbols
|
||||
which are not the address. */
|
||||
&& CUR_SYMBOL_VALUE >= pst->textlow)
|
||||
{
|
||||
END_PSYMTAB (pst, psymtab_include_list, includes_used,
|
||||
symnum * symbol_size,
|
||||
CUR_SYMBOL_VALUE > pst->texthigh
|
||||
? CUR_SYMBOL_VALUE : pst->texthigh,
|
||||
dependency_list, dependencies_used, textlow_not_set);
|
||||
pst = (struct partial_symtab *) 0;
|
||||
includes_used = 0;
|
||||
dependencies_used = 0;
|
||||
}
|
||||
else
|
||||
past_first_source_file = 1;
|
||||
last_o_file_start = CUR_SYMBOL_VALUE;
|
||||
}
|
||||
else
|
||||
goto record_it;
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
|
||||
case N_DATA:
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
goto record_it;
|
||||
|
||||
case N_UNDF | N_EXT:
|
||||
#ifdef DBXREAD_ONLY
|
||||
if (CUR_SYMBOL_VALUE != 0) {
|
||||
/* This is a "Fortran COMMON" symbol. See if the target
|
||||
environment knows where it has been relocated to. */
|
||||
|
||||
CORE_ADDR reladdr;
|
||||
|
||||
SET_NAMESTRING();
|
||||
if (target_lookup_symbol (namestring, &reladdr)) {
|
||||
continue; /* Error in lookup; ignore symbol for now. */
|
||||
}
|
||||
CUR_SYMBOL_TYPE ^= (N_BSS^N_UNDF); /* Define it as a bss-symbol */
|
||||
CUR_SYMBOL_VALUE = reladdr;
|
||||
goto bss_ext_symbol;
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue; /* Just undefined, not COMMON */
|
||||
|
||||
case N_UNDF:
|
||||
#ifdef DBXREAD_ONLY
|
||||
if (processing_acc_compilation && CUR_SYMBOL_STRX == 1) {
|
||||
/* Deal with relative offsets in the string table
|
||||
used in ELF+STAB under Solaris. If we want to use the
|
||||
n_strx field, which contains the name of the file,
|
||||
we must adjust file_string_table_offset *before* calling
|
||||
SET_NAMESTRING(). */
|
||||
past_first_source_file = 1;
|
||||
file_string_table_offset = next_file_string_table_offset;
|
||||
next_file_string_table_offset =
|
||||
file_string_table_offset + CUR_SYMBOL_VALUE;
|
||||
if (next_file_string_table_offset < file_string_table_offset)
|
||||
error ("string table offset backs up at %d", symnum);
|
||||
/* FIXME -- replace error() with complaint. */
|
||||
continue;
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
|
||||
/* Lots of symbol types we can just ignore. */
|
||||
|
||||
case N_ABS:
|
||||
case N_NBDATA:
|
||||
case N_NBBSS:
|
||||
continue;
|
||||
|
||||
/* Keep going . . .*/
|
||||
|
||||
/*
|
||||
* Special symbol types for GNU
|
||||
*/
|
||||
case N_INDR:
|
||||
case N_INDR | N_EXT:
|
||||
case N_SETA:
|
||||
case N_SETA | N_EXT:
|
||||
case N_SETT:
|
||||
case N_SETT | N_EXT:
|
||||
case N_SETD:
|
||||
case N_SETD | N_EXT:
|
||||
case N_SETB:
|
||||
case N_SETB | N_EXT:
|
||||
case N_SETV:
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Debugger symbols
|
||||
*/
|
||||
|
||||
case N_SO: {
|
||||
unsigned long valu;
|
||||
static int prev_so_symnum = -10;
|
||||
static int first_so_symnum;
|
||||
char *p;
|
||||
int prev_textlow_not_set;
|
||||
|
||||
valu = CUR_SYMBOL_VALUE + ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
|
||||
prev_textlow_not_set = textlow_not_set;
|
||||
|
||||
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
|
||||
/* A zero value is probably an indication for the SunPRO 3.0
|
||||
compiler. end_psymtab explicitly tests for zero, so
|
||||
don't relocate it. */
|
||||
|
||||
if (CUR_SYMBOL_VALUE == 0)
|
||||
{
|
||||
textlow_not_set = 1;
|
||||
valu = 0;
|
||||
}
|
||||
else
|
||||
textlow_not_set = 0;
|
||||
#else
|
||||
textlow_not_set = 0;
|
||||
#endif
|
||||
past_first_source_file = 1;
|
||||
|
||||
if (prev_so_symnum != symnum - 1)
|
||||
{ /* Here if prev stab wasn't N_SO */
|
||||
first_so_symnum = symnum;
|
||||
|
||||
if (pst)
|
||||
{
|
||||
END_PSYMTAB (pst, psymtab_include_list, includes_used,
|
||||
symnum * symbol_size,
|
||||
valu > pst->texthigh ? valu : pst->texthigh,
|
||||
dependency_list, dependencies_used,
|
||||
prev_textlow_not_set);
|
||||
pst = (struct partial_symtab *) 0;
|
||||
includes_used = 0;
|
||||
dependencies_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
prev_so_symnum = symnum;
|
||||
|
||||
/* End the current partial symtab and start a new one */
|
||||
|
||||
SET_NAMESTRING();
|
||||
|
||||
/* Null name means end of .o file. Don't start a new one. */
|
||||
if (*namestring == '\000')
|
||||
continue;
|
||||
|
||||
/* Some compilers (including gcc) emit a pair of initial N_SOs.
|
||||
The first one is a directory name; the second the file name.
|
||||
If pst exists, is empty, and has a filename ending in '/',
|
||||
we assume the previous N_SO was a directory name. */
|
||||
|
||||
p = strrchr (namestring, '/');
|
||||
if (p && *(p+1) == '\000')
|
||||
continue; /* Simply ignore directory name SOs */
|
||||
|
||||
/* Some other compilers (C++ ones in particular) emit useless
|
||||
SOs for non-existant .c files. We ignore all subsequent SOs that
|
||||
immediately follow the first. */
|
||||
|
||||
if (!pst)
|
||||
pst = START_PSYMTAB (objfile, section_offsets,
|
||||
namestring, valu,
|
||||
first_so_symnum * symbol_size,
|
||||
objfile -> global_psymbols.next,
|
||||
objfile -> static_psymbols.next);
|
||||
continue;
|
||||
}
|
||||
|
||||
case N_BINCL:
|
||||
{
|
||||
#ifdef DBXREAD_ONLY
|
||||
enum language tmp_language;
|
||||
/* Add this bincl to the bincl_list for future EXCLs. No
|
||||
need to save the string; it'll be around until
|
||||
read_dbx_symtab function returns */
|
||||
|
||||
SET_NAMESTRING();
|
||||
|
||||
tmp_language = deduce_language_from_filename (namestring);
|
||||
|
||||
/* Only change the psymtab's language if we've learned
|
||||
something useful (eg. tmp_language is not language_unknown).
|
||||
In addition, to match what start_subfile does, never change
|
||||
from C++ to C. */
|
||||
if (tmp_language != language_unknown
|
||||
&& (tmp_language != language_c
|
||||
|| psymtab_language != language_cplus))
|
||||
psymtab_language = tmp_language;
|
||||
|
||||
if (pst == NULL)
|
||||
{
|
||||
/* FIXME: we should not get here without a PST to work on.
|
||||
Attempt to recover. */
|
||||
complain (&unclaimed_bincl_complaint, namestring, symnum);
|
||||
continue;
|
||||
}
|
||||
add_bincl_to_list (pst, namestring, CUR_SYMBOL_VALUE);
|
||||
|
||||
/* Mark down an include file in the current psymtab */
|
||||
|
||||
goto record_include_file;
|
||||
|
||||
#else /* DBXREAD_ONLY */
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
|
||||
case N_SOL:
|
||||
{
|
||||
enum language tmp_language;
|
||||
/* Mark down an include file in the current psymtab */
|
||||
|
||||
SET_NAMESTRING();
|
||||
|
||||
tmp_language = deduce_language_from_filename (namestring);
|
||||
|
||||
/* Only change the psymtab's language if we've learned
|
||||
something useful (eg. tmp_language is not language_unknown).
|
||||
In addition, to match what start_subfile does, never change
|
||||
from C++ to C. */
|
||||
if (tmp_language != language_unknown
|
||||
&& (tmp_language != language_c
|
||||
|| psymtab_language != language_cplus))
|
||||
psymtab_language = tmp_language;
|
||||
|
||||
/* In C++, one may expect the same filename to come round many
|
||||
times, when code is coming alternately from the main file
|
||||
and from inline functions in other files. So I check to see
|
||||
if this is a file we've seen before -- either the main
|
||||
source file, or a previously included file.
|
||||
|
||||
This seems to be a lot of time to be spending on N_SOL, but
|
||||
things like "break c-exp.y:435" need to work (I
|
||||
suppose the psymtab_include_list could be hashed or put
|
||||
in a binary tree, if profiling shows this is a major hog). */
|
||||
if (pst && STREQ (namestring, pst->filename))
|
||||
continue;
|
||||
{
|
||||
register int i;
|
||||
for (i = 0; i < includes_used; i++)
|
||||
if (STREQ (namestring, psymtab_include_list[i]))
|
||||
{
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
if (i == -1)
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DBXREAD_ONLY
|
||||
record_include_file:
|
||||
#endif
|
||||
|
||||
psymtab_include_list[includes_used++] = namestring;
|
||||
if (includes_used >= includes_allocated)
|
||||
{
|
||||
char **orig = psymtab_include_list;
|
||||
|
||||
psymtab_include_list = (char **)
|
||||
alloca ((includes_allocated *= 2) *
|
||||
sizeof (char *));
|
||||
memcpy ((PTR)psymtab_include_list, (PTR)orig,
|
||||
includes_used * sizeof (char *));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case N_LSYM: /* Typedef or automatic variable. */
|
||||
case N_STSYM: /* Data seg var -- static */
|
||||
case N_LCSYM: /* BSS " */
|
||||
case N_ROSYM: /* Read-only data seg var -- static. */
|
||||
case N_NBSTS: /* Gould nobase. */
|
||||
case N_NBLCS: /* symbols. */
|
||||
case N_FUN:
|
||||
case N_GSYM: /* Global (extern) variable; can be
|
||||
data or bss (sigh FIXME). */
|
||||
|
||||
/* Following may probably be ignored; I'll leave them here
|
||||
for now (until I do Pascal and Modula 2 extensions). */
|
||||
|
||||
case N_PC: /* I may or may not need this; I
|
||||
suspect not. */
|
||||
case N_M2C: /* I suspect that I can ignore this here. */
|
||||
case N_SCOPE: /* Same. */
|
||||
|
||||
SET_NAMESTRING();
|
||||
|
||||
#ifdef DBXREAD_ONLY
|
||||
/* See if this is an end of function stab. */
|
||||
if (CUR_SYMBOL_TYPE == N_FUN && *namestring == '\000')
|
||||
{
|
||||
unsigned long valu;
|
||||
|
||||
/* It's value is the size (in bytes) of the function for
|
||||
function relative stabs, or the address of the function's
|
||||
end for old style stabs. */
|
||||
valu = CUR_SYMBOL_VALUE + last_function_start;
|
||||
if (pst->texthigh == 0 || valu > pst->texthigh)
|
||||
pst->texthigh = valu;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
p = (char *) strchr (namestring, ':');
|
||||
if (!p)
|
||||
continue; /* Not a debugging symbol. */
|
||||
|
||||
|
||||
|
||||
/* Main processing section for debugging symbols which
|
||||
the initial read through the symbol tables needs to worry
|
||||
about. If we reach this point, the symbol which we are
|
||||
considering is definitely one we are interested in.
|
||||
p must also contain the (valid) index into the namestring
|
||||
which indicates the debugging type symbol. */
|
||||
|
||||
switch (p[1])
|
||||
{
|
||||
case 'S':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
#ifdef STATIC_TRANSFORM_NAME
|
||||
namestring = STATIC_TRANSFORM_NAME (namestring);
|
||||
#endif
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_STATIC,
|
||||
&objfile->static_psymbols,
|
||||
0, CUR_SYMBOL_VALUE,
|
||||
psymtab_language, objfile);
|
||||
continue;
|
||||
case 'G':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
|
||||
/* The addresses in these entries are reported to be
|
||||
wrong. See the code that reads 'G's for symtabs. */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_STATIC,
|
||||
&objfile->global_psymbols,
|
||||
0, CUR_SYMBOL_VALUE,
|
||||
psymtab_language, objfile);
|
||||
continue;
|
||||
|
||||
case 'T':
|
||||
if (p != namestring) /* a name is there, not just :T... */
|
||||
{
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
STRUCT_NAMESPACE, LOC_TYPEDEF,
|
||||
&objfile->static_psymbols,
|
||||
CUR_SYMBOL_VALUE, 0,
|
||||
psymtab_language, objfile);
|
||||
if (p[2] == 't')
|
||||
{
|
||||
/* Also a typedef with the same name. */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
&objfile->static_psymbols,
|
||||
CUR_SYMBOL_VALUE, 0,
|
||||
psymtab_language, objfile);
|
||||
p += 1;
|
||||
}
|
||||
/* The semantics of C++ state that "struct foo { ... }"
|
||||
also defines a typedef for "foo". Unfortuantely, cfront
|
||||
never makes the typedef when translating from C++ to C.
|
||||
We make the typedef here so that "ptype foo" works as
|
||||
expected for cfront translated code. */
|
||||
else if (psymtab_language == language_cplus)
|
||||
{
|
||||
/* Also a typedef with the same name. */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
&objfile->static_psymbols,
|
||||
CUR_SYMBOL_VALUE, 0,
|
||||
psymtab_language, objfile);
|
||||
}
|
||||
}
|
||||
goto check_enum;
|
||||
case 't':
|
||||
if (p != namestring) /* a name is there, not just :T... */
|
||||
{
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_TYPEDEF,
|
||||
&objfile->static_psymbols,
|
||||
CUR_SYMBOL_VALUE, 0,
|
||||
psymtab_language, objfile);
|
||||
}
|
||||
check_enum:
|
||||
/* If this is an enumerated type, we need to
|
||||
add all the enum constants to the partial symbol
|
||||
table. This does not cover enums without names, e.g.
|
||||
"enum {a, b} c;" in C, but fortunately those are
|
||||
rare. There is no way for GDB to find those from the
|
||||
enum type without spending too much time on it. Thus
|
||||
to solve this problem, the compiler needs to put out the
|
||||
enum in a nameless type. GCC2 does this. */
|
||||
|
||||
/* We are looking for something of the form
|
||||
<name> ":" ("t" | "T") [<number> "="] "e"
|
||||
{<constant> ":" <value> ","} ";". */
|
||||
|
||||
/* Skip over the colon and the 't' or 'T'. */
|
||||
p += 2;
|
||||
/* This type may be given a number. Also, numbers can come
|
||||
in pairs like (0,26). Skip over it. */
|
||||
while ((*p >= '0' && *p <= '9')
|
||||
|| *p == '(' || *p == ',' || *p == ')'
|
||||
|| *p == '=')
|
||||
p++;
|
||||
|
||||
if (*p++ == 'e')
|
||||
{
|
||||
/* The aix4 compiler emits extra crud before the members. */
|
||||
if (*p == '-')
|
||||
{
|
||||
/* Skip over the type (?). */
|
||||
while (*p != ':')
|
||||
p++;
|
||||
|
||||
/* Skip over the colon. */
|
||||
p++;
|
||||
}
|
||||
|
||||
/* We have found an enumerated type. */
|
||||
/* According to comments in read_enum_type
|
||||
a comma could end it instead of a semicolon.
|
||||
I don't know where that happens.
|
||||
Accept either. */
|
||||
while (*p && *p != ';' && *p != ',')
|
||||
{
|
||||
char *q;
|
||||
|
||||
/* Check for and handle cretinous dbx symbol name
|
||||
continuation! */
|
||||
if (*p == '\\' || (*p == '?' && p[1] == '\0'))
|
||||
p = next_symbol_text (objfile);
|
||||
|
||||
/* Point to the character after the name
|
||||
of the enum constant. */
|
||||
for (q = p; *q && *q != ':'; q++)
|
||||
;
|
||||
/* Note that the value doesn't matter for
|
||||
enum constants in psymtabs, just in symtabs. */
|
||||
add_psymbol_to_list (p, q - p,
|
||||
VAR_NAMESPACE, LOC_CONST,
|
||||
&objfile->static_psymbols, 0,
|
||||
0, psymtab_language, objfile);
|
||||
/* Point past the name. */
|
||||
p = q;
|
||||
/* Skip over the value. */
|
||||
while (*p && *p != ',')
|
||||
p++;
|
||||
/* Advance past the comma. */
|
||||
if (*p)
|
||||
p++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
case 'c':
|
||||
/* Constant, e.g. from "const" in Pascal. */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_CONST,
|
||||
&objfile->static_psymbols, CUR_SYMBOL_VALUE,
|
||||
0, psymtab_language, objfile);
|
||||
continue;
|
||||
|
||||
case 'f':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
#ifdef DBXREAD_ONLY
|
||||
/* Keep track of the start of the last function so we
|
||||
can handle end of function symbols. */
|
||||
last_function_start = CUR_SYMBOL_VALUE;
|
||||
/* Kludges for ELF/STABS with Sun ACC */
|
||||
last_function_name = namestring;
|
||||
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
|
||||
/* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
|
||||
value for the bottom of the text seg in those cases. */
|
||||
if (pst && textlow_not_set)
|
||||
{
|
||||
pst->textlow =
|
||||
find_stab_function_addr (namestring, pst, objfile);
|
||||
textlow_not_set = 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (startup_file_end == 0)
|
||||
startup_file_end = CUR_SYMBOL_VALUE;
|
||||
#endif
|
||||
/* End kludge. */
|
||||
|
||||
/* In reordered executables this function may lie outside
|
||||
the bounds created by N_SO symbols. If that's the case
|
||||
use the address of this function as the low bound for
|
||||
the partial symbol table. */
|
||||
if (textlow_not_set
|
||||
|| (CUR_SYMBOL_VALUE < pst->textlow
|
||||
&& CUR_SYMBOL_VALUE
|
||||
!= ANOFFSET (section_offsets, SECT_OFF_TEXT)))
|
||||
{
|
||||
pst->textlow = CUR_SYMBOL_VALUE;
|
||||
textlow_not_set = 0;
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_BLOCK,
|
||||
&objfile->static_psymbols,
|
||||
0, CUR_SYMBOL_VALUE,
|
||||
psymtab_language, objfile);
|
||||
continue;
|
||||
|
||||
/* Global functions were ignored here, but now they
|
||||
are put into the global psymtab like one would expect.
|
||||
They're also in the minimal symbol table. */
|
||||
case 'F':
|
||||
CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
|
||||
#ifdef DBXREAD_ONLY
|
||||
/* Keep track of the start of the last function so we
|
||||
can handle end of function symbols. */
|
||||
last_function_start = CUR_SYMBOL_VALUE;
|
||||
/* Kludges for ELF/STABS with Sun ACC */
|
||||
last_function_name = namestring;
|
||||
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
|
||||
/* Do not fix textlow==0 for .o or NLM files, as 0 is a legit
|
||||
value for the bottom of the text seg in those cases. */
|
||||
if (pst && textlow_not_set)
|
||||
{
|
||||
pst->textlow =
|
||||
find_stab_function_addr (namestring, pst, objfile);
|
||||
textlow_not_set = 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (startup_file_end == 0)
|
||||
startup_file_end = CUR_SYMBOL_VALUE;
|
||||
#endif
|
||||
/* End kludge. */
|
||||
/* In reordered executables this function may lie outside
|
||||
the bounds created by N_SO symbols. If that's the case
|
||||
use the address of this function as the low bound for
|
||||
the partial symbol table. */
|
||||
if (textlow_not_set
|
||||
|| (CUR_SYMBOL_VALUE < pst->textlow
|
||||
&& CUR_SYMBOL_VALUE
|
||||
!= ANOFFSET (section_offsets, SECT_OFF_TEXT)))
|
||||
{
|
||||
pst->textlow = CUR_SYMBOL_VALUE;
|
||||
textlow_not_set = 0;
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
add_psymbol_to_list (namestring, p - namestring,
|
||||
VAR_NAMESPACE, LOC_BLOCK,
|
||||
&objfile->global_psymbols,
|
||||
0, CUR_SYMBOL_VALUE,
|
||||
psymtab_language, objfile);
|
||||
continue;
|
||||
|
||||
/* Two things show up here (hopefully); static symbols of
|
||||
local scope (static used inside braces) or extensions
|
||||
of structure symbols. We can ignore both. */
|
||||
case 'V':
|
||||
case '(':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
case '#': /* for symbol identification (used in live ranges) */
|
||||
/* added to support cfront stabs strings */
|
||||
case 'Z': /* for definition continuations */
|
||||
case 'P': /* for prototypes */
|
||||
continue;
|
||||
|
||||
case ':':
|
||||
/* It is a C++ nested symbol. We don't need to record it
|
||||
(I don't think); if we try to look up foo::bar::baz,
|
||||
then symbols for the symtab containing foo should get
|
||||
read in, I think. */
|
||||
/* Someone says sun cc puts out symbols like
|
||||
/foo/baz/maclib::/usr/local/bin/maclib,
|
||||
which would get here with a symbol type of ':'. */
|
||||
continue;
|
||||
|
||||
default:
|
||||
/* Unexpected symbol descriptor. The second and subsequent stabs
|
||||
of a continued stab can show up here. The question is
|
||||
whether they ever can mimic a normal stab--it would be
|
||||
nice if not, since we certainly don't want to spend the
|
||||
time searching to the end of every string looking for
|
||||
a backslash. */
|
||||
|
||||
complain (&unknown_symchar_complaint, p[1]);
|
||||
|
||||
/* Ignore it; perhaps it is an extension that we don't
|
||||
know about. */
|
||||
continue;
|
||||
}
|
||||
|
||||
case N_EXCL:
|
||||
#ifdef DBXREAD_ONLY
|
||||
|
||||
SET_NAMESTRING();
|
||||
|
||||
/* Find the corresponding bincl and mark that psymtab on the
|
||||
psymtab dependency list */
|
||||
{
|
||||
struct partial_symtab *needed_pst =
|
||||
find_corresponding_bincl_psymtab (namestring, CUR_SYMBOL_VALUE);
|
||||
|
||||
/* If this include file was defined earlier in this file,
|
||||
leave it alone. */
|
||||
if (needed_pst == pst) continue;
|
||||
|
||||
if (needed_pst)
|
||||
{
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
for (i = 0; i < dependencies_used; i++)
|
||||
if (dependency_list[i] == needed_pst)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If it's already in the list, skip the rest. */
|
||||
if (found) continue;
|
||||
|
||||
dependency_list[dependencies_used++] = needed_pst;
|
||||
if (dependencies_used >= dependencies_allocated)
|
||||
{
|
||||
struct partial_symtab **orig = dependency_list;
|
||||
dependency_list =
|
||||
(struct partial_symtab **)
|
||||
alloca ((dependencies_allocated *= 2)
|
||||
* sizeof (struct partial_symtab *));
|
||||
memcpy ((PTR)dependency_list, (PTR)orig,
|
||||
(dependencies_used
|
||||
* sizeof (struct partial_symtab *)));
|
||||
#ifdef DEBUG_INFO
|
||||
fprintf_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n");
|
||||
fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n",
|
||||
dependencies_allocated);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* DBXREAD_ONLY */
|
||||
continue;
|
||||
|
||||
case N_ENDM:
|
||||
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
|
||||
/* Solaris 2 end of module, finish current partial symbol table.
|
||||
END_PSYMTAB will set pst->texthigh to the proper value, which
|
||||
is necessary if a module compiled without debugging info
|
||||
follows this module. */
|
||||
if (pst)
|
||||
{
|
||||
END_PSYMTAB (pst, psymtab_include_list, includes_used,
|
||||
symnum * symbol_size,
|
||||
(CORE_ADDR) 0,
|
||||
dependency_list, dependencies_used, textlow_not_set);
|
||||
pst = (struct partial_symtab *) 0;
|
||||
includes_used = 0;
|
||||
dependencies_used = 0;
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case N_RBRAC:
|
||||
#ifdef HANDLE_RBRAC
|
||||
HANDLE_RBRAC(CUR_SYMBOL_VALUE);
|
||||
continue;
|
||||
#endif
|
||||
case N_EINCL:
|
||||
case N_DSLINE:
|
||||
case N_BSLINE:
|
||||
case N_SSYM: /* Claim: Structure or union element.
|
||||
Hopefully, I can ignore this. */
|
||||
case N_ENTRY: /* Alternate entry point; can ignore. */
|
||||
case N_MAIN: /* Can definitely ignore this. */
|
||||
case N_CATCH: /* These are GNU C++ extensions */
|
||||
case N_EHDECL: /* that can safely be ignored here. */
|
||||
case N_LENG:
|
||||
case N_BCOMM:
|
||||
case N_ECOMM:
|
||||
case N_ECOML:
|
||||
case N_FNAME:
|
||||
case N_SLINE:
|
||||
case N_RSYM:
|
||||
case N_PSYM:
|
||||
case N_LBRAC:
|
||||
case N_NSYMS: /* Ultrix 4.0: symbol count */
|
||||
case N_DEFD: /* GNU Modula-2 */
|
||||
case N_ALIAS: /* SunPro F77: alias name, ignore for now. */
|
||||
|
||||
case N_OBJ: /* useless types from Solaris */
|
||||
case N_OPT:
|
||||
/* These symbols aren't interesting; don't worry about them */
|
||||
|
||||
continue;
|
||||
|
||||
default:
|
||||
/* If we haven't found it yet, ignore it. It's probably some
|
||||
new type we don't know about yet. */
|
||||
complain (&unknown_symtype_complaint,
|
||||
local_hex_string (CUR_SYMBOL_TYPE));
|
||||
continue;
|
||||
}
|
@ -1,211 +0,0 @@
|
||||
/* Native-dependent code for ptx 4.0
|
||||
Copyright 1988, 1989, 1991, 1992, 1994, 1999, 2000, 2001
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
#include <sys/procfs.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/param.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* Prototypes for supply_gregset etc. */
|
||||
#include "gregset.h"
|
||||
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
supply_register (EAX_REGNUM, (char *) &(*gregsetp)[EAX]);
|
||||
supply_register (EDX_REGNUM, (char *) &(*gregsetp)[EDX]);
|
||||
supply_register (ECX_REGNUM, (char *) &(*gregsetp)[ECX]);
|
||||
supply_register (EBX_REGNUM, (char *) &(*gregsetp)[EBX]);
|
||||
supply_register (ESI_REGNUM, (char *) &(*gregsetp)[ESI]);
|
||||
supply_register (EDI_REGNUM, (char *) &(*gregsetp)[EDI]);
|
||||
supply_register (ESP_REGNUM, (char *) &(*gregsetp)[UESP]);
|
||||
supply_register (EBP_REGNUM, (char *) &(*gregsetp)[EBP]);
|
||||
supply_register (EIP_REGNUM, (char *) &(*gregsetp)[EIP]);
|
||||
supply_register (EFLAGS_REGNUM, (char *) &(*gregsetp)[EFL]);
|
||||
}
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
|
||||
for (regi = 0; regi < NUM_REGS; regi++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
(*gregsetp)[regi] = *(greg_t *) & registers[REGISTER_BYTE (regi)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a pointer to a floating point register set in /proc format
|
||||
(fpregset_t *), unpack the register contents and supply them as gdb's
|
||||
idea of the current floating point register values. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
supply_fpu_registers ((struct fpusave *) &fpregsetp->fp_reg_set);
|
||||
supply_fpa_registers ((struct fpasave *) &fpregsetp->f_wregs);
|
||||
}
|
||||
|
||||
/* Given a pointer to a floating point register set in /proc format
|
||||
(fpregset_t *), update the register specified by REGNO from gdb's idea
|
||||
of the current floating point register set. If REGNO is -1, update
|
||||
them all. */
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int regi;
|
||||
char *to;
|
||||
char *from;
|
||||
|
||||
/* FIXME: see m68k-tdep.c for an example, for the m68k. */
|
||||
}
|
||||
|
||||
/*
|
||||
* This doesn't quite do the same thing as the procfs.c version, but give
|
||||
* it the same name so we don't have to put an ifdef in solib.c.
|
||||
*/
|
||||
/* this could use elf_interpreter() from elfread.c */
|
||||
int
|
||||
proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
|
||||
{
|
||||
vaddr_t curseg, memptr;
|
||||
pt_vseg_t pv;
|
||||
int rv, cmperr;
|
||||
sec_ptr interp_sec;
|
||||
char *interp_content;
|
||||
int interp_fd, funcstat;
|
||||
unsigned int size;
|
||||
char buf1[NBPG], buf2[NBPG];
|
||||
|
||||
/*
|
||||
* The following is really vile. We can get the name of the
|
||||
* shared library from the exec_bfd, and we can get a list of
|
||||
* each virtual memory segment, but there is no simple way to
|
||||
* find the mapped segment from the shared library (ala
|
||||
* procfs's PIOCOPENMEM). As a pretty nasty kludge, we
|
||||
* compare the virtual memory segment to the contents of the
|
||||
* .interp file. If they match, we assume that we've got the
|
||||
* right one.
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: for attach, use XPT_OPENT to get the executable, in
|
||||
* case we're attached without knowning the executable's
|
||||
* filename.
|
||||
*/
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf ("proc_iter\n");
|
||||
#endif
|
||||
interp_sec = bfd_get_section_by_name (exec_bfd, ".interp");
|
||||
if (!interp_sec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = bfd_section_size (exec_bfd, interp_sec);
|
||||
interp_content = alloca (size);
|
||||
if (0 == bfd_get_section_contents (exec_bfd, interp_sec,
|
||||
interp_content, (file_ptr) 0, size))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf ("proc_iter: \"%s\"\n", interp_content);
|
||||
#endif
|
||||
interp_fd = open (interp_content, O_RDONLY, 0);
|
||||
if (-1 == interp_fd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
curseg = 0;
|
||||
while (1)
|
||||
{
|
||||
rv = ptrace (PT_NEXT_VSEG, PIDGET (inferior_ptid), &pv, curseg);
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf ("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno);
|
||||
#endif
|
||||
if (-1 == rv)
|
||||
break;
|
||||
if (0 == rv)
|
||||
break;
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf ("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n",
|
||||
pv.pv_start, pv.pv_size, pv.pv_prot);
|
||||
#endif
|
||||
curseg = pv.pv_start + pv.pv_size;
|
||||
|
||||
rv = lseek (interp_fd, 0, SEEK_SET);
|
||||
if (-1 == rv)
|
||||
{
|
||||
perror ("lseek");
|
||||
close (interp_fd);
|
||||
return 0;
|
||||
}
|
||||
for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size;
|
||||
memptr += NBPG)
|
||||
{
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf ("memptr 0x%x\n", memptr);
|
||||
#endif
|
||||
rv = read (interp_fd, buf1, NBPG);
|
||||
if (-1 == rv)
|
||||
{
|
||||
perror ("read");
|
||||
close (interp_fd);
|
||||
return 0;
|
||||
}
|
||||
rv = ptrace (PT_RDATA_PAGE, PIDGET (inferior_ptid), buf2,
|
||||
memptr);
|
||||
if (-1 == rv)
|
||||
{
|
||||
perror ("ptrace");
|
||||
close (interp_fd);
|
||||
return 0;
|
||||
}
|
||||
cmperr = memcmp (buf1, buf2, NBPG);
|
||||
if (cmperr)
|
||||
break;
|
||||
}
|
||||
if (0 == cmperr)
|
||||
{
|
||||
/* this is it */
|
||||
funcstat = (*func) (interp_fd, pv.pv_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
close (interp_fd);
|
||||
return 0;
|
||||
}
|
@ -1,452 +0,0 @@
|
||||
/* Pyramid target-dependent code for GDB.
|
||||
Copyright (C) 1988, 1989, 1991 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/*** Prettier register printing. ***/
|
||||
|
||||
/* Print registers in the same format as pyramid's dbx, adb, sdb. */
|
||||
pyr_print_registers(reg_buf, regnum)
|
||||
long *reg_buf[];
|
||||
{
|
||||
register int regno;
|
||||
int usp, ksp;
|
||||
struct user u;
|
||||
|
||||
for (regno = 0; regno < 16; regno++) {
|
||||
printf_unfiltered/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n",
|
||||
REGISTER_NAME (regno), reg_buf[regno],
|
||||
REGISTER_NAME (regno+16), reg_buf[regno+16],
|
||||
REGISTER_NAME (regno+32), reg_buf[regno+32],
|
||||
REGISTER_NAME (regno+48), reg_buf[regno+48]);
|
||||
}
|
||||
usp = ptrace (3, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_usp) -
|
||||
((char *)&u), 0);
|
||||
ksp = ptrace (3, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_ksp) -
|
||||
((char *)&u), 0);
|
||||
printf_unfiltered/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n",
|
||||
REGISTER_NAME (CSP_REGNUM),reg_buf[CSP_REGNUM],
|
||||
REGISTER_NAME (KSP_REGNUM), reg_buf[KSP_REGNUM], ksp,
|
||||
"usp", usp);
|
||||
}
|
||||
|
||||
/* Print the register regnum, or all registers if regnum is -1.
|
||||
fpregs is currently ignored. */
|
||||
|
||||
pyr_do_registers_info (regnum, fpregs)
|
||||
int regnum;
|
||||
int fpregs;
|
||||
{
|
||||
/* On a pyr, we know a virtual register can always fit in an long.
|
||||
Here (and elsewhere) we take advantage of that. Yuk. */
|
||||
long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
|
||||
register int i;
|
||||
|
||||
for (i = 0 ; i < 64 ; i++) {
|
||||
read_relative_register_raw_bytes(i, raw_regs+i);
|
||||
}
|
||||
if (regnum == -1)
|
||||
pyr_print_registers (raw_regs, regnum);
|
||||
else
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
if (i == regnum) {
|
||||
long val = raw_regs[i];
|
||||
|
||||
fputs_filtered (REGISTER_NAME (i), gdb_stdout);
|
||||
printf_filtered(":");
|
||||
print_spaces_filtered (6 - strlen (REGISTER_NAME (i)), gdb_stdout);
|
||||
if (val == 0)
|
||||
printf_filtered ("0");
|
||||
else
|
||||
printf_filtered ("%s %d", local_hex_string_custom(val,"08"), val);
|
||||
printf_filtered("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*** Debugging editions of various macros from m-pyr.h ****/
|
||||
|
||||
CORE_ADDR frame_locals_address (frame)
|
||||
struct frame_info *frame;
|
||||
{
|
||||
register int addr = find_saved_register (frame,CFP_REGNUM);
|
||||
register int result = read_memory_integer (addr, 4);
|
||||
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
|
||||
frame->frame,
|
||||
REGISTER_NAME (CFP_REGNUM),
|
||||
result, addr,
|
||||
frame->frame_cfp, (CFP_REGNUM),
|
||||
|
||||
|
||||
read_register(13), read_register(29), read_register(61),
|
||||
find_saved_register(frame, 61));
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
|
||||
/* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
|
||||
or at least CFP_REGNUM relative to FRAME (ie, result).
|
||||
There seems to be a bug in the way the innermost frame is set up. */
|
||||
|
||||
return ((frame->next) ? result: frame->frame_cfp);
|
||||
}
|
||||
|
||||
CORE_ADDR frame_args_addr (frame)
|
||||
struct frame_info *frame;
|
||||
{
|
||||
register int addr = find_saved_register (frame,CFP_REGNUM);
|
||||
register int result = read_memory_integer (addr, 4);
|
||||
|
||||
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
|
||||
frame->frame,
|
||||
REGISTER_NAME (CFP_REGNUM),
|
||||
result, addr,
|
||||
frame->frame_cfp, read_register(CFP_REGNUM),
|
||||
|
||||
read_register(13), read_register(29), read_register(61),
|
||||
find_saved_register(frame, 61));
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
|
||||
/* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
|
||||
or at least CFP_REGNUM relative to FRAME (ie, result).
|
||||
There seems to be a bug in the way the innermost frame is set up. */
|
||||
return ((frame->next) ? result: frame->frame_cfp);
|
||||
}
|
||||
|
||||
#include "symtab.h"
|
||||
#include "opcode/pyr.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
|
||||
/* A couple of functions used for debugging frame-handling on
|
||||
Pyramids. (The Pyramid-dependent handling of register values for
|
||||
windowed registers is known to be buggy.)
|
||||
|
||||
When debugging, these functions can supplant the normal definitions of some
|
||||
of the macros in tm-pyramid.h The quantity of information produced
|
||||
when these functions are used makes the gdb unusable as a
|
||||
debugger for user programs. */
|
||||
|
||||
extern unsigned pyr_saved_pc(), pyr_frame_chain();
|
||||
|
||||
CORE_ADDR pyr_frame_chain(frame)
|
||||
CORE_ADDR frame;
|
||||
{
|
||||
int foo=frame - CONTROL_STACK_FRAME_SIZE;
|
||||
/* printf_unfiltered ("...following chain from %x: got %x\n", frame, foo);*/
|
||||
return foo;
|
||||
}
|
||||
|
||||
CORE_ADDR pyr_saved_pc(frame)
|
||||
CORE_ADDR frame;
|
||||
{
|
||||
int foo=0;
|
||||
foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
|
||||
printf_unfiltered ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
|
||||
frame, 60/4, foo);
|
||||
return foo;
|
||||
}
|
||||
|
||||
/* Pyramid instructions are never longer than this many bytes. */
|
||||
#define MAXLEN 24
|
||||
|
||||
/* Number of elements in the opcode table. */
|
||||
/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
|
||||
#define NOPCODES (nopcodes)
|
||||
|
||||
/* Let's be byte-independent so we can use this as a cross-assembler. */
|
||||
|
||||
#define NEXTLONG(p) \
|
||||
(p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
|
||||
|
||||
/* Print one instruction at address MEMADDR in debugged memory,
|
||||
on STREAM. Returns length of the instruction, in bytes. */
|
||||
|
||||
int
|
||||
pyr_print_insn (memaddr, stream)
|
||||
CORE_ADDR memaddr;
|
||||
GDB_FILE *stream;
|
||||
{
|
||||
unsigned char buffer[MAXLEN];
|
||||
register int i, nargs, insn_size =4;
|
||||
register unsigned char *p;
|
||||
register char *d;
|
||||
register int insn_opcode, operand_mode;
|
||||
register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
|
||||
long insn; /* first word of the insn, not broken down. */
|
||||
pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
|
||||
long extra_1, extra_2;
|
||||
|
||||
read_memory (memaddr, buffer, MAXLEN);
|
||||
insn_decode = *((pyr_insn_format *) buffer);
|
||||
insn = * ((int *) buffer);
|
||||
insn_opcode = insn_decode.operator;
|
||||
operand_mode = insn_decode.mode;
|
||||
index_multiplier = insn_decode.index_scale;
|
||||
index_reg_regno = insn_decode.index_reg;
|
||||
op_1_regno = insn_decode.operand_1;
|
||||
op_2_regno = insn_decode.operand_2;
|
||||
|
||||
|
||||
if (*((int *)buffer) == 0x0) {
|
||||
/* "halt" looks just like an invalid "jump" to the insn decoder,
|
||||
so is dealt with as a special case */
|
||||
fprintf_unfiltered (stream, "halt");
|
||||
return (4);
|
||||
}
|
||||
|
||||
for (i = 0; i < NOPCODES; i++)
|
||||
if (pyr_opcodes[i].datum.code == insn_opcode)
|
||||
break;
|
||||
|
||||
if (i == NOPCODES)
|
||||
/* FIXME: Handle unrecognised instructions better. */
|
||||
fprintf_unfiltered (stream, "???\t#%08x\t(op=%x mode =%x)",
|
||||
insn, insn_decode.operator, insn_decode.mode);
|
||||
else
|
||||
{
|
||||
/* Print the mnemonic for the instruction. Pyramid insn operands
|
||||
are so regular that we can deal with almost all of them
|
||||
separately.
|
||||
Unconditional branches are an exception: they are encoded as
|
||||
conditional branches (branch if false condition, I think)
|
||||
with no condition specified. The average user will not be
|
||||
aware of this. To maintain their illusion that an
|
||||
unconditional branch insn exists, we will have to FIXME to
|
||||
treat the insn mnemnonic of all branch instructions here as a
|
||||
special case: check the operands of branch insn and print an
|
||||
appropriate mnemonic. */
|
||||
|
||||
fprintf_unfiltered (stream, "%s\t", pyr_opcodes[i].name);
|
||||
|
||||
/* Print the operands of the insn (as specified in
|
||||
insn.operand_mode).
|
||||
Branch operands of branches are a special case: they are a word
|
||||
offset, not a byte offset. */
|
||||
|
||||
if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
|
||||
register int bit_codes=(insn >> 16)&0xf;
|
||||
register int i;
|
||||
register int displacement = (insn & 0x0000ffff) << 2;
|
||||
|
||||
static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
|
||||
|
||||
/* Is bfc and no bits specified an unconditional branch?*/
|
||||
for (i=0;i<4;i++) {
|
||||
if ((bit_codes) & 0x1)
|
||||
fputc_unfiltered (cc_bit_names[i], stream);
|
||||
bit_codes >>= 1;
|
||||
}
|
||||
|
||||
fprintf_unfiltered (stream, ",%0x",
|
||||
displacement + memaddr);
|
||||
return (insn_size);
|
||||
}
|
||||
|
||||
switch (operand_mode) {
|
||||
case 0:
|
||||
fprintf_unfiltered (stream, "%s,%s",
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf_unfiltered (stream, " 0x%0x,%s",
|
||||
op_1_regno,
|
||||
REGISTER_NAME (op_2_regno));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream, " $0x%0x,%s",
|
||||
extra_1,
|
||||
REGISTER_NAME (op_2_regno));
|
||||
break;
|
||||
case 3:
|
||||
fprintf_unfiltered (stream, " (%s),%s",
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream, " 0x%0x(%s),%s",
|
||||
extra_1,
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno));
|
||||
break;
|
||||
|
||||
/* S1 destination mode */
|
||||
case 5:
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
|
||||
: " $%#0x,(%s)"),
|
||||
op_1_regno,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
|
||||
: " $%#0x,(%s)"),
|
||||
extra_1,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno)
|
||||
? "%#0x(%s),(%s)[%s*%1d]"
|
||||
: "%#0x(%s),(%s)"),
|
||||
extra_1,
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
/* S2 destination mode */
|
||||
case 10:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
|
||||
REGISTER_NAME (op_1_regno),
|
||||
extra_1,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
case 11:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ?
|
||||
" $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
|
||||
op_1_regno,
|
||||
extra_1,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
case 12:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
read_memory (memaddr+8, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_2 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ?
|
||||
" $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
|
||||
extra_1,
|
||||
extra_2,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno)
|
||||
? " (%s),%#0x(%s)[%s*%1d]"
|
||||
: " (%s),%#0x(%s)"),
|
||||
REGISTER_NAME (op_1_regno),
|
||||
extra_1,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
case 14:
|
||||
read_memory (memaddr+4, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_1 = * ((int *) buffer);
|
||||
read_memory (memaddr+8, buffer, MAXLEN);
|
||||
insn_size += 4;
|
||||
extra_2 = * ((int *) buffer);
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
|
||||
: "%#0x(%s),%#0x(%s) "),
|
||||
extra_1,
|
||||
REGISTER_NAME (op_1_regno),
|
||||
extra_2,
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf_unfiltered (stream,
|
||||
((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
|
||||
REGISTER_NAME (op_1_regno),
|
||||
REGISTER_NAME (op_2_regno),
|
||||
REGISTER_NAME (index_reg_regno),
|
||||
index_multiplier);
|
||||
fprintf_unfiltered (stream,
|
||||
"\t\t# unknown mode in %08x",
|
||||
insn);
|
||||
break;
|
||||
} /* switch */
|
||||
}
|
||||
|
||||
{
|
||||
return insn_size;
|
||||
}
|
||||
abort ();
|
||||
}
|
@ -1,370 +0,0 @@
|
||||
/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
|
||||
Copyright (C) 1988, 1989, 1991 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/dir.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* #include <fcntl.h> Can we live without this? */
|
||||
|
||||
#include "gdbcore.h"
|
||||
#include <sys/user.h> /* After a.out.h */
|
||||
#include <sys/file.h>
|
||||
#include "gdb_stat.h"
|
||||
|
||||
|
||||
void
|
||||
fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
register int datum;
|
||||
register unsigned int regaddr;
|
||||
int reg_buf[NUM_REGS+1];
|
||||
struct user u;
|
||||
register int skipped_frames = 0;
|
||||
|
||||
registers_fetched ();
|
||||
|
||||
for (regno = 0; regno < 64; regno++) {
|
||||
reg_buf[regno] = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0);
|
||||
|
||||
#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
|
||||
printf_unfiltered ("Fetching register %s, got %0x\n",
|
||||
REGISTER_NAME (regno),
|
||||
reg_buf[regno]);
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
|
||||
if (reg_buf[regno] == -1 && errno == EIO) {
|
||||
printf_unfiltered("fetch_interior_registers: fetching register %s\n",
|
||||
REGISTER_NAME (regno));
|
||||
errno = 0;
|
||||
}
|
||||
supply_register (regno, reg_buf+regno);
|
||||
}
|
||||
/* that leaves regs 64, 65, and 66 */
|
||||
datum = ptrace (3, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE) (((char *)&u.u_pcb.pcb_csp) -
|
||||
((char *)&u)), 0);
|
||||
|
||||
|
||||
|
||||
/* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
|
||||
register (ie, NOT windowed), that gets saved in a frame iff
|
||||
the code for that frame has a prologue (ie, "adsf N"). If
|
||||
there is a prologue, the adsf insn saves the old cfp in
|
||||
pr13, cfp is set to sp, and N bytes of locals are allocated
|
||||
(sp is decremented by n).
|
||||
This makes finding CFP hard. I guess the right way to do it
|
||||
is:
|
||||
- If this is the innermost frame, believe ptrace() or
|
||||
the core area.
|
||||
- Otherwise:
|
||||
Find the first insn of the current frame.
|
||||
- find the saved pc;
|
||||
- find the call insn that saved it;
|
||||
- figure out where the call is to;
|
||||
- if the first insn is an adsf, we got a frame
|
||||
pointer. */
|
||||
|
||||
|
||||
/* Normal processors have separate stack pointers for user and
|
||||
kernel mode. Getting the last user mode frame on such
|
||||
machines is easy: the kernel context of the ptrace()'d
|
||||
process is on the kernel stack, and the USP points to what
|
||||
we want. But Pyramids only have a single cfp for both user and
|
||||
kernel mode. And processes being ptrace()'d have some
|
||||
kernel-context control frames on their stack.
|
||||
To avoid tracing back into the kernel context of an inferior,
|
||||
we skip 0 or more contiguous control frames where the pc is
|
||||
in the kernel. */
|
||||
|
||||
while (1) {
|
||||
register int inferior_saved_pc;
|
||||
inferior_saved_pc = ptrace (1, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE) (datum+((32+15)*4)), 0);
|
||||
if (inferior_saved_pc > 0) break;
|
||||
#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
|
||||
printf_unfiltered("skipping kernel frame %08x, pc=%08x\n", datum,
|
||||
inferior_saved_pc);
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
skipped_frames++;
|
||||
datum -= CONTROL_STACK_FRAME_SIZE;
|
||||
}
|
||||
|
||||
reg_buf[CSP_REGNUM] = datum;
|
||||
supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
|
||||
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
|
||||
if (skipped_frames) {
|
||||
fprintf_unfiltered (gdb_stderr,
|
||||
"skipped %d frames from %x to %x; cfp was %x, now %x\n",
|
||||
skipped_frames, reg_buf[CSP_REGNUM]);
|
||||
}
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is -1, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
register unsigned int regaddr;
|
||||
char buf[80];
|
||||
|
||||
if (regno >= 0)
|
||||
{
|
||||
if ((0 <= regno) && (regno < 64)) {
|
||||
/*regaddr = register_addr (regno, offset);*/
|
||||
regaddr = regno;
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing register number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
/*regaddr = register_addr (regno, offset);*/
|
||||
regaddr = regno;
|
||||
errno = 0;
|
||||
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
read_register (regno));
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (buf, "writing all regs, number %d", regno);
|
||||
perror_with_name (buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*** Extensions to core and dump files, for GDB. */
|
||||
|
||||
extern unsigned int last_frame_offset;
|
||||
|
||||
#ifdef PYRAMID_CORE
|
||||
|
||||
/* Can't make definitions here static, since corefile.c needs them
|
||||
to do bounds checking on the core-file areas. O well. */
|
||||
|
||||
/* have two stacks: one for data, one for register windows. */
|
||||
extern CORE_ADDR reg_stack_start;
|
||||
extern CORE_ADDR reg_stack_end;
|
||||
|
||||
/* need this so we can find the global registers: they never get saved. */
|
||||
CORE_ADDR global_reg_offset;
|
||||
static CORE_ADDR last_frame_address;
|
||||
CORE_ADDR last_frame_offset;
|
||||
|
||||
|
||||
/* Address in core file of start of register window stack area.
|
||||
Don't know if is this any of meaningful, useful or necessary. */
|
||||
extern int reg_stack_offset;
|
||||
|
||||
#endif /* PYRAMID_CORE */
|
||||
|
||||
|
||||
/* Work with core dump and executable files, for GDB.
|
||||
This code would be in corefile.c if it weren't machine-dependent. */
|
||||
|
||||
void
|
||||
core_file_command (filename, from_tty)
|
||||
char *filename;
|
||||
int from_tty;
|
||||
{
|
||||
int val;
|
||||
extern char registers[];
|
||||
|
||||
/* Discard all vestiges of any previous core file
|
||||
and mark data and stack spaces as empty. */
|
||||
|
||||
if (corefile)
|
||||
free (corefile);
|
||||
corefile = 0;
|
||||
|
||||
if (corechan >= 0)
|
||||
close (corechan);
|
||||
corechan = -1;
|
||||
|
||||
data_start = 0;
|
||||
data_end = 0;
|
||||
stack_start = STACK_END_ADDR;
|
||||
stack_end = STACK_END_ADDR;
|
||||
|
||||
#ifdef PYRAMID_CORE
|
||||
reg_stack_start = CONTROL_STACK_ADDR;
|
||||
reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
|
||||
#endif /* PYRAMID_CORE */
|
||||
|
||||
/* Now, if a new core file was specified, open it and digest it. */
|
||||
|
||||
if (filename)
|
||||
{
|
||||
filename = tilde_expand (filename);
|
||||
make_cleanup (free, filename);
|
||||
|
||||
if (have_inferior_p ())
|
||||
error ("To look at a core file, you must kill the program with \"kill\".");
|
||||
corechan = open (filename, O_RDONLY, 0);
|
||||
if (corechan < 0)
|
||||
perror_with_name (filename);
|
||||
/* 4.2-style (and perhaps also sysV-style) core dump file. */
|
||||
{
|
||||
struct user u;
|
||||
|
||||
unsigned int reg_offset;
|
||||
|
||||
val = myread (corechan, &u, sizeof u);
|
||||
if (val < 0)
|
||||
perror_with_name ("Not a core file: reading upage");
|
||||
if (val != sizeof u)
|
||||
error ("Not a core file: could only read %d bytes", val);
|
||||
data_start = exec_data_start;
|
||||
|
||||
data_end = data_start + NBPG * u.u_dsize;
|
||||
data_offset = NBPG * UPAGES;
|
||||
stack_offset = NBPG * (UPAGES + u.u_dsize);
|
||||
|
||||
/* find registers in core file */
|
||||
#ifdef PYRAMID_PTRACE
|
||||
stack_start = stack_end - NBPG * u.u_ussize;
|
||||
reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
|
||||
reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
|
||||
|
||||
last_frame_address = ((int) u.u_pcb.pcb_csp);
|
||||
last_frame_offset = reg_stack_offset + last_frame_address
|
||||
- CONTROL_STACK_ADDR ;
|
||||
global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
|
||||
|
||||
/* skip any control-stack frames that were executed in the
|
||||
kernel. */
|
||||
|
||||
while (1) {
|
||||
char buf[4];
|
||||
val = lseek (corechan, last_frame_offset+(47*4), 0);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
val = myread (corechan, buf, sizeof buf);
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
if (*(int *)buf >= 0)
|
||||
break;
|
||||
printf_unfiltered ("skipping frame %s\n", local_hex_string (last_frame_address));
|
||||
last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
|
||||
last_frame_address -= CONTROL_STACK_FRAME_SIZE;
|
||||
}
|
||||
reg_offset = last_frame_offset;
|
||||
|
||||
#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
|
||||
printf_unfiltered ("Control stack pointer = %s\n",
|
||||
local_hex_string (u.u_pcb.pcb_csp));
|
||||
printf_unfiltered ("offset to control stack %d outermost frame %d (%s)\n",
|
||||
reg_stack_offset, reg_offset, local_hex_string (last_frame_address));
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
|
||||
#else /* not PYRAMID_CORE */
|
||||
stack_start = stack_end - NBPG * u.u_ssize;
|
||||
reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
|
||||
#endif /* not PYRAMID_CORE */
|
||||
|
||||
#ifdef __not_on_pyr_yet
|
||||
/* Some machines put an absolute address in here and some put
|
||||
the offset in the upage of the regs. */
|
||||
reg_offset = (int) u.u_ar0;
|
||||
if (reg_offset > NBPG * UPAGES)
|
||||
reg_offset -= KERNEL_U_ADDR;
|
||||
#endif
|
||||
|
||||
/* I don't know where to find this info.
|
||||
So, for now, mark it as not available. */
|
||||
N_SET_MAGIC (core_aouthdr, 0);
|
||||
|
||||
/* Read the register values out of the core file and store
|
||||
them where `read_register' will find them. */
|
||||
|
||||
{
|
||||
register int regno;
|
||||
|
||||
for (regno = 0; regno < 64; regno++)
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
val = lseek (corechan, register_addr (regno, reg_offset), 0);
|
||||
if (val < 0
|
||||
|| (val = myread (corechan, buf, sizeof buf)) < 0)
|
||||
{
|
||||
char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
|
||||
+ 30);
|
||||
strcpy (buffer, "Reading register ");
|
||||
strcat (buffer, REGISTER_NAME (regno));
|
||||
|
||||
perror_with_name (buffer);
|
||||
}
|
||||
|
||||
if (val < 0)
|
||||
perror_with_name (filename);
|
||||
#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
|
||||
printf_unfiltered ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
|
||||
REGISTER_NAME (regno), regno, filename,
|
||||
register_addr(regno, reg_offset),
|
||||
regno * 4 + last_frame_address,
|
||||
*((int *)buf));
|
||||
#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filename[0] == '/')
|
||||
corefile = savestring (filename, strlen (filename));
|
||||
else
|
||||
{
|
||||
corefile = concat (current_directory, "/", filename, NULL);
|
||||
}
|
||||
|
||||
#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
|
||||
printf_unfiltered ("Providing CSP (%s) as nominal address of current frame.\n",
|
||||
local_hex_string(last_frame_address));
|
||||
#endif PYRAMID_CONTROL_FRAME_DEBUGGING
|
||||
/* FIXME: Which of the following is correct? */
|
||||
#if 0
|
||||
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
|
||||
read_pc ()));
|
||||
#else
|
||||
set_current_frame ( create_new_frame (last_frame_address,
|
||||
read_pc ()));
|
||||
#endif
|
||||
|
||||
select_frame (get_current_frame (), 0);
|
||||
validate_files ();
|
||||
}
|
||||
else if (from_tty)
|
||||
printf_unfiltered ("No core file now.\n");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,228 +0,0 @@
|
||||
/* Remote target communications for d10v connected via a serial line.
|
||||
Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997 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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_string.h"
|
||||
#include <fcntl.h>
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "target.h"
|
||||
#include "wait.h"
|
||||
/*#include "terminal.h"*/
|
||||
#include "gdbcmd.h"
|
||||
#include "objfiles.h"
|
||||
#include "gdb-stabs.h"
|
||||
#include "gdbthread.h"
|
||||
|
||||
#include "dcache.h"
|
||||
|
||||
#ifdef USG
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
#include "serial.h"
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void remote_d10v_open PARAMS ((char *name, int from_tty));
|
||||
|
||||
/* Define the target subroutine names */
|
||||
static struct target_ops remote_d10v_ops;
|
||||
|
||||
/* Open a connection to a remote debugger.
|
||||
NAME is the filename used for communication. */
|
||||
|
||||
static void
|
||||
remote_d10v_open (name, from_tty)
|
||||
char *name;
|
||||
int from_tty;
|
||||
{
|
||||
pop_target ();
|
||||
push_remote_target (name, from_tty);
|
||||
}
|
||||
|
||||
|
||||
/* Translate a GDB virtual ADDR/LEN into a format the remote target
|
||||
understands. Returns number of bytes that can be transfered
|
||||
starting at taddr, ZERO if no bytes can be transfered. */
|
||||
int
|
||||
remote_d10v_translate_xfer_address (memaddr, nr_bytes, taddr)
|
||||
CORE_ADDR memaddr;
|
||||
int nr_bytes;
|
||||
CORE_ADDR *taddr;
|
||||
{
|
||||
CORE_ADDR phys;
|
||||
CORE_ADDR seg;
|
||||
CORE_ADDR off;
|
||||
char *from = "unknown";
|
||||
char *to = "unknown";
|
||||
unsigned short imap0 = read_register (IMAP0_REGNUM);
|
||||
unsigned short imap1 = read_register (IMAP1_REGNUM);
|
||||
unsigned short dmap = read_register (DMAP_REGNUM);
|
||||
|
||||
/* GDB interprets addresses as:
|
||||
|
||||
0x00xxxxxx: Logical data address segment (DMAP translated memory)
|
||||
0x01xxxxxx: Logical instruction address segment (IMAP translated memory)
|
||||
0x10xxxxxx: Physical data memory segment (On-chip data memory)
|
||||
0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)
|
||||
0x12xxxxxx: Phisical unified memory segment (Unified memory)
|
||||
|
||||
The remote d10v board interprets addresses as:
|
||||
|
||||
0x00xxxxxx: Phisical unified memory segment (Unified memory)
|
||||
0x01xxxxxx: Physical instruction memory segment (On-chip insn memory)
|
||||
0x02xxxxxx: Physical data memory segment (On-chip data memory)
|
||||
|
||||
Translate according to current IMAP/dmap registers */
|
||||
|
||||
enum {
|
||||
targ_unified = 0x00000000,
|
||||
targ_insn = 0x01000000,
|
||||
targ_data = 0x02000000,
|
||||
};
|
||||
|
||||
seg = (memaddr >> 24);
|
||||
off = (memaddr & 0xffffffL);
|
||||
|
||||
switch (seg)
|
||||
{
|
||||
case 0x00: /* in logical data address segment */
|
||||
{
|
||||
from = "logical-data";
|
||||
if (off <= 0x7fffL)
|
||||
{
|
||||
/* On chip data */
|
||||
phys = targ_data + off;
|
||||
if (off + nr_bytes > 0x7fffL)
|
||||
/* don't cross VM boundary */
|
||||
nr_bytes = 0x7fffL - off + 1;
|
||||
to = "chip-data";
|
||||
}
|
||||
else if (off <= 0xbfffL)
|
||||
{
|
||||
short map = dmap;
|
||||
if (map & 0x1000)
|
||||
{
|
||||
/* Instruction memory */
|
||||
phys = targ_insn | ((map & 0xf) << 14) | (off & 0x3fff);
|
||||
to = "chip-insn";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unified memory */
|
||||
phys = targ_unified | ((map & 0x3ff) << 14) | (off & 0x3fff);
|
||||
to = "unified";
|
||||
}
|
||||
if (off + nr_bytes > 0xbfffL)
|
||||
/* don't cross VM boundary */
|
||||
nr_bytes = (0xbfffL - off + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Logical address out side of data segments, not supported */
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x01: /* in logical instruction address segment */
|
||||
{
|
||||
short map;
|
||||
from = "logical-insn";
|
||||
if (off <= 0x1ffffL)
|
||||
{
|
||||
map = imap0;
|
||||
}
|
||||
else if (off <= 0x3ffffL)
|
||||
{
|
||||
map = imap1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Logical address outside of IMAP[01] segment, not
|
||||
supported */
|
||||
return (0);
|
||||
}
|
||||
if ((off & 0x1ffff) + nr_bytes > 0x1ffffL)
|
||||
{
|
||||
/* don't cross VM boundary */
|
||||
nr_bytes = 0x1ffffL - (off & 0x1ffffL) + 1;
|
||||
}
|
||||
if (map & 0x1000)
|
||||
/* Instruction memory */
|
||||
{
|
||||
phys = targ_insn | off;
|
||||
to = "chip-insn";
|
||||
}
|
||||
else
|
||||
{
|
||||
phys = ((map & 0x7fL) << 17) + (off & 0x1ffffL);
|
||||
if (phys > 0xffffffL)
|
||||
/* Address outside of unified address segment */
|
||||
return (0);
|
||||
phys |= targ_unified;
|
||||
to = "unified";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x10: /* Physical data memory segment */
|
||||
from = "phys-data";
|
||||
phys = targ_data | off;
|
||||
to = "chip-data";
|
||||
break;
|
||||
|
||||
case 0x11: /* Physical instruction memory */
|
||||
from = "phys-insn";
|
||||
phys = targ_insn | off;
|
||||
to = "chip-insn";
|
||||
break;
|
||||
|
||||
case 0x12: /* Physical unified memory */
|
||||
from = "phys-unified";
|
||||
phys = targ_unified | off;
|
||||
to = "unified";
|
||||
break;
|
||||
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
*taddr = phys;
|
||||
return nr_bytes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_initialize_remote_d10v ()
|
||||
{
|
||||
remote_d10v_ops.to_shortname = "d10v";
|
||||
remote_d10v_ops.to_longname = "Remote d10v serial target in gdb-specific protocol";
|
||||
remote_d10v_ops.to_doc = "Use a remote d10v via a serial line, using a gdb-specific protocol.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
remote_d10v_ops.to_open = remote_d10v_open;
|
||||
|
||||
add_target (&remote_d10v_ops);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,169 +0,0 @@
|
||||
/* Remote debugging interface for EST-300 ICE, for GDB
|
||||
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
Written by Steve Chamberlain for Cygnus Support.
|
||||
Re-written by Stu Grossman of Cygnus Support
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "regcache.h"
|
||||
|
||||
static void est_open (char *args, int from_tty);
|
||||
|
||||
static void
|
||||
est_supply_register (char *regname, int regnamelen, char *val, int vallen)
|
||||
{
|
||||
int regno;
|
||||
|
||||
if (regnamelen != 2)
|
||||
return;
|
||||
|
||||
switch (regname[0])
|
||||
{
|
||||
case 'S':
|
||||
if (regname[1] != 'R')
|
||||
return;
|
||||
regno = PS_REGNUM;
|
||||
break;
|
||||
case 'P':
|
||||
if (regname[1] != 'C')
|
||||
return;
|
||||
regno = PC_REGNUM;
|
||||
break;
|
||||
case 'D':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + D0_REGNUM;
|
||||
break;
|
||||
case 'A':
|
||||
if (regname[1] < '0' || regname[1] > '7')
|
||||
return;
|
||||
regno = regname[1] - '0' + A0_REGNUM;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_supply_register (regno, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* This array of registers needs to match the indexes used by GDB. The
|
||||
* whole reason this exists is because the various ROM monitors use
|
||||
* different names than GDB does, and don't support all the
|
||||
* registers either. So, typing "info reg sp" becomes a "r30".
|
||||
*/
|
||||
|
||||
static char *est_regnames[NUM_REGS] =
|
||||
{
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
|
||||
"SR", "PC",
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the monitor command strings. Since these are passed directly
|
||||
* through to a printf style function, we need can include formatting
|
||||
* strings. We also need a CR or LF on the end.
|
||||
*/
|
||||
|
||||
static struct target_ops est_ops;
|
||||
|
||||
static char *est_inits[] =
|
||||
{"he\r", /* Resets the prompt, and clears repeated cmds */
|
||||
NULL};
|
||||
|
||||
static struct monitor_ops est_cmds;
|
||||
|
||||
static void
|
||||
init_est_cmds (void)
|
||||
{
|
||||
est_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_NEED_REGDUMP_AFTER_CONT |
|
||||
MO_SREC_ACK | MO_SREC_ACK_PLUS;
|
||||
est_cmds.init = est_inits; /* Init strings */
|
||||
est_cmds.cont = "go\r"; /* continue command */
|
||||
est_cmds.step = "sidr\r"; /* single step */
|
||||
est_cmds.stop = "\003"; /* ^C interrupts the program */
|
||||
est_cmds.set_break = "sb %x\r"; /* set a breakpoint */
|
||||
est_cmds.clr_break = "rb %x\r"; /* clear a breakpoint */
|
||||
est_cmds.clr_all_break = "rb\r"; /* clear all breakpoints */
|
||||
est_cmds.fill = "bfb %x %x %x\r"; /* fill (start end val) */
|
||||
est_cmds.setmem.cmdb = "smb %x %x\r"; /* setmem.cmdb (addr, value) */
|
||||
est_cmds.setmem.cmdw = "smw %x %x\r"; /* setmem.cmdw (addr, value) */
|
||||
est_cmds.setmem.cmdl = "sml %x %x\r"; /* setmem.cmdl (addr, value) */
|
||||
est_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
est_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
|
||||
est_cmds.setmem.term = NULL; /* setreg.term */
|
||||
est_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
|
||||
est_cmds.getmem.cmdb = "dmb %x %x\r"; /* getmem.cmdb (addr, len) */
|
||||
est_cmds.getmem.cmdw = "dmw %x %x\r"; /* getmem.cmdw (addr, len) */
|
||||
est_cmds.getmem.cmdl = "dml %x %x\r"; /* getmem.cmdl (addr, len) */
|
||||
est_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
|
||||
est_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
|
||||
est_cmds.getmem.term = NULL; /* getmem.term */
|
||||
est_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
|
||||
est_cmds.setreg.cmd = "sr %s %x\r"; /* setreg.cmd (name, value) */
|
||||
est_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
est_cmds.setreg.term = NULL; /* setreg.term */
|
||||
est_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
est_cmds.getreg.cmd = "dr %s\r"; /* getreg.cmd (name) */
|
||||
est_cmds.getreg.resp_delim = " = "; /* getreg.resp_delim */
|
||||
est_cmds.getreg.term = NULL; /* getreg.term */
|
||||
est_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */
|
||||
est_cmds.dump_registers = "dr\r"; /* dump_registers */
|
||||
est_cmds.register_pattern = "\\(\\w+\\) = \\([0-9a-fA-F]+\\)"; /* register_pattern */
|
||||
est_cmds.supply_register = est_supply_register; /* supply_register */
|
||||
est_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
est_cmds.load = "dl\r"; /* download command */
|
||||
est_cmds.loadresp = "+"; /* load response */
|
||||
est_cmds.prompt = ">BKM>"; /* monitor command prompt */
|
||||
est_cmds.line_term = "\r"; /* end-of-line terminator */
|
||||
est_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
est_cmds.target = &est_ops; /* target operations */
|
||||
est_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
est_cmds.regnames = est_regnames; /* registers names */
|
||||
est_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
} /* init_est_cmds */
|
||||
|
||||
static void
|
||||
est_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &est_cmds, from_tty);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_est (void)
|
||||
{
|
||||
init_est_cmds ();
|
||||
init_monitor_ops (&est_ops);
|
||||
|
||||
est_ops.to_shortname = "est";
|
||||
est_ops.to_longname = "EST background debug monitor";
|
||||
est_ops.to_doc = "Debug via the EST BDM.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
est_ops.to_open = est_open;
|
||||
|
||||
add_target (&est_ops);
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
/* Remote debugging interface for Hitachi HMS Monitor Version 1.0
|
||||
Copyright 1995, 1996, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support. Written by Steve Chamberlain
|
||||
(sac@cygnus.com).
|
||||
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "monitor.h"
|
||||
#include "serial.h"
|
||||
#include "regcache.h"
|
||||
|
||||
static void hms_open (char *args, int from_tty);
|
||||
static void
|
||||
hms_supply_register (char *regname, int regnamelen, char *val, int vallen)
|
||||
{
|
||||
int regno;
|
||||
|
||||
if (regnamelen != 2)
|
||||
return;
|
||||
if (regname[0] != 'P')
|
||||
return;
|
||||
/* We scan off all the registers in one go */
|
||||
|
||||
val = monitor_supply_register (PC_REGNUM, val);
|
||||
/* Skip the ccr string */
|
||||
while (*val != '=' && *val)
|
||||
val++;
|
||||
|
||||
val = monitor_supply_register (CCR_REGNUM, val + 1);
|
||||
|
||||
/* Skip up to rest of regs */
|
||||
while (*val != '=' && *val)
|
||||
val++;
|
||||
|
||||
for (regno = 0; regno < 7; regno++)
|
||||
{
|
||||
val = monitor_supply_register (regno, val + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This array of registers needs to match the indexes used by GDB. The
|
||||
* whole reason this exists is because the various ROM monitors use
|
||||
* different names than GDB does, and don't support all the
|
||||
* registers either. So, typing "info reg sp" becomes a "r30".
|
||||
*/
|
||||
|
||||
static char *hms_regnames[NUM_REGS] =
|
||||
{
|
||||
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC"
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the monitor command strings. Since these are passed directly
|
||||
* through to a printf style function, we need can include formatting
|
||||
* strings. We also need a CR or LF on the end.
|
||||
*/
|
||||
|
||||
static struct target_ops hms_ops;
|
||||
|
||||
static char *hms_inits[] =
|
||||
{"\003", /* Resets the prompt, and clears repeated cmds */
|
||||
NULL};
|
||||
|
||||
static struct monitor_ops hms_cmds;
|
||||
|
||||
static void
|
||||
init_hms_cmds (void)
|
||||
{
|
||||
hms_cmds.flags = MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_GETMEM_NEEDS_RANGE;
|
||||
hms_cmds.init = hms_inits; /* Init strings */
|
||||
hms_cmds.cont = "g\r"; /* continue command */
|
||||
hms_cmds.step = "s\r"; /* single step */
|
||||
hms_cmds.stop = "\003"; /* ^C interrupts the program */
|
||||
hms_cmds.set_break = "b %x\r"; /* set a breakpoint */
|
||||
hms_cmds.clr_break = "b - %x\r"; /* clear a breakpoint */
|
||||
hms_cmds.clr_all_break = "b -\r"; /* clear all breakpoints */
|
||||
hms_cmds.fill = "f %x %x %x\r"; /* fill (start end val) */
|
||||
hms_cmds.setmem.cmdb = "m.b %x=%x\r"; /* setmem.cmdb (addr, value) */
|
||||
hms_cmds.setmem.cmdw = "m.w %x=%x\r"; /* setmem.cmdw (addr, value) */
|
||||
hms_cmds.setmem.cmdl = NULL; /* setmem.cmdl (addr, value) */
|
||||
hms_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
|
||||
hms_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
|
||||
hms_cmds.setmem.term = NULL; /* setreg.term */
|
||||
hms_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
|
||||
hms_cmds.getmem.cmdb = "m.b %x %x\r"; /* getmem.cmdb (addr, addr) */
|
||||
hms_cmds.getmem.cmdw = "m.w %x %x\r"; /* getmem.cmdw (addr, addr) */
|
||||
hms_cmds.getmem.cmdl = NULL; /* getmem.cmdl (addr, addr) */
|
||||
hms_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, addr) */
|
||||
hms_cmds.getmem.resp_delim = ": "; /* getmem.resp_delim */
|
||||
hms_cmds.getmem.term = ">"; /* getmem.term */
|
||||
hms_cmds.getmem.term_cmd = "\003"; /* getmem.term_cmd */
|
||||
hms_cmds.setreg.cmd = "r %s=%x\r"; /* setreg.cmd (name, value) */
|
||||
hms_cmds.setreg.resp_delim = NULL; /* setreg.resp_delim */
|
||||
hms_cmds.setreg.term = NULL; /* setreg.term */
|
||||
hms_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */
|
||||
hms_cmds.getreg.cmd = "r %s\r"; /* getreg.cmd (name) */
|
||||
hms_cmds.getreg.resp_delim = " ("; /* getreg.resp_delim */
|
||||
hms_cmds.getreg.term = ":"; /* getreg.term */
|
||||
hms_cmds.getreg.term_cmd = "\003"; /* getreg.term_cmd */
|
||||
hms_cmds.dump_registers = "r\r"; /* dump_registers */
|
||||
hms_cmds.register_pattern = "\\(\\w+\\)=\\([0-9a-fA-F]+\\)"; /* register_pattern */
|
||||
hms_cmds.supply_register = hms_supply_register; /* supply_register */
|
||||
hms_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
|
||||
hms_cmds.load = "tl\r"; /* download command */
|
||||
hms_cmds.loadresp = NULL; /* load response */
|
||||
hms_cmds.prompt = ">"; /* monitor command prompt */
|
||||
hms_cmds.line_term = "\r"; /* end-of-command delimitor */
|
||||
hms_cmds.cmd_end = NULL; /* optional command terminator */
|
||||
hms_cmds.target = &hms_ops; /* target operations */
|
||||
hms_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
|
||||
hms_cmds.regnames = hms_regnames; /* registers names */
|
||||
hms_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
|
||||
} /* init_hms-cmds */
|
||||
|
||||
static void
|
||||
hms_open (char *args, int from_tty)
|
||||
{
|
||||
monitor_open (args, &hms_cmds, from_tty);
|
||||
}
|
||||
|
||||
int write_dos_tick_delay;
|
||||
|
||||
void
|
||||
_initialize_remote_hms (void)
|
||||
{
|
||||
init_hms_cmds ();
|
||||
init_monitor_ops (&hms_ops);
|
||||
|
||||
hms_ops.to_shortname = "hms";
|
||||
hms_ops.to_longname = "Hitachi Microsystems H8/300 debug monitor";
|
||||
hms_ops.to_doc = "Debug via the HMS monitor.\n\
|
||||
Specify the serial device it is connected to (e.g. /dev/ttya).";
|
||||
hms_ops.to_open = hms_open;
|
||||
/* By trial and error I've found that this delay doesn't break things */
|
||||
write_dos_tick_delay = 1;
|
||||
add_target (&hms_ops);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user