summaryrefslogtreecommitdiffstats
path: root/contrib/gdb
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>2000-08-04 09:35:05 +0000
committerobrien <obrien@FreeBSD.org>2000-08-04 09:35:05 +0000
commit07961757d46994f722e72fb6f6da9db86f6c00a8 (patch)
tree11b9bbe5afb0f7b3e446b3e0f262aeecdbc9eed0 /contrib/gdb
parent5d522df45b49d6b5cb503e2f69b60e64bb65fa68 (diff)
downloadFreeBSD-src-07961757d46994f722e72fb6f6da9db86f6c00a8.zip
FreeBSD-src-07961757d46994f722e72fb6f6da9db86f6c00a8.tar.gz
Virgin import of gdb-5.0
Diffstat (limited to 'contrib/gdb')
-rw-r--r--contrib/gdb/gdb/CONTRIBUTE153
-rw-r--r--contrib/gdb/gdb/abug-rom.c128
-rw-r--r--contrib/gdb/gdb/acconfig.h51
-rw-r--r--contrib/gdb/gdb/alpha-nat.c107
-rw-r--r--contrib/gdb/gdb/arm-convert.s32
-rw-r--r--contrib/gdb/gdb/arm-tdep.c1823
-rw-r--r--contrib/gdb/gdb/arm-xdep.c1134
-rw-r--r--contrib/gdb/gdb/c-exp.tab.c245
-rw-r--r--contrib/gdb/gdb/core-sol2.c51
-rw-r--r--contrib/gdb/gdb/f-exp.tab.c233
-rw-r--r--contrib/gdb/gdb/fr30-tdep.c388
-rw-r--r--contrib/gdb/gdb/i386-stub.c202
-rw-r--r--contrib/gdb/gdb/kdb-start.c31
-rw-r--r--contrib/gdb/gdb/m2-exp.tab.c259
-rw-r--r--contrib/gdb/gdb/monitor.c1010
-rw-r--r--contrib/gdb/gdb/monitor.h161
-rw-r--r--contrib/gdb/gdb/osfsolib.c610
-rw-r--r--contrib/gdb/gdb/ppcbug-rom.c150
-rw-r--r--contrib/gdb/gdb/procfs.c9138
-rw-r--r--contrib/gdb/gdb/remote-mips.c1371
-rw-r--r--contrib/gdb/gdb/remote-rdp.c306
-rw-r--r--contrib/gdb/gdb/remote-sim.c344
-rw-r--r--contrib/gdb/gdb/remote-st.c360
-rw-r--r--contrib/gdb/gdb/srec.h29
-rw-r--r--contrib/gdb/gdb/standalone.c93
-rw-r--r--contrib/gdb/gdb/stuff.c56
26 files changed, 9487 insertions, 8978 deletions
diff --git a/contrib/gdb/gdb/CONTRIBUTE b/contrib/gdb/gdb/CONTRIBUTE
new file mode 100644
index 0000000..4f02ddf
--- /dev/null
+++ b/contrib/gdb/gdb/CONTRIBUTE
@@ -0,0 +1,153 @@
+
+ Contributing to GDB
+
+GDB is a collaborative project and one which wants to encourage new
+development. You may wish to fix GDB bugs, improve testing, port GDB
+to a new platform, update documentation, add new GDB features, and the
+like. To help with this, there is a lot of documentation
+available.. In addition to the user guide and internals manual
+included in the GDB distribution, the GDB web pages also contain much
+information.
+
+You may also want to submit your change so that can be considered for
+conclusion in a future version of GDB (see below). Regardless, we
+encourage you to distribute the change yourself.
+
+If you don't feel up to hacking GDB, there are still plenty of ways to
+help! You can answer questions on the mailing lists, write
+documentation, find bugs, create a GDB related website (contribute to
+the official GDB web site), or create a GDB related software
+package. We welcome all of the above and feel free to ask on the GDB
+mailing lists if you are looking for feedback or for people to review
+a work in progress.
+
+Ref: http://sourceware.cygnus.com/gdb
+
+Finally, there are certain legal requirements and style issues which
+all contributors need to be aware of.
+
+o Coding Standards
+
+ All contributions must conform to the GNU Coding Standard.
+ http://www.gnu.ai.mit.edu/prep/standards_toc.html
+ Submissions which do not conform to the standards will be
+ returned with a request to reformat the changes.
+
+ For GDB, that standard is more tightly defined. GDB's
+ coding standard is determined by the output of
+ gnu-indent.
+
+ This situation came about because, by the start of '99,
+ GDB's coding style was so bad an inconsistent that it was
+ decided to restart things from scratch.
+
+
+o Copyright Assignment
+
+ There are certain legal requirements
+
+ Before we can accept code contributions from you, we need a
+ copyright assignment form filled out.
+
+ If you've developed some addition or patch to GDB that you
+ would like to contribute, you should fill out a copyright
+ assignment form and send it in to the FSF. We are unable to
+ use code from you until this is on-file at the FSF, so get
+ that paperwork in! This form covers one batch of changes.
+ Ref: http://gcc.gnu.org/fsf-forms/assignment-instructions.html
+
+ If you think you're going to be doing continuing work on GDB, it
+ would be easier to use a different form, which arranges to
+ assign the copyright for all your future changes to GDB. It is
+ called assign.future. Please note that if you switch
+ employers, the new employer will need to fill out the
+ disclaim.future form; there is no need to fill out the
+ assign.future form again.
+ Ref: http://gcc.gnu.org/fsf-forms/assign.future
+ Ref: http://gcc.gnu.org/fsf-forms/disclaim.future
+
+ There are several other forms you can fill out for different
+ circumstances (e.g. to contribute an entirely new program, to
+ contribute significant changes to a manual, etc.)
+ Ref: http://gcc.gnu.org/fsf-forms/copyrights.html
+
+ Small changes can be accepted without a copyright assignment
+ form on file.
+
+ This is pretty confusing! If you are unsure of what is
+ necessary, just ask the GDB mailing list and we'll figure out
+ what is best for you.
+
+ Note: Many of these forms have a place for "name of
+ program". Insert the name of one program in that place -- in
+ this case, "GDB".
+
+
+o Submitting Patches
+
+ Every patch must have several pieces of information before we
+ can properly evaluate it.
+
+ A description of the bug and how your patch fixes this
+ bug. A reference to a testsuite failure is very helpful. For
+ new features a description of the feature and your
+ implementation.
+
+ A ChangeLog entry as plaintext (separate from the patch); see
+ the various ChangeLog files for format and content. Note that,
+ unlike some other projects, we do require ChangeLogs also for
+ documentation (i.e., .texi files).
+
+ The patch itself. If you are accessing the CVS repository at:
+ Cygnus, use "cvs update; cvs diff -c3p"; else, use "diff -c3p
+ OLD NEW" or "diff -up OLD NEW". If your version of diff does
+ not support these options, then get the latest version of GNU
+ diff.
+
+ We accept patches as plain text (preferred for the compilers
+ themselves), MIME attachments (preferred for the web pages),
+ or as uuencoded gzipped text.
+
+ When you have all these pieces, bundle them up in a mail
+ message and send it to gdb-patches@sourceware.cygnus.com. All
+ patches and related discussion should be sent to the
+ gdb-patches mailinglist. For further information on the GDB
+ CVS repository, see the Anonymous read-only CVS access and
+ Read-write CVS access page.
+
+--
+
+Supplemental information for GDB:
+
+o Please try to run the relevant testsuite before and after
+ committing a patch
+
+ If the contributor doesn't do it then the maintainer will. A
+ contributor might include before/after test results in their
+ contribution.
+
+
+o For bug fixes, please try to include a way of
+ demonstrating that the patch actually fixes something.
+
+ The best way of doing this is to ensure that the
+ testsuite contains one or more test cases that
+ fail without the fix but pass with the fix.
+
+ People are encouraged to submit patches that extend
+ the testsuite.
+
+
+o Please read your patch before submitting it.
+
+ A patch containing several unrelated changes or
+ arbitrary reformats will be returned with a request
+ to re-formatting / split it.
+
+
+o If ``gdb/configure.in'' is modified then you don't
+ need to include patches to the regenerated file
+ ``configure''.
+
+ The maintainer will re-generate those files
+ using autoconf (2.13 as of 2000-02-29).
diff --git a/contrib/gdb/gdb/abug-rom.c b/contrib/gdb/gdb/abug-rom.c
index 97ff0f8..e1bd628 100644
--- a/contrib/gdb/gdb/abug-rom.c
+++ b/contrib/gdb/gdb/abug-rom.c
@@ -3,21 +3,22 @@
Written by Rob Savoye of Cygnus Support
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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"
@@ -92,61 +93,62 @@ static char *abug_regnames[NUM_REGS] =
static struct target_ops abug_ops;
-static char *abug_inits[] = {"\r", NULL};
+static char *abug_inits[] =
+{"\r", NULL};
-static struct monitor_ops abug_cmds ;
+static struct monitor_ops abug_cmds;
-static void
-init_abug_cmds(void)
+static void
+init_abug_cmds (void)
{
- abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
- abug_cmds.init = abug_inits; /* Init strings */
- abug_cmds.cont = "g\r"; /* continue command */
- abug_cmds.step = "t\r"; /* single step */
- abug_cmds.stop = NULL; /* interrupt command */
- abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
- abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
- abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
- abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
- abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
- abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
- abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
- abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
- abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
- abug_cmds.setmem.term = NULL; /* setreg.term */
- abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
- abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
- abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
- abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
- abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
- abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
- abug_cmds.getmem.term = NULL; /* getmem.term */
- abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
- abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
- abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
- abug_cmds.setreg.term = "? "; /* setreg.term */
- abug_cmds.setreg.term_cmd = ".\r" ; /* setreg.term_cmd */
- abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
- abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
- abug_cmds.getreg.term = "? "; /* getreg.term */
- abug_cmds.getreg.term_cmd = ".\r" ; /* getreg.term_cmd */
- abug_cmds.dump_registers = "rd\r"; /* dump_registers */
- abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
- abug_cmds.supply_register = abug_supply_register; /* supply_register */
- abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
- abug_cmds.load = "lo 0\r"; /* download command */
- abug_cmds.loadresp = "\n"; /* load response */
- abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
- abug_cmds.line_term = "\r"; /* end-of-line terminator */
- abug_cmds.cmd_end = NULL; /* optional command terminator */
- abug_cmds.target = &abug_ops; /* target operations */
- abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
- abug_cmds.regnames = abug_regnames; /* registers names */
- abug_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
-};
+ abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
+ abug_cmds.init = abug_inits; /* Init strings */
+ abug_cmds.cont = "g\r"; /* continue command */
+ abug_cmds.step = "t\r"; /* single step */
+ abug_cmds.stop = NULL; /* interrupt command */
+ abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
+ abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
+ abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
+ abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
+ abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
+ abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
+ abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
+ abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
+ abug_cmds.setmem.term = NULL; /* setreg.term */
+ abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
+ abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
+ abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
+ abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
+ abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
+ abug_cmds.getmem.term = NULL; /* getmem.term */
+ abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
+ abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
+ abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
+ abug_cmds.setreg.term = "? "; /* setreg.term */
+ abug_cmds.setreg.term_cmd = ".\r"; /* setreg.term_cmd */
+ abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
+ abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
+ abug_cmds.getreg.term = "? "; /* getreg.term */
+ abug_cmds.getreg.term_cmd = ".\r"; /* getreg.term_cmd */
+ abug_cmds.dump_registers = "rd\r"; /* dump_registers */
+ abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ abug_cmds.supply_register = abug_supply_register; /* supply_register */
+ abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
+ abug_cmds.load = "lo 0\r"; /* download command */
+ abug_cmds.loadresp = "\n"; /* load response */
+ abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
+ abug_cmds.line_term = "\r"; /* end-of-line terminator */
+ abug_cmds.cmd_end = NULL; /* optional command terminator */
+ abug_cmds.target = &abug_ops; /* target operations */
+ abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ abug_cmds.regnames = abug_regnames; /* registers names */
+ abug_cmds.magic = MONITOR_OPS_MAGIC; /* magic */
+};
static void
-abug_open(args, from_tty)
+abug_open (args, from_tty)
char *args;
int from_tty;
{
@@ -156,7 +158,7 @@ abug_open(args, from_tty)
void
_initialize_abug_rom ()
{
- init_abug_cmds() ;
+ init_abug_cmds ();
init_monitor_ops (&abug_ops);
abug_ops.to_shortname = "abug";
diff --git a/contrib/gdb/gdb/acconfig.h b/contrib/gdb/gdb/acconfig.h
index 9ad5020..1199194 100644
--- a/contrib/gdb/gdb/acconfig.h
+++ b/contrib/gdb/gdb/acconfig.h
@@ -1,16 +1,5 @@
-
-/* Whether malloc must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_MALLOC
-
-/* Whether realloc must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_REALLOC
-
-/* Whether free must be declared even if <stdlib.h> is included. */
-#undef NEED_DECLARATION_FREE
-
-/* Whether strerror must be declared even if <string.h> is included. */
-#undef NEED_DECLARATION_STRERROR
-@TOP@
+/* Define if compiling on Solaris 7. */
+#undef _MSE_INT_H
/* Define if pstatus_t type is available */
#undef HAVE_PSTATUS_T
@@ -24,13 +13,28 @@
/* Define if gregset_t type is available. */
#undef HAVE_GREGSET_T
+/* Define if <sys/procfs.h> has prgregset_t. */
+#undef HAVE_PRGREGSET_T
+
+/* Define if <sys/procfs.h> has prfpregset_t. */
+#undef HAVE_PRFPREGSET_T
+
+/* Define if <sys/procfs.h> has lwpid_t. */
+#undef HAVE_LWPID_T
+
+/* Define if <sys/procfs.h> has psaddr_t. */
+#undef HAVE_PSADDR_T
+
+/* Define if the prfpregset_t type is broken. */
+#undef PRFPREGSET_T_BROKEN
+
+/* Define if you want to use new multi-fd /proc interface
+ (replaces HAVE_MULTIPLE_PROC_FDS as well as other macros). */
+#undef NEW_PROC_API
+
/* Define if ioctl argument PIOCSET is available. */
#undef HAVE_PROCFS_PIOCSET
-/* /proc PID entries are directories containing the files
- ctl as map status */
-#undef HAVE_MULTIPLE_PROC_FDS
-
/* Define if the `long long' type works. */
#undef CC_HAS_LONG_LONG
@@ -88,8 +92,17 @@
name, as a C string. */
#undef TARGET_CPU_DEFAULT
+/* Define if the simulator is being linked in. */
+#undef WITH_SIM
+
/* Set to true if the save_state_t structure is present */
-#define HAVE_STRUCT_SAVE_STATE_T 0
+#undef HAVE_STRUCT_SAVE_STATE_T
/* Set to true if the save_state_t structure has the ss_wide member */
-#define HAVE_STRUCT_MEMBER_SS_WIDE 0
+#undef HAVE_STRUCT_MEMBER_SS_WIDE
+
+/* Define if <sys/ptrace.h> defines the PTRACE_GETREGS request. */
+#undef HAVE_PTRACE_GETREGS
+
+/* Define if <sys/ptrace.h> defines the PTRACE_GETXFPREGS request. */
+#undef HAVE_PTRACE_GETXFPREGS
diff --git a/contrib/gdb/gdb/alpha-nat.c b/contrib/gdb/gdb/alpha-nat.c
index 59bd0d8..089e56f 100644
--- a/contrib/gdb/gdb/alpha-nat.c
+++ b/contrib/gdb/gdb/alpha-nat.c
@@ -1,21 +1,22 @@
/* Low level Alpha interface, for GDB when running native.
Copyright 1993, 1995, 1996, 1998 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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"
@@ -23,10 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "target.h"
#include <sys/ptrace.h>
#ifdef __linux__
-# include <asm/reg.h>
-# include <alpha/ptrace.h>
+#include <asm/reg.h>
+#include <alpha/ptrace.h>
#else
-# include <machine/reg.h>
+#include <machine/reg.h>
#endif
#include <sys/user.h>
@@ -62,13 +63,13 @@ get_longjmp_target (pc)
CORE_ADDR jb_addr;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
- jb_addr = read_register(A0_REGNUM);
+ jb_addr = read_register (A0_REGNUM);
- if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
- sizeof(CORE_ADDR)))
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
+ sizeof (CORE_ADDR)))
return 0;
- *pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
+ *pc = extract_address (raw_buffer, sizeof (CORE_ADDR));
return 1;
}
@@ -78,11 +79,11 @@ get_longjmp_target (pc)
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).
+ 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.
+ 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
@@ -101,17 +102,18 @@ fetch_osf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
static int core_reg_mapping[NUM_REGS] =
{
#define EFL (EF_SIZE / 8)
- EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
- EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
- EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
- EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
- EFL+0, EFL+1, EFL+2, EFL+3, EFL+4, EFL+5, EFL+6, EFL+7,
- EFL+8, EFL+9, EFL+10, EFL+11, EFL+12, EFL+13, EFL+14, EFL+15,
- EFL+16, EFL+17, EFL+18, EFL+19, EFL+20, EFL+21, EFL+22, EFL+23,
- EFL+24, EFL+25, EFL+26, EFL+27, EFL+28, EFL+29, EFL+30, EFL+31,
- EF_PC, -1
+ EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
+ EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
+ EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
+ EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
+ EFL + 0, EFL + 1, EFL + 2, EFL + 3, EFL + 4, EFL + 5, EFL + 6, EFL + 7,
+ EFL + 8, EFL + 9, EFL + 10, EFL + 11, EFL + 12, EFL + 13, EFL + 14, EFL + 15,
+ EFL + 16, EFL + 17, EFL + 18, EFL + 19, EFL + 20, EFL + 21, EFL + 22, EFL + 23,
+ EFL + 24, EFL + 25, EFL + 26, EFL + 27, EFL + 28, EFL + 29, EFL + 30, EFL + 31,
+ EF_PC, -1
};
- static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] =
+ {0};
for (regno = 0; regno < NUM_REGS; regno++)
{
@@ -144,7 +146,7 @@ fetch_elf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
int which;
CORE_ADDR reg_addr;
{
- if (core_reg_size < 32*8)
+ if (core_reg_size < 32 * 8)
{
error ("Core file register section too small (%u bytes).", core_reg_size);
return;
@@ -153,15 +155,15 @@ fetch_elf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
if (which == 2)
{
/* The FPU Registers. */
- memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31*8);
- memset (&registers[REGISTER_BYTE (FP0_REGNUM+31)], 0, 8);
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31 * 8);
+ memset (&registers[REGISTER_BYTE (FP0_REGNUM + 31)], 0, 8);
memset (&register_valid[FP0_REGNUM], 1, 32);
}
else
{
/* The General Registers. */
- memcpy (&registers[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31*8);
- memcpy (&registers[REGISTER_BYTE (PC_REGNUM)], core_reg_sect+31*8, 8);
+ memcpy (&registers[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31 * 8);
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)], core_reg_sect + 31 * 8, 8);
memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, 8);
memset (&register_valid[V0_REGNUM], 1, 32);
register_valid[PC_REGNUM] = 1;
@@ -201,18 +203,19 @@ kernel_u_size ()
* See the comment in m68k-tdep.c regarding the utility of these functions.
*/
-void
+void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register long *regp = ALPHA_REGSET_BASE (gregsetp);
- static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] =
+ {0};
for (regi = 0; regi < 31; regi++)
- supply_register (regi, (char *)(regp + regi));
+ supply_register (regi, (char *) (regp + regi));
- supply_register (PC_REGNUM, (char *)(regp + 31));
+ supply_register (PC_REGNUM, (char *) (regp + 31));
/* Fill inaccessible registers with zero. */
supply_register (ZERO_REGNUM, zerobuf);
@@ -248,7 +251,7 @@ supply_fpregset (fpregsetp)
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
for (regi = 0; regi < 32; regi++)
- supply_register (regi + FP0_REGNUM, (char *)(regp + regi));
+ supply_register (regi + FP0_REGNUM, (char *) (regp + regi));
}
void
@@ -269,24 +272,28 @@ fill_fpregset (fpregsetp, regno)
}
}
#endif
-
+
/* Register that we are able to handle alpha core file formats. */
static struct core_fns alpha_osf_core_fns =
{
/* This really is bfd_target_unknown_flavour. */
- bfd_target_unknown_flavour,
- fetch_osf_core_registers,
- NULL
+ bfd_target_unknown_flavour, /* core_flavour */
+ default_check_format, /* check_format */
+ default_core_sniffer, /* core_sniffer */
+ fetch_osf_core_registers, /* core_read_registers */
+ NULL /* next */
};
static struct core_fns alpha_elf_core_fns =
{
- bfd_target_elf_flavour,
- fetch_elf_core_registers,
- NULL
+ bfd_target_elf_flavour, /* core_flavour */
+ default_check_format, /* check_format */
+ default_core_sniffer, /* core_sniffer */
+ fetch_elf_core_registers, /* core_read_registers */
+ NULL /* next */
};
void
diff --git a/contrib/gdb/gdb/arm-convert.s b/contrib/gdb/gdb/arm-convert.s
index 416132b..8124052 100644
--- a/contrib/gdb/gdb/arm-convert.s
+++ b/contrib/gdb/gdb/arm-convert.s
@@ -1,16 +1,16 @@
- .text
- .global _convert_from_extended
-
-_convert_from_extended:
-
- ldfe f0,[a1]
- stfd f0,[a2]
- movs pc,lr
-
- .global _convert_to_extended
-
-_convert_to_extended:
-
- ldfd f0,[a1]
- stfe f0,[a2]
- movs pc,lr
+/* 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 */
diff --git a/contrib/gdb/gdb/arm-tdep.c b/contrib/gdb/gdb/arm-tdep.c
index 607dc8f..7112c4c 100644
--- a/contrib/gdb/gdb/arm-tdep.c
+++ b/contrib/gdb/gdb/arm-tdep.c
@@ -1,22 +1,23 @@
-/* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
- Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999
+/* Common target dependent code for GDB on ARM systems.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000
Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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"
@@ -26,42 +27,180 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "symfile.h"
#include "gdb_string.h"
#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
+#include "dis-asm.h" /* For register flavors. */
+#include <ctype.h> /* for isupper () */
+
+extern void _initialize_arm_tdep (void);
+
+/* Number of different reg name sets (options). */
+static int num_flavor_options;
+
+/* We have more registers than the disassembler as gdb can print the value
+ of special registers as well.
+ The general register names are overwritten by whatever is being used by
+ the disassembler at the moment. We also adjust the case of cpsr and fps. */
+
+/* Initial value: Register names used in ARM's ISA documentation. */
+static char * arm_register_name_strings[] =
+{"r0", "r1", "r2", "r3", /* 0 1 2 3 */
+ "r4", "r5", "r6", "r7", /* 4 5 6 7 */
+ "r8", "r9", "r10", "r11", /* 8 9 10 11 */
+ "r12", "sp", "lr", "pc", /* 12 13 14 15 */
+ "f0", "f1", "f2", "f3", /* 16 17 18 19 */
+ "f4", "f5", "f6", "f7", /* 20 21 22 23 */
+ "fps", "cpsr" }; /* 24 25 */
+char **arm_register_names = arm_register_name_strings;
+
+/* Valid register name flavors. */
+static char **valid_flavors;
+
+/* Disassembly flavor to use. Default to "std" register names. */
+static char *disassembly_flavor;
+static int current_option; /* Index to that option in the opcodes table. */
+
+/* This is used to keep the bfd arch_info in sync with the disassembly
+ flavor. */
+static void set_disassembly_flavor_sfunc(char *, int,
+ struct cmd_list_element *);
+static void set_disassembly_flavor (void);
+
+static void convert_from_extended (void *ptr, void *dbl);
+
+/* Define other aspects of the stack frame. We keep the offsets of
+ all saved registers, 'cause we need 'em a lot! We also keep the
+ current size of the stack frame, and the offset of the frame
+ pointer from the stack pointer (for frameless functions, and when
+ we're still in the prologue of a function with a frame) */
+
+struct frame_extra_info
+ {
+ struct frame_saved_regs fsr;
+ int framesize;
+ int frameoffset;
+ int framereg;
+ };
-/*
- The following macros are actually wrong. Neither arm nor thumb can
- or should set the lsb on addr.
- The thumb addresses are mod 2, so (addr & 2) would be a good heuristic
- to use when checking for thumb (see arm_pc_is_thumb() below).
- Unfortunately, something else depends on these (incorrect) macros, so
- fixing them actually breaks gdb. I didn't have time to investigate. Z.R.
-*/
-/* Thumb function addresses are odd (bit 0 is set). Here are some
- macros to test, set, or clear bit 0 of addresses. */
+/* Addresses for calling Thumb functions have the bit 0 set.
+ Here are some macros to test, set, or clear bit 0 of addresses. */
#define IS_THUMB_ADDR(addr) ((addr) & 1)
#define MAKE_THUMB_ADDR(addr) ((addr) | 1)
#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
-/* Macros to round N up or down to the next A boundary; A must be
- a power of two. */
-#define ROUND_DOWN(n,a) ((n) & ~((a) - 1))
-#define ROUND_UP(n,a) (((n) + (a) - 1) & ~((a) - 1))
-
-/* Should call_function allocate stack space for a struct return? */
-/* The system C compiler uses a similar structure return convention to gcc */
+#define SWAP_TARGET_AND_HOST(buffer,len) \
+ do \
+ { \
+ if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* Will a function return an aggregate type in memory or in a
+ register? Return 0 if an aggregate type can be returned in a
+ register, 1 if it must be returned in memory. */
+
int
-arm_use_struct_convention (gcc_p, type)
- int gcc_p;
- struct type *type;
+arm_use_struct_convention (int gcc_p, struct type *type)
{
- return (TYPE_LENGTH (type) > 4);
+ int nRc;
+ register enum type_code code;
+
+ /* In the ARM ABI, "integer" like aggregate types are returned in
+ registers. For an aggregate type to be integer like, its size
+ must be less than or equal to REGISTER_SIZE and the offset of
+ each addressable subfield must be zero. Note that bit fields are
+ not addressable, and all addressable subfields of unions always
+ start at offset zero.
+
+ This function is based on the behaviour of GCC 2.95.1.
+ See: gcc/arm.c: arm_return_in_memory() for details.
+
+ Note: All versions of GCC before GCC 2.95.2 do not set up the
+ parameters correctly for a function returning the following
+ structure: struct { float f;}; This should be returned in memory,
+ not a register. Richard Earnshaw sent me a patch, but I do not
+ know of any way to detect if a function like the above has been
+ compiled with the correct calling convention. */
+
+ /* All aggregate types that won't fit in a register must be returned
+ in memory. */
+ if (TYPE_LENGTH (type) > REGISTER_SIZE)
+ {
+ return 1;
+ }
+
+ /* The only aggregate types that can be returned in a register are
+ structs and unions. Arrays must be returned in memory. */
+ code = TYPE_CODE (type);
+ if ((TYPE_CODE_STRUCT != code) && (TYPE_CODE_UNION != code))
+ {
+ return 1;
+ }
+
+ /* Assume all other aggregate types can be returned in a register.
+ Run a check for structures, unions and arrays. */
+ nRc = 0;
+
+ if ((TYPE_CODE_STRUCT == code) || (TYPE_CODE_UNION == code))
+ {
+ int i;
+ /* Need to check if this struct/union is "integer" like. For
+ this to be true, its size must be less than or equal to
+ REGISTER_SIZE and the offset of each addressable subfield
+ must be zero. Note that bit fields are not addressable, and
+ unions always start at offset zero. If any of the subfields
+ is a floating point type, the struct/union cannot be an
+ integer type. */
+
+ /* For each field in the object, check:
+ 1) Is it FP? --> yes, nRc = 1;
+ 2) Is it addressable (bitpos != 0) and
+ not packed (bitsize == 0)?
+ --> yes, nRc = 1
+ */
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ enum type_code field_type_code;
+ field_type_code = TYPE_CODE (TYPE_FIELD_TYPE (type, i));
+
+ /* Is it a floating point type field? */
+ if (field_type_code == TYPE_CODE_FLT)
+ {
+ nRc = 1;
+ break;
+ }
+
+ /* If bitpos != 0, then we have to care about it. */
+ if (TYPE_FIELD_BITPOS (type, i) != 0)
+ {
+ /* Bitfields are not addressable. If the field bitsize is
+ zero, then the field is not packed. Hence it cannot be
+ a bitfield or any other packed type. */
+ if (TYPE_FIELD_BITSIZE (type, i) == 0)
+ {
+ nRc = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ return nRc;
}
int
-arm_frame_chain_valid (chain, thisframe)
- CORE_ADDR chain;
- struct frame_info *thisframe;
+arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
{
-#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */
return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC));
}
@@ -69,60 +208,67 @@ arm_frame_chain_valid (chain, thisframe)
int arm_apcs_32 = 1;
-/* Flag set by arm_fix_call_dummy that tells whether the target function
- is a Thumb function. This flag is checked by arm_push_arguments.
- FIXME: Change the PUSH_ARGUMENTS macro (and its use in valops.c) to
- pass the function address as an additional parameter. */
+/* Flag set by arm_fix_call_dummy that tells whether the target
+ function is a Thumb function. This flag is checked by
+ arm_push_arguments. FIXME: Change the PUSH_ARGUMENTS macro (and
+ its use in valops.c) to pass the function address as an additional
+ parameter. */
static int target_is_thumb;
-/* Flag set by arm_fix_call_dummy that tells whether the calling function
- is a Thumb function. This flag is checked by arm_pc_is_thumb
- and arm_call_dummy_breakpoint_offset. */
+/* Flag set by arm_fix_call_dummy that tells whether the calling
+ function is a Thumb function. This flag is checked by
+ arm_pc_is_thumb and arm_call_dummy_breakpoint_offset. */
static int caller_is_thumb;
-/* Tell if the program counter value in MEMADDR is in a Thumb function. */
+/* Determine if the program counter specified in MEMADDR is in a Thumb
+ function. */
int
-arm_pc_is_thumb (memaddr)
- bfd_vma memaddr;
+arm_pc_is_thumb (bfd_vma memaddr)
{
- struct minimal_symbol * sym;
- CORE_ADDR sp;
+ struct minimal_symbol *sym;
- /* If bit 0 of the address is set, assume this is a Thumb address. */
+ /* If bit 0 of the address is set, assume this is a Thumb address. */
if (IS_THUMB_ADDR (memaddr))
return 1;
- /* Thumb function have a "special" bit set in minimal symbols */
+ /* Thumb functions have a "special" bit set in minimal symbols. */
sym = lookup_minimal_symbol_by_pc (memaddr);
if (sym)
{
- return (MSYMBOL_IS_SPECIAL(sym));
+ return (MSYMBOL_IS_SPECIAL (sym));
}
else
- return 0;
+ {
+ return 0;
+ }
}
-/* Tell if the program counter value in MEMADDR is in a call dummy that
- is being called from a Thumb function. */
+/* Determine if the program counter specified in MEMADDR is in a call
+ dummy being called from a Thumb function. */
int
-arm_pc_is_thumb_dummy (memaddr)
- bfd_vma memaddr;
+arm_pc_is_thumb_dummy (bfd_vma memaddr)
{
- CORE_ADDR sp = read_sp();
-
- if (PC_IN_CALL_DUMMY (memaddr, sp, sp+64))
+ CORE_ADDR sp = read_sp ();
+
+ /* FIXME: Until we switch for the new call dummy macros, this heuristic
+ is the best we can do. We are trying to determine if the pc is on
+ the stack, which (hopefully) will only happen in a call dummy.
+ We hope the current stack pointer is not so far alway from the dummy
+ frame location (true if we have not pushed large data structures or
+ gone too many levels deep) and that our 1024 is not enough to consider
+ code regions as part of the stack (true for most practical purposes) */
+ if (PC_IN_CALL_DUMMY (memaddr, sp, sp + 1024))
return caller_is_thumb;
else
return 0;
}
CORE_ADDR
-arm_addr_bits_remove (val)
- CORE_ADDR val;
+arm_addr_bits_remove (CORE_ADDR val)
{
if (arm_pc_is_thumb (val))
return (val & (arm_apcs_32 ? 0xfffffffe : 0x03fffffe));
@@ -131,123 +277,178 @@ arm_addr_bits_remove (val)
}
CORE_ADDR
-arm_saved_pc_after_call (frame)
- struct frame_info *frame;
+arm_saved_pc_after_call (struct frame_info *frame)
{
return ADDR_BITS_REMOVE (read_register (LR_REGNUM));
}
+int
+arm_frameless_function_invocation (struct frame_info *fi)
+{
+ CORE_ADDR func_start, after_prologue;
+ int frameless;
+
+ func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET);
+ after_prologue = SKIP_PROLOGUE (func_start);
+
+ /* There are some frameless functions whose first two instructions
+ follow the standard APCS form, in which case after_prologue will
+ be func_start + 8. */
+
+ frameless = (after_prologue < func_start + 12);
+ return frameless;
+}
+
/* A typical Thumb prologue looks like this:
- push {r7, lr}
- add sp, sp, #-28
- add r7, sp, #12
+ push {r7, lr}
+ add sp, sp, #-28
+ add r7, sp, #12
Sometimes the latter instruction may be replaced by:
- mov r7, sp
-*/
+ mov r7, sp
+
+ or like this:
+ push {r7, lr}
+ mov r7, sp
+ sub sp, #12
+
+ or, on tpcs, like this:
+ sub sp,#16
+ push {r7, lr}
+ (many instructions)
+ mov r7, sp
+ sub sp, #12
+
+ There is always one instruction of three classes:
+ 1 - push
+ 2 - setting of r7
+ 3 - adjusting of sp
+
+ When we have found at least one of each class we are done with the prolog.
+ Note that the "sub sp, #NN" before the push does not count.
+ */
static CORE_ADDR
-thumb_skip_prologue (pc)
- CORE_ADDR pc;
+thumb_skip_prologue (CORE_ADDR pc, CORE_ADDR func_end)
{
CORE_ADDR current_pc;
+ int findmask = 0; /* findmask:
+ bit 0 - push { rlist }
+ bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
+ bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
+ */
- for (current_pc = pc; current_pc < pc + 20; current_pc += 2)
+ for (current_pc = pc; current_pc + 2 < func_end && current_pc < pc + 40; current_pc += 2)
{
unsigned short insn = read_memory_unsigned_integer (current_pc, 2);
- if ( (insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */
- && (insn & 0xff00) != 0xb000 /* add sp, #simm */
- && (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */
- && insn != 0x466f /* mov r7, sp */
- && (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */
- break;
+ if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
+ {
+ findmask |= 1; /* push found */
+ }
+ else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
+ {
+ if ((findmask & 1) == 0) /* before push ? */
+ continue;
+ else
+ findmask |= 4; /* add/sub sp found */
+ }
+ else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
+ {
+ findmask |= 2; /* setting of r7 found */
+ }
+ else if (insn == 0x466f) /* mov r7, sp */
+ {
+ findmask |= 2; /* setting of r7 found */
+ }
+ else
+ continue; /* something in the prolog that we don't care about or some
+ instruction from outside the prolog scheduled here for optimization */
}
return current_pc;
}
-/* APCS (ARM procedure call standard) defines the following prologue:
+/* The APCS (ARM Procedure Call Standard) defines the following
+ prologue:
- mov ip, sp
- [stmfd sp!, {a1,a2,a3,a4}]
- stmfd sp!, {...,fp,ip,lr,pc}
- [stfe f7, [sp, #-12]!]
- [stfe f6, [sp, #-12]!]
- [stfe f5, [sp, #-12]!]
- [stfe f4, [sp, #-12]!]
- sub fp, ip, #nn // nn == 20 or 4 depending on second ins
-*/
+ mov ip, sp
+ [stmfd sp!, {a1,a2,a3,a4}]
+ stmfd sp!, {...,fp,ip,lr,pc}
+ [stfe f7, [sp, #-12]!]
+ [stfe f6, [sp, #-12]!]
+ [stfe f5, [sp, #-12]!]
+ [stfe f4, [sp, #-12]!]
+ sub fp, ip, #nn @@ nn == 20 or 4 depending on second insn */
CORE_ADDR
-arm_skip_prologue (pc)
- CORE_ADDR pc;
+arm_skip_prologue (CORE_ADDR pc)
{
unsigned long inst;
CORE_ADDR skip_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))
+ /* 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)
+ if ((sal.line != 0) && (sal.end < func_end))
return sal.end;
}
/* Check if this is Thumb code. */
if (arm_pc_is_thumb (pc))
- return thumb_skip_prologue (pc);
+ return thumb_skip_prologue (pc, func_end);
/* Can't find the prologue end in the symbol table, try it the hard way
by disassembling the instructions. */
skip_pc = pc;
inst = read_memory_integer (skip_pc, 4);
- if (inst != 0xe1a0c00d) /* mov ip, sp */
+ if (inst != 0xe1a0c00d) /* mov ip, sp */
return pc;
skip_pc += 4;
inst = read_memory_integer (skip_pc, 4);
- if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */
+ if ((inst & 0xfffffff0) == 0xe92d0000) /* stmfd sp!,{a1,a2,a3,a4} */
{
skip_pc += 4;
inst = read_memory_integer (skip_pc, 4);
}
- if ((inst & 0xfffff800) != 0xe92dd800) /* stmfd sp!,{...,fp,ip,lr,pc} */
+ if ((inst & 0xfffff800) != 0xe92dd800) /* stmfd sp!,{...,fp,ip,lr,pc} */
return pc;
skip_pc += 4;
inst = read_memory_integer (skip_pc, 4);
/* Any insns after this point may float into the code, if it makes
- for better instruction scheduling, so we skip them only if
- we find them, but still consdier the function to be frame-ful */
+ for better instruction scheduling, so we skip them only if we
+ find them, but still consdier the function to be frame-ful. */
- /* We may have either one sfmfd instruction here, or several stfe insns,
- depending on the version of floating point code we support. */
- if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */
+ /* We may have either one sfmfd instruction here, or several stfe
+ insns, depending on the version of floating point code we
+ support. */
+ if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */
{
skip_pc += 4;
inst = read_memory_integer (skip_pc, 4);
}
else
{
- while ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */
- {
- skip_pc += 4;
- inst = read_memory_integer (skip_pc, 4);
- }
+ while ((inst & 0xffff8fff) == 0xed6d0103) /* stfe fn, [sp, #-12]! */
+ {
+ skip_pc += 4;
+ inst = read_memory_integer (skip_pc, 4);
+ }
}
- if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */
+ if ((inst & 0xfffff000) == 0xe24cb000) /* sub fp, ip, #nn */
skip_pc += 4;
return skip_pc;
}
-
-
-
+/* *INDENT-OFF* */
/* Function: thumb_scan_prologue (helper function for arm_scan_prologue)
This function decodes a Thumb function prologue to determine:
1) the size of the stack frame
@@ -256,41 +457,46 @@ arm_skip_prologue (pc)
4) the offset from the stack pointer to the frame pointer
This information is stored in the "extra" fields of the frame_info.
- A typical Thumb function prologue might look like this:
- push {r7, lr}
- sub sp, #28,
- add r7, sp, #12
- Which would create this stack frame (offsets relative to FP)
+ A typical Thumb function prologue would create this stack frame
+ (offsets relative to FP)
old SP -> 24 stack parameters
20 LR
16 R7
R7 -> 0 local variables (16 bytes)
SP -> -12 additional stack space (12 bytes)
The frame size would thus be 36 bytes, and the frame offset would be
- 12 bytes. The frame register is R7. */
-
+ 12 bytes. The frame register is R7.
+
+ The comments for thumb_skip_prolog() describe the algorithm we use to detect
+ the end of the prolog */
+/* *INDENT-ON* */
+
static void
-thumb_scan_prologue (fi)
- struct frame_info * fi;
+thumb_scan_prologue (struct frame_info *fi)
{
CORE_ADDR prologue_start;
CORE_ADDR prologue_end;
CORE_ADDR current_pc;
- int saved_reg[16]; /* which register has been copied to register n? */
- int i;
+ int saved_reg[16]; /* which register has been copied to register n? */
+ int findmask = 0; /* findmask:
+ bit 0 - push { rlist }
+ bit 1 - mov r7, sp OR add r7, sp, #imm (setting of r7)
+ bit 2 - sub sp, #simm OR add sp, #simm (adjusting of sp)
+ */
+ int i;
- if (find_pc_partial_function (fi->pc, NULL, & prologue_start, & prologue_end))
+ if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end))
{
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
- if (sal.line == 0) /* no line info, use current PC */
+ if (sal.line == 0) /* no line info, use current PC */
prologue_end = fi->pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
- prologue_end = sal.end; /* (probably means no prologue) */
+ prologue_end = sal.end; /* (probably means no prologue) */
}
else
- prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */
- /* 16 pushes, an add, and "mv fp,sp" */
+ prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */
+ /* 16 pushes, an add, and "mv fp,sp" */
prologue_end = min (prologue_end, fi->pc);
@@ -300,10 +506,13 @@ thumb_scan_prologue (fi)
saved_reg[i] = i;
/* Search the prologue looking for instructions that set up the
- frame pointer, adjust the stack pointer, and save registers. */
+ frame pointer, adjust the stack pointer, and save registers.
+ Do this until all basic prolog instructions are found. */
fi->framesize = 0;
- for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 2)
+ for (current_pc = prologue_start;
+ (current_pc < prologue_end) && ((findmask & 7) != 7);
+ current_pc += 2)
{
unsigned short insn;
int regno;
@@ -311,73 +520,83 @@ thumb_scan_prologue (fi)
insn = read_memory_unsigned_integer (current_pc, 2);
- if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
+ if ((insn & 0xfe00) == 0xb400) /* push { rlist } */
{
+ int mask;
+ findmask |= 1; /* push found */
/* Bits 0-7 contain a mask for registers R0-R7. Bit 8 says
whether to save LR (R14). */
- int mask = (insn & 0xff) | ((insn & 0x100) << 6);
+ mask = (insn & 0xff) | ((insn & 0x100) << 6);
/* Calculate offsets of saved R0-R7 and LR. */
for (regno = LR_REGNUM; regno >= 0; regno--)
if (mask & (1 << regno))
- {
+ {
fi->framesize += 4;
fi->fsr.regs[saved_reg[regno]] = -(fi->framesize);
saved_reg[regno] = regno; /* reset saved register map */
}
}
- else if ((insn & 0xff00) == 0xb000) /* add sp, #simm */
+ else if ((insn & 0xff00) == 0xb000) /* add sp, #simm OR sub sp, #simm */
{
- offset = (insn & 0x7f) << 2; /* get scaled offset */
- if (insn & 0x80) /* is it signed? */
- offset = -offset;
+ if ((findmask & 1) == 0) /* before push ? */
+ continue;
+ else
+ findmask |= 4; /* add/sub sp found */
+
+ offset = (insn & 0x7f) << 2; /* get scaled offset */
+ if (insn & 0x80) /* is it signed? (==subtracting) */
+ {
+ fi->frameoffset += offset;
+ offset = -offset;
+ }
fi->framesize -= offset;
}
else if ((insn & 0xff00) == 0xaf00) /* add r7, sp, #imm */
{
+ findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
- fi->frameoffset = (insn & 0xff) << 2; /* get scaled offset */
+ fi->frameoffset = (insn & 0xff) << 2; /* get scaled offset */
}
else if (insn == 0x466f) /* mov r7, sp */
{
+ findmask |= 2; /* setting of r7 found */
fi->framereg = THUMB_FP_REGNUM;
fi->frameoffset = 0;
saved_reg[THUMB_FP_REGNUM] = SP_REGNUM;
}
else if ((insn & 0xffc0) == 0x4640) /* mov r0-r7, r8-r15 */
{
- int lo_reg = insn & 7; /* dest. register (r0-r7) */
+ int lo_reg = insn & 7; /* dest. register (r0-r7) */
int hi_reg = ((insn >> 3) & 7) + 8; /* source register (r8-15) */
- saved_reg[lo_reg] = hi_reg; /* remember hi reg was saved */
+ saved_reg[lo_reg] = hi_reg; /* remember hi reg was saved */
}
else
- break; /* anything else isn't prologue */
+ continue; /* something in the prolog that we don't care about or some
+ instruction from outside the prolog scheduled here for optimization */
}
}
-/* Function: check_prologue_cache
- Check if prologue for this frame's PC has already been scanned.
- If it has, copy the relevant information about that prologue and
+/* Check if prologue for this frame's PC has already been scanned. If
+ it has, copy the relevant information about that prologue and
return non-zero. Otherwise do not copy anything and return zero.
The information saved in the cache includes:
- * the frame register number;
- * the size of the stack frame;
- * the offsets of saved regs (relative to the old SP); and
- * the offset from the stack pointer to the frame pointer
-
- The cache contains only one entry, since this is adequate
- for the typical sequence of prologue scan requests we get.
- When performing a backtrace, GDB will usually ask to scan
- the same function twice in a row (once to get the frame chain,
- and once to fill in the extra frame information).
-*/
+ * the frame register number;
+ * the size of the stack frame;
+ * the offsets of saved regs (relative to the old SP); and
+ * the offset from the stack pointer to the frame pointer
+
+ The cache contains only one entry, since this is adequate for the
+ typical sequence of prologue scan requests we get. When performing
+ a backtrace, GDB will usually ask to scan the same function twice
+ in a row (once to get the frame chain, and once to fill in the
+ extra frame information). */
static struct frame_info prologue_cache;
static int
-check_prologue_cache (fi)
- struct frame_info * fi;
+check_prologue_cache (struct frame_info *fi)
{
int i;
@@ -395,52 +614,92 @@ check_prologue_cache (fi)
}
-/* Function: save_prologue_cache
- Copy the prologue information from fi to the prologue cache.
-*/
+/* Copy the prologue information from fi to the prologue cache. */
static void
-save_prologue_cache (fi)
- struct frame_info * fi;
+save_prologue_cache (struct frame_info *fi)
{
int i;
- prologue_cache.pc = fi->pc;
- prologue_cache.framereg = fi->framereg;
- prologue_cache.framesize = fi->framesize;
+ prologue_cache.pc = fi->pc;
+ prologue_cache.framereg = fi->framereg;
+ prologue_cache.framesize = fi->framesize;
prologue_cache.frameoffset = fi->frameoffset;
-
+
for (i = 0; i <= NUM_REGS; i++)
prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
}
-/* Function: arm_scan_prologue
- This function decodes an ARM function prologue to determine:
- 1) the size of the stack frame
- 2) which registers are saved on it
- 3) the offsets of saved regs
- 4) the offset from the stack pointer to the frame pointer
+/* This function decodes an ARM function prologue to determine:
+ 1) the size of the stack frame
+ 2) which registers are saved on it
+ 3) the offsets of saved regs
+ 4) the offset from the stack pointer to the frame pointer
This information is stored in the "extra" fields of the frame_info.
- A typical Arm function prologue might look like this:
- mov ip, sp
- stmfd sp!, {fp, ip, lr, pc}
- sub fp, ip, #4
- sub sp, sp, #16
+ There are two basic forms for the ARM prologue. The fixed argument
+ function call will look like:
+
+ mov ip, sp
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #4
+ [sub sp, sp, #4]
+
Which would create this stack frame (offsets relative to FP):
- IP -> 4 (caller's stack)
- FP -> 0 PC (points to address of stmfd instruction + 12 in callee)
- -4 LR (return address in caller)
- -8 IP (copy of caller's SP)
- -12 FP (caller's FP)
- SP -> -28 Local variables
+ IP -> 4 (caller's stack)
+ FP -> 0 PC (points to address of stmfd instruction + 8 in callee)
+ -4 LR (return address in caller)
+ -8 IP (copy of caller's SP)
+ -12 FP (caller's FP)
+ SP -> -28 Local variables
+
The frame size would thus be 32 bytes, and the frame offset would be
- 28 bytes. */
+ 28 bytes. The stmfd call can also save any of the vN registers it
+ plans to use, which increases the frame size accordingly.
+
+ Note: The stored PC is 8 off of the STMFD instruction that stored it
+ because the ARM Store instructions always store PC + 8 when you read
+ the PC register.
+
+ A variable argument function call will look like:
+
+ mov ip, sp
+ stmfd sp!, {a1, a2, a3, a4}
+ stmfd sp!, {fp, ip, lr, pc}
+ sub fp, ip, #20
+
+ Which would create this stack frame (offsets relative to FP):
+ IP -> 20 (caller's stack)
+ 16 A4
+ 12 A3
+ 8 A2
+ 4 A1
+ FP -> 0 PC (points to address of stmfd instruction + 8 in callee)
+ -4 LR (return address in caller)
+ -8 IP (copy of caller's SP)
+ -12 FP (caller's FP)
+ SP -> -28 Local variables
+
+ The frame size would thus be 48 bytes, and the frame offset would be
+ 28 bytes.
+
+ There is another potential complication, which is that the optimizer
+ will try to separate the store of fp in the "stmfd" instruction from
+ the "sub fp, ip, #NN" instruction. Almost anything can be there, so
+ we just key on the stmfd, and then scan for the "sub fp, ip, #NN"...
+
+ Also, note, the original version of the ARM toolchain claimed that there
+ should be an
+
+ instruction at the end of the prologue. I have never seen GCC produce
+ this, and the ARM docs don't mention it. We still test for it below in
+ case it happens...
+
+ */
static void
-arm_scan_prologue (fi)
- struct frame_info * fi;
+arm_scan_prologue (struct frame_info *fi)
{
int regno, sp_offset, fp_offset;
CORE_ADDR prologue_start, prologue_end, current_pc;
@@ -450,8 +709,8 @@ arm_scan_prologue (fi)
return;
/* Assume there is no frame until proven otherwise. */
- fi->framereg = SP_REGNUM;
- fi->framesize = 0;
+ fi->framereg = SP_REGNUM;
+ fi->framesize = 0;
fi->frameoffset = 0;
/* Check for Thumb prologue. */
@@ -470,64 +729,115 @@ arm_scan_prologue (fi)
in the function and the first source line. */
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
- if (sal.line == 0) /* no line info, use current PC */
+ if (sal.line == 0) /* no line info, use current PC */
prologue_end = fi->pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
- prologue_end = sal.end; /* (probably means no prologue) */
+ prologue_end = sal.end; /* (probably means no prologue) */
}
else
{
/* Get address of the stmfd in the prologue of the callee; the saved
- PC is the address of the stmfd + 12. */
- prologue_start = (read_memory_integer (fi->frame, 4) & 0x03fffffc) - 12;
- prologue_end = prologue_start + 40; /* FIXME: should be big enough */
+ PC is the address of the stmfd + 8. */
+ prologue_start = ADDR_BITS_REMOVE (read_memory_integer (fi->frame, 4))
+ - 8;
+ prologue_end = prologue_start + 64; /* This is all the insn's
+ that could be in the prologue,
+ plus room for 5 insn's inserted
+ by the scheduler. */
}
/* Now search the prologue looking for instructions that set up the
- frame pointer, adjust the stack pointer, and save registers. */
+ frame pointer, adjust the stack pointer, and save registers.
+
+ Be careful, however, and if it doesn't look like a prologue,
+ don't try to scan it. If, for instance, a frameless function
+ begins with stmfd sp!, then we will tell ourselves there is
+ a frame, which will confuse stack traceback, as well ad"finish"
+ and other operations that rely on a knowledge of the stack
+ traceback.
+
+ In the APCS, the prologue should start with "mov ip, sp" so
+ if we don't see this as the first insn, we will stop. */
sp_offset = fp_offset = 0;
- for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 4)
- {
- unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
- if ((insn & 0xffff0000) == 0xe92d0000) /* stmfd sp!, {..., r7, lr} */
+ if (read_memory_unsigned_integer (prologue_start, 4)
+ == 0xe1a0c00d) /* mov ip, sp */
+ {
+ for (current_pc = prologue_start + 4; current_pc < prologue_end;
+ current_pc += 4)
{
- int mask = insn & 0xffff;
+ unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
- /* Calculate offsets of saved registers. */
- for (regno = PC_REGNUM; regno >= 0; regno--)
- if (mask & (1 << regno))
- {
- sp_offset -= 4;
- fi->fsr.regs[regno] = sp_offset;
- }
- }
- else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
- {
- unsigned imm = insn & 0xff; /* immediate value */
- unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
- imm = (imm >> rot) | (imm << (32-rot));
- fp_offset = -imm;
- fi->framereg = FP_REGNUM;
- }
- else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
- {
- unsigned imm = insn & 0xff; /* immediate value */
- unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
- imm = (imm >> rot) | (imm << (32-rot));
- sp_offset -= imm;
- }
- else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
- {
- sp_offset -= 12;
- regno = F0_REGNUM + ((insn >> 12) & 0x07);
- fi->fsr.regs[regno] = sp_offset;
+ if ((insn & 0xffff0000) == 0xe92d0000)
+ /* stmfd sp!, {..., fp, ip, lr, pc}
+ or
+ stmfd sp!, {a1, a2, a3, a4} */
+ {
+ int mask = insn & 0xffff;
+
+ /* Calculate offsets of saved registers. */
+ for (regno = PC_REGNUM; regno >= 0; regno--)
+ if (mask & (1 << regno))
+ {
+ sp_offset -= 4;
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ }
+ else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32 - rot));
+ fp_offset = -imm;
+ fi->framereg = FP_REGNUM;
+ }
+ else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
+ {
+ unsigned imm = insn & 0xff; /* immediate value */
+ unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
+ imm = (imm >> rot) | (imm << (32 - rot));
+ sp_offset -= imm;
+ }
+ else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
+ {
+ sp_offset -= 12;
+ regno = F0_REGNUM + ((insn >> 12) & 0x07);
+ fi->fsr.regs[regno] = sp_offset;
+ }
+ else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
+ {
+ int n_saved_fp_regs;
+ unsigned int fp_start_reg, fp_bound_reg;
+
+ if ((insn & 0x800) == 0x800) /* N0 is set */
+ {
+ if ((insn & 0x40000) == 0x40000) /* N1 is set */
+ n_saved_fp_regs = 3;
+ else
+ n_saved_fp_regs = 1;
+ }
+ else
+ {
+ if ((insn & 0x40000) == 0x40000) /* N1 is set */
+ n_saved_fp_regs = 2;
+ else
+ n_saved_fp_regs = 4;
+ }
+
+ fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
+ fp_bound_reg = fp_start_reg + n_saved_fp_regs;
+ for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
+ {
+ sp_offset -= 12;
+ fi->fsr.regs[fp_start_reg++] = sp_offset;
+ }
+ }
+ else
+ /* The optimizer might shove anything into the prologue,
+ so we just skip what we don't recognize. */
+ continue;
}
- else if (insn == 0xe1a0c00d) /* mov ip, sp */
- continue;
- else
- break; /* not a recognized prologue instruction */
}
/* The frame size is just the negative of the offset (from the original SP)
@@ -535,37 +845,33 @@ arm_scan_prologue (fi)
[new FP] - [new SP]. */
fi->framesize = -sp_offset;
fi->frameoffset = fp_offset - sp_offset;
-
+
save_prologue_cache (fi);
}
-
-/* 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. */
+/* 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. */
static CORE_ADDR
-arm_find_callers_reg (fi, regnum)
- struct frame_info * fi;
- int regnum;
+arm_find_callers_reg (struct frame_info *fi, int regnum)
{
for (; fi; fi = fi->next)
-
-#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, regnum);
else
#endif
- if (fi->fsr.regs[regnum] != 0)
- return read_memory_integer (fi->fsr.regs[regnum],
- REGISTER_RAW_SIZE(regnum));
+ if (fi->fsr.regs[regnum] != 0)
+ return read_memory_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE (regnum));
return read_register (regnum);
}
-
-
+/* *INDENT-OFF* */
/* 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
@@ -581,27 +887,27 @@ arm_find_callers_reg (fi, regnum)
read_memory_integer ((thisframe)->frame - 12, 4) :\
0)
*/
+/* *INDENT-ON* */
CORE_ADDR
-arm_frame_chain (fi)
- struct frame_info * fi;
+arm_frame_chain (struct frame_info *fi)
{
-#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
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 */
+ 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: */
+ callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
fp = arm_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 (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 */
+ return 0; /* in _start fn, don't chain further */
#endif
CORE_ADDR caller_pc, fn_start;
struct frame_info caller_fi;
@@ -622,9 +928,9 @@ arm_frame_chain (fi)
frame register number. */
if (arm_pc_is_thumb (caller_pc) != arm_pc_is_thumb (fi->pc))
{
- memset (& caller_fi, 0, sizeof (caller_fi));
+ memset (&caller_fi, 0, sizeof (caller_fi));
caller_fi.pc = caller_pc;
- arm_scan_prologue (& caller_fi);
+ arm_scan_prologue (&caller_fi);
framereg = caller_fi.framereg;
}
@@ -636,16 +942,17 @@ arm_frame_chain (fi)
return fi->frame + fi->framesize;
}
-/* Function: init_extra_frame_info
- This function actually figures out the frame address for a given pc and
- sp. This is tricky 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. */
+/* This function actually figures out the frame address for a given pc
+ and sp. This is tricky 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. FROMLEAF is a little confusing, it means
+ this is the next frame up the chain AFTER a frameless function. If
+ this is true, then the frame value for this frame is still in the
+ fp register. */
void
-arm_init_extra_frame_info (fi)
- struct frame_info * fi;
+arm_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
int reg;
@@ -654,32 +961,39 @@ arm_init_extra_frame_info (fi)
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
-#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
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;
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->framesize = 0;
fi->frameoffset = 0;
return;
}
- else
+ else
#endif
{
arm_scan_prologue (fi);
- if (!fi->next) /* this is the innermost frame? */
+ if (!fi->next)
+ /* this is the innermost frame? */
fi->frame = read_register (fi->framereg);
- else /* not the innermost frame */
- /* If we have an FP, the callee saved it. */
- if (fi->framereg == FP_REGNUM || fi->framereg == THUMB_FP_REGNUM)
+ else if (fi->framereg == FP_REGNUM || fi->framereg == THUMB_FP_REGNUM)
+ {
+ /* not the innermost frame */
+ /* If we have an FP, the callee saved it. */
if (fi->next->fsr.regs[fi->framereg] != 0)
- fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
- 4);
+ fi->frame =
+ read_memory_integer (fi->next->fsr.regs[fi->framereg], 4);
+ else if (fromleaf)
+ /* If we were called by a frameless fn. then our frame is
+ still in the frame pointer register on the board... */
+ fi->frame = read_fp ();
+ }
- /* Calculate actual addresses of saved registers using offsets determined
- by arm_scan_prologue. */
+ /* Calculate actual addresses of saved registers using offsets
+ determined by arm_scan_prologue. */
for (reg = 0; reg < NUM_REGS; reg++)
if (fi->fsr.regs[reg] != 0)
fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
@@ -687,20 +1001,18 @@ arm_init_extra_frame_info (fi)
}
-/* Function: frame_saved_pc
- Find the caller of this frame. We do this by seeing if LR_REGNUM is saved
- in the stack anywhere, otherwise we get it from the registers.
+/* Find the caller of this frame. We do this by seeing if LR_REGNUM
+ is saved in the stack anywhere, otherwise we get it from the
+ registers.
The old definition of this function was a macro:
- #define FRAME_SAVED_PC(FRAME) \
- ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4))
-*/
+ #define FRAME_SAVED_PC(FRAME) \
+ ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4)) */
CORE_ADDR
-arm_frame_saved_pc (fi)
- struct frame_info * fi;
+arm_frame_saved_pc (struct frame_info *fi)
{
-#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
+#if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
else
@@ -711,32 +1023,29 @@ arm_frame_saved_pc (fi)
}
}
-
/* Return the frame address. On ARM, it is R11; on Thumb it is R7.
Examine the Program Status Register to decide which state we're in. */
CORE_ADDR
-arm_target_read_fp ()
+arm_target_read_fp (void)
{
if (read_register (PS_REGNUM) & 0x20) /* Bit 5 is Thumb state bit */
return read_register (THUMB_FP_REGNUM); /* R7 if Thumb */
else
- return read_register (FP_REGNUM); /* R11 if ARM */
+ return read_register (FP_REGNUM); /* R11 if ARM */
}
+/* Calculate the frame offsets of the saved registers (ARM version). */
-/* Calculate the frame offsets of the saved registers (ARM version). */
void
-arm_frame_find_saved_regs (fi, regaddr)
- struct frame_info *fi;
- struct frame_saved_regs *regaddr;
+arm_frame_find_saved_regs (struct frame_info *fi,
+ struct frame_saved_regs *regaddr)
{
memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs));
}
-
void
-arm_push_dummy_frame ()
+arm_push_dummy_frame (void)
{
CORE_ADDR old_sp = read_register (SP_REGNUM);
CORE_ADDR sp = old_sp;
@@ -750,62 +1059,56 @@ arm_push_dummy_frame ()
/* stmdb sp!, {r0-r10, fp, ip, lr, pc} */
prologue_start = sp = push_word (sp, 0xe92ddfff);
- /* push a pointer to the dummy prologue + 12, because when
- stm instruction stores the PC, it stores the address of the stm
+ /* Push a pointer to the dummy prologue + 12, because when stm
+ instruction stores the PC, it stores the address of the stm
instruction itself plus 12. */
fp = sp = push_word (sp, prologue_start + 12);
- sp = push_word (sp, read_register (PC_REGNUM)); /* FIXME: was PS_REGNUM */
+ sp = push_word (sp, read_register (PC_REGNUM)); /* FIXME: was PS_REGNUM */
sp = push_word (sp, old_sp);
sp = push_word (sp, read_register (FP_REGNUM));
-
- for (regnum = 10; regnum >= 0; regnum --)
+
+ for (regnum = 10; regnum >= 0; regnum--)
sp = push_word (sp, read_register (regnum));
-
+
write_register (FP_REGNUM, fp);
write_register (THUMB_FP_REGNUM, fp);
write_register (SP_REGNUM, sp);
}
/* Fix up the call dummy, based on whether the processor is currently
- in Thumb or ARM mode, and whether the target function is Thumb
- or ARM. There are three different situations requiring three
+ in Thumb or ARM mode, and whether the target function is Thumb or
+ ARM. There are three different situations requiring three
different dummies:
* ARM calling ARM: uses the call dummy in tm-arm.h, which has already
- been copied into the dummy parameter to this function.
+ been copied into the dummy parameter to this function.
* ARM calling Thumb: uses the call dummy in tm-arm.h, but with the
- "mov pc,r4" instruction patched to be a "bx r4" instead.
+ "mov pc,r4" instruction patched to be a "bx r4" instead.
* Thumb calling anything: uses the Thumb dummy defined below, which
- works for calling both ARM and Thumb functions.
+ works for calling both ARM and Thumb functions.
- All three call dummies expect to receive the target function address
- in R4, with the low bit set if it's a Thumb function.
-*/
+ All three call dummies expect to receive the target function
+ address in R4, with the low bit set if it's a Thumb function. */
void
-arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
- char * dummy;
- CORE_ADDR pc;
- CORE_ADDR fun;
- int nargs;
- value_ptr * args;
- struct type * type;
- int gcc_p;
+arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ value_ptr *args, struct type *type, int gcc_p)
{
static short thumb_dummy[4] =
{
- 0xf000, 0xf801, /* bl label */
- 0xdf18, /* swi 24 */
- 0x4720, /* label: bx r4 */
+ 0xf000, 0xf801, /* bl label */
+ 0xdf18, /* swi 24 */
+ 0x4720, /* label: bx r4 */
};
static unsigned long arm_bx_r4 = 0xe12fff14; /* bx r4 instruction */
/* Set flag indicating whether the current PC is in a Thumb function. */
- caller_is_thumb = arm_pc_is_thumb (read_pc());
+ caller_is_thumb = arm_pc_is_thumb (read_pc ());
- /* If the target function is Thumb, set the low bit of the function address.
- And if the CPU is currently in ARM mode, patch the second instruction
- of call dummy to use a BX instruction to switch to Thumb mode. */
+ /* If the target function is Thumb, set the low bit of the function
+ address. And if the CPU is currently in ARM mode, patch the
+ second instruction of call dummy to use a BX instruction to
+ switch to Thumb mode. */
target_is_thumb = arm_pc_is_thumb (fun);
if (target_is_thumb)
{
@@ -830,21 +1133,20 @@ arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p)
}
}
- /* Put the target address in r4; the call dummy will copy this to the PC. */
+ /* Put the target address in r4; the call dummy will copy this to
+ the PC. */
write_register (4, fun);
}
-
/* Return the offset in the call dummy of the instruction that needs
- to have a breakpoint placed on it. This is the offset of the 'swi 24'
- instruction, which is no longer actually used, but simply acts
+ to have a breakpoint placed on it. This is the offset of the 'swi
+ 24' instruction, which is no longer actually used, but simply acts
as a place-holder now.
- This implements the CALL_DUMMY_BREAK_OFFSET macro.
-*/
+ This implements the CALL_DUMMY_BREAK_OFFSET macro. */
int
-arm_call_dummy_breakpoint_offset ()
+arm_call_dummy_breakpoint_offset (void)
{
if (caller_is_thumb)
return 4;
@@ -852,225 +1154,297 @@ arm_call_dummy_breakpoint_offset ()
return 8;
}
+/* Note: ScottB
+
+ This function does not support passing parameters using the FPA
+ variant of the APCS. It passes any floating point arguments in the
+ general registers and/or on the stack. */
CORE_ADDR
-arm_push_arguments(nargs, args, sp, struct_return, struct_addr)
- int nargs;
- value_ptr * args;
- CORE_ADDR sp;
- int struct_return;
- CORE_ADDR struct_addr;
+arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
{
- int argreg;
- int float_argreg;
- int argnum;
- int stack_offset;
- struct stack_arg {
- char *val;
+ char *fp;
+ int argnum, argreg, nstack_size;
+
+ /* Walk through the list of args and determine how large a temporary
+ stack is required. Need to take care here as structs may be
+ passed on the stack, and we have to to push them. */
+ nstack_size = -4 * REGISTER_SIZE; /* Some arguments go into A1-A4. */
+ if (struct_return) /* The struct address goes in A1. */
+ nstack_size += REGISTER_SIZE;
+
+ /* Walk through the arguments and add their size to nstack_size. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
int len;
- int offset;
- };
- struct stack_arg *stack_args =
- (struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
- int nstack_args = 0;
+ struct type *arg_type;
+
+ arg_type = check_typedef (VALUE_TYPE (args[argnum]));
+ len = TYPE_LENGTH (arg_type);
+ /* ANSI C code passes float arguments as integers, K&R code
+ passes float arguments as doubles. Correct for this here. */
+ if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len)
+ nstack_size += FP_REGISTER_VIRTUAL_SIZE;
+ else
+ nstack_size += len;
+ }
+
+ /* Allocate room on the stack, and initialize our stack frame
+ pointer. */
+ fp = NULL;
+ if (nstack_size > 0)
+ {
+ sp -= nstack_size;
+ fp = (char *) sp;
+ }
- /* Initialize the integer and float register pointers. */
+ /* Initialize the integer argument register pointer. */
argreg = A1_REGNUM;
- float_argreg = F0_REGNUM;
- /* the struct_return pointer occupies the first parameter-passing reg */
+ /* The struct_return pointer occupies the first parameter passing
+ register. */
if (struct_return)
- write_register (argreg++, struct_addr);
-
- /* The offset onto the stack at which we will start copying parameters
- (after the registers are used up) begins at 16 in the old ABI.
- This leaves room for the "home" area for register parameters. */
- stack_offset = REGISTER_SIZE * 4;
+ write_register (argreg++, struct_addr);
- /* Process args from left to right. Store as many as allowed in
- registers, save the rest to be pushed on the stack */
- for(argnum = 0; argnum < nargs; argnum++)
+ /* Process arguments from left to right. Store as many as allowed
+ in the parameter passing registers (A1-A4), and save the rest on
+ the temporary stack. */
+ for (argnum = 0; argnum < nargs; argnum++)
{
- char * val;
- value_ptr arg = args[argnum];
- struct type * arg_type = check_typedef (VALUE_TYPE (arg));
- struct type * target_type = TYPE_TARGET_TYPE (arg_type);
- int len = TYPE_LENGTH (arg_type);
- enum type_code typecode = TYPE_CODE (arg_type);
- CORE_ADDR regval;
- int newarg;
-
- val = (char *) VALUE_CONTENTS (arg);
-
- /* If the argument is a pointer to a function, and it's a Thumb
+ int len;
+ char *val;
+ double dbl_arg;
+ CORE_ADDR regval;
+ enum type_code typecode;
+ struct type *arg_type, *target_type;
+
+ arg_type = check_typedef (VALUE_TYPE (args[argnum]));
+ target_type = TYPE_TARGET_TYPE (arg_type);
+ len = TYPE_LENGTH (arg_type);
+ typecode = TYPE_CODE (arg_type);
+ val = (char *) VALUE_CONTENTS (args[argnum]);
+
+ /* ANSI C code passes float arguments as integers, K&R code
+ passes float arguments as doubles. The .stabs record for
+ for ANSI prototype floating point arguments records the
+ type as FP_INTEGER, while a K&R style (no prototype)
+ .stabs records the type as FP_FLOAT. In this latter case
+ the compiler converts the float arguments to double before
+ calling the function. */
+ if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
+ {
+ float f;
+ double d;
+ char * bufo = (char *) &d;
+ char * bufd = (char *) &dbl_arg;
+
+ len = sizeof (double);
+ f = *(float *) val;
+ SWAP_TARGET_AND_HOST (&f, sizeof (float)); /* adjust endianess */
+ d = f;
+ /* We must revert the longwords so they get loaded into the
+ the right registers. */
+ memcpy (bufd, bufo + len / 2, len / 2);
+ SWAP_TARGET_AND_HOST (bufd, len / 2); /* adjust endianess */
+ memcpy (bufd + len / 2, bufo, len / 2);
+ SWAP_TARGET_AND_HOST (bufd + len / 2, len / 2); /* adjust endianess */
+ val = (char *) &dbl_arg;
+ }
+#if 1
+ /* I don't know why this code was disable. The only logical use
+ for a function pointer is to call that function, so setting
+ the mode bit is perfectly fine. FN */
+ /* If the argument is a pointer to a function, and it is a Thumb
function, set the low bit of the pointer. */
- if (typecode == TYPE_CODE_PTR
- && target_type != NULL
- && TYPE_CODE (target_type) == TYPE_CODE_FUNC)
+ if (TYPE_CODE_PTR == typecode
+ && NULL != target_type
+ && TYPE_CODE_FUNC == TYPE_CODE (target_type))
{
- regval = extract_address (val, len);
+ CORE_ADDR regval = extract_address (val, len);
if (arm_pc_is_thumb (regval))
store_address (val, len, MAKE_THUMB_ADDR (regval));
}
-
-#define MAPCS_FLOAT 0 /* --mapcs-float not implemented by the compiler yet */
-#if MAPCS_FLOAT
- /* Up to four floating point arguments can be passed in floating
- point registers on ARM (not on Thumb). */
- if (typecode == TYPE_CODE_FLT
- && float_argreg <= ARM_LAST_FP_ARG_REGNUM
- && !target_is_thumb)
- {
- /* This is a floating point value that fits entirely
- in a single register. */
- regval = extract_address (val, len);
- write_register (float_argreg++, regval);
- }
- else
#endif
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ while (len > 0)
{
- /* Copy the argument to general registers or the stack in
- register-sized pieces. Large arguments are split between
- registers and stack. */
- while (len > 0)
+ int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
+
+ if (argreg <= ARM_LAST_ARG_REGNUM)
{
- if (argreg <= ARM_LAST_ARG_REGNUM)
- {
- int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
- regval = extract_address (val, partial_len);
-
- /* It's a simple argument being passed in a general
- register. */
- write_register (argreg, regval);
- argreg++;
- len -= partial_len;
- val += partial_len;
- }
- else
- {
- /* keep for later pushing */
- stack_args[nstack_args].val = val;
- stack_args[nstack_args++].len = len;
- break;
- }
+ /* It's an argument being passed in a general register. */
+ regval = extract_address (val, partial_len);
+ write_register (argreg++, regval);
}
+ else
+ {
+ /* Push the arguments onto the stack. */
+ write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE);
+ fp += REGISTER_SIZE;
+ }
+
+ len -= partial_len;
+ val += partial_len;
}
}
- /* now do the real stack pushing, process args right to left */
- while(nstack_args--)
- {
- sp -= stack_args[nstack_args].len;
- write_memory(sp, stack_args[nstack_args].val,
- stack_args[nstack_args].len);
- }
/* Return adjusted stack pointer. */
return sp;
}
void
-arm_pop_frame ()
+arm_pop_frame (void)
{
- struct frame_info *frame = get_current_frame();
int regnum;
+ struct frame_info *frame = get_current_frame ();
+
+ if (!PC_IN_CALL_DUMMY(frame->pc, frame->frame, read_fp()))
+ {
+ CORE_ADDR old_SP;
- for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (frame->fsr.regs[regnum] != 0)
- write_register (regnum,
+ old_SP = read_register (frame->framereg);
+ 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 (frame->framereg));
+ write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
+ write_register (SP_REGNUM, old_SP);
+ }
+ else
+ {
+ CORE_ADDR sp;
+
+ sp = read_register (FP_REGNUM);
+ sp -= sizeof(CORE_ADDR); /* we don't care about this first word */
+
+ write_register (PC_REGNUM, read_memory_integer (sp, 4));
+ sp -= sizeof(CORE_ADDR);
+ write_register (SP_REGNUM, read_memory_integer (sp, 4));
+ sp -= sizeof(CORE_ADDR);
+ write_register (FP_REGNUM, read_memory_integer (sp, 4));
+ sp -= sizeof(CORE_ADDR);
+
+ for (regnum = 10; regnum >= 0; regnum--)
+ {
+ write_register (regnum, read_memory_integer (sp, 4));
+ sp -= sizeof(CORE_ADDR);
+ }
+ }
flush_cached_frames ();
}
static void
-print_fpu_flags (flags)
- int flags;
+print_fpu_flags (int flags)
{
- if (flags & (1 << 0)) fputs ("IVO ", stdout);
- if (flags & (1 << 1)) fputs ("DVZ ", stdout);
- if (flags & (1 << 2)) fputs ("OFL ", stdout);
- if (flags & (1 << 3)) fputs ("UFL ", stdout);
- if (flags & (1 << 4)) fputs ("INX ", stdout);
- putchar ('\n');
+ if (flags & (1 << 0))
+ fputs ("IVO ", stdout);
+ if (flags & (1 << 1))
+ fputs ("DVZ ", stdout);
+ if (flags & (1 << 2))
+ fputs ("OFL ", stdout);
+ if (flags & (1 << 3))
+ fputs ("UFL ", stdout);
+ if (flags & (1 << 4))
+ fputs ("INX ", stdout);
+ putchar ('\n');
}
void
-arm_float_info ()
+arm_float_info (void)
{
- register unsigned long status = read_register (FPS_REGNUM);
- int type;
-
- type = (status >> 24) & 127;
- printf ("%s FPU type %d\n",
- (status & (1<<31)) ? "Hardware" : "Software",
- type);
- fputs ("mask: ", stdout);
- print_fpu_flags (status >> 16);
- fputs ("flags: ", stdout);
- print_fpu_flags (status);
+ register unsigned long status = read_register (FPS_REGNUM);
+ int type;
+
+ type = (status >> 24) & 127;
+ printf ("%s FPU type %d\n",
+ (status & (1 << 31)) ? "Hardware" : "Software",
+ type);
+ fputs ("mask: ", stdout);
+ print_fpu_flags (status >> 16);
+ fputs ("flags: ", stdout);
+ print_fpu_flags (status);
}
-static char *original_register_names[] =
-{ "a1", "a2", "a3", "a4", /* 0 1 2 3 */
- "v1", "v2", "v3", "v4", /* 4 5 6 7 */
- "v5", "v6", "sl", "fp", /* 8 9 10 11 */
- "ip", "sp", "lr", "pc", /* 12 13 14 15 */
- "f0", "f1", "f2", "f3", /* 16 17 18 19 */
- "f4", "f5", "f6", "f7", /* 20 21 22 23 */
- "fps","ps" } /* 24 25 */;
-
-/* These names are the ones which gcc emits, and
- I find them less confusing. Toggle between them
- using the `othernames' command. */
-static char *additional_register_names[] =
-{ "r0", "r1", "r2", "r3", /* 0 1 2 3 */
- "r4", "r5", "r6", "r7", /* 4 5 6 7 */
- "r8", "r9", "sl", "fp", /* 8 9 10 11 */
- "ip", "sp", "lr", "pc", /* 12 13 14 15 */
- "f0", "f1", "f2", "f3", /* 16 17 18 19 */
- "f4", "f5", "f6", "f7", /* 20 21 22 23 */
- "fps","ps" } /* 24 25 */;
-
-char **arm_register_names = original_register_names;
+#if 0
+/* FIXME: The generated assembler works but sucks. Instead of using
+ r0, r1 it pushes them on the stack, then loads them into r3, r4 and
+ uses those registers. I must be missing something. ScottB */
+void
+convert_from_extended (void *ptr, void *dbl)
+{
+ __asm__ ("
+ ldfe f0,[%0]
+ stfd f0,[%1] "
+: /* no output */
+: "r" (ptr), "r" (dbl));
+}
+void
+convert_to_extended (void *dbl, void *ptr)
+{
+ __asm__ ("
+ ldfd f0,[%0]
+ stfe f0,[%1] "
+: /* no output */
+: "r" (dbl), "r" (ptr));
+}
+#else
static void
-arm_othernames ()
+convert_from_extended (void *ptr, void *dbl)
+{
+ *(double *) dbl = *(double *) ptr;
+}
+
+void
+convert_to_extended (void *dbl, void *ptr)
+{
+ *(double *) ptr = *(double *) dbl;
+}
+#endif
+
+/* Nonzero if register N requires conversion from raw format to
+ virtual format. */
+
+int
+arm_register_convertible (unsigned int regnum)
{
- static int toggle;
- arm_register_names = (toggle
- ? additional_register_names
- : original_register_names);
- toggle = !toggle;
+ return ((regnum - F0_REGNUM) < 8);
}
-/* FIXME: Fill in with the 'right thing', see asm
- template in arm-convert.s */
+/* Convert data from raw format for register REGNUM in buffer FROM to
+ virtual format with type TYPE in buffer TO. */
-void
-convert_from_extended (ptr, dbl)
- void * ptr;
- double * dbl;
+void
+arm_register_convert_to_virtual (unsigned int regnum, struct type *type,
+ void *from, void *to)
{
- *dbl = *(double*)ptr;
+ double val;
+
+ convert_from_extended (from, &val);
+ store_floating (to, TYPE_LENGTH (type), val);
}
-void
-convert_to_extended (dbl, ptr)
- void * ptr;
- double * dbl;
+/* Convert data from virtual format with type TYPE in buffer FROM to
+ raw format for register REGNUM in buffer TO. */
+
+void
+arm_register_convert_to_raw (unsigned int regnum, struct type *type,
+ void *from, void *to)
{
- *(double*)ptr = *dbl;
+ double val = extract_floating (from, TYPE_LENGTH (type));
+
+ convert_to_extended (&val, to);
}
static int
-condition_true (cond, status_reg)
- unsigned long cond;
- unsigned long status_reg;
+condition_true (unsigned long cond, unsigned long status_reg)
{
if (cond == INST_AL || cond == INST_NV)
return 1;
@@ -1121,78 +1495,72 @@ condition_true (cond, status_reg)
#define ARM_PC_32 1
static unsigned long
-shifted_reg_val (inst, carry, pc_val, status_reg)
- unsigned long inst;
- int carry;
- unsigned long pc_val;
- unsigned long status_reg;
+shifted_reg_val (unsigned long inst, int carry, unsigned long pc_val,
+ unsigned long status_reg)
{
unsigned long res, shift;
int rm = bits (inst, 0, 3);
unsigned long shifttype = bits (inst, 5, 6);
-
- if (bit(inst, 4))
+
+ if (bit (inst, 4))
{
int rs = bits (inst, 8, 11);
shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF;
}
else
shift = bits (inst, 7, 11);
-
- res = (rm == 15
+
+ res = (rm == 15
? ((pc_val | (ARM_PC_32 ? 0 : status_reg))
- + (bit (inst, 4) ? 12 : 8))
+ + (bit (inst, 4) ? 12 : 8))
: read_register (rm));
switch (shifttype)
{
- case 0: /* LSL */
+ case 0: /* LSL */
res = shift >= 32 ? 0 : res << shift;
break;
-
- case 1: /* LSR */
+
+ case 1: /* LSR */
res = shift >= 32 ? 0 : res >> shift;
break;
- case 2: /* ASR */
- if (shift >= 32) shift = 31;
+ case 2: /* ASR */
+ if (shift >= 32)
+ shift = 31;
res = ((res & 0x80000000L)
? ~((~res) >> shift) : res >> shift);
break;
- case 3: /* ROR/RRX */
+ case 3: /* ROR/RRX */
shift &= 31;
if (shift == 0)
res = (res >> 1) | (carry ? 0x80000000L : 0);
else
- res = (res >> shift) | (res << (32-shift));
+ res = (res >> shift) | (res << (32 - shift));
break;
}
return res & 0xffffffff;
}
-
/* Return number of 1-bits in VAL. */
static int
-bitcount (val)
- unsigned long val;
+bitcount (unsigned long val)
{
int nbits;
for (nbits = 0; val != 0; nbits++)
- val &= val - 1; /* delete rightmost 1-bit in val */
+ val &= val - 1; /* delete rightmost 1-bit in val */
return nbits;
}
-
static CORE_ADDR
-thumb_get_next_pc (pc)
- CORE_ADDR pc;
+thumb_get_next_pc (CORE_ADDR pc)
{
- unsigned long pc_val = ((unsigned long)pc) + 4; /* PC after prefetch */
+ unsigned long pc_val = ((unsigned long) pc) + 4; /* PC after prefetch */
unsigned short inst1 = read_memory_integer (pc, 2);
- CORE_ADDR nextpc = pc + 2; /* default is next instruction */
+ CORE_ADDR nextpc = pc + 2; /* default is next instruction */
unsigned long offset;
if ((inst1 & 0xff00) == 0xbd00) /* pop {rlist, pc} */
@@ -1211,7 +1579,7 @@ thumb_get_next_pc (pc)
else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
{
unsigned long status = read_register (PS_REGNUM);
- unsigned long cond = bits (inst1, 8, 11);
+ unsigned long cond = bits (inst1, 8, 11);
if (cond != 0x0f && condition_true (cond, status)) /* 0x0f = SWI */
nextpc = pc_val + (sbits (inst1, 0, 7) << 1);
}
@@ -1222,17 +1590,15 @@ thumb_get_next_pc (pc)
else if ((inst1 & 0xf800) == 0xf000) /* long branch with link */
{
unsigned short inst2 = read_memory_integer (pc + 2, 2);
- offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
+ offset = (sbits (inst1, 0, 10) << 12) + (bits (inst2, 0, 10) << 1);
nextpc = pc_val + offset;
}
return nextpc;
}
-
CORE_ADDR
-arm_get_next_pc (pc)
- CORE_ADDR pc;
+arm_get_next_pc (CORE_ADDR pc)
{
unsigned long pc_val;
unsigned long this_instr;
@@ -1245,93 +1611,98 @@ arm_get_next_pc (pc)
pc_val = (unsigned long) pc;
this_instr = read_memory_integer (pc, 4);
status = read_register (PS_REGNUM);
- nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
+ nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
if (condition_true (bits (this_instr, 28, 31), status))
{
switch (bits (this_instr, 24, 27))
{
- case 0x0: case 0x1: /* data processing */
- case 0x2: case 0x3:
+ case 0x0:
+ case 0x1: /* data processing */
+ case 0x2:
+ case 0x3:
{
unsigned long operand1, operand2, result = 0;
unsigned long rn;
int c;
-
+
if (bits (this_instr, 12, 15) != 15)
break;
if (bits (this_instr, 22, 25) == 0
- && bits (this_instr, 4, 7) == 9) /* multiply */
+ && bits (this_instr, 4, 7) == 9) /* multiply */
error ("Illegal update to pc in instruction");
/* Multiply into PC */
c = (status & FLAG_C) ? 1 : 0;
rn = bits (this_instr, 16, 19);
operand1 = (rn == 15) ? pc_val + 8 : read_register (rn);
-
+
if (bit (this_instr, 25))
{
unsigned long immval = bits (this_instr, 0, 7);
unsigned long rotate = 2 * bits (this_instr, 8, 11);
- operand2 = ((immval >> rotate) | (immval << (32-rotate)))
- & 0xffffffff;
+ operand2 = ((immval >> rotate) | (immval << (32 - rotate)))
+ & 0xffffffff;
}
- else /* operand 2 is a shifted register */
+ else /* operand 2 is a shifted register */
operand2 = shifted_reg_val (this_instr, c, pc_val, status);
-
+
switch (bits (this_instr, 21, 24))
{
- case 0x0: /*and*/
+ case 0x0: /*and */
result = operand1 & operand2;
break;
- case 0x1: /*eor*/
+ case 0x1: /*eor */
result = operand1 ^ operand2;
break;
- case 0x2: /*sub*/
+ case 0x2: /*sub */
result = operand1 - operand2;
break;
- case 0x3: /*rsb*/
+ case 0x3: /*rsb */
result = operand2 - operand1;
break;
- case 0x4: /*add*/
+ case 0x4: /*add */
result = operand1 + operand2;
break;
- case 0x5: /*adc*/
+ case 0x5: /*adc */
result = operand1 + operand2 + c;
break;
- case 0x6: /*sbc*/
+ case 0x6: /*sbc */
result = operand1 - operand2 + c;
break;
- case 0x7: /*rsc*/
+ case 0x7: /*rsc */
result = operand2 - operand1 + c;
break;
- case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb: /* tst, teq, cmp, cmn */
result = (unsigned long) nextpc;
break;
- case 0xc: /*orr*/
+ case 0xc: /*orr */
result = operand1 | operand2;
break;
- case 0xd: /*mov*/
+ case 0xd: /*mov */
/* Always step into a function. */
result = operand2;
- break;
+ break;
- case 0xe: /*bic*/
+ case 0xe: /*bic */
result = operand1 & ~operand2;
break;
- case 0xf: /*mvn*/
+ case 0xf: /*mvn */
result = ~operand2;
break;
}
@@ -1341,18 +1712,20 @@ arm_get_next_pc (pc)
error ("Infinite loop detected");
break;
}
-
- case 0x4: case 0x5: /* data transfer */
- case 0x6: case 0x7:
+
+ case 0x4:
+ case 0x5: /* data transfer */
+ case 0x6:
+ case 0x7:
if (bit (this_instr, 20))
{
/* load */
if (bits (this_instr, 12, 15) == 15)
{
/* rd == pc */
- unsigned long rn;
+ unsigned long rn;
unsigned long base;
-
+
if (bit (this_instr, 22))
error ("Illegal update to pc in instruction");
@@ -1364,18 +1737,18 @@ arm_get_next_pc (pc)
/* pre-indexed */
int c = (status & FLAG_C) ? 1 : 0;
unsigned long offset =
- (bit (this_instr, 25)
- ? shifted_reg_val (this_instr, c, pc_val)
- : bits (this_instr, 0, 11));
+ (bit (this_instr, 25)
+ ? shifted_reg_val (this_instr, c, pc_val, status)
+ : bits (this_instr, 0, 11));
if (bit (this_instr, 23))
base += offset;
else
base -= offset;
}
- nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
+ nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
4);
-
+
nextpc = ADDR_BITS_REMOVE (nextpc);
if (nextpc == pc)
@@ -1383,8 +1756,9 @@ arm_get_next_pc (pc)
}
}
break;
-
- case 0x8: case 0x9: /* block transfer */
+
+ case 0x8:
+ case 0x9: /* block transfer */
if (bit (this_instr, 20))
{
/* LDM */
@@ -1398,18 +1772,18 @@ arm_get_next_pc (pc)
/* up */
unsigned long reglist = bits (this_instr, 0, 14);
offset = bitcount (reglist) * 4;
- if (bit (this_instr, 24)) /* pre */
+ if (bit (this_instr, 24)) /* pre */
offset += 4;
}
else if (bit (this_instr, 24))
offset = -4;
-
+
{
- unsigned long rn_val =
- read_register (bits (this_instr, 16, 19));
+ unsigned long rn_val =
+ read_register (bits (this_instr, 16, 19));
nextpc =
(CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val
- + offset),
+ + offset),
4);
}
nextpc = ADDR_BITS_REMOVE (nextpc);
@@ -1418,9 +1792,9 @@ arm_get_next_pc (pc)
}
}
break;
-
- case 0xb: /* branch & link */
- case 0xa: /* branch */
+
+ case 0xb: /* branch & link */
+ case 0xa: /* branch */
{
nextpc = BranchDest (pc, this_instr);
@@ -1429,10 +1803,11 @@ arm_get_next_pc (pc)
error ("Infinite loop detected");
break;
}
-
- case 0xc: case 0xd:
- case 0xe: /* coproc ops */
- case 0xf: /* SWI */
+
+ case 0xc:
+ case 0xd:
+ case 0xe: /* coproc ops */
+ case 0xf: /* SWI */
break;
default:
@@ -1448,17 +1823,15 @@ arm_get_next_pc (pc)
#include "libcoff.h"
static int
-gdb_print_insn_arm (memaddr, info)
- bfd_vma memaddr;
- disassemble_info * info;
+gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
{
if (arm_pc_is_thumb (memaddr))
{
- static asymbol * asym;
- static combined_entry_type ce;
- static struct coff_symbol_struct csym;
- static struct _bfd fake_bfd;
- static bfd_target fake_target;
+ static asymbol *asym;
+ static combined_entry_type ce;
+ static struct coff_symbol_struct csym;
+ static struct _bfd fake_bfd;
+ static bfd_target fake_target;
if (csym.native == NULL)
{
@@ -1466,113 +1839,112 @@ gdb_print_insn_arm (memaddr, info)
solely so that the code in print_insn_little_arm() and
print_insn_big_arm() in opcodes/arm-dis.c will detect the presence
of a Thumb symbol and switch to decoding Thumb instructions. */
-
- fake_target.flavour = bfd_target_coff_flavour;
- fake_bfd.xvec = & fake_target;
+
+ fake_target.flavour = bfd_target_coff_flavour;
+ fake_bfd.xvec = &fake_target;
ce.u.syment.n_sclass = C_THUMBEXTFUNC;
- csym.native = & ce;
- csym.symbol.the_bfd = & fake_bfd;
- csym.symbol.name = "fake";
- asym = (asymbol *) & csym;
+ csym.native = &ce;
+ csym.symbol.the_bfd = &fake_bfd;
+ csym.symbol.name = "fake";
+ asym = (asymbol *) & csym;
}
-
+
memaddr = UNMAKE_THUMB_ADDR (memaddr);
- info->symbols = & asym;
+ info->symbols = &asym;
}
else
info->symbols = NULL;
-
+
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
return print_insn_big_arm (memaddr, info);
else
return print_insn_little_arm (memaddr, info);
}
-/* Sequence of bytes for breakpoint instruction. */
-#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7} /* Recognized illegal opcodes */
-#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
-#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
-#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
-
-/* The following has been superseded by BREAKPOINT_FOR_PC, but
- is defined merely to keep mem-break.c happy. */
-#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT
-#define BIG_BREAKPOINT ARM_BE_BREAKPOINT
-
-/* This function implements the BREAKPOINT_FROM_PC macro. It uses the program
- counter value to determine whether a 16- or 32-bit breakpoint should be
- used. It returns a pointer to a string of bytes that encode a breakpoint
- instruction, stores the length of the string to *lenptr, and adjusts pc
- (if necessary) to point to the actual memory location where the
+/* This function implements the BREAKPOINT_FROM_PC macro. It uses the
+ program counter value to determine whether a 16-bit or 32-bit
+ breakpoint should be used. It returns a pointer to a string of
+ bytes that encode a breakpoint instruction, stores the length of
+ the string to *lenptr, and adjusts the program counter (if
+ necessary) to point to the actual memory location where the
breakpoint should be inserted. */
unsigned char *
-arm_breakpoint_from_pc (pcptr, lenptr)
- CORE_ADDR * pcptr;
- int * lenptr;
+arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
{
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
- {
- static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
- *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
- *lenptr = sizeof (thumb_breakpoint);
- return thumb_breakpoint;
- }
+ {
+ static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
else
- {
- static char thumb_breakpoint[] = THUMB_LE_BREAKPOINT;
- *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
- *lenptr = sizeof (thumb_breakpoint);
- return thumb_breakpoint;
- }
+ {
+ static char thumb_breakpoint[] = THUMB_LE_BREAKPOINT;
+ *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
+ *lenptr = sizeof (thumb_breakpoint);
+ return thumb_breakpoint;
+ }
}
else
{
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
- {
- static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
- *lenptr = sizeof (arm_breakpoint);
- return arm_breakpoint;
- }
+ {
+ static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
else
- {
- static char arm_breakpoint[] = ARM_LE_BREAKPOINT;
- *lenptr = sizeof (arm_breakpoint);
- return arm_breakpoint;
- }
+ {
+ static char arm_breakpoint[] = ARM_LE_BREAKPOINT;
+ *lenptr = sizeof (arm_breakpoint);
+ return arm_breakpoint;
+ }
}
}
-/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
- This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */
+
+/* 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. */
+
+void
+arm_extract_return_value (struct type *type,
+ char regbuf[REGISTER_BYTES],
+ char *valbuf)
+{
+ if (TYPE_CODE_FLT == TYPE_CODE (type))
+ convert_from_extended (&regbuf[REGISTER_BYTE (F0_REGNUM)], valbuf);
+ else
+ memcpy (valbuf, &regbuf[REGISTER_BYTE (A1_REGNUM)], TYPE_LENGTH (type));
+}
+
+/* Return non-zero if the PC is inside a thumb call thunk. */
int
-arm_in_call_stub (pc, name)
- CORE_ADDR pc;
- char * name;
+arm_in_call_stub (CORE_ADDR pc, char *name)
{
CORE_ADDR start_addr;
- /* Find the starting address of the function containing the PC. If the
- caller didn't give us a name, look it up at the same time. */
+ /* Find the starting address of the function containing the PC. If
+ the caller didn't give us a name, look it up at the same time. */
if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
return 0;
return strncmp (name, "_call_via_r", 11) == 0;
}
-
-/* If PC is in a Thumb call or return stub, return the address of the target
- PC, which is in a register. The thunk functions are called _called_via_xx,
- where x is the register name. The possible names are r0-r9, sl, fp, ip,
- sp, and lr. */
+/* If PC is in a Thumb call or return stub, return the address of the
+ target PC, which is in a register. The thunk functions are called
+ _called_via_xx, where x is the register name. The possible names
+ are r0-r9, sl, fp, ip, sp, and lr. */
CORE_ADDR
-arm_skip_stub (pc)
- CORE_ADDR pc;
+arm_skip_stub (CORE_ADDR pc)
{
- char * name;
+ char *name;
CORE_ADDR start_addr;
/* Find the starting address and name of the function containing the PC. */
@@ -1582,45 +1954,162 @@ arm_skip_stub (pc)
/* Call thunks always start with "_call_via_". */
if (strncmp (name, "_call_via_", 10) == 0)
{
- /* Use the name suffix to determine which register contains
- the target PC. */
- static char *table[15] =
- { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "sl", "fp", "ip", "sp", "lr"
- };
+ /* Use the name suffix to determine which register contains the
+ target PC. */
+ static char *table[15] =
+ {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "sl", "fp", "ip", "sp", "lr"
+ };
int regno;
for (regno = 0; regno <= 14; regno++)
if (strcmp (&name[10], table[regno]) == 0)
return read_register (regno);
}
- return 0; /* not a stub */
+
+ return 0; /* not a stub */
+}
+
+/* If the user changes the register disassembly flavor used for info register
+ and other commands, we have to also switch the flavor used in opcodes
+ for disassembly output.
+ This function is run in the set disassembly_flavor command, and does that. */
+
+static void
+set_disassembly_flavor_sfunc (char *args, int from_tty,
+ struct cmd_list_element *c)
+{
+ set_disassembly_flavor ();
+}
+
+static void
+set_disassembly_flavor (void)
+{
+ const char *setname, *setdesc, **regnames;
+ int numregs, j;
+
+ /* Find the flavor that the user wants in the opcodes table. */
+ int current = 0;
+ numregs = get_arm_regnames (current, &setname, &setdesc, &regnames);
+ while ((disassembly_flavor != setname)
+ && (current < num_flavor_options))
+ get_arm_regnames (++current, &setname, &setdesc, &regnames);
+ current_option = current;
+
+ /* Fill our copy. */
+ for (j = 0; j < numregs; j++)
+ arm_register_names[j] = (char *) regnames[j];
+
+ /* Adjust case. */
+ if (isupper (*regnames[PC_REGNUM]))
+ {
+ arm_register_names[FPS_REGNUM] = "FPS";
+ arm_register_names[PS_REGNUM] = "CPSR";
+ }
+ else
+ {
+ arm_register_names[FPS_REGNUM] = "fps";
+ arm_register_names[PS_REGNUM] = "cpsr";
+ }
+
+ /* Synchronize the disassembler. */
+ set_arm_regname_option (current);
}
+/* arm_othernames implements the "othernames" command. This is kind
+ of hacky, and I prefer the set-show disassembly-flavor which is
+ also used for the x86 gdb. I will keep this around, however, in
+ case anyone is actually using it. */
+
+static void
+arm_othernames (char *names, int n)
+{
+ /* Circle through the various flavors. */
+ current_option = (current_option + 1) % num_flavor_options;
+
+ disassembly_flavor = valid_flavors[current_option];
+ set_disassembly_flavor ();
+}
void
-_initialize_arm_tdep ()
+_initialize_arm_tdep (void)
{
+ struct ui_file *stb;
+ long length;
+ struct cmd_list_element *new_cmd;
+ const char *setname, *setdesc, **regnames;
+ int numregs, i, j;
+ static char *helptext;
+
tm_print_insn = gdb_print_insn_arm;
- add_com ("othernames", class_obscure, arm_othernames,
- "Switch to the other set of register names.");
+ /* Get the number of possible sets of register names defined in opcodes. */
+ num_flavor_options = get_arm_regname_num_options ();
+
+ /* Sync the opcode insn printer with our register viewer: */
+ parse_arm_disassembler_option ("reg-names-std");
+
+ /* Begin creating the help text. */
+ stb = mem_fileopen ();
+ fprintf_unfiltered (stb, "Set the disassembly flavor.\n\
+The valid values are:\n");
+
+ /* Initialize the array that will be passed to add_set_enum_cmd(). */
+ valid_flavors = xmalloc ((num_flavor_options + 1) * sizeof (char *));
+ for (i = 0; i < num_flavor_options; i++)
+ {
+ numregs = get_arm_regnames (i, &setname, &setdesc, &regnames);
+ valid_flavors[i] = (char *) setname;
+ fprintf_unfiltered (stb, "%s - %s\n", setname,
+ setdesc);
+ /* Copy the default names (if found) and synchronize disassembler. */
+ if (!strcmp (setname, "std"))
+ {
+ disassembly_flavor = (char *) setname;
+ current_option = i;
+ for (j = 0; j < numregs; j++)
+ arm_register_names[j] = (char *) regnames[j];
+ set_arm_regname_option (i);
+ }
+ }
+ /* Mark the end of valid options. */
+ valid_flavors[num_flavor_options] = NULL;
+
+ /* Finish the creation of the help text. */
+ fprintf_unfiltered (stb, "The default is \"std\".");
+ helptext = ui_file_xstrdup (stb, &length);
+ ui_file_delete (stb);
+
+ /* Add the disassembly-flavor command */
+ new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class,
+ valid_flavors,
+ (char *) &disassembly_flavor,
+ helptext,
+ &setlist);
+ new_cmd->function.sfunc = set_disassembly_flavor_sfunc;
+ add_show_from_set (new_cmd, &showlist);
/* ??? Maybe this should be a boolean. */
add_show_from_set (add_set_cmd ("apcs32", no_class,
- var_zinteger, (char *)&arm_apcs_32,
+ var_zinteger, (char *) &arm_apcs_32,
"Set usage of ARM 32-bit mode.\n", &setlist),
- & showlist);
+ &showlist);
+
+ /* Add the deprecated "othernames" command */
+ add_com ("othernames", class_obscure, arm_othernames,
+ "Switch to the next set of register names.");
}
-/* Test whether the coff symbol specific value corresponds to a Thumb function */
+/* Test whether the coff symbol specific value corresponds to a Thumb
+ function. */
+
int
-coff_sym_is_thumb(int val)
+coff_sym_is_thumb (int val)
{
- return (val == C_THUMBEXT ||
- val == C_THUMBSTAT ||
- val == C_THUMBEXTFUNC ||
- val == C_THUMBSTATFUNC ||
- val == C_THUMBLABEL);
+ return (val == C_THUMBEXT ||
+ val == C_THUMBSTAT ||
+ val == C_THUMBEXTFUNC ||
+ val == C_THUMBSTATFUNC ||
+ val == C_THUMBLABEL);
}
diff --git a/contrib/gdb/gdb/arm-xdep.c b/contrib/gdb/gdb/arm-xdep.c
index f0d806e..64ca900 100644
--- a/contrib/gdb/gdb/arm-xdep.c
+++ b/contrib/gdb/gdb/arm-xdep.c
@@ -1,559 +1,575 @@
-/* Acorn Risc Machine host machine support.
- 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 "arm-opcode.h"
-
-#include <sys/param.h>
-#include <sys/dir.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/ptrace.h>
-#include <machine/reg.h>
-
-#define N_TXTADDR(hdr) 0x8000
-#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
-
-#include "gdbcore.h"
-
-#include <sys/user.h> /* After a.out.h */
-#include <sys/file.h>
-#include "gdb_stat.h"
-
-#include <errno.h>
-
-void
-fetch_inferior_registers (regno)
- int regno; /* Original value discarded */
-{
- register unsigned int regaddr;
- char buf[MAX_REGISTER_RAW_SIZE];
- register int i;
-
- struct user u;
- unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
- offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- - KERNEL_U_ADDR;
-
- registers_fetched ();
-
- for (regno = 0; regno < 16; regno++)
- {
- regaddr = offset + regno * 4;
- *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
- (PTRACE_ARG3_TYPE) regaddr, 0);
- if (regno == PC_REGNUM)
- *(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
- supply_register (regno, buf);
- }
- *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
- (PTRACE_ARG3_TYPE) (offset + PC*4), 0);
- supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
-
- /* read the floating point registers */
- offset = (char *) &u.u_fp_regs - (char *)&u;
- *(int *)buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0);
- supply_register (FPS_REGNUM, buf);
- for (regno = 16; regno < 24; regno++) {
- regaddr = offset + 4 + 12 * (regno - 16);
- for (i = 0; i < 12; i += sizeof(int))
- *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
- (PTRACE_ARG3_TYPE) (regaddr + i), 0);
- 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 (regno)
- int regno;
-{
- register unsigned int regaddr;
- char buf[80];
-
- struct user u;
- unsigned long value;
- unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
- offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- - KERNEL_U_ADDR;
-
- if (regno >= 0) {
- if (regno >= 16) return;
- regaddr = offset + 4 * regno;
- errno = 0;
- value = read_register(regno);
- if (regno == PC_REGNUM)
- value = SET_PC_PART(read_register (PS_REGNUM), value);
- ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
- if (errno != 0)
- {
- sprintf (buf, "writing register number %d", regno);
- perror_with_name (buf);
- }
- }
- else for (regno = 0; regno < 15; regno++)
- {
- regaddr = offset + regno * 4;
- errno = 0;
- value = read_register(regno);
- if (regno == PC_REGNUM)
- value = SET_PC_PART(read_register (PS_REGNUM), value);
- ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
- if (errno != 0)
- {
- sprintf (buf, "writing all regs, number %d", regno);
- perror_with_name (buf);
- }
- }
-}
-
-/* Work with core dump and executable files, for GDB.
- This code would be in corefile.c if it weren't machine-dependent. */
-
-/* Structure to describe the chain of shared libraries used
- by the execfile.
- e.g. prog shares Xt which shares X11 which shares c. */
-
-struct shared_library {
- struct exec_header header;
- char name[SHLIBLEN];
- CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
- long data_offset; /* offset of data section in file */
- int chan; /* file descriptor for the file */
- struct shared_library *shares; /* library this one shares */
-};
-static struct shared_library *shlib = 0;
-
-/* Hook for `exec_file_command' command to call. */
-
-extern void (*exec_file_display_hook) ();
-
-static CORE_ADDR unshared_text_start;
-
-/* extended header from exec file (for shared library info) */
-
-static struct exec_header exec_header;
-
-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;
-
- /* 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, fp_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);
-
- /* We are depending on exec_file_command having been called
- previously to set exec_data_start. Since the executable
- and the core file share the same text segment, the address
- of the data segment will be the same in both. */
- data_start = exec_data_start;
-
- data_end = data_start + NBPG * u.u_dsize;
- stack_start = stack_end - NBPG * u.u_ssize;
- data_offset = NBPG * UPAGES;
- stack_offset = NBPG * (UPAGES + u.u_dsize);
-
- /* 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;
- fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
-
- /* 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 < NUM_REGS; regno++)
- {
- char buf[MAX_REGISTER_RAW_SIZE];
-
- if (regno < 16)
- val = lseek (corechan, reg_offset + 4 * regno, 0);
- else if (regno < 24)
- val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
- else if (regno == 24)
- val = lseek (corechan, fp_reg_offset, 0);
- else if (regno == 25)
- val = lseek (corechan, reg_offset + 4 * PC, 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 (regno == PC_REGNUM)
- *(int *)buf = GET_PC_PART(*(int *)buf);
- supply_register (regno, buf);
- }
- }
- }
- if (filename[0] == '/')
- corefile = savestring (filename, strlen (filename));
- else
- {
- corefile = concat (current_directory, "/", filename, NULL);
- }
-
- flush_cached_frames ();
- select_frame (get_current_frame (), 0);
- validate_files ();
- }
- else if (from_tty)
- printf ("No core file now.\n");
-}
-
-#if 0
-/* Work with core dump and executable files, for GDB.
- This code would be in corefile.c if it weren't machine-dependent. */
-
-/* Structure to describe the chain of shared libraries used
- by the execfile.
- e.g. prog shares Xt which shares X11 which shares c. */
-
-struct shared_library {
- struct exec_header header;
- char name[SHLIBLEN];
- CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
- long data_offset; /* offset of data section in file */
- int chan; /* file descriptor for the file */
- struct shared_library *shares; /* library this one shares */
-};
-static struct shared_library *shlib = 0;
-
-/* Hook for `exec_file_command' command to call. */
-
-extern void (*exec_file_display_hook) ();
-
-static CORE_ADDR unshared_text_start;
-
-/* extended header from exec file (for shared library info) */
-
-static struct exec_header exec_header;
-
-void
-exec_file_command (filename, from_tty)
- char *filename;
- int from_tty;
-{
- int val;
-
- /* Eliminate all traces of old exec file.
- Mark text segment as empty. */
-
- if (execfile)
- free (execfile);
- execfile = 0;
- data_start = 0;
- data_end -= exec_data_start;
- text_start = 0;
- unshared_text_start = 0;
- text_end = 0;
- exec_data_start = 0;
- exec_data_end = 0;
- if (execchan >= 0)
- close (execchan);
- execchan = -1;
- if (shlib) {
- close_shared_library(shlib);
- shlib = 0;
- }
-
- /* Now open and digest the file the user requested, if any. */
-
- if (filename)
- {
- filename = tilde_expand (filename);
- make_cleanup (free, filename);
-
- execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
- &execfile);
- if (execchan < 0)
- perror_with_name (filename);
-
- {
- struct stat st_exec;
-
-#ifdef HEADER_SEEK_FD
- HEADER_SEEK_FD (execchan);
-#endif
-
- val = myread (execchan, &exec_header, sizeof exec_header);
- exec_aouthdr = exec_header.a_exec;
-
- if (val < 0)
- perror_with_name (filename);
-
- text_start = 0x8000;
-
- /* Look for shared library if needed */
- if (exec_header.a_exec.a_magic & MF_USES_SL)
- shlib = open_shared_library(exec_header.a_shlibname, text_start);
-
- text_offset = N_TXTOFF (exec_aouthdr);
- exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
-
- if (shlib) {
- unshared_text_start = shared_text_end(shlib) & ~0x7fff;
- stack_start = shlib->header.a_exec.a_sldatabase;
- stack_end = STACK_END_ADDR;
- } else
- unshared_text_start = 0x8000;
- text_end = unshared_text_start + exec_aouthdr.a_text;
-
- exec_data_start = unshared_text_start + exec_aouthdr.a_text;
- exec_data_end = exec_data_start + exec_aouthdr.a_data;
-
- data_start = exec_data_start;
- data_end += exec_data_start;
-
- fstat (execchan, &st_exec);
- exec_mtime = st_exec.st_mtime;
- }
-
- validate_files ();
- }
- else if (from_tty)
- printf ("No executable file now.\n");
-
- /* Tell display code (if any) about the changed file name. */
- if (exec_file_display_hook)
- (*exec_file_display_hook) (filename);
-}
-#endif
-
-#if 0
-/* Read from the program's memory (except for inferior processes).
- This function is misnamed, since it only reads, never writes; and
- since it will use the core file and/or executable file as necessary.
-
- It should be extended to write as well as read, FIXME, for patching files.
-
- Return 0 if address could be read, EIO if addresss out of bounds. */
-
-int
-xfer_core_file (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
-{
- register int i;
- register int val;
- int xferchan;
- char **xferfile;
- int fileptr;
- int returnval = 0;
-
- while (len > 0)
- {
- xferfile = 0;
- xferchan = 0;
-
- /* Determine which file the next bunch of addresses reside in,
- and where in the file. Set the file's read/write pointer
- to point at the proper place for the desired address
- and set xferfile and xferchan for the correct file.
-
- If desired address is nonexistent, leave them zero.
-
- i is set to the number of bytes that can be handled
- along with the next address.
-
- We put the most likely tests first for efficiency. */
-
- /* Note that if there is no core file
- data_start and data_end are equal. */
- if (memaddr >= data_start && memaddr < data_end)
- {
- i = min (len, data_end - memaddr);
- fileptr = memaddr - data_start + data_offset;
- xferfile = &corefile;
- xferchan = corechan;
- }
- /* Note that if there is no core file
- stack_start and stack_end define the shared library data. */
- else if (memaddr >= stack_start && memaddr < stack_end)
- {
- if (corechan < 0) {
- struct shared_library *lib;
- for (lib = shlib; lib; lib = lib->shares)
- if (memaddr >= lib->header.a_exec.a_sldatabase &&
- memaddr < lib->header.a_exec.a_sldatabase +
- lib->header.a_exec.a_data)
- break;
- if (lib) {
- i = min (len, lib->header.a_exec.a_sldatabase +
- lib->header.a_exec.a_data - memaddr);
- fileptr = lib->data_offset + memaddr -
- lib->header.a_exec.a_sldatabase;
- xferfile = execfile;
- xferchan = lib->chan;
- }
- } else {
- i = min (len, stack_end - memaddr);
- fileptr = memaddr - stack_start + stack_offset;
- xferfile = &corefile;
- xferchan = corechan;
- }
- }
- else if (corechan < 0
- && memaddr >= exec_data_start && memaddr < exec_data_end)
- {
- i = min (len, exec_data_end - memaddr);
- fileptr = memaddr - exec_data_start + exec_data_offset;
- xferfile = &execfile;
- xferchan = execchan;
- }
- else if (memaddr >= text_start && memaddr < text_end)
- {
- struct shared_library *lib;
- for (lib = shlib; lib; lib = lib->shares)
- if (memaddr >= lib->text_start &&
- memaddr < lib->text_start + lib->header.a_exec.a_text)
- break;
- if (lib) {
- i = min (len, lib->header.a_exec.a_text +
- lib->text_start - memaddr);
- fileptr = memaddr - lib->text_start + text_offset;
- xferfile = &execfile;
- xferchan = lib->chan;
- } else {
- i = min (len, text_end - memaddr);
- fileptr = memaddr - unshared_text_start + text_offset;
- xferfile = &execfile;
- xferchan = execchan;
- }
- }
- else if (memaddr < text_start)
- {
- i = min (len, text_start - memaddr);
- }
- else if (memaddr >= text_end
- && memaddr < (corechan >= 0? data_start : exec_data_start))
- {
- i = min (len, data_start - memaddr);
- }
- else if (corechan >= 0
- && memaddr >= data_end && memaddr < stack_start)
- {
- i = min (len, stack_start - memaddr);
- }
- else if (corechan < 0 && memaddr >= exec_data_end)
- {
- i = min (len, - memaddr);
- }
- else if (memaddr >= stack_end && stack_end != 0)
- {
- i = min (len, - memaddr);
- }
- else
- {
- /* Address did not classify into one of the known ranges.
- This shouldn't happen; we catch the endpoints. */
- fatal ("Internal: Bad case logic in xfer_core_file.");
- }
-
- /* Now we know which file to use.
- Set up its pointer and transfer the data. */
- if (xferfile)
- {
- if (*xferfile == 0)
- if (xferfile == &execfile)
- error ("No program file to examine.");
- else
- error ("No core dump file or running program to examine.");
- val = lseek (xferchan, fileptr, 0);
- if (val < 0)
- perror_with_name (*xferfile);
- val = myread (xferchan, myaddr, i);
- if (val < 0)
- perror_with_name (*xferfile);
- }
- /* If this address is for nonexistent memory,
- read zeros if reading, or do nothing if writing.
- Actually, we never right. */
- else
- {
- memset (myaddr, '\0', i);
- returnval = EIO;
- }
-
- memaddr += i;
- myaddr += i;
- len -= i;
- }
- return returnval;
-}
-#endif
+/* 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 */
diff --git a/contrib/gdb/gdb/c-exp.tab.c b/contrib/gdb/gdb/c-exp.tab.c
index c9395fa..46ff436 100644
--- a/contrib/gdb/gdb/c-exp.tab.c
+++ b/contrib/gdb/gdb/c-exp.tab.c
@@ -1,52 +1,52 @@
/* A Bison parser, made from c-exp.y
- by GNU Bison version 1.25
+ by GNU Bison version 1.27
*/
#define YYBISON 1 /* Identify Bison output. */
-#define INT 258
-#define FLOAT 259
-#define STRING 260
-#define NAME 261
-#define TYPENAME 262
-#define NAME_OR_INT 263
-#define STRUCT 264
-#define CLASS 265
-#define UNION 266
-#define ENUM 267
-#define SIZEOF 268
-#define UNSIGNED 269
-#define COLONCOLON 270
-#define TEMPLATE 271
-#define ERROR 272
-#define SIGNED_KEYWORD 273
-#define LONG 274
-#define SHORT 275
-#define INT_KEYWORD 276
-#define CONST_KEYWORD 277
-#define VOLATILE_KEYWORD 278
-#define DOUBLE_KEYWORD 279
-#define VARIABLE 280
-#define ASSIGN_MODIFY 281
-#define THIS 282
-#define TRUEKEYWORD 283
-#define FALSEKEYWORD 284
-#define ABOVE_COMMA 285
-#define OROR 286
-#define ANDAND 287
-#define EQUAL 288
-#define NOTEQUAL 289
-#define LEQ 290
-#define GEQ 291
-#define LSH 292
-#define RSH 293
-#define UNARY 294
-#define INCREMENT 295
-#define DECREMENT 296
-#define ARROW 297
-#define BLOCKNAME 298
-#define FILENAME 299
+#define INT 257
+#define FLOAT 258
+#define STRING 259
+#define NAME 260
+#define TYPENAME 261
+#define NAME_OR_INT 262
+#define STRUCT 263
+#define CLASS 264
+#define UNION 265
+#define ENUM 266
+#define SIZEOF 267
+#define UNSIGNED 268
+#define COLONCOLON 269
+#define TEMPLATE 270
+#define ERROR 271
+#define SIGNED_KEYWORD 272
+#define LONG 273
+#define SHORT 274
+#define INT_KEYWORD 275
+#define CONST_KEYWORD 276
+#define VOLATILE_KEYWORD 277
+#define DOUBLE_KEYWORD 278
+#define VARIABLE 279
+#define ASSIGN_MODIFY 280
+#define THIS 281
+#define TRUEKEYWORD 282
+#define FALSEKEYWORD 283
+#define ABOVE_COMMA 284
+#define OROR 285
+#define ANDAND 286
+#define EQUAL 287
+#define NOTEQUAL 288
+#define LEQ 289
+#define GEQ 290
+#define LSH 291
+#define RSH 292
+#define UNARY 293
+#define INCREMENT 294
+#define DECREMENT 295
+#define ARROW 296
+#define BLOCKNAME 297
+#define FILENAME 298
#line 38 "c-exp.y"
@@ -170,7 +170,7 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
#define YYFLAG -32768
#define YYNTBASE 69
-#define YYTRANSLATE(x) ((unsigned)(x) <= 299 ? yytranslate[x] : 91)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 298 ? yytranslate[x] : 91)
static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -198,11 +198,11 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 31, 34, 35, 39, 40, 43,
- 44, 45, 46, 53, 54, 55, 56, 60, 61
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 31, 34, 35, 39, 40, 43, 44,
+ 45, 46, 53, 54, 55, 56, 60, 61
};
#if YYDEBUG != 0
@@ -558,7 +558,8 @@ static const short yycheck[] = { 0,
56, 57, 58, 59
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/stone/jimb/main-98r2/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
+/* This file comes from bison-1.27. */
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -575,44 +576,64 @@ static const short yycheck[] = { 0,
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
-#ifndef alloca
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
#include <alloca.h>
#else /* not sparc */
-#if defined (MSDOS) && !defined (__TURBOC__)
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for xmalloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#endif
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
#pragma alloca
-#else /* not MSDOS, __TURBOC__, or _AIX */
-#ifdef __hpux
-#ifdef __cplusplus
-extern "C" {
-void *alloca (unsigned int);
-};
-#else /* not __cplusplus */
-void *alloca ();
-#endif /* not __cplusplus */
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
#endif /* __hpux */
+#endif
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc. */
-#endif /* not GNU C. */
-#endif /* alloca not defined. */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC xmalloc
+#endif
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
@@ -622,8 +643,8 @@ void *alloca ();
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
-#define YYACCEPT return(0)
-#define YYABORT return(1)
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
This remains here temporarily to ease the
@@ -704,12 +725,12 @@ int yydebug; /* nonzero means print parse trace */
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-int yyparse (void);
-#endif
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
@@ -721,7 +742,7 @@ static void
__yy_memcpy (to, from, count)
char *to;
char *from;
- int count;
+ unsigned int count;
{
register char *f = from;
register char *t = to;
@@ -736,10 +757,10 @@ __yy_memcpy (to, from, count)
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
-__yy_memcpy (char *to, char *from, int count)
+__yy_memcpy (char *to, char *from, unsigned int count)
{
- register char *f = from;
register char *t = to;
+ register char *f = from;
register int i = count;
while (i-- > 0)
@@ -749,7 +770,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif
#endif
-#line 196 "/stone/jimb/main-98r2/share/bison.simple"
+#line 216 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -770,6 +791,15 @@ __yy_memcpy (char *to, char *from, int count)
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
int
yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
@@ -798,6 +828,7 @@ yyparse(YYPARSE_PARAM_ARG)
#endif
int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
#ifdef YYPURE
int yychar;
@@ -882,18 +913,32 @@ yynewstate:
if (yystacksize >= YYMAXDEPTH)
{
yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
return 2;
}
yystacksize *= 2;
if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH;
- yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
- __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp));
- yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
- __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp));
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
- __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp));
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
@@ -1767,7 +1812,7 @@ case 131:
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 498 "/stone/jimb/main-98r2/share/bison.simple"
+#line 542 "/usr/lib/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
@@ -1962,6 +2007,30 @@ yyerrhandle:
yystate = yyn;
goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
}
#line 911 "c-exp.y"
diff --git a/contrib/gdb/gdb/core-sol2.c b/contrib/gdb/gdb/core-sol2.c
index 3c69e63..3ce9cd4 100644
--- a/contrib/gdb/gdb/core-sol2.c
+++ b/contrib/gdb/gdb/core-sol2.c
@@ -1,21 +1,22 @@
/* Machine independent support for Solaris 2 core files for GDB.
Copyright 1994 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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. */
/* Solaris comes with two flavours of core files, cores generated by
@@ -62,15 +63,15 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
{
#define gregs ((struct regs *)core_reg_sect)
/* G0 *always* holds 0. */
- *(int *)&registers[REGISTER_BYTE (0)] = 0;
+ *(int *) &registers[REGISTER_BYTE (0)] = 0;
/* The globals and output registers. */
- memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
15 * REGISTER_RAW_SIZE (G1_REGNUM));
- *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
- *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
- *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
- *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+ *(int *) &registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+ *(int *) &registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+ *(int *) &registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+ *(int *) &registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
/* My best guess at where to get the locals and input
registers is exactly where they usually are, right above
@@ -80,9 +81,9 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
{
int sp;
- sp = *(int *)&registers[REGISTER_BYTE (SP_REGNUM)];
+ sp = *(int *) &registers[REGISTER_BYTE (SP_REGNUM)];
if (0 != target_read_memory (sp,
- &registers[REGISTER_BYTE (L0_REGNUM)],
+ &registers[REGISTER_BYTE (L0_REGNUM)],
16 * REGISTER_RAW_SIZE (L0_REGNUM)))
{
warning ("couldn't read input and local registers from core file\n");
@@ -115,15 +116,17 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
}
}
}
-
+
/* Register that we are able to handle solaris core file formats. */
static struct core_fns solaris_core_fns =
{
- bfd_target_elf_flavour,
- fetch_core_registers,
- NULL
+ 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
diff --git a/contrib/gdb/gdb/f-exp.tab.c b/contrib/gdb/gdb/f-exp.tab.c
index ef7d25e..c493248 100644
--- a/contrib/gdb/gdb/f-exp.tab.c
+++ b/contrib/gdb/gdb/f-exp.tab.c
@@ -1,46 +1,46 @@
/* A Bison parser, made from f-exp.y
- by GNU Bison version 1.25
+ by GNU Bison version 1.27
*/
#define YYBISON 1 /* Identify Bison output. */
-#define INT 258
-#define FLOAT 259
-#define STRING_LITERAL 260
-#define BOOLEAN_LITERAL 261
-#define NAME 262
-#define TYPENAME 263
-#define NAME_OR_INT 264
-#define SIZEOF 265
-#define ERROR 266
-#define INT_KEYWORD 267
-#define INT_S2_KEYWORD 268
-#define LOGICAL_S1_KEYWORD 269
-#define LOGICAL_S2_KEYWORD 270
-#define LOGICAL_KEYWORD 271
-#define REAL_KEYWORD 272
-#define REAL_S8_KEYWORD 273
-#define REAL_S16_KEYWORD 274
-#define COMPLEX_S8_KEYWORD 275
-#define COMPLEX_S16_KEYWORD 276
-#define COMPLEX_S32_KEYWORD 277
-#define BOOL_AND 278
-#define BOOL_OR 279
-#define BOOL_NOT 280
-#define CHARACTER 281
-#define VARIABLE 282
-#define ASSIGN_MODIFY 283
-#define ABOVE_COMMA 284
-#define EQUAL 285
-#define NOTEQUAL 286
-#define LESSTHAN 287
-#define GREATERTHAN 288
-#define LEQ 289
-#define GEQ 290
-#define LSH 291
-#define RSH 292
-#define UNARY 293
+#define INT 257
+#define FLOAT 258
+#define STRING_LITERAL 259
+#define BOOLEAN_LITERAL 260
+#define NAME 261
+#define TYPENAME 262
+#define NAME_OR_INT 263
+#define SIZEOF 264
+#define ERROR 265
+#define INT_KEYWORD 266
+#define INT_S2_KEYWORD 267
+#define LOGICAL_S1_KEYWORD 268
+#define LOGICAL_S2_KEYWORD 269
+#define LOGICAL_KEYWORD 270
+#define REAL_KEYWORD 271
+#define REAL_S8_KEYWORD 272
+#define REAL_S16_KEYWORD 273
+#define COMPLEX_S8_KEYWORD 274
+#define COMPLEX_S16_KEYWORD 275
+#define COMPLEX_S32_KEYWORD 276
+#define BOOL_AND 277
+#define BOOL_OR 278
+#define BOOL_NOT 279
+#define CHARACTER 280
+#define VARIABLE 281
+#define ASSIGN_MODIFY 282
+#define ABOVE_COMMA 283
+#define EQUAL 284
+#define NOTEQUAL 285
+#define LESSTHAN 286
+#define GREATERTHAN 287
+#define LEQ 288
+#define GEQ 289
+#define LSH 290
+#define RSH 291
+#define UNARY 292
#line 43 "f-exp.y"
@@ -157,7 +157,7 @@ static int parse_number PARAMS ((char *, int, int, YYSTYPE *));
#define YYFLAG -32768
#define YYNTBASE 55
-#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 71)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 71)
static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -185,11 +185,11 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 30, 36, 37, 38, 39, 40, 41,
- 42, 43, 50
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 30, 36, 37, 38, 39, 40, 41, 42,
+ 43, 50
};
#if YYDEBUG != 0
@@ -433,7 +433,8 @@ static const short yycheck[] = { 0,
44, 45, 46, 47, 48, 49, -1, 51
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/stone/jimb/main-98r2/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
+/* This file comes from bison-1.27. */
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -450,44 +451,64 @@ static const short yycheck[] = { 0,
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
-#ifndef alloca
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
#include <alloca.h>
#else /* not sparc */
-#if defined (MSDOS) && !defined (__TURBOC__)
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for xmalloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#endif
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
#pragma alloca
-#else /* not MSDOS, __TURBOC__, or _AIX */
-#ifdef __hpux
-#ifdef __cplusplus
-extern "C" {
-void *alloca (unsigned int);
-};
-#else /* not __cplusplus */
-void *alloca ();
-#endif /* not __cplusplus */
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
#endif /* __hpux */
+#endif
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc. */
-#endif /* not GNU C. */
-#endif /* alloca not defined. */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC xmalloc
+#endif
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
@@ -497,8 +518,8 @@ void *alloca ();
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
-#define YYACCEPT return(0)
-#define YYABORT return(1)
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
This remains here temporarily to ease the
@@ -579,12 +600,12 @@ int yydebug; /* nonzero means print parse trace */
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-int yyparse (void);
-#endif
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
@@ -596,7 +617,7 @@ static void
__yy_memcpy (to, from, count)
char *to;
char *from;
- int count;
+ unsigned int count;
{
register char *f = from;
register char *t = to;
@@ -611,10 +632,10 @@ __yy_memcpy (to, from, count)
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
-__yy_memcpy (char *to, char *from, int count)
+__yy_memcpy (char *to, char *from, unsigned int count)
{
- register char *f = from;
register char *t = to;
+ register char *f = from;
register int i = count;
while (i-- > 0)
@@ -624,7 +645,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif
#endif
-#line 196 "/stone/jimb/main-98r2/share/bison.simple"
+#line 216 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -645,6 +666,15 @@ __yy_memcpy (char *to, char *from, int count)
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
int
yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
@@ -673,6 +703,7 @@ yyparse(YYPARSE_PARAM_ARG)
#endif
int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
#ifdef YYPURE
int yychar;
@@ -757,18 +788,32 @@ yynewstate:
if (yystacksize >= YYMAXDEPTH)
{
yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
return 2;
}
yystacksize *= 2;
if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH;
- yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
- __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp));
- yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
- __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp));
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
- __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp));
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
@@ -1336,7 +1381,7 @@ case 82:
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 498 "/stone/jimb/main-98r2/share/bison.simple"
+#line 542 "/usr/lib/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
@@ -1531,6 +1576,30 @@ yyerrhandle:
yystate = yyn;
goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
}
#line 624 "f-exp.y"
diff --git a/contrib/gdb/gdb/fr30-tdep.c b/contrib/gdb/gdb/fr30-tdep.c
index 0d442da..55b713a 100644
--- a/contrib/gdb/gdb/fr30-tdep.c
+++ b/contrib/gdb/gdb/fr30-tdep.c
@@ -1,21 +1,22 @@
/* Target-dependent code for the Fujitsu FR30.
Copyright 1999, Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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"
@@ -28,6 +29,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "gdbcore.h"
#include "symfile.h"
+/* An expression that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. */
+int
+fr30_frameless_function_invocation (fi)
+ struct frame_info *fi;
+{
+ int frameless;
+ CORE_ADDR func_start, after_prologue;
+ func_start = (get_pc_function_start ((fi)->pc) +
+ FUNCTION_START_OFFSET);
+ after_prologue = func_start;
+ after_prologue = SKIP_PROLOGUE (after_prologue);
+ frameless = (after_prologue == func_start);
+ return frameless;
+}
+
/* Function: pop_frame
This routine gets called when either the user uses the `return'
command, or the call dummy breakpoint gets hit. */
@@ -35,32 +52,75 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
void
fr30_pop_frame ()
{
- struct frame_info *frame = get_current_frame();
+ struct frame_info *frame = get_current_frame ();
int regnum;
- CORE_ADDR sp = read_register(SP_REGNUM);
+ CORE_ADDR sp = read_register (SP_REGNUM);
- if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
+ if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
{
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
for (regnum = 0; regnum < NUM_REGS; regnum++)
- if (frame->fsr.regs[regnum] != 0) {
- write_register (regnum,
- read_memory_unsigned_integer (frame->fsr.regs[regnum],
- REGISTER_RAW_SIZE(regnum)));
- }
+ if (frame->fsr.regs[regnum] != 0)
+ {
+ write_register (regnum,
+ read_memory_unsigned_integer (frame->fsr.regs[regnum],
+ REGISTER_RAW_SIZE (regnum)));
+ }
write_register (SP_REGNUM, sp + frame->framesize);
}
flush_cached_frames ();
}
+
+/* Function: fr30_store_return_value
+ Put a value where a caller expects to see it. Used by the 'return'
+ command. */
+void
+fr30_store_return_value (struct type *type,
+ char *valbuf)
+{
+ /* Here's how the FR30 returns values (gleaned from gcc/config/
+ fr30/fr30.h):
+
+ If the return value is 32 bits long or less, it goes in r4.
+
+ If the return value is 64 bits long or less, it goes in r4 (most
+ significant word) and r5 (least significant word.
+
+ If the function returns a structure, of any size, the caller
+ passes the function an invisible first argument where the callee
+ should store the value. But GDB doesn't let you do that anyway.
+
+ If you're returning a value smaller than a word, it's not really
+ necessary to zero the upper bytes of the register; the caller is
+ supposed to ignore them. However, the FR30 typically keeps its
+ values extended to the full register width, so we should emulate
+ that. */
+
+ /* The FR30 is big-endian, so if we return a small value (like a
+ short or a char), we need to position it correctly within the
+ register. We round the size up to a register boundary, and then
+ adjust the offset so as to place the value at the right end. */
+ int value_size = TYPE_LENGTH (type);
+ int returned_size = (value_size + FR30_REGSIZE - 1) & ~(FR30_REGSIZE - 1);
+ int offset = (REGISTER_BYTE (RETVAL_REG)
+ + (returned_size - value_size));
+ char *zeros = alloca (returned_size);
+ memset (zeros, 0, returned_size);
+
+ write_register_bytes (REGISTER_BYTE (RETVAL_REG), zeros, returned_size);
+ write_register_bytes (offset, valbuf, value_size);
+}
+
+
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
CORE_ADDR
-fr30_skip_prologue(CORE_ADDR pc)
+fr30_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
@@ -72,8 +132,9 @@ fr30_skip_prologue(CORE_ADDR pc)
sal = find_pc_line (func_addr, 0);
- if (sal.line != 0 && sal.end < func_end) {
- return sal.end;
+ if (sal.line != 0 && sal.end < func_end)
+ {
+ return sal.end;
}
}
@@ -95,96 +156,99 @@ fr30_skip_prologue(CORE_ADDR pc)
is passed in as a secret first argument (always in FIRST_ARGREG).
Stack space for the args has NOT been allocated: that job is up to us.
-*/
+ */
CORE_ADDR
-fr30_push_arguments(nargs, args, sp, struct_return, struct_addr)
- int nargs;
- value_ptr * args;
- CORE_ADDR sp;
- int struct_return;
- CORE_ADDR struct_addr;
+fr30_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
{
int argreg;
int argnum;
int stack_offset;
- struct stack_arg {
+ struct stack_arg
+ {
char *val;
int len;
int offset;
};
struct stack_arg *stack_args =
- (struct stack_arg*)alloca (nargs * sizeof (struct stack_arg));
+ (struct stack_arg *) alloca (nargs * sizeof (struct stack_arg));
int nstack_args = 0;
argreg = FIRST_ARGREG;
/* the struct_return pointer occupies the first parameter-passing reg */
if (struct_return)
- write_register (argreg++, struct_addr);
+ write_register (argreg++, struct_addr);
stack_offset = 0;
/* Process args from left to right. Store as many as allowed in
- registers, save the rest to be pushed on the stack */
- for(argnum = 0; argnum < nargs; argnum++)
+ registers, save the rest to be pushed on the stack */
+ for (argnum = 0; argnum < nargs; argnum++)
{
- char * val;
- value_ptr arg = args[argnum];
- struct type * arg_type = check_typedef (VALUE_TYPE (arg));
- struct type * target_type = TYPE_TARGET_TYPE (arg_type);
- int len = TYPE_LENGTH (arg_type);
+ char *val;
+ value_ptr arg = args[argnum];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ struct type *target_type = TYPE_TARGET_TYPE (arg_type);
+ int len = TYPE_LENGTH (arg_type);
enum type_code typecode = TYPE_CODE (arg_type);
- CORE_ADDR regval;
+ CORE_ADDR regval;
int newarg;
val = (char *) VALUE_CONTENTS (arg);
- {
- /* Copy the argument to general registers or the stack in
- register-sized pieces. Large arguments are split between
- registers and stack. */
- while (len > 0)
- {
- if (argreg <= LAST_ARGREG)
- {
- int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
- regval = extract_address (val, partial_len);
-
- /* It's a simple argument being passed in a general
- register. */
- write_register (argreg, regval);
- argreg++;
- len -= partial_len;
- val += partial_len;
- }
- else
- {
- /* keep for later pushing */
- stack_args[nstack_args].val = val;
- stack_args[nstack_args++].len = len;
- break;
- }
- }
- }
- }
- /* now do the real stack pushing, process args right to left */
- while(nstack_args--)
{
- sp -= stack_args[nstack_args].len;
- write_memory(sp, stack_args[nstack_args].val,
- stack_args[nstack_args].len);
+ /* Copy the argument to general registers or the stack in
+ register-sized pieces. Large arguments are split between
+ registers and stack. */
+ while (len > 0)
+ {
+ if (argreg <= LAST_ARGREG)
+ {
+ int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;
+ regval = extract_address (val, partial_len);
+
+ /* It's a simple argument being passed in a general
+ register. */
+ write_register (argreg, regval);
+ argreg++;
+ len -= partial_len;
+ val += partial_len;
+ }
+ else
+ {
+ /* keep for later pushing */
+ stack_args[nstack_args].val = val;
+ stack_args[nstack_args++].len = len;
+ break;
+ }
+ }
}
+ }
+ /* now do the real stack pushing, process args right to left */
+ while (nstack_args--)
+ {
+ sp -= stack_args[nstack_args].len;
+ write_memory (sp, stack_args[nstack_args].val,
+ stack_args[nstack_args].len);
+ }
/* Return adjusted stack pointer. */
return sp;
}
-_initialize_fr30_tdep()
-{
- extern int print_insn_fr30(bfd_vma, disassemble_info *);
+void _initialize_fr30_tdep PARAMS ((void));
- tm_print_insn = print_insn_fr30;
+void
+_initialize_fr30_tdep ()
+{
+ extern int print_insn_fr30 (bfd_vma, disassemble_info *);
+ tm_print_insn = print_insn_fr30;
}
/* Function: check_prologue_cache
@@ -193,23 +257,23 @@ _initialize_fr30_tdep()
return non-zero. Otherwise do not copy anything and return zero.
The information saved in the cache includes:
- * the frame register number;
- * the size of the stack frame;
- * the offsets of saved regs (relative to the old SP); and
- * the offset from the stack pointer to the frame pointer
+ * the frame register number;
+ * the size of the stack frame;
+ * the offsets of saved regs (relative to the old SP); and
+ * the offset from the stack pointer to the frame pointer
The cache contains only one entry, since this is adequate
for the typical sequence of prologue scan requests we get.
When performing a backtrace, GDB will usually ask to scan
the same function twice in a row (once to get the frame chain,
and once to fill in the extra frame information).
-*/
+ */
static struct frame_info prologue_cache;
static int
check_prologue_cache (fi)
- struct frame_info * fi;
+ struct frame_info *fi;
{
int i;
@@ -229,22 +293,23 @@ check_prologue_cache (fi)
/* Function: save_prologue_cache
Copy the prologue information from fi to the prologue cache.
-*/
+ */
static void
save_prologue_cache (fi)
- struct frame_info * fi;
+ struct frame_info *fi;
{
int i;
- prologue_cache.pc = fi->pc;
- prologue_cache.framereg = fi->framereg;
- prologue_cache.framesize = fi->framesize;
+ prologue_cache.pc = fi->pc;
+ prologue_cache.framereg = fi->framereg;
+ prologue_cache.framesize = fi->framesize;
prologue_cache.frameoffset = fi->frameoffset;
-
- for (i = 0; i <= NUM_REGS; i++) {
- prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
- }
+
+ for (i = 0; i <= NUM_REGS; i++)
+ {
+ prologue_cache.fsr.regs[i] = fi->fsr.regs[i];
+ }
}
@@ -259,7 +324,7 @@ save_prologue_cache (fi)
static void
fr30_scan_prologue (fi)
- struct frame_info * fi;
+ struct frame_info *fi;
{
int sp_offset, fp_offset;
CORE_ADDR prologue_start, prologue_end, current_pc;
@@ -269,8 +334,8 @@ fr30_scan_prologue (fi)
return;
/* Assume there is no frame until proven otherwise. */
- fi->framereg = SP_REGNUM;
- fi->framesize = 0;
+ fi->framereg = SP_REGNUM;
+ fi->framesize = 0;
fi->frameoffset = 0;
/* Find the function prologue. If we can't find the function in
@@ -281,10 +346,10 @@ fr30_scan_prologue (fi)
in the function and the first source line. */
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
- if (sal.line == 0) /* no line info, use current PC */
+ if (sal.line == 0) /* no line info, use current PC */
prologue_end = fi->pc;
else if (sal.end < prologue_end) /* next line begins after fn end */
- prologue_end = sal.end; /* (probably means no prologue) */
+ prologue_end = sal.end; /* (probably means no prologue) */
}
else
{
@@ -303,14 +368,14 @@ fr30_scan_prologue (fi)
insn = read_memory_unsigned_integer (current_pc, 2);
- if ((insn & 0xfe00) == 0x8e00) /* stm0 or stm1 */
+ if ((insn & 0xfe00) == 0x8e00) /* stm0 or stm1 */
{
int reg, mask = insn & 0xff;
/* scan in one sweep - create virtual 16-bit mask from either insn's mask */
- if((insn & 0x0100) == 0)
+ if ((insn & 0x0100) == 0)
{
- mask <<= 8; /* stm0 - move to upper byte in virtual mask */
+ mask <<= 8; /* stm0 - move to upper byte in virtual mask */
}
/* Calculate offsets of saved registers (to be turned later into addresses). */
@@ -321,53 +386,53 @@ fr30_scan_prologue (fi)
fi->fsr.regs[reg] = sp_offset;
}
}
- else if((insn & 0xfff0) == 0x1700) /* st rx,@-r15 */
- {
+ else if ((insn & 0xfff0) == 0x1700) /* st rx,@-r15 */
+ {
int reg = insn & 0xf;
sp_offset -= 4;
fi->fsr.regs[reg] = sp_offset;
}
- else if((insn & 0xff00) == 0x0f00) /* enter */
- {
+ else if ((insn & 0xff00) == 0x0f00) /* enter */
+ {
fp_offset = fi->fsr.regs[FP_REGNUM] = sp_offset - 4;
sp_offset -= 4 * (insn & 0xff);
fi->framereg = FP_REGNUM;
}
- else if(insn == 0x1781) /* st rp,@-sp */
+ else if (insn == 0x1781) /* st rp,@-sp */
{
- sp_offset -= 4;
- fi->fsr.regs[RP_REGNUM] = sp_offset;
+ sp_offset -= 4;
+ fi->fsr.regs[RP_REGNUM] = sp_offset;
}
- else if(insn == 0x170e) /* st fp,@-sp */
+ else if (insn == 0x170e) /* st fp,@-sp */
{
- sp_offset -= 4;
- fi->fsr.regs[FP_REGNUM] = sp_offset;
+ sp_offset -= 4;
+ fi->fsr.regs[FP_REGNUM] = sp_offset;
}
- else if(insn == 0x8bfe) /* mov sp,fp */
+ else if (insn == 0x8bfe) /* mov sp,fp */
{
fi->framereg = FP_REGNUM;
}
- else if((insn & 0xff00) == 0xa300) /* addsp xx */
+ else if ((insn & 0xff00) == 0xa300) /* addsp xx */
{
- sp_offset += 4 * (signed char)(insn & 0xff);
+ sp_offset += 4 * (signed char) (insn & 0xff);
}
- else if((insn & 0xff0f) == 0x9b00 && /* ldi:20 xx,r0 */
- read_memory_unsigned_integer(current_pc+4, 2)
- == 0xac0f) /* sub r0,sp */
+ else if ((insn & 0xff0f) == 0x9b00 && /* ldi:20 xx,r0 */
+ read_memory_unsigned_integer (current_pc + 4, 2)
+ == 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
- sp_offset -= (((insn & 0xf0) << 12) | read_memory_unsigned_integer(current_pc+2, 2));
+ sp_offset -= (((insn & 0xf0) << 12) | read_memory_unsigned_integer (current_pc + 2, 2));
current_pc += 4;
}
- else if(insn == 0x9f80 && /* ldi:32 xx,r0 */
- read_memory_unsigned_integer(current_pc+6, 2)
- == 0xac0f) /* sub r0,sp */
+ else if (insn == 0x9f80 && /* ldi:32 xx,r0 */
+ read_memory_unsigned_integer (current_pc + 6, 2)
+ == 0xac0f) /* sub r0,sp */
{
/* large stack adjustment */
sp_offset -=
- (read_memory_unsigned_integer(current_pc+2, 2) << 16 |
- read_memory_unsigned_integer(current_pc+4, 2));
+ (read_memory_unsigned_integer (current_pc + 2, 2) << 16 |
+ read_memory_unsigned_integer (current_pc + 4, 2));
current_pc += 6;
}
}
@@ -377,7 +442,7 @@ fr30_scan_prologue (fi)
[new FP] - [new SP]. */
fi->framesize = -sp_offset;
fi->frameoffset = fp_offset - sp_offset;
-
+
save_prologue_cache (fi);
}
@@ -396,7 +461,7 @@ fr30_scan_prologue (fi)
void
fr30_init_extra_frame_info (fi)
- struct frame_info * fi;
+ struct frame_info *fi;
{
int reg;
@@ -408,28 +473,29 @@ fr30_init_extra_frame_info (fi)
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;
+ by assuming it's always FP. */
+ fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM);
+ fi->framesize = 0;
fi->frameoffset = 0;
return;
}
- fr30_scan_prologue (fi);
-
- if (!fi->next) /* this is the innermost frame? */
- fi->frame = read_register (fi->framereg);
- else /* not the innermost frame */
- /* If we have an FP, the callee saved it. */
- if (fi->framereg == FP_REGNUM)
- if (fi->next->fsr.regs[fi->framereg] != 0)
- fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
- 4);
- /* Calculate actual addresses of saved registers using offsets determined
- by fr30_scan_prologue. */
- for (reg = 0; reg < NUM_REGS; reg++)
- if (fi->fsr.regs[reg] != 0) {
- fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
- }
+ fr30_scan_prologue (fi);
+
+ if (!fi->next) /* this is the innermost frame? */
+ fi->frame = read_register (fi->framereg);
+ else
+ /* not the innermost frame */
+ /* If we have an FP, the callee saved it. */ if (fi->framereg == FP_REGNUM)
+ if (fi->next->fsr.regs[fi->framereg] != 0)
+ fi->frame = read_memory_integer (fi->next->fsr.regs[fi->framereg],
+ 4);
+ /* Calculate actual addresses of saved registers using offsets determined
+ by fr30_scan_prologue. */
+ for (reg = 0; reg < NUM_REGS; reg++)
+ if (fi->fsr.regs[reg] != 0)
+ {
+ fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset;
+ }
}
/* Function: find_callers_reg
@@ -449,8 +515,8 @@ fr30_find_callers_reg (fi, regnum)
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_unsigned_integer (fi->fsr.regs[regnum],
- REGISTER_RAW_SIZE(regnum));
+ return read_memory_unsigned_integer (fi->fsr.regs[regnum],
+ REGISTER_RAW_SIZE (regnum));
return read_register (regnum);
}
@@ -466,7 +532,7 @@ fr30_find_callers_reg (fi, regnum)
CORE_ADDR
fr30_frame_chain (fi)
- struct frame_info * fi;
+ struct frame_info *fi;
{
CORE_ADDR fn_start, callers_pc, fp;
struct frame_info caller_fi;
@@ -474,17 +540,17 @@ fr30_frame_chain (fi)
/* 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 */
+ 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: */
+ callers_pc = FRAME_SAVED_PC (fi); /* find out who called us: */
fp = fr30_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 (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 */
+ return 0; /* in _start fn, don't chain further */
framereg = fi->framereg;
@@ -493,9 +559,9 @@ fr30_frame_chain (fi)
if (fn_start == entry_point_address ())
return 0;
- memset (& caller_fi, 0, sizeof (caller_fi));
+ memset (&caller_fi, 0, sizeof (caller_fi));
caller_fi.pc = callers_pc;
- fr30_scan_prologue (& caller_fi);
+ fr30_scan_prologue (&caller_fi);
framereg = caller_fi.framereg;
/* If the caller used a frame register, return its value.
@@ -517,8 +583,8 @@ CORE_ADDR
fr30_frame_saved_pc (fi)
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);
+ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
+ return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM);
else
return fr30_find_callers_reg (fi, RP_REGNUM);
}
@@ -526,9 +592,9 @@ fr30_frame_saved_pc (fi)
/* Function: fix_call_dummy
Pokes the callee function's address into the CALL_DUMMY assembly stub.
Assumes that the CALL_DUMMY looks like this:
- jarl <offset24>, r31
- trap
- */
+ jarl <offset24>, r31
+ trap
+ */
int
fr30_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
@@ -546,7 +612,7 @@ fr30_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
offset24 &= 0x3fffff;
offset24 |= 0xff800000; /* jarl <offset24>, r31 */
- store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
- store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
+ store_unsigned_integer ((unsigned int *) &dummy[2], 2, offset24 & 0xffff);
+ store_unsigned_integer ((unsigned int *) &dummy[0], 2, offset24 >> 16);
return 0;
}
diff --git a/contrib/gdb/gdb/i386-stub.c b/contrib/gdb/gdb/i386-stub.c
index 768f00c..157779c 100644
--- a/contrib/gdb/gdb/i386-stub.c
+++ b/contrib/gdb/gdb/i386-stub.c
@@ -43,7 +43,6 @@
* It should use the same privilege level it runs at. It should
* install it as an interrupt gate so that interrupts are masked
* while the handler runs.
- * Also, need to assign exceptionHook and oldExceptionHook.
*
* Because gdb will sometimes write to the stack area to execute function
* calls, this program cannot rely on using the supervisor stack so it
@@ -97,14 +96,10 @@
*
* external low-level support routines
*/
-typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
-typedef void (*Function)(); /* pointer to a function */
extern void putDebugChar(); /* write a single character */
extern int getDebugChar(); /* read and return a single char */
-
-extern Function exceptionHandler(); /* assign an exception handler */
-extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
+extern void exceptionHandler(); /* assign an exception handler */
/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
@@ -116,8 +111,6 @@ static char initialized; /* boolean flag. != 0 means we've been initialized */
int remote_debug;
/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
-void waitabit();
-
static const char hexchars[]="0123456789abcdef";
/* Number of registers. */
@@ -140,14 +133,6 @@ int registers[NUMREGS];
int remcomStack[STACKSIZE/sizeof(int)];
static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
-/*
- * In many cases, the system will want to continue exception processing
- * when a continue command is given.
- * oldExceptionHook is a function to invoke in this case.
- */
-
-static ExceptionHook oldExceptionHook;
-
/*************************** ASSEMBLY CODE MACROS *************************/
/* */
@@ -458,65 +443,85 @@ char ch;
return (-1);
}
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
/* scan for the sequence $<data>#<checksum> */
-void getpacket(buffer)
-char * buffer;
+
+unsigned char *
+getpacket ()
{
+ unsigned char *buffer = &remcomInBuffer[0];
unsigned char checksum;
unsigned char xmitcsum;
- int i;
- int count;
+ int count;
char ch;
- do {
- /* wait around for the start character, ignore all other characters */
- while ((ch = (getDebugChar() & 0x7f)) != '$');
- checksum = 0;
- xmitcsum = -1;
-
- count = 0;
-
- /* now, read until a # or end of buffer is found */
- while (count < BUFMAX) {
- ch = getDebugChar() & 0x7f;
- if (ch == '#') break;
- checksum = checksum + ch;
- buffer[count] = ch;
- count = count + 1;
- }
- buffer[count] = 0;
-
- if (ch == '#') {
- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
- xmitcsum += hex(getDebugChar() & 0x7f);
- if ((remote_debug ) && (checksum != xmitcsum)) {
- fprintf (stderr ,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
- checksum,xmitcsum,buffer);
- }
-
- if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
- else {
- putDebugChar('+'); /* successful transfer */
- /* if a sequence char is present, reply the sequence ID */
- if (buffer[2] == ':') {
- putDebugChar( buffer[0] );
- putDebugChar( buffer[1] );
- /* remove sequence chars from buffer */
- count = strlen(buffer);
- for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
- }
- }
+ while (1)
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = getDebugChar ()) != '$')
+ ;
+
+retry:
+ checksum = 0;
+ xmitcsum = -1;
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar ();
+ if (ch == '$')
+ goto retry;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ ch = getDebugChar ();
+ xmitcsum = hex (ch) << 4;
+ ch = getDebugChar ();
+ xmitcsum += hex (ch);
+
+ if (checksum != xmitcsum)
+ {
+ if (remote_debug)
+ {
+ fprintf (stderr,
+ "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum, xmitcsum, buffer);
+ }
+ putDebugChar ('-'); /* failed checksum */
+ }
+ else
+ {
+ putDebugChar ('+'); /* successful transfer */
+
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ putDebugChar (buffer[0]);
+ putDebugChar (buffer[1]);
+
+ return &buffer[3];
+ }
+
+ return &buffer[0];
+ }
+ }
}
- } while (checksum != xmitcsum);
-
}
/* send the packet in buffer. */
-
void putpacket(buffer)
-char * buffer;
+ unsigned char *buffer;
{
unsigned char checksum;
int count;
@@ -538,15 +543,10 @@ char * buffer;
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum % 16]);
- } while ((getDebugChar() & 0x7f) != '+');
+ } while (getDebugChar() != '+');
}
-char remcomInBuffer[BUFMAX];
-char remcomOutBuffer[BUFMAX];
-static short error;
-
-
void debug_error(format, parm)
char * format;
char * parm;
@@ -700,7 +700,7 @@ int hexToInt(char **ptr, int *intValue)
*/
void handle_exception(int exceptionVector)
{
- int sigval;
+ int sigval, stepping;
int addr, length;
char * ptr;
int newPC;
@@ -721,11 +721,13 @@ void handle_exception(int exceptionVector)
putpacket(remcomOutBuffer);
+ stepping = 0;
+
while (1==1) {
- error = 0;
remcomOutBuffer[0] = 0;
- getpacket(remcomInBuffer);
- switch (remcomInBuffer[0]) {
+ ptr = getpacket();
+
+ switch (*ptr++) {
case '?' : remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
@@ -737,14 +739,13 @@ void handle_exception(int exceptionVector)
mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
break;
case 'G' : /* set the value of the CPU registers - return OK */
- hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0);
+ hex2mem(ptr, (char*) registers, NUMREGBYTES, 0);
strcpy(remcomOutBuffer,"OK");
break;
case 'P' : /* set the value of a single CPU register - return OK */
{
int regno;
- ptr = &remcomInBuffer[1];
if (hexToInt (&ptr, &regno) && *ptr++ == '=')
if (regno >= 0 && regno < NUMREGS)
{
@@ -760,7 +761,6 @@ void handle_exception(int exceptionVector)
/* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
case 'm' :
/* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
- ptr = &remcomInBuffer[1];
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
@@ -777,14 +777,12 @@ void handle_exception(int exceptionVector)
if (ptr)
{
strcpy(remcomOutBuffer,"E01");
- debug_error("malformed read memory command: %s",remcomInBuffer);
}
break;
/* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
case 'M' :
/* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
- ptr = &remcomInBuffer[1];
if (hexToInt(&ptr,&addr))
if (*(ptr++) == ',')
if (hexToInt(&ptr,&length))
@@ -805,16 +803,15 @@ void handle_exception(int exceptionVector)
if (ptr)
{
strcpy(remcomOutBuffer,"E02");
- debug_error("malformed write memory command: %s",remcomInBuffer);
}
break;
/* cAA..AA Continue at address AA..AA(optional) */
/* sAA..AA Step one instruction from AA..AA(optional) */
- case 'c' :
case 's' :
+ stepping = 1;
+ case 'c' :
/* try to read optional parameter, pc unchanged if no parm */
- ptr = &remcomInBuffer[1];
if (hexToInt(&ptr,&addr))
registers[ PC ] = addr;
@@ -824,27 +821,9 @@ void handle_exception(int exceptionVector)
registers[ PS ] &= 0xfffffeff;
/* set the trace bit if we're stepping */
- if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x100;
-
- /*
- * If we found a match for the PC AND we are not returning
- * as a result of a breakpoint (33),
- * trace exception (9), nmi (31), jmp to
- * the old exception handler as if this code never ran.
- */
-#if 0
- /* Don't really think we need this, except maybe for protection
- exceptions. */
- /*
- * invoke the previous handler.
- */
- if (oldExceptionHook)
- (*oldExceptionHook) (frame->exceptionVector);
- newPC = registers[ PC ]; /* pc may have changed */
-#endif /* 0 */
+ if (stepping) registers[ PS ] |= 0x100;
_returnFromException(); /* this is a jump */
-
break;
/* kill the program */
@@ -887,18 +866,7 @@ int exception;
exceptionHandler (14, _catchException14);
exceptionHandler (16, _catchException16);
- if (exceptionHook != remcomHandler)
- {
- oldExceptionHook = exceptionHook;
- exceptionHook = remcomHandler;
- }
-
- /* In case GDB is started before us, ack any packets (presumably
- "$?#xx") sitting there. */
- putDebugChar ('+');
-
initialized = 1;
-
}
/* This function will generate a breakpoint exception. It is used at the
@@ -909,19 +877,5 @@ int exception;
void breakpoint()
{
if (initialized)
-#if 0
- handle_exception(3);
-#else
BREAKPOINT();
-#endif
- waitabit();
-}
-
-int waitlimit = 1000000;
-
-void
-waitabit()
-{
- int i;
- for (i = 0; i < waitlimit; i++) ;
}
diff --git a/contrib/gdb/gdb/kdb-start.c b/contrib/gdb/gdb/kdb-start.c
index bec558f..7a4acb7 100644
--- a/contrib/gdb/gdb/kdb-start.c
+++ b/contrib/gdb/gdb/kdb-start.c
@@ -1,27 +1,30 @@
/* 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 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 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.
+ 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. */
+ 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 *args[] =
+{"kdb", "kdb-symbols", 0};
-static char *environment[] = {0};
+static char *environment[] =
+{0};
char **environ;
diff --git a/contrib/gdb/gdb/m2-exp.tab.c b/contrib/gdb/gdb/m2-exp.tab.c
index 2bfc681..eefdf80 100644
--- a/contrib/gdb/gdb/m2-exp.tab.c
+++ b/contrib/gdb/gdb/m2-exp.tab.c
@@ -1,56 +1,56 @@
/* A Bison parser, made from m2-exp.y
- by GNU Bison version 1.25
+ by GNU Bison version 1.27
*/
#define YYBISON 1 /* Identify Bison output. */
-#define INT 258
-#define HEX 259
-#define ERROR 260
-#define UINT 261
-#define M2_TRUE 262
-#define M2_FALSE 263
-#define CHAR 264
-#define FLOAT 265
-#define STRING 266
-#define NAME 267
-#define BLOCKNAME 268
-#define IDENT 269
-#define VARNAME 270
-#define TYPENAME 271
-#define SIZE 272
-#define CAP 273
-#define ORD 274
-#define HIGH 275
-#define ABS 276
-#define MIN_FUNC 277
-#define MAX_FUNC 278
-#define FLOAT_FUNC 279
-#define VAL 280
-#define CHR 281
-#define ODD 282
-#define TRUNC 283
-#define INC 284
-#define DEC 285
-#define INCL 286
-#define EXCL 287
-#define COLONCOLON 288
-#define INTERNAL_VAR 289
-#define ABOVE_COMMA 290
-#define ASSIGN 291
-#define LEQ 292
-#define GEQ 293
-#define NOTEQUAL 294
-#define IN 295
-#define OROR 296
-#define LOGICAL_AND 297
-#define DIV 298
-#define MOD 299
-#define UNARY 300
-#define DOT 301
-#define NOT 302
-#define QID 303
+#define INT 257
+#define HEX 258
+#define ERROR 259
+#define UINT 260
+#define M2_TRUE 261
+#define M2_FALSE 262
+#define CHAR 263
+#define FLOAT 264
+#define STRING 265
+#define NAME 266
+#define BLOCKNAME 267
+#define IDENT 268
+#define VARNAME 269
+#define TYPENAME 270
+#define SIZE 271
+#define CAP 272
+#define ORD 273
+#define HIGH 274
+#define ABS 275
+#define MIN_FUNC 276
+#define MAX_FUNC 277
+#define FLOAT_FUNC 278
+#define VAL 279
+#define CHR 280
+#define ODD 281
+#define TRUNC 282
+#define INC 283
+#define DEC 284
+#define INCL 285
+#define EXCL 286
+#define COLONCOLON 287
+#define INTERNAL_VAR 288
+#define ABOVE_COMMA 289
+#define ASSIGN 290
+#define LEQ 291
+#define GEQ 292
+#define NOTEQUAL 293
+#define IN 294
+#define OROR 295
+#define LOGICAL_AND 296
+#define DIV 297
+#define MOD 298
+#define UNARY 299
+#define DOT 300
+#define NOT 301
+#define QID 302
#line 40 "m2-exp.y"
@@ -174,7 +174,7 @@ typedef union
#define YYFLAG -32768
#define YYNTBASE 68
-#define YYTRANSLATE(x) ((unsigned)(x) <= 303 ? yytranslate[x] : 82)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 302 ? yytranslate[x] : 82)
static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -202,12 +202,12 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 36,
- 37, 40, 41, 43, 45, 46, 47, 54, 55, 56,
- 58, 61, 63
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 36, 37,
+ 40, 41, 43, 45, 46, 47, 54, 55, 56, 58,
+ 61, 63
};
#if YYDEBUG != 0
@@ -540,7 +540,8 @@ static const short yycheck[] = { 0,
55, -1, 57, 58, 59, 60
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/stone/jimb/main-98r2/share/bison.simple"
+#line 3 "/usr/lib/bison.simple"
+/* This file comes from bison-1.27. */
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -557,44 +558,64 @@ static const short yycheck[] = { 0,
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
-#ifndef alloca
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
#include <alloca.h>
#else /* not sparc */
-#if defined (MSDOS) && !defined (__TURBOC__)
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for xmalloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#endif
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
#pragma alloca
-#else /* not MSDOS, __TURBOC__, or _AIX */
-#ifdef __hpux
-#ifdef __cplusplus
-extern "C" {
-void *alloca (unsigned int);
-};
-#else /* not __cplusplus */
-void *alloca ();
-#endif /* not __cplusplus */
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
#endif /* __hpux */
+#endif
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc. */
-#endif /* not GNU C. */
-#endif /* alloca not defined. */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC xmalloc
+#endif
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
@@ -604,8 +625,8 @@ void *alloca ();
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
-#define YYACCEPT return(0)
-#define YYABORT return(1)
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
This remains here temporarily to ease the
@@ -686,12 +707,12 @@ int yydebug; /* nonzero means print parse trace */
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-int yyparse (void);
-#endif
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
@@ -703,7 +724,7 @@ static void
__yy_memcpy (to, from, count)
char *to;
char *from;
- int count;
+ unsigned int count;
{
register char *f = from;
register char *t = to;
@@ -718,10 +739,10 @@ __yy_memcpy (to, from, count)
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
-__yy_memcpy (char *to, char *from, int count)
+__yy_memcpy (char *to, char *from, unsigned int count)
{
- register char *f = from;
register char *t = to;
+ register char *f = from;
register int i = count;
while (i-- > 0)
@@ -731,7 +752,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif
#endif
-#line 196 "/stone/jimb/main-98r2/share/bison.simple"
+#line 216 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -752,6 +773,15 @@ __yy_memcpy (char *to, char *from, int count)
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
int
yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
@@ -780,6 +810,7 @@ yyparse(YYPARSE_PARAM_ARG)
#endif
int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
#ifdef YYPURE
int yychar;
@@ -864,18 +895,32 @@ yynewstate:
if (yystacksize >= YYMAXDEPTH)
{
yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
return 2;
}
yystacksize *= 2;
if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH;
- yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
- __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp));
- yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
- __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp));
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
- __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp));
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
@@ -1439,7 +1484,7 @@ case 79:
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 498 "/stone/jimb/main-98r2/share/bison.simple"
+#line 542 "/usr/lib/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
@@ -1634,6 +1679,30 @@ yyerrhandle:
yystate = yyn;
goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
}
#line 644 "m2-exp.y"
@@ -2045,6 +2114,10 @@ yylex ()
case LOC_LABEL:
case LOC_UNRESOLVED:
error("internal: Unforseen case in m2lex()");
+
+ default:
+ error ("unhandled token in m2lex()");
+ break;
}
}
else
diff --git a/contrib/gdb/gdb/monitor.c b/contrib/gdb/gdb/monitor.c
index dc47d8c..b857bbc 100644
--- a/contrib/gdb/gdb/monitor.c
+++ b/contrib/gdb/gdb/monitor.c
@@ -1,24 +1,24 @@
/* Remote debugging interface for boot monitors, for GDB.
- Copyright 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1999
- Free Software Foundation, Inc.
+ Copyright 1990-1993, 1995-1997, 1999-2000 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
Resurrected from the ashes by Stu Grossman.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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 was derived from various remote-* modules. It is a collection
of generic support functions so GDB can talk directly to a ROM based
@@ -40,12 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
-#include "wait.h"
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
+#include "gdb_wait.h"
#include <signal.h>
#include <ctype.h>
#include "gdb_string.h"
@@ -55,7 +50,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "monitor.h"
#include "gdbcmd.h"
#include "inferior.h"
-#include "gnu-regex.h"
+#include "gdb_regex.h"
#include "dcache.h"
#include "srec.h"
@@ -66,13 +61,11 @@ static void monitor_vsprintf PARAMS ((char *sndbuf, char *pattern, va_list args)
static int readchar PARAMS ((int timeout));
-static void monitor_command PARAMS ((char *args, int fromtty));
-
static void monitor_fetch_register PARAMS ((int regno));
static void monitor_store_register PARAMS ((int regno));
-static int monitor_printable_string PARAMS ((char *newstr, char *oldstr));
-static void monitor_error PARAMS ((char *format, CORE_ADDR memaddr, int len, char *string, int final_char));
+static void monitor_printable_string (char *newstr, char *oldstr, int len);
+static void monitor_error (char *function, char *message, CORE_ADDR memaddr, int len, char *string, int final_char);
static void monitor_detach PARAMS ((char *args, int from_tty));
static void monitor_resume PARAMS ((int pid, int step, enum target_signal sig));
static void monitor_interrupt PARAMS ((int signo));
@@ -80,12 +73,12 @@ static void monitor_interrupt_twice PARAMS ((int signo));
static void monitor_interrupt_query PARAMS ((void));
static void monitor_wait_cleanup PARAMS ((void *old_timeout));
-static int monitor_wait PARAMS ((int pid, struct target_waitstatus *status));
+static int monitor_wait PARAMS ((int pid, struct target_waitstatus * status));
static void monitor_fetch_registers PARAMS ((int regno));
static void monitor_store_registers PARAMS ((int regno));
static void monitor_prepare_to_store PARAMS ((void));
-static int monitor_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *target));
-static void monitor_files_info PARAMS ((struct target_ops *ops));
+static int monitor_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops * target));
+static void monitor_files_info PARAMS ((struct target_ops * ops));
static int monitor_insert_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
static int monitor_remove_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
static void monitor_kill PARAMS ((void));
@@ -93,17 +86,17 @@ static void monitor_load PARAMS ((char *file, int from_tty));
static void monitor_mourn_inferior PARAMS ((void));
static void monitor_stop PARAMS ((void));
-static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
-static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr, int len));
+static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr, int len));
static int monitor_write_memory_bytes PARAMS ((CORE_ADDR addr,
- char *myaddr,int len));
-static int monitor_write_memory_block PARAMS((
- CORE_ADDR memaddr ,
- char * myaddr ,
- int len)) ;
-static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
+ char *myaddr, int len));
+static int monitor_write_memory_block PARAMS ((
+ CORE_ADDR memaddr,
+ char *myaddr,
+ int len));
+static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer * pat,
char *buf, int buflen));
-static void monitor_dump_regs PARAMS((void)) ;
+static void monitor_dump_regs PARAMS ((void));
#if 0
static int from_hex PARAMS ((int a));
static unsigned long get_hex_word PARAMS ((void));
@@ -118,13 +111,9 @@ static int timeout = 30;
static int in_monitor_wait = 0; /* Non-zero means we are in monitor_wait() */
-static void (*ofunc)(); /* Old SIGINT signal handler */
+static void (*ofunc) (); /* Old SIGINT signal handler */
-/* Extra remote debugging for developing a new rom monitor variation */
-#if ! defined(EXTRA_RDEBUG)
-#define EXTRA_RDEBUG 0
-#endif
-#define RDEBUG(stuff) { if (EXTRA_RDEBUG && remote_debug) printf stuff ; }
+static CORE_ADDR *breakaddr;
/* Descriptor for I/O to remote machine. Initialize it to NULL so
that monitor_open knows that we don't have a file open when the
@@ -144,24 +133,53 @@ static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when
monitor_wait wakes up. */
static DCACHE *remote_dcache;
-static int first_time=0; /* is this the first time we're executing after
- gaving created the child proccess? */
+static int first_time = 0; /* is this the first time we're executing after
+ gaving created the child proccess? */
-/* Convert a string into a printable representation, Return # byte in the
- new string. */
+#define TARGET_BUF_SIZE 2048
-static int
-monitor_printable_string (newstr, oldstr)
- char *newstr;
- char *oldstr;
+/* Monitor specific debugging information. Typically only useful to
+ the developer of a new monitor interface. */
+
+static void monitor_debug (const char *fmt, ...) ATTR_FORMAT(printf, 1, 2);
+
+static int monitor_debug_p = 0;
+
+/* NOTE: This file alternates between monitor_debug_p and remote_debug
+ when determining if debug information is printed. Perhaphs this
+ could be simplified. */
+
+static void
+monitor_debug (const char *fmt, ...)
+{
+ if (monitor_debug_p)
+ {
+ va_list args;
+ va_start (args, fmt);
+ vfprintf_filtered (gdb_stdlog, fmt, args);
+ va_end (args);
+ }
+}
+
+
+/* Convert a string into a printable representation, Return # byte in
+ the new string. When LEN is >0 it specifies the size of the
+ string. Otherwize strlen(oldstr) is used. */
+
+static void
+monitor_printable_string (char *newstr, char *oldstr, int len)
{
- char *save = newstr;
int ch;
+ int i;
- while ((ch = *oldstr++) != '\0')
+ if (len <= 0)
+ len = strlen (oldstr);
+
+ for (i = 0; i < len; i++)
{
+ ch = oldstr[i];
switch (ch)
- {
+ {
default:
if (isprint (ch))
*newstr++ = ch;
@@ -173,41 +191,55 @@ monitor_printable_string (newstr, oldstr)
}
break;
- case '\\': *newstr++ = '\\'; *newstr++ = '\\'; break;
- case '\b': *newstr++ = '\\'; *newstr++ = 'b'; break;
- case '\f': *newstr++ = '\\'; *newstr++ = 't'; break;
- case '\n': *newstr++ = '\\'; *newstr++ = 'n'; break;
- case '\r': *newstr++ = '\\'; *newstr++ = 'r'; break;
- case '\t': *newstr++ = '\\'; *newstr++ = 't'; break;
- case '\v': *newstr++ = '\\'; *newstr++ = 'v'; break;
- }
+ case '\\':
+ *newstr++ = '\\';
+ *newstr++ = '\\';
+ break;
+ case '\b':
+ *newstr++ = '\\';
+ *newstr++ = 'b';
+ break;
+ case '\f':
+ *newstr++ = '\\';
+ *newstr++ = 't';
+ break;
+ case '\n':
+ *newstr++ = '\\';
+ *newstr++ = 'n';
+ break;
+ case '\r':
+ *newstr++ = '\\';
+ *newstr++ = 'r';
+ break;
+ case '\t':
+ *newstr++ = '\\';
+ *newstr++ = 't';
+ break;
+ case '\v':
+ *newstr++ = '\\';
+ *newstr++ = 'v';
+ break;
+ }
}
*newstr++ = '\0';
- return newstr - save;
}
/* Print monitor errors with a string, converting the string to printable
representation. */
static void
-monitor_error (format, memaddr, len, string, final_char)
- char *format;
- CORE_ADDR memaddr;
- int len;
- char *string;
- int final_char;
+monitor_error (char *function, char *message,
+ CORE_ADDR memaddr, int len, char *string, int final_char)
{
- int real_len = (len == 0 && string != (char *)0) ? strlen (string) : len;
+ int real_len = (len == 0 && string != (char *) 0) ? strlen (string) : len;
char *safe_string = alloca ((real_len * 4) + 1);
- char *p, *q;
- int ch;
- int safe_len = monitor_printable_string (safe_string, string);
+ monitor_printable_string (safe_string, string, real_len);
if (final_char)
- error (format, (int)memaddr, p - safe_string, safe_string, final_char);
+ error ("%s (0x%s): %s: %s%c", function, paddr_nz (memaddr), message, safe_string, final_char);
else
- error (format, (int)memaddr, p - safe_string, safe_string);
+ error ("%s (0x%s): %s: %s", function, paddr_nz (memaddr), message, safe_string);
}
/* Convert hex digit A to a number. */
@@ -220,10 +252,10 @@ fromhex (a)
return a - '0';
else if (a >= 'a' && a <= 'f')
return a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
else
- if (a >= 'A' && a <= 'F')
- return a - 'A' + 10 ;
- else error ("Invalid hex digit %d", a);
+ error ("Invalid hex digit %d", a);
}
/* monitor_vsprintf - similar to vsprintf but handles 64-bit addresses
@@ -238,8 +270,8 @@ fromhex (a)
argument is assumed to be a long integer.
%% is also turned into a single %.
-*/
-
+ */
+
static void
monitor_vsprintf (sndbuf, pattern, args)
char *sndbuf;
@@ -264,7 +296,7 @@ monitor_vsprintf (sndbuf, pattern, args)
i++, p++)
format[i] = *p;
format[i] = fmt = *p;
- format[i+1] = '\0';
+ format[i + 1] = '\0';
/* Fetch the next argument and print it. */
switch (fmt)
@@ -298,24 +330,13 @@ monitor_vsprintf (sndbuf, pattern, args)
Works just like printf. */
void
-#ifdef ANSI_PROTOTYPES
-monitor_printf_noecho (char *pattern, ...)
-#else
-monitor_printf_noecho (va_alist)
- va_dcl
-#endif
+monitor_printf_noecho (char *pattern,...)
{
va_list args;
char sndbuf[2000];
int len;
-#if ANSI_PROTOTYPES
va_start (args, pattern);
-#else
- char *pattern;
- va_start (args);
- pattern = va_arg (args, char *);
-#endif
monitor_vsprintf (sndbuf, pattern, args);
@@ -323,18 +344,13 @@ monitor_printf_noecho (va_alist)
if (len + 1 > sizeof sndbuf)
abort ();
-#if 0
- if (remote_debug > 0)
- puts_debug ("sent -->", sndbuf, "<--");
-#endif
- if (EXTRA_RDEBUG
- && remote_debug)
+ if (monitor_debug_p)
{
char *safe_string = (char *) alloca ((strlen (sndbuf) * 4) + 1);
- monitor_printable_string (safe_string, sndbuf);
- printf ("sent[%s]\n", safe_string);
+ monitor_printable_string (safe_string, sndbuf, 0);
+ fprintf_unfiltered (gdb_stdlog, "sent[%s]\n", safe_string);
}
-
+
monitor_write (sndbuf, len);
}
@@ -342,24 +358,13 @@ monitor_printf_noecho (va_alist)
printf. */
void
-#ifdef ANSI_PROTOTYPES
-monitor_printf (char *pattern, ...)
-#else
-monitor_printf (va_alist)
- va_dcl
-#endif
+monitor_printf (char *pattern,...)
{
va_list args;
char sndbuf[2000];
int len;
-#ifdef ANSI_PROTOTYPES
va_start (args, pattern);
-#else
- char *pattern;
- va_start (args);
- pattern = va_arg (args, char *);
-#endif
monitor_vsprintf (sndbuf, pattern, args);
@@ -367,16 +372,11 @@ monitor_printf (va_alist)
if (len + 1 > sizeof sndbuf)
abort ();
-#if 0
- if (remote_debug > 0)
- puts_debug ("sent -->", sndbuf, "<--");
-#endif
- if (EXTRA_RDEBUG
- && remote_debug)
+ if (monitor_debug_p)
{
char *safe_string = (char *) alloca ((len * 4) + 1);
- monitor_printable_string (safe_string, sndbuf);
- printf ("sent[%s]\n", safe_string);
+ monitor_printable_string (safe_string, sndbuf, 0);
+ fprintf_unfiltered (gdb_stdlog, "sent[%s]\n", safe_string);
}
monitor_write (sndbuf, len);
@@ -385,8 +385,8 @@ monitor_printf (va_alist)
just output, but sometimes some extra junk appeared before the characters
we expected, like an extra prompt, or a portmaster sending telnet negotiations.
So, just start searching for what we sent, and skip anything unknown. */
- RDEBUG(("ExpectEcho\n"))
- monitor_expect (sndbuf, (char *)0, 0);
+ monitor_debug ("ExpectEcho\n");
+ monitor_expect (sndbuf, (char *) 0, 0);
}
@@ -397,7 +397,7 @@ monitor_write (buf, buflen)
char *buf;
int buflen;
{
- if (SERIAL_WRITE(monitor_desc, buf, buflen))
+ if (SERIAL_WRITE (monitor_desc, buf, buflen))
fprintf_unfiltered (gdb_stderr, "SERIAL_WRITE failed: %s\n",
safe_strerror (errno));
}
@@ -419,7 +419,7 @@ monitor_readchar ()
c = SERIAL_READCHAR (monitor_desc, timeout);
if (c >= 0)
- c &= 0xff; /* don't lose bit 7 */
+ c &= 0xff; /* don't lose bit 7 */
}
while (looping);
@@ -427,7 +427,7 @@ monitor_readchar ()
return c;
if (c == SERIAL_TIMEOUT)
- error ("Timeout reading from remote system.");
+ error ("Timeout reading from remote system.");
perror_with_name ("remote-monitor");
}
@@ -441,7 +441,11 @@ readchar (timeout)
int timeout;
{
int c;
- static enum { last_random, last_nl, last_cr, last_crnl } state = last_random;
+ static enum
+ {
+ last_random, last_nl, last_cr, last_crnl
+ }
+ state = last_random;
int looping;
do
@@ -452,18 +456,16 @@ readchar (timeout)
if (c >= 0)
{
c &= 0x7f;
-#if 0
/* This seems to interfere with proper function of the
input stream */
- if (remote_debug > 0)
+ if (monitor_debug_p || remote_debug)
{
char buf[2];
buf[0] = c;
buf[1] = '\0';
puts_debug ("read -->", buf, "<--");
}
-
-#endif
+
}
/* Canonicialize \n\r combinations into one \r */
@@ -492,7 +494,7 @@ readchar (timeout)
return c;
if (c == SERIAL_TIMEOUT)
-#if 0 /* MAINTENANCE_CMDS */
+#if 0
/* I fail to see how detaching here can be useful */
if (in_monitor_wait) /* Watchdog went off */
{
@@ -524,12 +526,11 @@ monitor_expect (string, buf, buflen)
int c;
extern struct target_ops *targ_ops;
- if (EXTRA_RDEBUG
- && remote_debug)
+ if (monitor_debug_p)
{
char *safe_string = (char *) alloca ((strlen (string) * 4) + 1);
- monitor_printable_string (safe_string, string);
- printf ("MON Expecting '%s'\n", safe_string);
+ monitor_printable_string (safe_string, string, 0);
+ fprintf_unfiltered (gdb_stdlog, "MON Expecting '%s'\n", safe_string);
}
immediate_quit = 1;
@@ -554,7 +555,7 @@ monitor_expect (string, buf, buflen)
c = readchar (timeout);
/* Don't expect any ^C sent to be echoed */
-
+
if (*p == '\003' || c == *p)
{
p++;
@@ -574,14 +575,48 @@ monitor_expect (string, buf, buflen)
else if ((c == '\021' || c == '\023') &&
(STREQ (targ_ops->to_shortname, "m32r")
|| STREQ (targ_ops->to_shortname, "mon2000")))
- { /* m32r monitor emits random DC1/DC3 chars */
+ { /* m32r monitor emits random DC1/DC3 chars */
continue;
}
else
{
- p = string;
- if (c == *p)
- p++;
+ /* We got a character that doesn't match the string. We need to
+ back up p, but how far? If we're looking for "..howdy" and the
+ monitor sends "...howdy"? There's certainly a match in there,
+ but when we receive the third ".", we won't find it if we just
+ restart the matching at the beginning of the string.
+
+ This is a Boyer-Moore kind of situation. We want to reset P to
+ the end of the longest prefix of STRING that is a suffix of
+ what we've read so far. In the example above, that would be
+ ".." --- the longest prefix of "..howdy" that is a suffix of
+ "...". This longest prefix could be the empty string, if C
+ is nowhere to be found in STRING.
+
+ If this longest prefix is not the empty string, it must contain
+ C, so let's search from the end of STRING for instances of C,
+ and see if the portion of STRING before that is a suffix of
+ what we read before C. Actually, we can search backwards from
+ p, since we know no prefix can be longer than that.
+
+ Note that we can use STRING itself, along with C, as a record
+ of what we've received so far. :) */
+ int i;
+
+ for (i = (p - string) - 1; i >= 0; i--)
+ if (string[i] == c)
+ {
+ /* Is this prefix a suffix of what we've read so far?
+ In other words, does
+ string[0 .. i-1] == string[p - i, p - 1]? */
+ if (! memcmp (string, p - i, i))
+ {
+ p = string + i + 1;
+ break;
+ }
+ }
+ if (i < 0)
+ p = string;
}
}
}
@@ -596,13 +631,13 @@ monitor_expect_regexp (pat, buf, buflen)
{
char *mybuf;
char *p;
- RDEBUG(("MON Expecting regexp\n")) ;
+ monitor_debug ("MON Expecting regexp\n");
if (buf)
mybuf = buf;
else
{
- mybuf = alloca (1024);
- buflen = 1024;
+ mybuf = alloca (TARGET_BUF_SIZE);
+ buflen = TARGET_BUF_SIZE;
}
p = mybuf;
@@ -647,7 +682,7 @@ monitor_expect_prompt (buf, buflen)
char *buf;
int buflen;
{
- RDEBUG(("MON Expecting prompt\n"))
+ monitor_debug ("MON Expecting prompt\n");
return monitor_expect (current_monitor->prompt, buf, buflen);
}
@@ -664,7 +699,7 @@ get_hex_word ()
do
ch = readchar (timeout);
- while (isspace(ch));
+ while (isspace (ch));
val = from_hex (ch);
@@ -757,7 +792,7 @@ monitor_open (args, mon_ops, from_tty)
perror_with_name (dev_name);
}
}
-
+
SERIAL_RAW (monitor_desc);
SERIAL_FLUSH_INPUT (monitor_desc);
@@ -775,27 +810,37 @@ monitor_open (args, mon_ops, from_tty)
{
monitor_stop ();
if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
- {
- RDEBUG(("EXP Open echo\n")) ;
- monitor_expect_prompt (NULL, 0);
- }
+ {
+ monitor_debug ("EXP Open echo\n");
+ monitor_expect_prompt (NULL, 0);
+ }
}
/* wake up the monitor and see if it's alive */
for (p = mon_ops->init; *p != NULL; p++)
{
/* Some of the characters we send may not be echoed,
- but we hope to get a prompt at the end of it all. */
-
+ but we hope to get a prompt at the end of it all. */
+
if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
- monitor_printf(*p);
+ monitor_printf (*p);
else
- monitor_printf_noecho (*p);
+ monitor_printf_noecho (*p);
monitor_expect_prompt (NULL, 0);
}
SERIAL_FLUSH_INPUT (monitor_desc);
+ /* Alloc breakpoints */
+ if (mon_ops->set_break != NULL)
+ {
+ if (mon_ops->num_breakpoints == 0)
+ mon_ops->num_breakpoints = 8;
+
+ breakaddr = (CORE_ADDR *) xmalloc (mon_ops->num_breakpoints * sizeof (CORE_ADDR));
+ memset (breakaddr, 0, mon_ops->num_breakpoints * sizeof (CORE_ADDR));
+ }
+
/* Remove all breakpoints */
if (mon_ops->clr_all_break)
@@ -831,6 +876,14 @@ monitor_close (quitting)
{
if (monitor_desc)
SERIAL_CLOSE (monitor_desc);
+
+ /* Free breakpoint memory */
+ if (breakaddr != NULL)
+ {
+ free (breakaddr);
+ breakaddr = NULL;
+ }
+
monitor_desc = NULL;
}
@@ -854,14 +907,36 @@ monitor_supply_register (regno, valstr)
int regno;
char *valstr;
{
- unsigned int val;
+ ULONGEST val;
unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
char *p;
- val = strtoul (valstr, &p, 16);
- RDEBUG(("Supplying Register %d %s\n",regno,valstr)) ;
+ val = 0;
+ p = valstr;
+ while (p && *p != '\0')
+ {
+ if (*p == '\r' || *p == '\n')
+ {
+ while (*p != '\0')
+ p++;
+ break;
+ }
+ if (isspace (*p))
+ {
+ p++;
+ continue;
+ }
+ if (!isxdigit (*p) && *p != 'x')
+ {
+ break;
+ }
+
+ val <<= 4;
+ val += fromhex (*p++);
+ }
+ monitor_debug ("Supplying Register %d %s\n", regno, valstr);
- if (val == 0 && valstr == p)
+ if (*p != '\0')
error ("monitor_supply_register (%d): bad value from monitor: %s.",
regno, valstr);
@@ -888,13 +963,13 @@ monitor_resume (pid, step, sig)
enum target_signal sig;
{
/* Some monitors require a different command when starting a program */
- RDEBUG(("MON resume\n")) ;
+ monitor_debug ("MON resume\n");
if (current_monitor->flags & MO_RUN_FIRST_TIME && first_time == 1)
{
first_time = 0;
monitor_printf ("run\r");
if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
- dump_reg_flag = 1;
+ dump_reg_flag = 1;
return;
}
dcache_flush (remote_dcache);
@@ -903,8 +978,9 @@ monitor_resume (pid, step, sig)
else
{
if (current_monitor->continue_hook)
- (*current_monitor->continue_hook)() ;
- else monitor_printf (current_monitor->cont);
+ (*current_monitor->continue_hook) ();
+ else
+ monitor_printf (current_monitor->cont);
if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
dump_reg_flag = 1;
}
@@ -920,13 +996,13 @@ parse_register_dump (buf, len)
char *buf;
int len;
{
- RDEBUG(("MON Parsing register dump\n"))
+ monitor_debug ("MON Parsing register dump\n");
while (1)
{
int regnamelen, vallen;
char *regname, *val;
/* Element 0 points to start of register name, and element 1
- points to the start of the register value. */
+ points to the start of the register value. */
struct re_registers register_strings;
memset (&register_strings, 0, sizeof (struct re_registers));
@@ -956,9 +1032,9 @@ monitor_interrupt (signo)
{
/* If this doesn't work, try more severe steps. */
signal (signo, monitor_interrupt_twice);
-
- if (remote_debug)
- printf_unfiltered ("monitor_interrupt called\n");
+
+ if (monitor_debug_p || remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "monitor_interrupt called\n");
target_stop ();
}
@@ -970,7 +1046,7 @@ monitor_interrupt_twice (signo)
int signo;
{
signal (signo, ofunc);
-
+
monitor_interrupt_query ();
signal (signo, monitor_interrupt);
@@ -997,24 +1073,25 @@ static void
monitor_wait_cleanup (old_timeout)
void *old_timeout;
{
- timeout = *(int*)old_timeout;
+ timeout = *(int *) old_timeout;
signal (SIGINT, ofunc);
in_monitor_wait = 0;
}
-void monitor_wait_filter(char * buf,
- int bufmax,
- int * ext_resp_len,
- struct target_waitstatus * status
- )
+void
+monitor_wait_filter (char *buf,
+ int bufmax,
+ int *ext_resp_len,
+ struct target_waitstatus *status
+)
{
- int resp_len ;
+ int resp_len;
do
{
resp_len = monitor_expect_prompt (buf, bufmax);
- * ext_resp_len =resp_len ;
+ *ext_resp_len = resp_len;
if (resp_len <= 0)
fprintf_unfiltered (gdb_stderr, "monitor_wait: excessive response from monitor: %s.", buf);
@@ -1023,8 +1100,8 @@ void monitor_wait_filter(char * buf,
/* Print any output characters that were preceded by ^O. */
/* FIXME - This would be great as a user settabgle flag */
- if (remote_debug ||
- current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
+ if (monitor_debug_p || remote_debug
+ || current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
{
int i;
@@ -1045,7 +1122,7 @@ monitor_wait (pid, status)
struct target_waitstatus *status;
{
int old_timeout = timeout;
- char buf[1024];
+ char buf[TARGET_BUF_SIZE];
int resp_len;
struct cleanup *old_chain;
@@ -1053,11 +1130,11 @@ monitor_wait (pid, status)
status->value.integer = 0;
old_chain = make_cleanup (monitor_wait_cleanup, &old_timeout);
- RDEBUG(("MON wait\n"))
+ monitor_debug ("MON wait\n");
-#if 0 /* MAINTENANCE_CMDS */
- /* This is somthing other than a maintenance command */
- in_monitor_wait = 1;
+#if 0
+ /* This is somthing other than a maintenance command */
+ in_monitor_wait = 1;
timeout = watchdog > 0 ? watchdog : -1;
#else
timeout = -1; /* Don't time out -- user program is running. */
@@ -1066,10 +1143,11 @@ monitor_wait (pid, status)
ofunc = (void (*)()) signal (SIGINT, monitor_interrupt);
if (current_monitor->wait_filter)
- (*current_monitor->wait_filter)(buf,sizeof (buf),&resp_len,status) ;
- else monitor_wait_filter(buf,sizeof (buf),&resp_len,status) ;
-
-#if 0 /* Transferred to monitor wait filter */
+ (*current_monitor->wait_filter) (buf, sizeof (buf), &resp_len, status);
+ else
+ monitor_wait_filter (buf, sizeof (buf), &resp_len, status);
+
+#if 0 /* Transferred to monitor wait filter */
do
{
resp_len = monitor_expect_prompt (buf, sizeof (buf));
@@ -1081,8 +1159,8 @@ monitor_wait (pid, status)
/* Print any output characters that were preceded by ^O. */
/* FIXME - This would be great as a user settabgle flag */
- if (remote_debug ||
- current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
+ if (monitor_debug_p || remote_debug
+ || current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
{
int i;
@@ -1090,7 +1168,7 @@ monitor_wait (pid, status)
if (buf[i] == 0x0f)
putchar_unfiltered (buf[++i]);
}
-#endif
+#endif
signal (SIGINT, ofunc);
@@ -1106,9 +1184,9 @@ monitor_wait (pid, status)
if (current_monitor->register_pattern)
parse_register_dump (buf, resp_len);
#else
- RDEBUG(("Wait fetching registers after stop\n")) ;
- monitor_dump_regs() ;
-#endif
+ monitor_debug ("Wait fetching registers after stop\n");
+ monitor_dump_regs ();
+#endif
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
@@ -1128,15 +1206,17 @@ monitor_fetch_register (regno)
int regno;
{
char *name;
- static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] =
+ {0};
char regbuf[MAX_REGISTER_RAW_SIZE * 2 + 1];
int i;
name = current_monitor->regnames[regno];
- RDEBUG(("MON fetchreg %d '%s'\n",regno,name))
+ monitor_debug ("MON fetchreg %d '%s'\n", regno, name ? name : "(null name)");
if (!name || (*name == '\0'))
- { RDEBUG(("No register known for %d\n",regno))
+ {
+ monitor_debug ("No register known for %d\n", regno);
supply_register (regno, zerobuf);
return;
}
@@ -1151,18 +1231,19 @@ monitor_fetch_register (regno)
if (current_monitor->getreg.resp_delim)
{
- RDEBUG(("EXP getreg.resp_delim\n"))
+ monitor_debug ("EXP getreg.resp_delim\n");
monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
/* Handle case of first 32 registers listed in pairs. */
if (current_monitor->flags & MO_32_REGS_PAIRED
- && regno & 1 == 1 && regno < 32)
- { RDEBUG(("EXP getreg.resp_delim\n")) ;
+ && (regno & 1) != 0 && regno < 32)
+ {
+ monitor_debug ("EXP getreg.resp_delim\n");
monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
}
}
/* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
- if (current_monitor->flags & MO_HEX_PREFIX)
+ if (current_monitor->flags & MO_HEX_PREFIX)
{
int c;
c = readchar (timeout);
@@ -1171,8 +1252,8 @@ monitor_fetch_register (regno)
if ((c == '0') && ((c = readchar (timeout)) == 'x'))
;
else
- error ("Bad value returned from monitor while fetching register %x.",
- regno);
+ error ("Bad value returned from monitor while fetching register %x.",
+ regno);
}
/* Read upto the maximum number of hex digits for this register, skipping
@@ -1193,7 +1274,7 @@ monitor_fetch_register (regno)
}
regbuf[i] = '\000'; /* terminate the number */
- RDEBUG(("REGVAL '%s'\n",regbuf)) ;
+ monitor_debug ("REGVAL '%s'\n", regbuf);
/* If TERM is present, we wait for that to show up. Also, (if TERM
is present), we will send TERM_CMD if that is present. In any
@@ -1202,17 +1283,18 @@ monitor_fetch_register (regno)
if (current_monitor->getreg.term)
{
- RDEBUG(("EXP getreg.term\n"))
- monitor_expect (current_monitor->getreg.term, NULL, 0); /* get response */
+ monitor_debug ("EXP getreg.term\n");
+ monitor_expect (current_monitor->getreg.term, NULL, 0); /* get response */
}
if (current_monitor->getreg.term_cmd)
- { RDEBUG(("EMIT getreg.term.cmd\n"))
- monitor_printf (current_monitor->getreg.term_cmd);
+ {
+ monitor_debug ("EMIT getreg.term.cmd\n");
+ monitor_printf (current_monitor->getreg.term_cmd);
}
- if (! current_monitor->getreg.term || /* Already expected or */
- current_monitor->getreg.term_cmd) /* ack expected */
- monitor_expect_prompt (NULL, 0); /* get response */
+ if (!current_monitor->getreg.term || /* Already expected or */
+ current_monitor->getreg.term_cmd) /* ack expected */
+ monitor_expect_prompt (NULL, 0); /* get response */
monitor_supply_register (regno, regbuf);
}
@@ -1220,15 +1302,16 @@ monitor_fetch_register (regno)
/* Sometimes, it takes several commands to dump the registers */
/* This is a primitive for use by variations of monitor interfaces in
case they need to compose the operation.
- */
-int monitor_dump_reg_block(char * block_cmd)
+ */
+int
+monitor_dump_reg_block (char *block_cmd)
{
- char buf[1024];
+ char buf[TARGET_BUF_SIZE];
int resp_len;
monitor_printf (block_cmd);
resp_len = monitor_expect_prompt (buf, sizeof (buf));
parse_register_dump (buf, resp_len);
- return 1 ;
+ return 1;
}
@@ -1238,26 +1321,26 @@ int monitor_dump_reg_block(char * block_cmd)
static void
monitor_dump_regs ()
{
- char buf[1024];
+ char buf[TARGET_BUF_SIZE];
int resp_len;
if (current_monitor->dumpregs)
- (*(current_monitor->dumpregs))() ; /* call supplied function */
- else
- if (current_monitor->dump_registers) /* default version */
- { monitor_printf (current_monitor->dump_registers);
+ (*(current_monitor->dumpregs)) (); /* call supplied function */
+ else if (current_monitor->dump_registers) /* default version */
+ {
+ monitor_printf (current_monitor->dump_registers);
resp_len = monitor_expect_prompt (buf, sizeof (buf));
parse_register_dump (buf, resp_len);
}
else
- abort(); /* Need some way to read registers */
+ abort (); /* Need some way to read registers */
}
static void
monitor_fetch_registers (regno)
int regno;
{
- RDEBUG(("MON fetchregs\n")) ;
- if (current_monitor->getreg.cmd)
+ monitor_debug ("MON fetchregs\n");
+ if (current_monitor->getreg.cmd)
{
if (regno >= 0)
{
@@ -1268,9 +1351,10 @@ monitor_fetch_registers (regno)
for (regno = 0; regno < NUM_REGS; regno++)
monitor_fetch_register (regno);
}
- else {
- monitor_dump_regs ();
- }
+ else
+ {
+ monitor_dump_regs ();
+ }
}
/* Store register REGNO, or all if REGNO == 0. Return errno value. */
@@ -1280,16 +1364,17 @@ monitor_store_register (regno)
int regno;
{
char *name;
- unsigned int val;
+ ULONGEST val;
name = current_monitor->regnames[regno];
if (!name || (*name == '\0'))
- { RDEBUG(("MON Cannot store unknown register\n"))
+ {
+ monitor_debug ("MON Cannot store unknown register\n");
return;
}
val = read_register (regno);
- RDEBUG(("MON storeg %d %08x\n",regno,(unsigned int)val))
+ monitor_debug ("MON storeg %d %s\n", regno, preg (val));
/* send the register deposit command */
@@ -1301,20 +1386,22 @@ monitor_store_register (regno)
monitor_printf (current_monitor->setreg.cmd, name, val);
if (current_monitor->setreg.term)
- { RDEBUG(("EXP setreg.term\n"))
+ {
+ monitor_debug ("EXP setreg.term\n");
monitor_expect (current_monitor->setreg.term, NULL, 0);
if (current_monitor->flags & MO_SETREG_INTERACTIVE)
- monitor_printf ("%x\r", val);
+ monitor_printf ("%s\r", paddr_nz (val));
monitor_expect_prompt (NULL, 0);
}
else
monitor_expect_prompt (NULL, 0);
- if (current_monitor->setreg.term_cmd) /* Mode exit required */
- { RDEBUG(("EXP setreg_termcmd\n")) ;
- monitor_printf("%s",current_monitor->setreg.term_cmd) ;
- monitor_expect_prompt(NULL,0) ;
+ if (current_monitor->setreg.term_cmd) /* Mode exit required */
+ {
+ monitor_debug ("EXP setreg_termcmd\n");
+ monitor_printf ("%s", current_monitor->setreg.term_cmd);
+ monitor_expect_prompt (NULL, 0);
}
-} /* monitor_store_register */
+} /* monitor_store_register */
/* Store the remote registers. */
@@ -1357,11 +1444,11 @@ monitor_write_memory (memaddr, myaddr, len)
char *myaddr;
int len;
{
- unsigned int val, hostval ;
+ unsigned int val, hostval;
char *cmd;
int i;
- RDEBUG(("MON write %d %08x\n",len,(unsigned long)memaddr))
+ monitor_debug ("MON write %d %s\n", len, paddr (memaddr));
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
memaddr = ADDR_BITS_REMOVE (memaddr);
@@ -1376,11 +1463,11 @@ monitor_write_memory (memaddr, myaddr, len)
if (i > 4) /* More than 4 zeros is worth doing */
{
- RDEBUG(("MON FILL %d\n",i))
- if (current_monitor->flags & MO_FILL_USES_ADDR)
- monitor_printf (current_monitor->fill, memaddr, (memaddr + i)-1, 0);
- else
- monitor_printf (current_monitor->fill, memaddr, i, 0);
+ monitor_debug ("MON FILL %d\n", i);
+ if (current_monitor->flags & MO_FILL_USES_ADDR)
+ monitor_printf (current_monitor->fill, memaddr, (memaddr + i) - 1, 0);
+ else
+ monitor_printf (current_monitor->fill, memaddr, i, 0);
monitor_expect_prompt (NULL, 0);
@@ -1414,10 +1501,11 @@ monitor_write_memory (memaddr, myaddr, len)
}
val = extract_unsigned_integer (myaddr, len);
-
+
if (len == 4)
- { hostval = * (unsigned int *) myaddr ;
- RDEBUG(("Hostval(%08x) val(%08x)\n",hostval,val)) ;
+ {
+ hostval = *(unsigned int *) myaddr;
+ monitor_debug ("Hostval(%08x) val(%08x)\n", hostval, val);
}
@@ -1429,13 +1517,14 @@ monitor_write_memory (memaddr, myaddr, len)
monitor_printf_noecho (cmd, memaddr);
if (current_monitor->setmem.term)
- { RDEBUG(("EXP setmem.term")) ;
+ {
+ monitor_debug ("EXP setmem.term");
monitor_expect (current_monitor->setmem.term, NULL, 0);
monitor_printf ("%x\r", val);
}
if (current_monitor->setmem.term_cmd)
- { /* Emit this to get out of the memory editing state */
- monitor_printf("%s",current_monitor->setmem.term_cmd) ;
+ { /* Emit this to get out of the memory editing state */
+ monitor_printf ("%s", current_monitor->setmem.term_cmd);
/* Drop through to expecting a prompt */
}
}
@@ -1449,145 +1538,164 @@ monitor_write_memory (memaddr, myaddr, len)
static int
-monitor_write_even_block(memaddr,myaddr,len)
- CORE_ADDR memaddr ;
- char * myaddr ;
- int len ;
+monitor_write_even_block (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
{
- unsigned int val ;
- int written = 0 ;;
+ unsigned int val;
+ int written = 0;;
/* Enter the sub mode */
- monitor_printf(current_monitor->setmem.cmdl,memaddr) ;
- monitor_expect_prompt(NULL,0) ;
-
+ monitor_printf (current_monitor->setmem.cmdl, memaddr);
+ monitor_expect_prompt (NULL, 0);
+
while (len)
{
- val = extract_unsigned_integer(myaddr,4) ; /* REALLY */
- monitor_printf("%x\r",val) ;
- myaddr += 4 ;
- memaddr += 4 ;
- written += 4 ;
- RDEBUG((" @ %08x\n",memaddr))
+ val = extract_unsigned_integer (myaddr, 4); /* REALLY */
+ monitor_printf ("%x\r", val);
+ myaddr += 4;
+ memaddr += 4;
+ written += 4;
+ monitor_debug (" @ %s\n", paddr (memaddr));
/* If we wanted to, here we could validate the address */
- monitor_expect_prompt(NULL,0) ;
+ monitor_expect_prompt (NULL, 0);
}
/* Now exit the sub mode */
monitor_printf (current_monitor->getreg.term_cmd);
- monitor_expect_prompt(NULL,0) ;
- return written ;
+ monitor_expect_prompt (NULL, 0);
+ return written;
}
-static int monitor_write_memory_bytes(memaddr,myaddr,len)
- CORE_ADDR memaddr ;
- char * myaddr ;
- int len ;
+static int
+monitor_write_memory_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
{
- unsigned char val ;
- int written = 0 ;
- if (len == 0) return 0 ;
+ unsigned char val;
+ int written = 0;
+ if (len == 0)
+ return 0;
/* Enter the sub mode */
- monitor_printf(current_monitor->setmem.cmdb,memaddr) ;
- monitor_expect_prompt(NULL,0) ;
+ monitor_printf (current_monitor->setmem.cmdb, memaddr);
+ monitor_expect_prompt (NULL, 0);
while (len)
{
- val = *myaddr ;
- monitor_printf("%x\r",val) ;
- myaddr++ ;
- memaddr++ ;
- written++ ;
+ val = *myaddr;
+ monitor_printf ("%x\r", val);
+ myaddr++;
+ memaddr++;
+ written++;
/* If we wanted to, here we could validate the address */
- monitor_expect_prompt(NULL,0) ;
- len-- ;
+ monitor_expect_prompt (NULL, 0);
+ len--;
}
/* Now exit the sub mode */
monitor_printf (current_monitor->getreg.term_cmd);
- monitor_expect_prompt(NULL,0) ;
- return written ;
+ monitor_expect_prompt (NULL, 0);
+ return written;
}
static void
-longlongendswap (unsigned char * a)
+longlongendswap (unsigned char *a)
{
- int i,j ;
- unsigned char x ;
- i = 0 ; j = 7 ;
+ int i, j;
+ unsigned char x;
+ i = 0;
+ j = 7;
while (i < 4)
- { x = *(a+i) ;
- *(a+i) = *(a+j) ;
- *(a+j) = x ;
- i++ , j-- ;
+ {
+ x = *(a + i);
+ *(a + i) = *(a + j);
+ *(a + j) = x;
+ i++, j--;
}
}
/* Format 32 chars of long long value, advance the pointer */
-static char * hexlate = "0123456789abcdef" ;
-static char * longlong_hexchars(unsigned long long value,
- char * outbuff )
+static char *hexlate = "0123456789abcdef";
+static char *
+longlong_hexchars (unsigned long long value,
+ char *outbuff)
{
- if (value == 0) { *outbuff++ = '0' ; return outbuff ; }
+ if (value == 0)
+ {
+ *outbuff++ = '0';
+ return outbuff;
+ }
else
- { static unsigned char disbuf[8] ; /* disassembly buffer */
- unsigned char * scan , * limit ; /* loop controls */
- unsigned char c , nib ;
- int leadzero = 1 ;
- scan = disbuf ; limit = scan + 8 ;
- { unsigned long long * dp ;
- dp = (unsigned long long *) scan ;
- *dp = value ;
+ {
+ static unsigned char disbuf[8]; /* disassembly buffer */
+ unsigned char *scan, *limit; /* loop controls */
+ unsigned char c, nib;
+ int leadzero = 1;
+ scan = disbuf;
+ limit = scan + 8;
+ {
+ unsigned long long *dp;
+ dp = (unsigned long long *) scan;
+ *dp = value;
}
- longlongendswap(disbuf) ; /* FIXME: ONly on big endian hosts */
+ longlongendswap (disbuf); /* FIXME: ONly on big endian hosts */
while (scan < limit)
- { c = *scan++ ; /* a byte of our long long value */
+ {
+ c = *scan++; /* a byte of our long long value */
if (leadzero)
- if (c == 0) continue ;
- else leadzero = 0 ; /* henceforth we print even zeroes */
- nib = c >> 4 ; /* high nibble bits */
- *outbuff++ = hexlate[nib] ;
- nib = c & 0x0f ; /* low nibble bits */
- *outbuff++ = hexlate[nib] ;
+ {
+ if (c == 0)
+ continue;
+ else
+ leadzero = 0; /* henceforth we print even zeroes */
+ }
+ nib = c >> 4; /* high nibble bits */
+ *outbuff++ = hexlate[nib];
+ nib = c & 0x0f; /* low nibble bits */
+ *outbuff++ = hexlate[nib];
}
- return outbuff ;
+ return outbuff;
}
-} /* longlong_hexchars */
+} /* longlong_hexchars */
/* I am only going to call this when writing virtual byte streams.
Which possably entails endian conversions
- */
-static int monitor_write_memory_longlongs(memaddr,myaddr,len)
- CORE_ADDR memaddr ;
- char * myaddr ;
- int len ;
+ */
+static int
+monitor_write_memory_longlongs (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
{
- static char hexstage[20] ; /* At least 16 digits required, plus null */
- char * endstring ;
- long long * llptr ;
- long long value ;
- int written = 0 ;
- llptr = (unsigned long long *) myaddr ;
- if (len == 0 ) return 0 ;
- monitor_printf(current_monitor->setmem.cmdll,memaddr) ;
- monitor_expect_prompt(NULL,0) ;
- while (len >= 8 )
- {
- value = *llptr ;
- endstring = longlong_hexchars(*llptr,hexstage) ;
- *endstring = '\0' ; /* NUll terminate for printf */
- monitor_printf("%s\r",hexstage) ;
- llptr++ ;
- memaddr += 8 ;
- written += 8 ;
+ static char hexstage[20]; /* At least 16 digits required, plus null */
+ char *endstring;
+ long long *llptr;
+ long long value;
+ int written = 0;
+ llptr = (unsigned long long *) myaddr;
+ if (len == 0)
+ return 0;
+ monitor_printf (current_monitor->setmem.cmdll, memaddr);
+ monitor_expect_prompt (NULL, 0);
+ while (len >= 8)
+ {
+ value = *llptr;
+ endstring = longlong_hexchars (*llptr, hexstage);
+ *endstring = '\0'; /* NUll terminate for printf */
+ monitor_printf ("%s\r", hexstage);
+ llptr++;
+ memaddr += 8;
+ written += 8;
/* If we wanted to, here we could validate the address */
- monitor_expect_prompt(NULL,0) ;
- len -= 8 ;
+ monitor_expect_prompt (NULL, 0);
+ len -= 8;
}
/* Now exit the sub mode */
monitor_printf (current_monitor->getreg.term_cmd);
- monitor_expect_prompt(NULL,0) ;
- return written ;
-} /* */
+ monitor_expect_prompt (NULL, 0);
+ return written;
+} /* */
@@ -1598,40 +1706,41 @@ static int monitor_write_memory_longlongs(memaddr,myaddr,len)
Without this, we will end up calling monitor_write_memory many times
and do the entry and exit of the sub mode many times
This currently assumes...
- MO_SETMEM_INTERACTIVE
- ! MO_NO_ECHO_ON_SETMEM
- To use this, the you have to patch the monitor_cmds block with
- this function. Otherwise, its not tuned up for use by all
- monitor variations.
- */
+ MO_SETMEM_INTERACTIVE
+ ! MO_NO_ECHO_ON_SETMEM
+ To use this, the you have to patch the monitor_cmds block with
+ this function. Otherwise, its not tuned up for use by all
+ monitor variations.
+ */
-static int monitor_write_memory_block(memaddr,myaddr,len)
- CORE_ADDR memaddr ;
- char * myaddr ;
- int len ;
+static int
+monitor_write_memory_block (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
{
- int written ;
- written = 0 ;
+ int written;
+ written = 0;
/* FIXME: This would be a good place to put the zero test */
-#if 1
+#if 1
if ((len > 8) && (((len & 0x07)) == 0) && current_monitor->setmem.cmdll)
- {
- return monitor_write_memory_longlongs(memaddr,myaddr,len) ;
- }
-#endif
-#if 0
+ {
+ return monitor_write_memory_longlongs (memaddr, myaddr, len);
+ }
+#endif
+#if 0
if (len > 4)
{
- int sublen ;
- written = monitor_write_even_block(memaddr,myaddr,len) ;
+ int sublen;
+ written = monitor_write_even_block (memaddr, myaddr, len);
/* Adjust calling parameters by written amount */
- memaddr += written ;
- myaddr += written ;
- len -= written ;
+ memaddr += written;
+ myaddr += written;
+ len -= written;
}
#endif
- written = monitor_write_memory_bytes(memaddr,myaddr,len) ;
- return written ;
+ written = monitor_write_memory_bytes (memaddr, myaddr, len);
+ return written;
}
/* This is an alternate form of monitor_read_memory which is used for monitors
@@ -1644,12 +1753,12 @@ monitor_read_memory_single (memaddr, myaddr, len)
int len;
{
unsigned int val;
- char membuf[sizeof(int) * 2 + 1];
+ char membuf[sizeof (int) * 2 + 1];
char *p;
char *cmd;
int i;
- RDEBUG(("MON read single\n")) ;
+ monitor_debug ("MON read single\n");
#if 0
/* Can't actually use long longs (nice idea, though). In fact, the
call to strtoul below will fail if it tries to convert a value
@@ -1686,7 +1795,8 @@ monitor_read_memory_single (memaddr, myaddr, len)
searching from the start of the buf. */
if (current_monitor->getmem.resp_delim)
- { RDEBUG(("EXP getmem.resp_delim\n")) ;
+ {
+ monitor_debug ("EXP getmem.resp_delim\n");
monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
}
@@ -1694,7 +1804,7 @@ monitor_read_memory_single (memaddr, myaddr, len)
skipping spaces. */
/* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set. */
- if (current_monitor->flags & MO_HEX_PREFIX)
+ if (current_monitor->flags & MO_HEX_PREFIX)
{
int c;
@@ -1704,7 +1814,8 @@ monitor_read_memory_single (memaddr, myaddr, len)
if ((c == '0') && ((c = readchar (timeout)) == 'x'))
;
else
- monitor_error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.",
+ monitor_error ("monitor_read_memory_single",
+ "bad response from monitor",
memaddr, i, membuf, c);
}
for (i = 0; i < len * 2; i++)
@@ -1719,7 +1830,8 @@ monitor_read_memory_single (memaddr, myaddr, len)
if (c == ' ')
continue;
- monitor_error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.",
+ monitor_error ("monitor_read_memory_single",
+ "bad response from monitor",
memaddr, i, membuf, c);
}
@@ -1734,7 +1846,7 @@ monitor_read_memory_single (memaddr, myaddr, len)
if (current_monitor->getmem.term)
{
- monitor_expect (current_monitor->getmem.term, NULL, 0); /* get response */
+ monitor_expect (current_monitor->getmem.term, NULL, 0); /* get response */
if (current_monitor->getmem.term_cmd)
{
@@ -1743,13 +1855,14 @@ monitor_read_memory_single (memaddr, myaddr, len)
}
}
else
- monitor_expect_prompt (NULL, 0); /* get response */
+ monitor_expect_prompt (NULL, 0); /* get response */
p = membuf;
val = strtoul (membuf, &p, 16);
if (val == 0 && membuf == p)
- monitor_error ("monitor_read_memory_single (0x%x): bad value from monitor: %s.",
+ monitor_error ("monitor_read_memory_single",
+ "bad value from monitor",
memaddr, 0, membuf, 0);
/* supply register stores in target byte order, so swap here */
@@ -1778,12 +1891,12 @@ monitor_read_memory (memaddr, myaddr, len)
if (len <= 0)
{
- RDEBUG (("Zero length call to monitor_read_memory\n"));
+ monitor_debug ("Zero length call to monitor_read_memory\n");
return 0;
}
- if (remote_debug) printf("MON read block ta(%08x) ha(%08x) %d\n",
- (unsigned long) memaddr , (unsigned long)myaddr, len);
+ monitor_debug ("MON read block ta(%s) ha(%lx) %d\n",
+ paddr_nz (memaddr), (long) myaddr, len);
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
memaddr = ADDR_BITS_REMOVE (memaddr);
@@ -1796,10 +1909,10 @@ monitor_read_memory (memaddr, myaddr, len)
/* Some dumpers align the first data with the preceeding 16
byte boundary. Some print blanks and start at the
requested boundary. EXACT_DUMPADDR
- */
+ */
dumpaddr = (current_monitor->flags & MO_EXACT_DUMPADDR)
- ? memaddr : memaddr & ~ 0x0f ;
+ ? memaddr : memaddr & ~0x0f;
/* See if xfer would cross a 16 byte boundary. If so, clip it. */
if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
@@ -1808,7 +1921,7 @@ monitor_read_memory (memaddr, myaddr, len)
/* send the memory examine command */
if (current_monitor->flags & MO_GETMEM_NEEDS_RANGE)
- monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len - 1);
+ monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len);
else if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
monitor_printf (current_monitor->getmem.cmdb, dumpaddr);
else
@@ -1821,10 +1934,11 @@ monitor_read_memory (memaddr, myaddr, len)
if (current_monitor->getmem.term)
{
- resp_len = monitor_expect (current_monitor->getmem.term, buf, sizeof buf); /* get response */
+ resp_len = monitor_expect (current_monitor->getmem.term, buf, sizeof buf); /* get response */
if (resp_len <= 0)
- monitor_error ("monitor_read_memory (0x%x): excessive response from monitor: %.*s.",
+ monitor_error ("monitor_read_memory",
+ "excessive response from monitor",
memaddr, resp_len, buf, 0);
if (current_monitor->getmem.term_cmd)
@@ -1835,7 +1949,7 @@ monitor_read_memory (memaddr, myaddr, len)
}
}
else
- resp_len = monitor_expect_prompt (buf, sizeof buf); /* get response */
+ resp_len = monitor_expect_prompt (buf, sizeof buf); /* get response */
p = buf;
@@ -1847,7 +1961,7 @@ monitor_read_memory (memaddr, myaddr, len)
{
int retval, tmp;
struct re_registers resp_strings;
- RDEBUG(("MON getmem.resp_delim %s\n",current_monitor->getmem.resp_delim)) ;
+ monitor_debug ("MON getmem.resp_delim %s\n", current_monitor->getmem.resp_delim);
memset (&resp_strings, 0, sizeof (struct re_registers));
tmp = strlen (p);
@@ -1855,47 +1969,55 @@ monitor_read_memory (memaddr, myaddr, len)
&resp_strings);
if (retval < 0)
- monitor_error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ monitor_error ("monitor_read_memory",
+ "bad response from monitor",
memaddr, resp_len, buf, 0);
p += resp_strings.end[0];
#if 0
p = strstr (p, current_monitor->getmem.resp_delim);
if (!p)
- monitor_error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ monitor_error ("monitor_read_memory",
+ "bad response from monitor",
memaddr, resp_len, buf, 0);
p += strlen (current_monitor->getmem.resp_delim);
#endif
}
- if (remote_debug) printf("MON scanning %d ,%08x '%s'\n",len,p,p) ;
+ monitor_debug ("MON scanning %d ,%lx '%s'\n", len, (long) p, p);
if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
{
- char c ;
- int fetched = 0 ;
+ char c;
+ int fetched = 0;
i = len;
- c = *p ;
+ c = *p;
+
-
- while (!(c == '\000' || c == '\n' || c == '\r') && i > 0)
- { if (isxdigit (c))
- { if ((dumpaddr >= memaddr) && (i > 0))
- { val = fromhex (c) * 16 + fromhex (*(p+1));
+ while (!(c == '\000' || c == '\n' || c == '\r') && i > 0)
+ {
+ if (isxdigit (c))
+ {
+ if ((dumpaddr >= memaddr) && (i > 0))
+ {
+ val = fromhex (c) * 16 + fromhex (*(p + 1));
*myaddr++ = val;
- if (remote_debug) printf("[%02x]",val) ;
+ if (monitor_debug_p || remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "[%02x]", val);
--i;
- fetched++ ;
+ fetched++;
}
++dumpaddr;
++p;
}
- ++p; /* skip a blank or other non hex char */
- c = *p ;
+ ++p; /* skip a blank or other non hex char */
+ c = *p;
}
- if (fetched == 0) error("Failed to read via monitor") ;
- if (remote_debug) printf("\n") ;
- return fetched ; /* Return the number of bytes actually read */
+ if (fetched == 0)
+ error ("Failed to read via monitor");
+ if (monitor_debug_p || remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "\n");
+ return fetched; /* Return the number of bytes actually read */
}
- RDEBUG(("MON scanning bytes\n")) ;
+ monitor_debug ("MON scanning bytes\n");
for (i = len; i > 0; i--)
{
@@ -1907,7 +2029,8 @@ monitor_read_memory (memaddr, myaddr, len)
break;
if (*p == '\000' || *p == '\n' || *p == '\r')
- monitor_error ("monitor_read_memory (0x%x): badly terminated response from monitor: %.*s",
+ monitor_error ("monitor_read_memory",
+ "badly terminated response from monitor",
memaddr, resp_len, buf, 0);
p++;
}
@@ -1915,7 +2038,8 @@ monitor_read_memory (memaddr, myaddr, len)
val = strtoul (p, &p1, 16);
if (val == 0 && p == p1)
- monitor_error ("monitor_read_memory (0x%x): bad value from monitor: %.*s.",
+ monitor_error ("monitor_read_memory",
+ "bad value from monitor",
memaddr, resp_len, buf, 0);
*myaddr++ = val;
@@ -1935,7 +2059,7 @@ monitor_xfer_memory (memaddr, myaddr, len, write, target)
char *myaddr;
int len;
int write;
- struct target_ops *target; /* ignored */
+ struct target_ops *target; /* ignored */
{
return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, write);
}
@@ -1943,7 +2067,7 @@ monitor_xfer_memory (memaddr, myaddr, len, write, target)
static void
monitor_kill ()
{
- return; /* ignore attempts to kill target system */
+ return; /* ignore attempts to kill target system */
}
/* All we actually do is set the PC to the start address of exec_bfd, and start
@@ -1975,10 +2099,6 @@ monitor_mourn_inferior ()
generic_mourn_inferior (); /* Do all the proper things now */
}
-#define NUM_MONITOR_BREAKPOINTS 8
-
-static CORE_ADDR breakaddr[NUM_MONITOR_BREAKPOINTS] = {0};
-
/* Tell the monitor to add a breakpoint. */
static int
@@ -1990,7 +2110,7 @@ monitor_insert_breakpoint (addr, shadow)
unsigned char *bp;
int bplen;
- RDEBUG(("MON inst bkpt %08x\n",addr))
+ monitor_debug ("MON inst bkpt %s\n", paddr (addr));
if (current_monitor->set_break == NULL)
error ("No set_break defined for this monitor");
@@ -2000,7 +2120,7 @@ monitor_insert_breakpoint (addr, shadow)
/* Determine appropriate breakpoint size for this address. */
bp = memory_breakpoint_from_pc (&addr, &bplen);
- for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ for (i = 0; i < current_monitor->num_breakpoints; i++)
{
if (breakaddr[i] == 0)
{
@@ -2012,7 +2132,7 @@ monitor_insert_breakpoint (addr, shadow)
}
}
- error ("Too many breakpoints (> %d) for monitor.", NUM_MONITOR_BREAKPOINTS);
+ error ("Too many breakpoints (> %d) for monitor.", current_monitor->num_breakpoints);
}
/* Tell the monitor to remove a breakpoint. */
@@ -2024,14 +2144,14 @@ monitor_remove_breakpoint (addr, shadow)
{
int i;
- RDEBUG(("MON rmbkpt %08x\n",addr))
+ monitor_debug ("MON rmbkpt %s\n", paddr (addr));
if (current_monitor->clr_break == NULL)
error ("No clr_break defined for this monitor");
if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
addr = ADDR_BITS_REMOVE (addr);
- for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ for (i = 0; i < current_monitor->num_breakpoints; i++)
{
if (breakaddr[i] == addr)
{
@@ -2048,7 +2168,8 @@ monitor_remove_breakpoint (addr, shadow)
}
}
fprintf_unfiltered (gdb_stderr,
- "Can't find breakpoint associated with 0x%x\n", addr);
+ "Can't find breakpoint associated with 0x%s\n",
+ paddr_nz (addr));
return 1;
}
@@ -2058,7 +2179,7 @@ monitor_remove_breakpoint (addr, shadow)
static int
monitor_wait_srec_ack ()
{
- int i, ch;
+ int ch;
if (current_monitor->flags & MO_SREC_ACK_PLUS)
{
@@ -2083,11 +2204,11 @@ monitor_wait_srec_ack ()
static void
monitor_load (file, from_tty)
- char *file;
- int from_tty;
+ char *file;
+ int from_tty;
{
dcache_flush (remote_dcache);
- RDEBUG(("MON load\n"))
+ monitor_debug ("MON load\n");
if (current_monitor->load_routine)
current_monitor->load_routine (monitor_desc, file, hashmark);
@@ -2111,7 +2232,7 @@ monitor_load (file, from_tty)
load_srec (monitor_desc, file, (bfd_vma) load_offset,
32, SREC_ALL, hashmark,
current_monitor->flags & MO_SREC_ACK ?
- monitor_wait_srec_ack : NULL);
+ monitor_wait_srec_ack : NULL);
monitor_expect_prompt (NULL, 0);
}
@@ -2135,21 +2256,20 @@ monitor_load (file, from_tty)
static void
monitor_stop ()
{
- RDEBUG(("MON stop\n")) ;
+ monitor_debug ("MON stop\n");
if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
SERIAL_SEND_BREAK (monitor_desc);
if (current_monitor->stop)
monitor_printf_noecho (current_monitor->stop);
}
-/* Put a command string, in args, out to MONITOR. Output from MONITOR
- is placed on the users terminal until the prompt is seen. FIXME: We
- read the characters ourseleves here cause of a nasty echo. */
+/* Put a COMMAND string out to MONITOR. Output from MONITOR is placed
+ in OUTPUT until the prompt is seen. FIXME: We read the characters
+ ourseleves here cause of a nasty echo. */
static void
-monitor_command (args, from_tty)
- char *args;
- int from_tty;
+monitor_rcmd (char *command,
+ struct ui_file *outbuf)
{
char *p;
int resp_len;
@@ -2163,11 +2283,11 @@ monitor_command (args, from_tty)
/* Send the command. Note that if no args were supplied, then we're
just sending the monitor a newline, which is sometimes useful. */
- monitor_printf ("%s\r", (args ? args : ""));
+ monitor_printf ("%s\r", (command ? command : ""));
resp_len = monitor_expect_prompt (buf, sizeof buf);
- fputs_unfiltered (buf, gdb_stdout); /* Output the response */
+ fputs_unfiltered (buf, outbuf); /* Output the response */
}
/* Convert hex digit A to a number. */
@@ -2176,7 +2296,7 @@ monitor_command (args, from_tty)
static int
from_hex (a)
int a;
-{
+{
if (a >= '0' && a <= '9')
return a - '0';
if (a >= 'a' && a <= 'f')
@@ -2250,6 +2370,7 @@ init_base_monitor_ops (void)
monitor_ops.to_notice_signals = 0;
monitor_ops.to_thread_alive = 0;
monitor_ops.to_stop = monitor_stop;
+ monitor_ops.to_rcmd = monitor_rcmd;
monitor_ops.to_pid_to_exec_file = NULL;
monitor_ops.to_core_file_to_sym_file = NULL;
monitor_ops.to_stratum = process_stratum;
@@ -2262,7 +2383,7 @@ init_base_monitor_ops (void)
monitor_ops.to_sections = 0;
monitor_ops.to_sections_end = 0;
monitor_ops.to_magic = OPS_MAGIC;
-} /* init_base_monitor_ops */
+} /* init_base_monitor_ops */
/* Init the target_ops structure pointed at by OPS */
@@ -2283,14 +2404,17 @@ _initialize_remote_monitors ()
{
init_base_monitor_ops ();
add_show_from_set (add_set_cmd ("hash", no_class, var_boolean,
- (char *)&hashmark,
+ (char *) &hashmark,
"Set display of activity while downloading a file.\n\
When enabled, a hashmark \'#\' is displayed.",
- &setlist),
+ &setlist),
&showlist);
- add_com ("monitor", class_obscure, monitor_command,
- "Send a command to the debug monitor.");
+ add_show_from_set
+ (add_set_cmd ("monitor", no_class, var_zinteger,
+ (char *) &monitor_debug_p,
+ "Set debugging of remote monitor communication.\n\
+When enabled, communication between GDB and the remote monitor\n\
+is displayed.", &setdebuglist),
+ &showdebuglist);
}
-
-
diff --git a/contrib/gdb/gdb/monitor.h b/contrib/gdb/gdb/monitor.h
index 4ccddd5..cef907b 100644
--- a/contrib/gdb/gdb/monitor.h
+++ b/contrib/gdb/gdb/monitor.h
@@ -1,23 +1,24 @@
/* Definitions for remote debugging interface for ROM monitors.
- Copyright 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
- Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
-
+ Copyright 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+
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.
-*/
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
#include "serial.h"
@@ -52,67 +53,70 @@
will also be ignored if TERM is NULL. */
struct memrw_cmd
-{
- char *cmdb; /* Command to send for byte read/write */
- char *cmdw; /* Command for word (16 bit) read/write */
- char *cmdl; /* Command for long (32 bit) read/write */
- char *cmdll; /* Command for long long (64 bit) read/write */
- char *resp_delim; /* String just prior to the desired value */
- char *term; /* Terminating string to search for */
- char *term_cmd; /* String to get out of sub-mode (if necessary) */
-};
+ {
+ char *cmdb; /* Command to send for byte read/write */
+ char *cmdw; /* Command for word (16 bit) read/write */
+ char *cmdl; /* Command for long (32 bit) read/write */
+ char *cmdll; /* Command for long long (64 bit) read/write */
+ char *resp_delim; /* String just prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+ };
struct regrw_cmd
-{
- char *cmd; /* Command to send for reg read/write */
- char *resp_delim; /* String (actually a regexp if getmem) just
+ {
+ char *cmd; /* Command to send for reg read/write */
+ char *resp_delim; /* String (actually a regexp if getmem) just
prior to the desired value */
- char *term; /* Terminating string to search for */
- char *term_cmd; /* String to get out of sub-mode (if necessary) */
-};
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+ };
struct monitor_ops
-{
- int flags; /* See below */
- char **init; /* List of init commands. NULL terminated. */
- char *cont; /* continue command */
- char *step; /* single step */
- char *stop; /* Interrupt program string */
- char *set_break; /* set a breakpoint */
- char *clr_break; /* clear a breakpoint */
- char *clr_all_break; /* Clear all breakpoints */
- char *fill; /* Memory fill cmd (addr len val) */
- struct memrw_cmd setmem; /* set memory to a value */
- struct memrw_cmd getmem; /* display memory */
- struct regrw_cmd setreg; /* set a register */
- struct regrw_cmd getreg; /* get a register */
- /* Some commands can dump a bunch of registers
- at once. This comes as a set of REG=VAL
- pairs. This should be called for each pair
- of registers that we can parse to supply
- GDB with the value of a register. */
- char *dump_registers; /* Command to dump all regs at once */
- char *register_pattern; /* Pattern that picks out register from reg dump */
- void (*supply_register) PARAMS ((char *name, int namelen,
- char *val, int vallen));
- void (*load_routine) PARAMS ((serial_t desc, char *file,
- int hashmark)); /* Download routine */
- int (*dumpregs) PARAMS((void)) ; /* routine to dump all registers */
- int (*continue_hook) PARAMS((void)) ; /* Emit the continue command */
- int (*wait_filter) PARAMS((char * buf, /* Maybe contains registers */
- int bufmax ,
- int * response_length,
- struct target_waitstatus * status)) ;
- char *load; /* load command */
- char *loadresp; /* Response to load command */
- char *prompt; /* monitor command prompt */
- char *line_term; /* end-of-command delimitor */
- char *cmd_end; /* optional command terminator */
- struct target_ops *target; /* target operations */
- int stopbits; /* number of stop bits */
- char **regnames; /* array of register names in ascii */
- int magic; /* Check value */
-};
+ {
+ int flags; /* See below */
+ char **init; /* List of init commands. NULL terminated. */
+ char *cont; /* continue command */
+ char *step; /* single step */
+ char *stop; /* Interrupt program string */
+ char *set_break; /* set a breakpoint. If NULL, monitor implementation
+ sets its own to_insert_breakpoint method. */
+ char *clr_break; /* clear a breakpoint */
+ char *clr_all_break; /* Clear all breakpoints */
+ char *fill; /* Memory fill cmd (addr len val) */
+ struct memrw_cmd setmem; /* set memory to a value */
+ struct memrw_cmd getmem; /* display memory */
+ struct regrw_cmd setreg; /* set a register */
+ struct regrw_cmd getreg; /* get a register */
+ /* Some commands can dump a bunch of registers
+ at once. This comes as a set of REG=VAL
+ pairs. This should be called for each pair
+ of registers that we can parse to supply
+ GDB with the value of a register. */
+ char *dump_registers; /* Command to dump all regs at once */
+ char *register_pattern; /* Pattern that picks out register from reg dump */
+ void (*supply_register) PARAMS ((char *name, int namelen,
+ char *val, int vallen));
+ void (*load_routine) PARAMS ((serial_t desc, char *file,
+ int hashmark)); /* Download routine */
+ int (*dumpregs) PARAMS ((void)); /* routine to dump all registers */
+ int (*continue_hook) PARAMS ((void)); /* Emit the continue command */
+ int (*wait_filter) PARAMS ((char *buf, /* Maybe contains registers */
+ int bufmax,
+ int *response_length,
+ struct target_waitstatus * status));
+ char *load; /* load command */
+ char *loadresp; /* Response to load command */
+ char *prompt; /* monitor command prompt */
+ char *line_term; /* end-of-command delimitor */
+ char *cmd_end; /* optional command terminator */
+ struct target_ops *target; /* target operations */
+ int stopbits; /* number of stop bits */
+ char **regnames; /* array of register names in ascii */
+ int num_breakpoints; /* If set_break != NULL, number of supported
+ breakpoints */
+ int magic; /* Check value */
+ };
/* The monitor ops magic number, used to detect if an ops structure doesn't
have the right number of entries filled in. */
@@ -214,8 +218,8 @@ struct monitor_ops
#define MO_PRINT_PROGRAM_OUTPUT 0x200000
/* Some dump bytes commands align the first data with the preceeding
-16 byte boundary. Some print blanks and start at the exactly the
-requested boundary. */
+ 16 byte boundary. Some print blanks and start at the exactly the
+ requested boundary. */
#define MO_EXACT_DUMPADDR 0x400000
@@ -224,24 +228,25 @@ requested boundary. */
the memory editing mode. You only need to worry about this
if you are doing memory downloading.
This engages a new write function registered with dcache.
- */
+ */
#define MO_HAS_BLOCKWRITES 0x800000
#define SREC_SIZE 160
-extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops,
+extern void monitor_open PARAMS ((char *args, struct monitor_ops * ops,
int from_tty));
extern void monitor_close PARAMS ((int quitting));
extern char *monitor_supply_register PARAMS ((int regno, char *valstr));
extern int monitor_expect PARAMS ((char *prompt, char *buf, int buflen));
extern int monitor_expect_prompt PARAMS ((char *buf, int buflen));
-extern void monitor_printf PARAMS ((char *, ...))
- ATTR_FORMAT(printf, 1, 2);
-extern void monitor_printf_noecho PARAMS ((char *, ...))
- ATTR_FORMAT(printf, 1, 2);
-extern void monitor_write PARAMS ((char *buf, int buflen));
-extern int monitor_readchar PARAMS ((void));
-extern char *monitor_get_dev_name PARAMS ((void));
-extern void init_monitor_ops PARAMS ((struct target_ops *));
-extern int monitor_dump_reg_block PARAMS((char * dump_cmd)) ;
-extern void flush_monitor_dcache PARAMS ((void));
+extern void monitor_printf
+PARAMS ((char *,...))
+ATTR_FORMAT (printf, 1, 2);
+ extern void monitor_printf_noecho PARAMS ((char *,...))
+ ATTR_FORMAT (printf, 1, 2);
+ extern void monitor_write PARAMS ((char *buf, int buflen));
+ extern int monitor_readchar PARAMS ((void));
+ extern char *monitor_get_dev_name PARAMS ((void));
+ extern void init_monitor_ops PARAMS ((struct target_ops *));
+ extern int monitor_dump_reg_block PARAMS ((char *dump_cmd));
+ extern void flush_monitor_dcache PARAMS ((void));
diff --git a/contrib/gdb/gdb/osfsolib.c b/contrib/gdb/gdb/osfsolib.c
index 31c9bf9..3ea550a 100644
--- a/contrib/gdb/gdb/osfsolib.c
+++ b/contrib/gdb/gdb/osfsolib.c
@@ -1,21 +1,22 @@
/* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
Copyright 1993, 94, 95, 96, 98, 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 file is part of GDB.
-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.
+ 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.
-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 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. */
/* FIXME: Most of this code could be merged with solib.c by using
next_link_map_member and xfer_link_map_member in solib.c. */
@@ -35,12 +36,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "command.h"
#include "target.h"
#include "frame.h"
-#include "gnu-regex.h"
+#include "gdb_regex.h"
#include "inferior.h"
#include "language.h"
#include "gdbcmd.h"
-#define MAX_PATH_SIZE 1024 /* FIXME: Should be dynamic */
+#define MAX_PATH_SIZE 1024 /* FIXME: Should be dynamic */
/* When handling shared libraries, GDB has to find out the pathnames
of all shared libraries that are currently loaded (to read in their
@@ -50,16 +51,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
Under OSF/1 there are two possibilities to get at this information:
1) Peek around in the runtime loader structures.
- These are not documented, and they are not defined in the system
- header files. The definitions below were obtained by experimentation,
- but they seem stable enough.
+ These are not documented, and they are not defined in the system
+ header files. The definitions below were obtained by experimentation,
+ but they seem stable enough.
2) Use the undocumented libxproc.a library, which contains the
- equivalent ldr_* routines.
- This approach is somewhat cleaner, but it requires that the GDB
- executable is dynamically linked. In addition it requires a
- NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
- linker specification for GDB and all applications that are using
- libgdb.
+ equivalent ldr_* routines.
+ This approach is somewhat cleaner, but it requires that the GDB
+ executable is dynamically linked. In addition it requires a
+ NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
+ linker specification for GDB and all applications that are using
+ libgdb.
We will use the peeking approach until it becomes unwieldy. */
#ifndef USE_LDR_ROUTINES
@@ -68,37 +69,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define RLD_CONTEXT_ADDRESS 0x3ffc0000000
typedef struct
-{
- CORE_ADDR next;
- CORE_ADDR previous;
- CORE_ADDR unknown1;
- char *module_name;
- CORE_ADDR modinfo_addr;
- long module_id;
- CORE_ADDR unknown2;
- CORE_ADDR unknown3;
- long region_count;
- CORE_ADDR regioninfo_addr;
-} ldr_module_info_t;
+ {
+ CORE_ADDR next;
+ CORE_ADDR previous;
+ CORE_ADDR unknown1;
+ char *module_name;
+ CORE_ADDR modinfo_addr;
+ long module_id;
+ CORE_ADDR unknown2;
+ CORE_ADDR unknown3;
+ long region_count;
+ CORE_ADDR regioninfo_addr;
+ }
+ldr_module_info_t;
typedef struct
-{
- long unknown1;
- CORE_ADDR regionname_addr;
- long protection;
- CORE_ADDR vaddr;
- CORE_ADDR mapaddr;
- long size;
- long unknown2[5];
-} ldr_region_info_t;
+ {
+ long unknown1;
+ CORE_ADDR regionname_addr;
+ long protection;
+ CORE_ADDR vaddr;
+ CORE_ADDR mapaddr;
+ long size;
+ long unknown2[5];
+ }
+ldr_region_info_t;
typedef struct
-{
- CORE_ADDR unknown1;
- CORE_ADDR unknown2;
- CORE_ADDR head;
- CORE_ADDR tail;
-} ldr_context_t;
+ {
+ CORE_ADDR unknown1;
+ CORE_ADDR unknown2;
+ CORE_ADDR head;
+ CORE_ADDR tail;
+ }
+ldr_context_t;
static ldr_context_t ldr_context;
@@ -125,7 +129,7 @@ ldr_read_memory (memaddr, myaddr, len, readstring)
{
target_read_string (memaddr, &buffer, len, &result);
if (result == 0)
- strcpy (myaddr, buffer);
+ strcpy (myaddr, buffer);
free (buffer);
}
else
@@ -141,34 +145,36 @@ ldr_read_memory (memaddr, myaddr, len, readstring)
/* Define our own link_map structure.
This will help to share code with solib.c. */
-struct link_map {
- CORE_ADDR l_offset; /* prelink to load address offset */
- char *l_name; /* full name of loaded object */
+struct link_map
+{
+ CORE_ADDR l_offset; /* prelink to load address offset */
+ char *l_name; /* full name of loaded object */
ldr_module_info_t module_info; /* corresponding module info */
};
#define LM_OFFSET(so) ((so) -> lm.l_offset)
#define LM_NAME(so) ((so) -> lm.l_name)
-struct so_list {
- struct so_list *next; /* next structure in linked list */
- struct link_map lm; /* copy of link map from inferior */
- struct link_map *lmaddr; /* addr in inferior lm was read from */
- CORE_ADDR lmend; /* upper addr bound of mapped object */
- char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
- char symbols_loaded; /* flag: symbols read in yet? */
- char from_tty; /* flag: print msgs? */
- struct objfile *objfile; /* objfile for loaded lib */
- struct section_table *sections;
- struct section_table *sections_end;
- struct section_table *textsection;
- bfd *abfd;
-};
+struct so_list
+ {
+ struct so_list *next; /* next structure in linked list */
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct section_table *textsection;
+ bfd *abfd;
+ };
static struct so_list *so_list_head; /* List of known shared objects */
extern int
-fdmatch PARAMS ((int, int)); /* In libiberty */
+fdmatch PARAMS ((int, int)); /* In libiberty */
/* Local function prototypes */
@@ -182,13 +188,13 @@ static int
symbol_add_stub PARAMS ((char *));
static struct so_list *
-find_solib PARAMS ((struct so_list *));
+ find_solib PARAMS ((struct so_list *));
static struct link_map *
-first_link_map_member PARAMS ((void));
+ first_link_map_member PARAMS ((void));
static struct link_map *
-next_link_map_member PARAMS ((struct so_list *));
+ next_link_map_member PARAMS ((struct so_list *));
static void
xfer_link_map_member PARAMS ((struct so_list *, struct link_map *));
@@ -198,29 +204,29 @@ solib_map_sections PARAMS ((char *));
/*
-LOCAL FUNCTION
+ LOCAL FUNCTION
- solib_map_sections -- open bfd and build sections for shared lib
+ solib_map_sections -- open bfd and build sections for shared lib
-SYNOPSIS
+ SYNOPSIS
- static int solib_map_sections (struct so_list *so)
+ static int solib_map_sections (struct so_list *so)
-DESCRIPTION
+ DESCRIPTION
- Given a pointer to one of the shared objects in our list
- of mapped objects, use the recorded name to open a bfd
- descriptor for the object, build a section table, and then
- relocate all the section addresses by the base address at
- which the shared object was mapped.
+ Given a pointer to one of the shared objects in our list
+ of mapped objects, use the recorded name to open a bfd
+ descriptor for the object, build a section table, and then
+ relocate all the section addresses by the base address at
+ which the shared object was mapped.
-FIXMES
+ FIXMES
- In most (all?) cases the shared object file name recorded in the
- dynamic linkage tables will be a fully qualified pathname. For
- cases where it isn't, do we really mimic the systems search
- mechanism correctly in the below code (particularly the tilde
- expansion stuff?).
+ In most (all?) cases the shared object file name recorded in the
+ dynamic linkage tables will be a fully qualified pathname. For
+ cases where it isn't, do we really mimic the systems search
+ mechanism correctly in the below code (particularly the tilde
+ expansion stuff?).
*/
static int
@@ -234,10 +240,10 @@ solib_map_sections (arg)
struct section_table *p;
struct cleanup *old_chain;
bfd *abfd;
-
- filename = tilde_expand (so -> so_name);
+
+ filename = tilde_expand (so->so_name);
old_chain = make_cleanup (free, filename);
-
+
scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&scratch_pathname);
if (scratch_chan < 0)
@@ -259,31 +265,31 @@ solib_map_sections (arg)
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
/* Leave bfd open, core_xfer_memory and "info files" need it. */
- so -> abfd = abfd;
- abfd -> cacheable = true;
+ so->abfd = abfd;
+ abfd->cacheable = true;
if (!bfd_check_format (abfd, bfd_object))
{
error ("\"%s\": not in executable format: %s.",
scratch_pathname, bfd_errmsg (bfd_get_error ()));
}
- if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ if (build_section_table (abfd, &so->sections, &so->sections_end))
{
- error ("Can't find the file sections in `%s': %s",
+ error ("Can't find the file sections in `%s': %s",
bfd_get_filename (exec_bfd), bfd_errmsg (bfd_get_error ()));
}
- for (p = so -> sections; p < so -> sections_end; p++)
+ for (p = so->sections; p < so->sections_end; p++)
{
/* Relocate the section binding addresses as recorded in the shared
- object's file by the offset to get the address to which the
- object was actually mapped. */
- p -> addr += LM_OFFSET (so);
- p -> endaddr += LM_OFFSET (so);
- so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
- if (STREQ (p -> the_bfd_section -> name, ".text"))
+ object's file by the offset to get the address to which the
+ object was actually mapped. */
+ p->addr += LM_OFFSET (so);
+ p->endaddr += LM_OFFSET (so);
+ so->lmend = (CORE_ADDR) max (p->endaddr, so->lmend);
+ if (STREQ (p->the_bfd_section->name, ".text"))
{
- so -> textsection = p;
+ so->textsection = p;
}
}
@@ -295,20 +301,20 @@ solib_map_sections (arg)
/*
-LOCAL FUNCTION
+ LOCAL FUNCTION
- first_link_map_member -- locate first member in dynamic linker's map
+ first_link_map_member -- locate first member in dynamic linker's map
-SYNOPSIS
+ SYNOPSIS
- static struct link_map *first_link_map_member (void)
+ static struct link_map *first_link_map_member (void)
-DESCRIPTION
+ DESCRIPTION
- Read in a copy of the first member in the inferior's dynamic
- link map from the inferior's dynamic linker structures, and return
- a pointer to the copy in our address space.
-*/
+ Read in a copy of the first member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the copy in our address space.
+ */
static struct link_map *
first_link_map_member ()
@@ -324,11 +330,11 @@ first_link_map_member ()
ldr_set_core_reader (ldr_read_memory);
ldr_xdetach (fake_ldr_process);
if (ldr_xattach (fake_ldr_process) != 0
- || ldr_next_module(fake_ldr_process, &mod_id) != 0
+ || ldr_next_module (fake_ldr_process, &mod_id) != 0
|| mod_id == LDR_NULL_MODULE
- || ldr_inq_module(fake_ldr_process, mod_id,
- &first_lm.module_info, sizeof(ldr_module_info_t),
- &retsize) != 0)
+ || ldr_inq_module (fake_ldr_process, mod_id,
+ &first_lm.module_info, sizeof (ldr_module_info_t),
+ &retsize) != 0)
return lm;
#else
CORE_ADDR ldr_context_addr;
@@ -363,11 +369,11 @@ next_link_map_member (so_list_ptr)
ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
size_t retsize;
- if (ldr_next_module(fake_ldr_process, &mod_id) != 0
+ if (ldr_next_module (fake_ldr_process, &mod_id) != 0
|| mod_id == LDR_NULL_MODULE
- || ldr_inq_module(fake_ldr_process, mod_id,
- &next_lm.module_info, sizeof(ldr_module_info_t),
- &retsize) != 0)
+ || ldr_inq_module (fake_ldr_process, mod_id,
+ &next_lm.module_info, sizeof (ldr_module_info_t),
+ &retsize) != 0)
return lm;
lm = &next_lm;
@@ -440,7 +446,7 @@ xfer_link_map_member (so_list_ptr, lm)
&retsize) != 0)
break;
region_offset = (CORE_ADDR) region_info.lri_mapaddr
- - (CORE_ADDR) region_info.lri_vaddr;
+ - (CORE_ADDR) region_info.lri_vaddr;
if (i == 0)
LM_OFFSET (so_list_ptr) = region_offset;
else if (LM_OFFSET (so_list_ptr) != region_offset)
@@ -465,7 +471,7 @@ xfer_link_map_member (so_list_ptr, lm)
CORE_ADDR region_offset;
if (target_read_memory (lm->module_info.regioninfo_addr
- + i * sizeof (region_info),
+ + i * sizeof (region_info),
(char *) &region_info,
sizeof (region_info)) != 0)
break;
@@ -482,7 +488,7 @@ xfer_link_map_member (so_list_ptr, lm)
else
region_name = "??";
warning ("cannot handle shared library relocation for %s (%s)",
- so_list_ptr->so_name, region_name);
+ so_list_ptr->so_name, region_name);
free (buffer);
}
}
@@ -496,25 +502,25 @@ xfer_link_map_member (so_list_ptr, lm)
/*
-LOCAL FUNCTION
+ LOCAL FUNCTION
- find_solib -- step through list of shared objects
+ find_solib -- step through list of shared objects
-SYNOPSIS
+ SYNOPSIS
- struct so_list *find_solib (struct so_list *so_list_ptr)
+ struct so_list *find_solib (struct so_list *so_list_ptr)
-DESCRIPTION
+ DESCRIPTION
- This module contains the routine which finds the names of any
- loaded "images" in the current process. The argument in must be
- NULL on the first call, and then the returned value must be passed
- in on subsequent calls. This provides the capability to "step" down
- the list of loaded objects. On the last object, a NULL value is
- returned.
+ This module contains the routine which finds the names of any
+ loaded "images" in the current process. The argument in must be
+ NULL on the first call, and then the returned value must be passed
+ in on subsequent calls. This provides the capability to "step" down
+ the list of loaded objects. On the last object, a NULL value is
+ returned.
- The arg and return value are "struct link_map" pointers, as defined
- in <link.h>.
+ The arg and return value are "struct link_map" pointers, as defined
+ in <link.h>.
*/
static struct so_list *
@@ -524,7 +530,7 @@ find_solib (so_list_ptr)
struct so_list *so_list_next = NULL;
struct link_map *lm = NULL;
struct so_list *new;
-
+
if (so_list_ptr == NULL)
{
/* We are setting up for a new scan through the loaded images. */
@@ -537,27 +543,27 @@ find_solib (so_list_ptr)
else
{
/* We have been called before, and are in the process of walking
- the shared library list. Advance to the next shared object. */
+ the shared library list. Advance to the next shared object. */
lm = next_link_map_member (so_list_ptr);
- so_list_next = so_list_ptr -> next;
+ so_list_next = so_list_ptr->next;
}
if ((so_list_next == NULL) && (lm != NULL))
{
/* Get next link map structure from inferior image and build a local
- abbreviated load_map structure */
+ abbreviated load_map structure */
new = (struct so_list *) xmalloc (sizeof (struct so_list));
memset ((char *) new, 0, sizeof (struct so_list));
- new -> lmaddr = lm;
+ new->lmaddr = lm;
/* Add the new node as the next node in the list, or as the root
- node if this is the first one. */
+ node if this is the first one. */
if (so_list_ptr != NULL)
{
- so_list_ptr -> next = new;
+ so_list_ptr->next = new;
}
else
{
so_list_head = new;
- }
+ }
so_list_next = new;
xfer_link_map_member (new, lm);
}
@@ -570,54 +576,56 @@ static int
symbol_add_stub (arg)
char *arg;
{
- register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
CORE_ADDR text_addr = 0;
+ struct section_addr_info section_addrs;
- if (so -> textsection)
- text_addr = so -> textsection -> addr;
- else if (so -> abfd != NULL)
+ memset (&section_addrs, 0, sizeof (section_addrs));
+ if (so->textsection)
+ text_addr = so->textsection->addr;
+ else if (so->abfd != NULL)
{
asection *lowest_sect;
/* If we didn't find a mapped non zero sized .text section, set up
- text_addr so that the relocation in symbol_file_add does no harm. */
+ text_addr so that the relocation in symbol_file_add does no harm. */
- lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+ lowest_sect = bfd_get_section_by_name (so->abfd, ".text");
if (lowest_sect == NULL)
- bfd_map_over_sections (so -> abfd, find_lowest_section,
+ bfd_map_over_sections (so->abfd, find_lowest_section,
(PTR) &lowest_sect);
if (lowest_sect)
- text_addr = bfd_section_vma (so -> abfd, lowest_sect) + LM_OFFSET (so);
+ text_addr = bfd_section_vma (so->abfd, lowest_sect) + LM_OFFSET (so);
}
-
- so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
- text_addr,
- 0, 0, 0, 0, 1);
+
+ section_addrs.text_addr = text_addr;
+ so->objfile = symbol_file_add (so->so_name, so->from_tty,
+ &section_addrs, 0, OBJF_SHARED);
return (1);
}
/*
-GLOBAL FUNCTION
+ GLOBAL FUNCTION
- solib_add -- add a shared library file to the symtab and section list
+ solib_add -- add a shared library file to the symtab and section list
-SYNOPSIS
+ SYNOPSIS
- void solib_add (char *arg_string, int from_tty,
- struct target_ops *target)
+ void solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
-DESCRIPTION
+ DESCRIPTION
-*/
+ */
void
solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
-{
- register struct so_list *so = NULL; /* link map state variable */
+{
+ register struct so_list *so = NULL; /* link map state variable */
/* Last shared library that we read. */
struct so_list *so_last = NULL;
@@ -625,13 +633,13 @@ solib_add (arg_string, from_tty, target)
char *re_err;
int count;
int old;
-
+
if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
{
error ("Invalid regexp: %s", re_err);
}
-
-
+
+
/* Add the shared library sections to the section table of the
specified target, if any. */
if (target)
@@ -641,72 +649,44 @@ solib_add (arg_string, from_tty, target)
count = 0;
while ((so = find_solib (so)) != NULL)
{
- if (so -> so_name[0])
+ if (so->so_name[0])
{
- count += so -> sections_end - so -> sections;
+ count += so->sections_end - so->sections;
}
}
-
+
if (count)
{
- int update_coreops;
-
- /* We must update the to_sections field in the core_ops structure
- here, otherwise we dereference a potential dangling pointer
- for each call to target_read/write_memory within this routine. */
- update_coreops = core_ops.to_sections == target->to_sections;
-
- /* Reallocate the target's section table including the new size. */
- if (target -> to_sections)
- {
- old = target -> to_sections_end - target -> to_sections;
- target -> to_sections = (struct section_table *)
- xrealloc ((char *)target -> to_sections,
- (sizeof (struct section_table)) * (count + old));
- }
- else
- {
- old = 0;
- target -> to_sections = (struct section_table *)
- xmalloc ((sizeof (struct section_table)) * count);
- }
- target -> to_sections_end = target -> to_sections + (count + old);
-
- /* Update the to_sections field in the core_ops structure
- if needed. */
- if (update_coreops)
- {
- core_ops.to_sections = target->to_sections;
- core_ops.to_sections_end = target->to_sections_end;
- }
-
/* Add these section table entries to the target's table. */
+
+ old = target_resize_to_sections (target, count);
+
while ((so = find_solib (so)) != NULL)
{
- if (so -> so_name[0])
+ if (so->so_name[0])
{
- count = so -> sections_end - so -> sections;
- memcpy ((char *) (target -> to_sections + old),
- so -> sections,
+ count = so->sections_end - so->sections;
+ memcpy ((char *) (target->to_sections + old),
+ so->sections,
(sizeof (struct section_table)) * count);
old += count;
}
}
}
}
-
+
/* Now add the symbol files. */
so = NULL;
while ((so = find_solib (so)) != NULL)
{
- if (so -> so_name[0] && re_exec (so -> so_name))
+ if (so->so_name[0] && re_exec (so->so_name))
{
- so -> from_tty = from_tty;
- if (so -> symbols_loaded)
+ so->from_tty = from_tty;
+ if (so->symbols_loaded)
{
if (from_tty)
{
- printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
+ printf_unfiltered ("Symbols already loaded for %s\n", so->so_name);
}
}
else if (catch_errors
@@ -715,7 +695,7 @@ solib_add (arg_string, from_tty, target)
RETURN_MASK_ALL))
{
so_last = so;
- so -> symbols_loaded = 1;
+ so->symbols_loaded = 1;
}
}
}
@@ -728,99 +708,99 @@ solib_add (arg_string, from_tty, target)
/*
-LOCAL FUNCTION
+ LOCAL FUNCTION
- info_sharedlibrary_command -- code for "info sharedlibrary"
+ info_sharedlibrary_command -- code for "info sharedlibrary"
-SYNOPSIS
+ SYNOPSIS
- static void info_sharedlibrary_command ()
+ static void info_sharedlibrary_command ()
-DESCRIPTION
+ DESCRIPTION
- Walk through the shared library list and print information
- about each attached library.
-*/
+ Walk through the shared library list and print information
+ about each attached library.
+ */
static void
info_sharedlibrary_command (ignore, from_tty)
char *ignore;
int from_tty;
{
- register struct so_list *so = NULL; /* link map state variable */
+ register struct so_list *so = NULL; /* link map state variable */
int header_done = 0;
-
+
if (exec_bfd == NULL)
{
- printf_unfiltered ("No exec file.\n");
+ printf_unfiltered ("No executable file.\n");
return;
}
while ((so = find_solib (so)) != NULL)
{
- if (so -> so_name[0])
+ if (so->so_name[0])
{
unsigned long txt_start = 0;
unsigned long txt_end = 0;
if (!header_done)
{
- printf_unfiltered("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read",
- "Shared Object Library");
+ printf_unfiltered ("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
header_done++;
}
- if (so -> textsection)
+ if (so->textsection)
{
- txt_start = (unsigned long) so -> textsection -> addr;
- txt_end = (unsigned long) so -> textsection -> endaddr;
+ txt_start = (unsigned long) so->textsection->addr;
+ txt_end = (unsigned long) so->textsection->endaddr;
}
printf_unfiltered ("%-20s", local_hex_string_custom (txt_start, "08l"));
printf_unfiltered ("%-20s", local_hex_string_custom (txt_end, "08l"));
- printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
- printf_unfiltered ("%s\n", so -> so_name);
+ printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so->so_name);
}
}
if (so_list_head == NULL)
{
- printf_unfiltered ("No shared libraries loaded at this time.\n");
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
}
}
/*
-GLOBAL FUNCTION
+ GLOBAL FUNCTION
- solib_address -- check to see if an address is in a shared lib
+ solib_address -- check to see if an address is in a shared lib
-SYNOPSIS
+ SYNOPSIS
- char *solib_address (CORE_ADDR address)
+ char *solib_address (CORE_ADDR address)
-DESCRIPTION
+ DESCRIPTION
- Provides a hook for other gdb routines to discover whether or
- not a particular address is within the mapped address space of
- a shared library. Any address between the base mapping address
- and the first address beyond the end of the last mapping, is
- considered to be within the shared library address space, for
- our purposes.
+ Provides a hook for other gdb routines to discover whether or
+ not a particular address is within the mapped address space of
+ a shared library. Any address between the base mapping address
+ and the first address beyond the end of the last mapping, is
+ considered to be within the shared library address space, for
+ our purposes.
- For example, this routine is called at one point to disable
- breakpoints which are in shared libraries that are not currently
- mapped in.
+ For example, this routine is called at one point to disable
+ breakpoints which are in shared libraries that are not currently
+ mapped in.
*/
char *
solib_address (address)
CORE_ADDR address;
{
- register struct so_list *so = 0; /* link map state variable */
-
+ register struct so_list *so = 0; /* link map state variable */
+
while ((so = find_solib (so)) != NULL)
{
- if (so -> so_name[0] && so -> textsection)
+ if (so->so_name[0] && so->textsection)
{
- if ((address >= (CORE_ADDR) so -> textsection -> addr) &&
- (address < (CORE_ADDR) so -> textsection -> endaddr))
+ if ((address >= (CORE_ADDR) so->textsection->addr) &&
+ (address < (CORE_ADDR) so->textsection->endaddr))
return (so->so_name);
}
}
@@ -829,24 +809,24 @@ solib_address (address)
/* Called by free_all_symtabs */
-void
-clear_solib()
+void
+clear_solib ()
{
struct so_list *next;
char *bfd_filename;
-
+
disable_breakpoints_in_shlibs (1);
while (so_list_head)
{
- if (so_list_head -> sections)
+ if (so_list_head->sections)
{
- free ((PTR)so_list_head -> sections);
+ free ((PTR) so_list_head->sections);
}
- if (so_list_head -> abfd)
+ if (so_list_head->abfd)
{
- bfd_filename = bfd_get_filename (so_list_head -> abfd);
- if (!bfd_close (so_list_head -> abfd))
+ bfd_filename = bfd_get_filename (so_list_head->abfd);
+ if (!bfd_close (so_list_head->abfd))
warning ("cannot close \"%s\": %s",
bfd_filename, bfd_errmsg (bfd_get_error ()));
}
@@ -854,52 +834,52 @@ clear_solib()
/* This happens for the executable on SVR4. */
bfd_filename = NULL;
- next = so_list_head -> next;
+ next = so_list_head->next;
if (bfd_filename)
- free ((PTR)bfd_filename);
- free ((PTR)so_list_head);
+ free ((PTR) bfd_filename);
+ free ((PTR) so_list_head);
so_list_head = next;
}
}
-
+
/*
-
-GLOBAL FUNCTION
-
- solib_create_inferior_hook -- shared library startup support
-
-SYNOPSIS
-
- void solib_create_inferior_hook()
-
-DESCRIPTION
-
- When gdb starts up the inferior, it nurses it along (through the
- shell) until it is ready to execute it's first instruction. At this
- point, this function gets called via expansion of the macro
- SOLIB_CREATE_INFERIOR_HOOK.
- For a statically bound executable, this first instruction is the
- one at "_start", or a similar text label. No further processing is
- needed in that case.
- For a dynamically bound executable, this first instruction is somewhere
- in the rld, and the actual user executable is not yet mapped in.
- We continue the inferior again, rld then maps in the actual user
- executable and any needed shared libraries and then sends
- itself a SIGTRAP.
- At that point we discover the names of all shared libraries and
- read their symbols in.
-
-FIXME
-
- This code does not properly handle hitting breakpoints which the
- user might have set in the rld itself. Proper handling would have
- to check if the SIGTRAP happened due to a kill call.
-
- Also, what if child has exit()ed? Must exit loop somehow.
- */
+
+ GLOBAL FUNCTION
+
+ solib_create_inferior_hook -- shared library startup support
+
+ SYNOPSIS
+
+ void solib_create_inferior_hook()
+
+ DESCRIPTION
+
+ When gdb starts up the inferior, it nurses it along (through the
+ shell) until it is ready to execute it's first instruction. At this
+ point, this function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+ For a statically bound executable, this first instruction is the
+ one at "_start", or a similar text label. No further processing is
+ needed in that case.
+ For a dynamically bound executable, this first instruction is somewhere
+ in the rld, and the actual user executable is not yet mapped in.
+ We continue the inferior again, rld then maps in the actual user
+ executable and any needed shared libraries and then sends
+ itself a SIGTRAP.
+ At that point we discover the names of all shared libraries and
+ read their symbols in.
+
+ FIXME
+
+ This code does not properly handle hitting breakpoints which the
+ user might have set in the rld itself. Proper handling would have
+ to check if the SIGTRAP happened due to a kill call.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
void
-solib_create_inferior_hook()
+solib_create_inferior_hook ()
{
/* Nothing to do for statically bound executables. */
@@ -913,7 +893,7 @@ solib_create_inferior_hook()
which point all of the libraries will have been mapped in and we
can go groveling around in the rld structures to find
out what we need to know about them. */
-
+
clear_proceed_status ();
stop_soon_quietly = 1;
stop_signal = TARGET_SIGNAL_0;
@@ -925,11 +905,11 @@ solib_create_inferior_hook()
while (stop_signal != TARGET_SIGNAL_TRAP);
/* solib_add will call reinit_frame_cache.
- But we are stopped in the runtime loader and we do not have symbols
- for the runtime loader. So heuristic_proc_start will be called
- and will put out an annoying warning.
- Delaying the resetting of stop_soon_quietly until after symbol loading
- suppresses the warning. */
+ But we are stopped in the runtime loader and we do not have symbols
+ for the runtime loader. So heuristic_proc_start will be called
+ and will put out an annoying warning.
+ Delaying the resetting of stop_soon_quietly until after symbol loading
+ suppresses the warning. */
if (auto_solib_add)
solib_add ((char *) 0, 0, (struct target_ops *) 0);
stop_soon_quietly = 0;
@@ -938,33 +918,33 @@ solib_create_inferior_hook()
/*
-LOCAL FUNCTION
+ LOCAL FUNCTION
- sharedlibrary_command -- handle command to explicitly add library
+ sharedlibrary_command -- handle command to explicitly add library
-SYNOPSIS
+ SYNOPSIS
- static void sharedlibrary_command (char *args, int from_tty)
+ static void sharedlibrary_command (char *args, int from_tty)
-DESCRIPTION
+ DESCRIPTION
-*/
+ */
static void
sharedlibrary_command (args, from_tty)
-char *args;
-int from_tty;
+ char *args;
+ int from_tty;
{
dont_repeat ();
solib_add (args, from_tty, (struct target_ops *) 0);
}
void
-_initialize_solib()
+_initialize_solib ()
{
add_com ("sharedlibrary", class_files, sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
- add_info ("sharedlibrary", info_sharedlibrary_command,
+ add_info ("sharedlibrary", info_sharedlibrary_command,
"Status of loaded shared object libraries.");
add_show_from_set
diff --git a/contrib/gdb/gdb/ppcbug-rom.c b/contrib/gdb/gdb/ppcbug-rom.c
index 9496916..123161a 100644
--- a/contrib/gdb/gdb/ppcbug-rom.c
+++ b/contrib/gdb/gdb/ppcbug-rom.c
@@ -4,21 +4,22 @@
Written by Stu Grossman of Cygnus Support
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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"
@@ -26,8 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "monitor.h"
#include "serial.h"
-static void ppcbug_open PARAMS ((char *args, int from_tty));
-
static void
ppcbug_supply_register (regname, regnamelen, val, vallen)
char *regname;
@@ -35,7 +34,7 @@ ppcbug_supply_register (regname, regnamelen, val, vallen)
char *val;
int vallen;
{
- int regno = 0, base = 0;
+ int regno = 0;
if (regnamelen < 2 || regnamelen > 4)
return;
@@ -107,18 +106,18 @@ ppcbug_supply_register (regname, regnamelen, val, vallen)
static char *ppcbug_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",
+ "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",
- "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
- "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
"fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
"fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
/* pc ps cnd lr cnt xer mq */
- "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
+ "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
};
/*
@@ -130,65 +129,66 @@ static char *ppcbug_regnames[NUM_REGS] =
static struct target_ops ppcbug_ops0;
static struct target_ops ppcbug_ops1;
-static char *ppcbug_inits[] = {"\r", NULL};
+static char *ppcbug_inits[] =
+{"\r", NULL};
static void
-init_ppc_cmds (char * LOAD_CMD,
- struct monitor_ops * OPS,
- struct target_ops * targops)
+init_ppc_cmds (char *LOAD_CMD,
+ struct monitor_ops *OPS,
+ struct target_ops *targops)
{
- OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;
- OPS->init = ppcbug_inits; /* Init strings */
- OPS->cont = "g\r"; /* continue command */
- OPS->step = "t\r"; /* single step */
- OPS->stop = NULL; /* interrupt command */
- OPS->set_break = "br %x\r"; /* set a breakpoint */
- OPS->clr_break = "nobr %x\r"; /* clear a breakpoint */
+ OPS->flags = MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL;
+ OPS->init = ppcbug_inits; /* Init strings */
+ OPS->cont = "g\r"; /* continue command */
+ OPS->step = "t\r"; /* single step */
+ OPS->stop = NULL; /* interrupt command */
+ OPS->set_break = "br %x\r"; /* set a breakpoint */
+ OPS->clr_break = "nobr %x\r"; /* clear a breakpoint */
OPS->clr_all_break = "nobr\r"; /* clear all breakpoints */
- OPS->fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
- OPS->setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
- OPS->setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
- OPS->setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
- OPS->setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
- OPS->setmem.resp_delim = NULL; /* setreg.resp_delim */
- OPS->setmem.term = NULL; /* setreg.term */
- OPS->setmem.term_cmd = NULL; /* setreg.term_cmd */
- OPS->getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
- OPS->getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
- OPS->getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
- OPS->getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
- OPS->getmem.resp_delim = " "; /* getmem.resp_delim */
- OPS->getmem.term = NULL; /* getmem.term */
- OPS->getmem.term_cmd = NULL; /* getmem.term_cmd */
- OPS->setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
- OPS->setreg.resp_delim = NULL; /* setreg.resp_delim */
- OPS->setreg.term = NULL; /* setreg.term */
- OPS->setreg.term_cmd = NULL ; /* setreg.term_cmd */
- OPS->getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
- OPS->getreg.resp_delim = "="; /* getreg.resp_delim */
- OPS->getreg.term = NULL; /* getreg.term */
- OPS->getreg.term_cmd = NULL ; /* getreg.term_cmd */
- OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
- OPS->supply_register = ppcbug_supply_register; /* supply_register */
- OPS->dump_registers = "rd\r"; /* dump all registers */
- OPS->load_routine = NULL; /* load_routine (defaults to SRECs) */
- OPS->load = LOAD_CMD; /* download command */
- OPS->loadresp = NULL; /* load response */
- OPS->prompt = "PPC1-Bug>"; /* monitor command prompt */
- OPS->line_term = "\r"; /* end-of-line terminator */
- OPS->cmd_end = NULL; /* optional command terminator */
- OPS->target = targops ; /* target operations */
- OPS->stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
- OPS->regnames = ppcbug_regnames; /* registers names */
- OPS->magic = MONITOR_OPS_MAGIC; /* magic */
+ OPS->fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
+ OPS->setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
+ OPS->setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
+ OPS->setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
+ OPS->setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
+ OPS->setmem.resp_delim = NULL; /* setreg.resp_delim */
+ OPS->setmem.term = NULL; /* setreg.term */
+ OPS->setmem.term_cmd = NULL; /* setreg.term_cmd */
+ OPS->getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
+ OPS->getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
+ OPS->getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
+ OPS->getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
+ OPS->getmem.resp_delim = " "; /* getmem.resp_delim */
+ OPS->getmem.term = NULL; /* getmem.term */
+ OPS->getmem.term_cmd = NULL; /* getmem.term_cmd */
+ OPS->setreg.cmd = "rs %s %x\r"; /* setreg.cmd (name, value) */
+ OPS->setreg.resp_delim = NULL; /* setreg.resp_delim */
+ OPS->setreg.term = NULL; /* setreg.term */
+ OPS->setreg.term_cmd = NULL; /* setreg.term_cmd */
+ OPS->getreg.cmd = "rs %s\r"; /* getreg.cmd (name) */
+ OPS->getreg.resp_delim = "="; /* getreg.resp_delim */
+ OPS->getreg.term = NULL; /* getreg.term */
+ OPS->getreg.term_cmd = NULL; /* getreg.term_cmd */
+ OPS->register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
+ OPS->supply_register = ppcbug_supply_register; /* supply_register */
+ OPS->dump_registers = "rd\r"; /* dump all registers */
+ OPS->load_routine = NULL; /* load_routine (defaults to SRECs) */
+ OPS->load = LOAD_CMD; /* download command */
+ OPS->loadresp = NULL; /* load response */
+ OPS->prompt = "PPC1-Bug>"; /* monitor command prompt */
+ OPS->line_term = "\r"; /* end-of-line terminator */
+ OPS->cmd_end = NULL; /* optional command terminator */
+ OPS->target = targops; /* target operations */
+ OPS->stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
+ OPS->regnames = ppcbug_regnames; /* registers names */
+ OPS->magic = MONITOR_OPS_MAGIC; /* magic */
}
-static struct monitor_ops ppcbug_cmds0 ;
-static struct monitor_ops ppcbug_cmds1 ;
+static struct monitor_ops ppcbug_cmds0;
+static struct monitor_ops ppcbug_cmds1;
static void
-ppcbug_open0(args, from_tty)
+ppcbug_open0 (args, from_tty)
char *args;
int from_tty;
{
@@ -196,7 +196,7 @@ ppcbug_open0(args, from_tty)
}
static void
-ppcbug_open1(args, from_tty)
+ppcbug_open1 (args, from_tty)
char *args;
int from_tty;
{
@@ -206,8 +206,8 @@ ppcbug_open1(args, from_tty)
void
_initialize_ppcbug_rom ()
{
- init_ppc_cmds("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0) ;
- init_ppc_cmds("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
+ init_ppc_cmds ("lo 0\r", &ppcbug_cmds0, &ppcbug_ops0);
+ init_ppc_cmds ("lo 1\r", &ppcbug_cmds1, &ppcbug_ops1);
init_monitor_ops (&ppcbug_ops0);
ppcbug_ops0.to_shortname = "ppcbug";
diff --git a/contrib/gdb/gdb/procfs.c b/contrib/gdb/gdb/procfs.c
index ff20240..f385e94 100644
--- a/contrib/gdb/gdb/procfs.c
+++ b/contrib/gdb/gdb/procfs.c
@@ -1,7 +1,7 @@
/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1991, 1992-98, 1999 Free Software Foundation, Inc.
- Written by Fred Fish at Cygnus Support. Changes for sysv4.2mp procfs
- compatibility by Geoffrey Noer at Cygnus Solutions.
+ Copyright 1999 Free Software Foundation, Inc.
+ Written by Michael Snyder at Cygnus Solutions.
+ Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
This file is part of GDB.
@@ -16,117 +16,260 @@ 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. */
+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 "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "gdbthread.h"
-/* N O T E S
-
-For information on the details of using /proc consult section proc(4)
-in the UNIX System V Release 4 System Administrator's Reference Manual.
-
-The general register and floating point register sets are manipulated
-separately. This file makes the assumption that if FP0_REGNUM is
-defined, then support for the floating point register set is desired,
-regardless of whether or not the actual target has floating point hardware.
+#if defined (NEW_PROC_API)
+#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
+#endif
+#include <sys/procfs.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/errno.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <ctype.h>
+
+#include "proc-utils.h"
+
+/*
+ * PROCFS.C
+ *
+ * This module provides the interface between GDB and the
+ * /proc file system, which is used on many versions of Unix
+ * as a means for debuggers to control other processes.
+ * Examples of the systems that use this interface are:
+ * Irix
+ * Solaris
+ * OSF
+ * Unixware
+ *
+ * /proc works by immitating a file system: you open a simulated file
+ * that represents the process you wish to interact with, and
+ * perform operations on that "file" in order to examine or change
+ * the state of the other process.
+ *
+ * The most important thing to know about /proc and this module
+ * is that there are two very different interfaces to /proc:
+ * One that uses the ioctl system call, and
+ * another that uses read and write system calls.
+ * This module has to support both /proc interfaces. This means
+ * that there are two different ways of doing every basic operation.
+ *
+ * In order to keep most of the code simple and clean, I have
+ * defined an interface "layer" which hides all these system calls.
+ * An ifdef (NEW_PROC_API) determines which interface we are using,
+ * and most or all occurrances of this ifdef should be confined to
+ * this interface layer.
*/
-#include "defs.h"
+/* Determine which /proc API we are using:
+ The ioctl API defines PIOCSTATUS, while
+ the read/write (multiple fd) API never does. */
+#ifdef NEW_PROC_API
#include <sys/types.h>
-#include <time.h>
-#include <sys/fault.h>
-#include <sys/syscall.h>
-#include <sys/procfs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "gdb_string.h"
-#include <stropts.h>
-#include <poll.h>
-#include <unistd.h>
-#include "gdb_stat.h"
+#include <dirent.h> /* opendir/readdir, for listing the LWP's */
+#endif
-#include "inferior.h"
-#include "target.h"
-#include "command.h"
-#include "gdbcore.h"
-#include "gdbthread.h"
+#include <fcntl.h> /* for O_RDONLY */
+#include <unistd.h> /* for "X_OK" */
+#include "gdb_stat.h" /* for struct stat */
-#if !defined(SYS_lwp_create) && defined(SYS_lwpcreate)
-# define SYS_lwp_create SYS_lwpcreate
-#endif
+/* =================== TARGET_OPS "MODULE" =================== */
-#if !defined(SYS_lwp_exit) && defined(SYS_lwpexit)
-# define SYS_lwp_exit SYS_lwpexit
-#endif
+/*
+ * This module defines the GDB target vector and its methods.
+ */
-#if !defined(SYS_lwp_wait) && defined(SYS_lwpwait)
-# define SYS_lwp_wait SYS_lwpwait
-#endif
+static void procfs_open PARAMS((char *, int));
+static void procfs_attach PARAMS ((char *, int));
+static void procfs_detach PARAMS ((char *, int));
+static void procfs_resume PARAMS ((int, int, enum target_signal));
+static int procfs_can_run PARAMS ((void));
+static void procfs_stop PARAMS ((void));
+static void procfs_files_info PARAMS ((struct target_ops *));
+static void procfs_fetch_registers PARAMS ((int));
+static void procfs_store_registers PARAMS ((int));
+static void procfs_notice_signals PARAMS ((int));
+static void procfs_prepare_to_store PARAMS ((void));
+static void procfs_kill_inferior PARAMS ((void));
+static void procfs_mourn_inferior PARAMS ((void));
+static void procfs_create_inferior PARAMS ((char *, char *, char **));
+static int procfs_wait PARAMS ((int,
+ struct target_waitstatus *));
+static int procfs_xfer_memory PARAMS ((CORE_ADDR,
+ char *, int, int,
+ struct target_ops *));
+
+static int procfs_thread_alive PARAMS ((int));
+
+void procfs_find_new_threads PARAMS ((void));
+char *procfs_pid_to_str PARAMS ((int));
+
+struct target_ops procfs_ops; /* the target vector */
-#if !defined(SYS_lwp_self) && defined(SYS_lwpself)
-# define SYS_lwp_self SYS_lwpself
-#endif
+static void
+init_procfs_ops ()
+{
+ procfs_ops.to_shortname = "procfs";
+ procfs_ops.to_longname = "Unix /proc child process";
+ procfs_ops.to_doc =
+ "Unix /proc child process (started by the \"run\" command).";
+ procfs_ops.to_open = procfs_open;
+ procfs_ops.to_can_run = procfs_can_run;
+ procfs_ops.to_create_inferior = procfs_create_inferior;
+ procfs_ops.to_kill = procfs_kill_inferior;
+ procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
+ procfs_ops.to_attach = procfs_attach;
+ procfs_ops.to_detach = procfs_detach;
+ procfs_ops.to_wait = procfs_wait;
+ procfs_ops.to_resume = procfs_resume;
+ procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
+ procfs_ops.to_fetch_registers = procfs_fetch_registers;
+ procfs_ops.to_store_registers = procfs_store_registers;
+ procfs_ops.to_xfer_memory = procfs_xfer_memory;
+ procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ procfs_ops.to_notice_signals = procfs_notice_signals;
+ procfs_ops.to_files_info = procfs_files_info;
+ procfs_ops.to_stop = procfs_stop;
+
+ procfs_ops.to_terminal_init = terminal_init_inferior;
+ procfs_ops.to_terminal_inferior = terminal_inferior;
+ procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ procfs_ops.to_terminal_ours = terminal_ours;
+ procfs_ops.to_terminal_info = child_terminal_info;
+
+ procfs_ops.to_find_new_threads = procfs_find_new_threads;
+ procfs_ops.to_thread_alive = procfs_thread_alive;
+ procfs_ops.to_pid_to_str = procfs_pid_to_str;
+
+ procfs_ops.to_has_all_memory = 1;
+ procfs_ops.to_has_memory = 1;
+ procfs_ops.to_has_execution = 1;
+ procfs_ops.to_has_stack = 1;
+ procfs_ops.to_has_registers = 1;
+ procfs_ops.to_stratum = process_stratum;
+ procfs_ops.to_has_thread_control = tc_schedlock;
+ procfs_ops.to_magic = OPS_MAGIC;
+}
-#if !defined(SYS_lwp_info) && defined(SYS_lwpinfo)
-# define SYS_lwp_info SYS_lwpinfo
-#endif
+/* =================== END, TARGET_OPS "MODULE" =================== */
-#if !defined(SYS_lwp_private) && defined(SYS_lwpprivate)
-# define SYS_lwp_private SYS_lwpprivate
-#endif
+/*
+ * Temporary debugging code:
+ *
+ * These macros allow me to trace the system calls that we make
+ * to control the child process. This is quite handy for comparing
+ * with the older version of procfs.
+ */
-#if !defined(SYS_lwp_kill) && defined(SYS_lwpkill)
-# define SYS_lwp_kill SYS_lwpkill
+#ifdef TRACE_PROCFS
+#ifdef NEW_PROC_API
+extern int write_with_trace PARAMS ((int, void *, size_t, char *, int));
+extern off_t lseek_with_trace PARAMS ((int, off_t, int, char *, int));
+#define write(X,Y,Z) write_with_trace (X, Y, Z, __FILE__, __LINE__)
+#define lseek(X,Y,Z) lseek_with_trace (X, Y, Z, __FILE__, __LINE__)
+#else
+extern int ioctl_with_trace PARAMS ((int, long, void *, char *, int));
+#define ioctl(X,Y,Z) ioctl_with_trace (X, Y, Z, __FILE__, __LINE__)
+#endif
+#define open(X,Y) open_with_trace (X, Y, __FILE__, __LINE__)
+#define close(X) close_with_trace (X, __FILE__, __LINE__)
+#define wait(X) wait_with_trace (X, __FILE__, __LINE__)
+#define PROCFS_NOTE(X) procfs_note (X, __FILE__, __LINE__)
+#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T) \
+proc_prettyfprint_status (X, Y, Z, T)
+#else
+#define PROCFS_NOTE(X)
+#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T)
#endif
-#if !defined(SYS_lwp_suspend) && defined(SYS_lwpsuspend)
-# define SYS_lwp_suspend SYS_lwpsuspend
-#endif
-#if !defined(SYS_lwp_continue) && defined(SYS_lwpcontinue)
-# define SYS_lwp_continue SYS_lwpcontinue
-#endif
+/*
+ * World Unification:
+ *
+ * Put any typedefs, defines etc. here that are required for
+ * the unification of code that handles different versions of /proc.
+ */
-/* the name of the proc status struct depends on the implementation */
-/* Wrap Light Weight Process member in THE_PR_LWP macro for clearer code */
-#ifndef HAVE_PSTATUS_T
- typedef prstatus_t gdb_prstatus_t;
-#define THE_PR_LWP(a) a
-#else /* HAVE_PSTATUS_T */
- typedef pstatus_t gdb_prstatus_t;
-#define THE_PR_LWP(a) a.pr_lwp
-#if !defined(HAVE_PRRUN_T) && defined(HAVE_MULTIPLE_PROC_FDS)
- /* Fallback definitions - for using configure information directly */
+#ifdef NEW_PROC_API /* Solaris 7 && 8 method for watchpoints */
#ifndef UNIXWARE
-#define UNIXWARE 1
+ enum { READ_WATCHFLAG = WA_READ,
+ WRITE_WATCHFLAG = WA_WRITE,
+ EXEC_WATCHFLAG = WA_EXEC,
+ AFTER_WATCHFLAG = WA_TRAPAFTER
+ };
#endif
-#if !defined(PROCFS_USE_READ_WRITE) && !defined(HAVE_PROCFS_PIOCSET)
-#define PROCFS_USE_READ_WRITE 1
+#else /* Irix method for watchpoints */
+ enum { READ_WATCHFLAG = MA_READ,
+ WRITE_WATCHFLAG = MA_WRITE,
+ EXEC_WATCHFLAG = MA_EXEC,
+ AFTER_WATCHFLAG = 0 /* trapafter not implemented */
+ };
#endif
-#endif /* !HAVE_PRRUN_T && HAVE_MULTIPLE_PROC_FDS */
-#endif /* HAVE_PSTATUS_T */
-#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
-/* proc name formats may vary depending on the proc implementation */
-#ifdef HAVE_MULTIPLE_PROC_FDS
-# ifndef CTL_PROC_NAME_FMT
-# define CTL_PROC_NAME_FMT "/proc/%d/ctl"
-# define AS_PROC_NAME_FMT "/proc/%d/as"
-# define MAP_PROC_NAME_FMT "/proc/%d/map"
+
+
+/* =================== STRUCT PROCINFO "MODULE" =================== */
+
+ /* FIXME: this comment will soon be out of date W.R.T. threads. */
+
+/* The procinfo struct is a wrapper to hold all the state information
+ concerning a /proc process. There should be exactly one procinfo
+ for each process, and since GDB currently can debug only one
+ process at a time, that means there should be only one procinfo.
+ All of the LWP's of a process can be accessed indirectly thru the
+ single process procinfo.
+
+ However, against the day when GDB may debug more than one process,
+ this data structure is kept in a list (which for now will hold no
+ more than one member), and many functions will have a pointer to a
+ procinfo as an argument.
+
+ There will be a separate procinfo structure for use by the (not yet
+ implemented) "info proc" command, so that we can print useful
+ information about any random process without interfering with the
+ inferior's procinfo information. */
+
+#ifdef NEW_PROC_API
+/* format strings for /proc paths */
+# ifndef CTL_PROC_NAME_FMT
+# define MAIN_PROC_NAME_FMT "/proc/%d"
+# define CTL_PROC_NAME_FMT "/proc/%d/ctl"
+# define AS_PROC_NAME_FMT "/proc/%d/as"
+# define MAP_PROC_NAME_FMT "/proc/%d/map"
# define STATUS_PROC_NAME_FMT "/proc/%d/status"
-# endif
-#else /* HAVE_MULTIPLE_PROC_FDS */
-# ifndef CTL_PROC_NAME_FMT
-# define CTL_PROC_NAME_FMT "/proc/%05d"
-# define AS_PROC_NAME_FMT "/proc/%05d"
-# define MAP_PROC_NAME_FMT "/proc/%05d"
+# define MAX_PROC_NAME_SIZE sizeof("/proc/99999/lwp/8096/lstatus")
+# endif
+/* the name of the proc status struct depends on the implementation */
+typedef pstatus_t gdb_prstatus_t;
+typedef lwpstatus_t gdb_lwpstatus_t;
+#else /* ! NEW_PROC_API */
+/* format strings for /proc paths */
+# ifndef CTL_PROC_NAME_FMT
+# define MAIN_PROC_NAME_FMT "/proc/%05d"
+# define CTL_PROC_NAME_FMT "/proc/%05d"
+# define AS_PROC_NAME_FMT "/proc/%05d"
+# define MAP_PROC_NAME_FMT "/proc/%05d"
# define STATUS_PROC_NAME_FMT "/proc/%05d"
-# endif
-#endif /* HAVE_MULTIPLE_PROC_FDS */
+# define MAX_PROC_NAME_SIZE sizeof("/proc/ttttppppp")
+# endif
+/* the name of the proc status struct depends on the implementation */
+typedef prstatus_t gdb_prstatus_t;
+typedef prstatus_t gdb_lwpstatus_t;
+#endif /* NEW_PROC_API */
/* These #ifdefs are for sol2.x in particular. sol2.x has
@@ -146,5297 +289,4431 @@ regardless of whether or not the actual target has floating point hardware.
typedef fpregset_t gdb_fpregset_t;
#endif
+/* Provide default composite pid manipulation macros for systems that
+ don't have threads. */
-#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
-
-struct target_ops procfs_ops;
-
-int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to
- be a runnable target. Used by targets
- that can sit atop procfs, such as solaris
- thread support. */
-
-#if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */
-CORE_ADDR kernel_u_addr;
+#ifndef PIDGET
+#define PIDGET(PID) (PID)
+#define TIDGET(PID) (PID)
+#endif
+#ifndef MERGEPID
+#define MERGEPID(PID, TID) (PID)
#endif
-#ifdef BROKEN_SIGINFO_H /* Workaround broken SGS <sys/siginfo.h> */
-#undef si_pid
-#define si_pid _data._proc.pid
-#undef si_uid
-#define si_uid _data._proc._pdata._kill.uid
-#endif /* BROKEN_SIGINFO_H */
-
-/* Define structures for passing commands to /proc/pid/ctl file. Note that
- while we create these for the PROCFS_USE_READ_WRITE world, we use them
- and ignore the extra cmd int in other proc schemes.
-*/
-/* generic ctl msg */
-struct proc_ctl {
- int cmd;
- long data;
-};
-
-/* set general registers */
-struct greg_ctl {
- int cmd;
- gdb_gregset_t gregset;
-};
-
-/* set fp registers */
-struct fpreg_ctl {
- int cmd;
- gdb_fpregset_t fpregset;
-};
-
-/* set signals to be traced */
-struct sig_ctl {
- int cmd;
- sigset_t sigset;
-};
-
-/* set faults to be traced */
-struct flt_ctl {
- int cmd;
- fltset_t fltset;
-};
-
-/* set system calls to be traced */
-struct sys_ctl {
- int cmd;
- sysset_t sysset;
-};
-
-/* set current signal to be traced */
-struct sigi_ctl {
- int cmd;
- siginfo_t siginfo;
-};
-
-/* All access to the inferior, either one started by gdb or one that has
- been attached to, is controlled by an instance of a procinfo structure,
- defined below. Since gdb currently only handles one inferior at a time,
- the procinfo structure for the inferior is statically allocated and
- only one exists at any given time. There is a separate procinfo
- structure for use by the "info proc" command, so that we can print
- useful information about any random process without interfering with
- the inferior's procinfo information. */
-
-struct procinfo {
+typedef struct procinfo {
struct procinfo *next;
- int pid; /* Process ID of inferior */
- int ctl_fd; /* File descriptor for /proc ctl file */
+ int pid; /* Process ID */
+ int tid; /* Thread/LWP id */
+
+ /* process state */
+ int was_stopped;
+ int ignore_next_sigstop;
+
+ /* The following four fd fields may be identical, or may contain
+ several different fd's, depending on the version of /proc
+ (old ioctl or new read/write). */
+
+ int ctl_fd; /* File descriptor for /proc control file */
+ /*
+ * The next three file descriptors are actually only needed in the
+ * read/write, multiple-file-descriptor implemenation (NEW_PROC_API).
+ * However, to avoid a bunch of #ifdefs in the code, we will use
+ * them uniformly by (in the case of the ioctl single-file-descriptor
+ * implementation) filling them with copies of the control fd.
+ */
int status_fd; /* File descriptor for /proc status file */
int as_fd; /* File descriptor for /proc as file */
- int map_fd; /* File descriptor for /proc map file */
- char *pathname; /* Pathname to /proc entry */
- int had_event; /* poll/select says something happened */
- int was_stopped; /* Nonzero if was stopped prior to attach */
- int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
-#ifdef HAVE_PRRUN_T
- prrun_t prrun; /* Control state when it is run */
-#endif
- gdb_prstatus_t prstatus; /* Current process status info */
- struct greg_ctl gregset; /* General register set */
- struct fpreg_ctl fpregset; /* Floating point register set */
- struct flt_ctl fltset; /* Current traced hardware fault set */
- struct sig_ctl trace; /* Current traced signal set */
- struct sys_ctl exitset; /* Current traced system call exit set */
- struct sys_ctl entryset; /* Current traced system call entry set */
- struct sig_ctl saved_sighold; /* Saved held signal set */
- struct flt_ctl saved_fltset; /* Saved traced hardware fault set */
- struct sig_ctl saved_trace; /* Saved traced signal set */
- struct sys_ctl saved_exitset; /* Saved traced system call exit set */
- struct sys_ctl saved_entryset;/* Saved traced system call entry set */
- int num_syscall_handlers; /* Number of syscall trap handlers
- currently installed */
- /* Pointer to list of syscall trap handlers */
- struct procfs_syscall_handler *syscall_handlers;
- int saved_rtnval; /* return value and status for wait(), */
- int saved_statval; /* as supplied by a syscall handler. */
- int new_child; /* Non-zero if it's a new thread */
-};
-
-/* List of inferior process information */
-static struct procinfo *procinfo_list = NULL;
-static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
-
-static int num_poll_list = 0; /* Number of entries in poll_list */
-
-/* Much of the information used in the /proc interface, particularly for
- printing status information, is kept as tables of structures of the
- following form. These tables can be used to map numeric values to
- their symbolic names and to a string that describes their specific use. */
-
-struct trans {
- int value; /* The numeric value */
- char *name; /* The equivalent symbolic value */
- char *desc; /* Short description of value */
-};
-
-/* Translate bits in the pr_flags member of the prstatus structure, into the
- names and desc information. */
-
-static struct trans pr_flag_table[] =
-{
-#if defined (PR_STOPPED)
- { PR_STOPPED, "PR_STOPPED", "Process is stopped" },
-#endif
-#if defined (PR_ISTOP)
- { PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest" },
-#endif
-#if defined (PR_DSTOP)
- { PR_DSTOP, "PR_DSTOP", "A stop directive is in effect" },
-#endif
-#if defined (PR_ASLEEP)
- { PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call" },
-#endif
-#if defined (PR_FORK)
- { PR_FORK, "PR_FORK", "Inherit-on-fork is in effect" },
-#endif
-#if defined (PR_RLC)
- { PR_RLC, "PR_RLC", "Run-on-last-close is in effect" },
-#endif
-#if defined (PR_PTRACE)
- { PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace" },
-#endif
-#if defined (PR_PCINVAL)
- { PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address" },
-#endif
-#if defined (PR_ISSYS)
- { PR_ISSYS, "PR_ISSYS", "Is a system process" },
-#endif
-#if defined (PR_STEP)
- { PR_STEP, "PR_STEP", "Process has single step pending" },
-#endif
-#if defined (PR_KLC)
- { PR_KLC, "PR_KLC", "Kill-on-last-close is in effect" },
-#endif
-#if defined (PR_ASYNC)
- { PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" },
-#endif
-#if defined (PR_PCOMPAT)
- { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
-#endif
-#if defined (PR_MSACCT)
- { PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
-#endif
-#if defined (PR_BPTADJ)
- { PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
-#endif
-#if defined (PR_ASLWP)
- { PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
-#endif
- { 0, NULL, NULL }
-};
-/* Translate values in the pr_why field of the prstatus struct. */
+ char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */
-static struct trans pr_why_table[] =
-{
-#if defined (PR_REQUESTED)
- { PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP" },
-#endif
-#if defined (PR_SIGNALLED)
- { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
-#endif
-#if defined (PR_SYSENTRY)
- { PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
-#endif
-#if defined (PR_SYSEXIT)
- { PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call" },
-#endif
-#if defined (PR_JOBCONTROL)
- { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
-#endif
-#if defined (PR_FAULTED)
- { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
-#endif
-#if defined (PR_SUSPENDED)
- { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
-#endif
-#if defined (PR_CHECKPOINT)
- { PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
-#endif
- { 0, NULL, NULL }
-};
-
-/* Hardware fault translation table. */
+ fltset_t saved_fltset; /* Saved traced hardware fault set */
+ sigset_t saved_sigset; /* Saved traced signal set */
+ sigset_t saved_sighold; /* Saved held signal set */
+ sysset_t saved_exitset; /* Saved traced system call exit set */
+ sysset_t saved_entryset; /* Saved traced system call entry set */
-static struct trans faults_table[] =
-{
-#if defined (FLTILL)
- { FLTILL, "FLTILL", "Illegal instruction" },
-#endif
-#if defined (FLTPRIV)
- { FLTPRIV, "FLTPRIV", "Privileged instruction" },
-#endif
-#if defined (FLTBPT)
- { FLTBPT, "FLTBPT", "Breakpoint trap" },
-#endif
-#if defined (FLTTRACE)
- { FLTTRACE, "FLTTRACE", "Trace trap" },
-#endif
-#if defined (FLTACCESS)
- { FLTACCESS, "FLTACCESS", "Memory access fault" },
-#endif
-#if defined (FLTBOUNDS)
- { FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation" },
-#endif
-#if defined (FLTIOVF)
- { FLTIOVF, "FLTIOVF", "Integer overflow" },
-#endif
-#if defined (FLTIZDIV)
- { FLTIZDIV, "FLTIZDIV", "Integer zero divide" },
-#endif
-#if defined (FLTFPE)
- { FLTFPE, "FLTFPE", "Floating-point exception" },
-#endif
-#if defined (FLTSTACK)
- { FLTSTACK, "FLTSTACK", "Unrecoverable stack fault" },
-#endif
-#if defined (FLTPAGE)
- { FLTPAGE, "FLTPAGE", "Recoverable page fault" },
-#endif
- { 0, NULL, NULL }
-};
-
-/* Translation table for signal generation information. See UNIX System
- V Release 4 Programmer's Reference Manual, siginfo(5). */
+ gdb_prstatus_t prstatus; /* Current process status info */
-static struct sigcode {
- int signo;
- int code;
- char *codename;
- char *desc;
-} siginfo_table[] = {
-#if defined (SIGILL) && defined (ILL_ILLOPC)
- { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode" },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLOPN)
- { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLADR)
- { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode" },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLTRP)
- { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap" },
-#endif
-#if defined (SIGILL) && defined (ILL_PRVOPC)
- { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode" },
-#endif
-#if defined (SIGILL) && defined (ILL_PRVREG)
- { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register" },
-#endif
-#if defined (SIGILL) && defined (ILL_COPROC)
- { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error" },
-#endif
-#if defined (SIGILL) && defined (ILL_BADSTK)
- { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error" },
-#endif
-#if defined (SIGFPE) && defined (FPE_INTDIV)
- { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero" },
-#endif
-#if defined (SIGFPE) && defined (FPE_INTOVF)
- { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTDIV)
- { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTOVF)
- { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTUND)
- { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTRES)
- { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTINV)
- { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation" },
+#ifndef NEW_PROC_API
+ gdb_fpregset_t fpregset; /* Current floating point registers */
#endif
-#if defined (SIGFPE) && defined (FPE_FLTSUB)
- { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range" },
-#endif
-#if defined (SIGSEGV) && defined (SEGV_MAPERR)
- { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object" },
-#endif
-#if defined (SIGSEGV) && defined (SEGV_ACCERR)
- { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object" },
-#endif
-#if defined (SIGBUS) && defined (BUS_ADRALN)
- { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment" },
-#endif
-#if defined (SIGBUS) && defined (BUS_ADRERR)
- { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address" },
-#endif
-#if defined (SIGBUS) && defined (BUS_OBJERR)
- { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error" },
-#endif
-#if defined (SIGTRAP) && defined (TRAP_BRKPT)
- { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint" },
-#endif
-#if defined (SIGTRAP) && defined (TRAP_TRACE)
- { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap" },
-#endif
-#if defined (SIGCLD) && defined (CLD_EXITED)
- { SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited" },
-#endif
-#if defined (SIGCLD) && defined (CLD_KILLED)
- { SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed" },
-#endif
-#if defined (SIGCLD) && defined (CLD_DUMPED)
- { SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally" },
-#endif
-#if defined (SIGCLD) && defined (CLD_TRAPPED)
- { SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped" },
-#endif
-#if defined (SIGCLD) && defined (CLD_STOPPED)
- { SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped" },
-#endif
-#if defined (SIGCLD) && defined (CLD_CONTINUED)
- { SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_IN)
- { SIGPOLL, POLL_IN, "POLL_IN", "Input input available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_OUT)
- { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_MSG)
- { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_ERR)
- { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_PRI)
- { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_HUP)
- { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected" },
-#endif
- { 0, 0, NULL, NULL }
-};
-
-static char *syscall_table[MAX_SYSCALLS];
-
-/* Prototypes for local functions */
-
-static void procfs_stop PARAMS ((void));
-
-static int procfs_thread_alive PARAMS ((int));
-
-static int procfs_can_run PARAMS ((void));
-
-static void procfs_mourn_inferior PARAMS ((void));
-
-static void procfs_fetch_registers PARAMS ((int));
-
-static int procfs_wait PARAMS ((int, struct target_waitstatus *));
-
-static void procfs_open PARAMS ((char *, int));
-
-static void procfs_files_info PARAMS ((struct target_ops *));
-
-static void procfs_prepare_to_store PARAMS ((void));
-
-static void procfs_detach PARAMS ((char *, int));
-
-static void procfs_attach PARAMS ((char *, int));
-
-static void proc_set_exec_trap PARAMS ((void));
+
+ struct procinfo *thread_list;
-static void procfs_init_inferior PARAMS ((int));
+ int status_valid : 1;
+ int gregs_valid : 1;
+ int fpregs_valid : 1;
+ int threads_valid: 1;
+} procinfo;
-static struct procinfo *create_procinfo PARAMS ((int));
+static char errmsg[128]; /* shared error msg buffer */
-static void procfs_store_registers PARAMS ((int));
+/* Function prototypes for procinfo module: */
-static int procfs_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+static procinfo *find_procinfo_or_die PARAMS ((int pid, int tid));
+static procinfo *find_procinfo PARAMS ((int pid, int tid));
+static procinfo *create_procinfo PARAMS ((int pid, int tid));
+static void destroy_procinfo PARAMS ((procinfo *p));
+static void dead_procinfo PARAMS ((procinfo *p,
+ char *msg, int killp));
+static int open_procinfo_files PARAMS ((procinfo *p, int which));
+static void close_procinfo_files PARAMS ((procinfo *p));
-static void procfs_kill_inferior PARAMS ((void));
+/* The head of the procinfo list: */
+static procinfo * procinfo_list;
-static char *sigcodedesc PARAMS ((siginfo_t *));
+/*
+ * Function: find_procinfo
+ *
+ * Search the procinfo list.
+ *
+ * Returns: pointer to procinfo, or NULL if not found.
+ */
-static char *sigcodename PARAMS ((siginfo_t *));
+static procinfo *
+find_procinfo (pid, tid)
+ int pid;
+ int tid;
+{
+ procinfo *pi;
-static struct procinfo *wait_fd PARAMS ((void));
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->pid == pid)
+ break;
-static void remove_fd PARAMS ((struct procinfo *));
+ if (pi)
+ if (tid)
+ {
+ /* Don't check threads_valid. If we're updating the
+ thread_list, we want to find whatever threads are already
+ here. This means that in general it is the caller's
+ responsibility to check threads_valid and update before
+ calling find_procinfo, if the caller wants to find a new
+ thread. */
+
+ for (pi = pi->thread_list; pi; pi = pi->next)
+ if (pi->tid == tid)
+ break;
+ }
-static void add_fd PARAMS ((struct procinfo *));
+ return pi;
+}
-static void set_proc_siginfo PARAMS ((struct procinfo *, int));
+/*
+ * Function: find_procinfo_or_die
+ *
+ * Calls find_procinfo, but errors on failure.
+ */
-static void init_syscall_table PARAMS ((void));
+static procinfo *
+find_procinfo_or_die (pid, tid)
+ int pid;
+ int tid;
+{
+ procinfo *pi = find_procinfo (pid, tid);
-static char *syscallname PARAMS ((int));
+ if (pi == NULL)
+ {
+ if (tid)
+ error ("procfs: couldn't find pid %d (kernel thread %d) in procinfo list.",
+ pid, tid);
+ else
+ error ("procfs: couldn't find pid %d in procinfo list.", pid);
+ }
+ return pi;
+}
-static char *signalname PARAMS ((int));
+/*
+ * Function: open_procinfo_files
+ *
+ * Open the file descriptor for the process or LWP.
+ * ifdef NEW_PROC_API, we only open the control file descriptor;
+ * the others are opened lazily as needed.
+ * else (if not NEW_PROC_API), there is only one real
+ * file descriptor, but we keep multiple copies of it so that
+ * the code that uses them does not have to be #ifdef'd.
+ *
+ * Return: file descriptor, or zero for failure.
+ */
-static char *errnoname PARAMS ((int));
+enum { FD_CTL, FD_STATUS, FD_AS };
-static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
+static int
+open_procinfo_files (pi, which)
+ procinfo *pi;
+ int which;
+{
+#ifdef NEW_PROC_API
+ char tmp[MAX_PROC_NAME_SIZE];
+#endif
+ int fd;
+
+ /*
+ * This function is getting ALMOST long enough to break up into several.
+ * Here is some rationale:
+ *
+ * NEW_PROC_API (Solaris 2.6, Solaris 2.7, Unixware):
+ * There are several file descriptors that may need to be open
+ * for any given process or LWP. The ones we're intereted in are:
+ * - control (ctl) write-only change the state
+ * - status (status) read-only query the state
+ * - address space (as) read/write access memory
+ * - map (map) read-only virtual addr map
+ * Most of these are opened lazily as they are needed.
+ * The pathnames for the 'files' for an LWP look slightly
+ * different from those of a first-class process:
+ * Pathnames for a process (<proc-id>):
+ * /proc/<proc-id>/ctl
+ * /proc/<proc-id>/status
+ * /proc/<proc-id>/as
+ * /proc/<proc-id>/map
+ * Pathnames for an LWP (lwp-id):
+ * /proc/<proc-id>/lwp/<lwp-id>/lwpctl
+ * /proc/<proc-id>/lwp/<lwp-id>/lwpstatus
+ * An LWP has no map or address space file descriptor, since
+ * the memory map and address space are shared by all LWPs.
+ *
+ * Everyone else (Solaris 2.5, Irix, OSF)
+ * There is only one file descriptor for each process or LWP.
+ * For convenience, we copy the same file descriptor into all
+ * three fields of the procinfo struct (ctl_fd, status_fd, and
+ * as_fd, see NEW_PROC_API above) so that code that uses them
+ * doesn't need any #ifdef's.
+ * Pathname for all:
+ * /proc/<proc-id>
+ *
+ * Solaris 2.5 LWP's:
+ * Each LWP has an independent file descriptor, but these
+ * are not obtained via the 'open' system call like the rest:
+ * instead, they're obtained thru an ioctl call (PIOCOPENLWP)
+ * to the file descriptor of the parent process.
+ *
+ * OSF threads:
+ * These do not even have their own independent file descriptor.
+ * All operations are carried out on the file descriptor of the
+ * parent process. Therefore we just call open again for each
+ * thread, getting a new handle for the same 'file'.
+ */
+
+#ifdef NEW_PROC_API
+ /*
+ * In this case, there are several different file descriptors that
+ * we might be asked to open. The control file descriptor will be
+ * opened early, but the others will be opened lazily as they are
+ * needed.
+ */
+
+ strcpy (tmp, pi->pathname);
+ switch (which) { /* which file descriptor to open? */
+ case FD_CTL:
+ if (pi->tid)
+ strcat (tmp, "/lwpctl");
+ else
+ strcat (tmp, "/ctl");
+ fd = open (tmp, O_WRONLY);
+ if (fd <= 0)
+ return 0; /* fail */
+ pi->ctl_fd = fd;
+ break;
+ case FD_AS:
+ if (pi->tid)
+ return 0; /* there is no 'as' file descriptor for an lwp */
+ strcat (tmp, "/as");
+ fd = open (tmp, O_RDWR);
+ if (fd <= 0)
+ return 0; /* fail */
+ pi->as_fd = fd;
+ break;
+ case FD_STATUS:
+ if (pi->tid)
+ strcat (tmp, "/lwpstatus");
+ else
+ strcat (tmp, "/status");
+ fd = open (tmp, O_RDONLY);
+ if (fd <= 0)
+ return 0; /* fail */
+ pi->status_fd = fd;
+ break;
+ default:
+ return 0; /* unknown file descriptor */
+ }
+#else /* not NEW_PROC_API */
+ /*
+ * In this case, there is only one file descriptor for each procinfo
+ * (ie. each process or LWP). In fact, only the file descriptor for
+ * the process can actually be opened by an 'open' system call.
+ * The ones for the LWPs have to be obtained thru an IOCTL call
+ * on the process's file descriptor.
+ *
+ * For convenience, we copy each procinfo's single file descriptor
+ * into all of the fields occupied by the several file descriptors
+ * of the NEW_PROC_API implementation. That way, the code that uses
+ * them can be written without ifdefs.
+ */
+
+
+#ifdef PIOCTSTATUS /* OSF */
+ if ((fd = open (pi->pathname, O_RDWR)) == 0) /* Only one FD; just open it. */
+ return 0;
+#else /* Sol 2.5, Irix, other? */
+ if (pi->tid == 0) /* Master procinfo for the process */
+ {
+ fd = open (pi->pathname, O_RDWR);
+ if (fd <= 0)
+ return 0; /* fail */
+ }
+ else /* LWP thread procinfo */
+ {
+#ifdef PIOCOPENLWP /* Sol 2.5, thread/LWP */
+ procinfo *process;
+ int lwpid = pi->tid;
+
+ /* Find the procinfo for the entire process. */
+ if ((process = find_procinfo (pi->pid, 0)) == NULL)
+ return 0; /* fail */
+
+ /* Now obtain the file descriptor for the LWP. */
+ if ((fd = ioctl (process->ctl_fd, PIOCOPENLWP, &lwpid)) <= 0)
+ return 0; /* fail */
+#else /* Irix, other? */
+ return 0; /* Don't know how to open threads */
+#endif /* Sol 2.5 PIOCOPENLWP */
+ }
+#endif /* OSF PIOCTSTATUS */
+ pi->ctl_fd = pi->as_fd = pi->status_fd = fd;
+#endif /* NEW_PROC_API */
-static int open_proc_file PARAMS ((int, struct procinfo *, int, int));
+ return 1; /* success */
+}
-static void close_proc_file PARAMS ((struct procinfo *));
+/*
+ * Function: create_procinfo
+ *
+ * Allocate a data structure and link it into the procinfo list.
+ * (First tries to find a pre-existing one (FIXME: why???)
+ *
+ * Return: pointer to new procinfo struct.
+ */
-static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
+static procinfo *
+create_procinfo (pid, tid)
+ int pid;
+ int tid;
+{
+ procinfo *pi, *parent;
-static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
+ if ((pi = find_procinfo (pid, tid)))
+ return pi; /* Already exists, nothing to do. */
-static void info_proc PARAMS ((char *, int));
+ /* find parent before doing malloc, to save having to cleanup */
+ if (tid != 0)
+ parent = find_procinfo_or_die (pid, 0); /* FIXME: should I
+ create it if it
+ doesn't exist yet? */
-static void info_proc_flags PARAMS ((struct procinfo *, int));
+ pi = (procinfo *) xmalloc (sizeof (procinfo));
+ memset (pi, 0, sizeof (procinfo));
+ pi->pid = pid;
+ pi->tid = tid;
-static void info_proc_stop PARAMS ((struct procinfo *, int));
+ /* Chain into list. */
+ if (tid == 0)
+ {
+ sprintf (pi->pathname, MAIN_PROC_NAME_FMT, pid);
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+ }
+ else
+ {
+#ifdef NEW_PROC_API
+ sprintf (pi->pathname, "/proc/%05d/lwp/%d", pid, tid);
+#else
+ sprintf (pi->pathname, MAIN_PROC_NAME_FMT, pid);
+#endif
+ pi->next = parent->thread_list;
+ parent->thread_list = pi;
+ }
+ return pi;
+}
-static void info_proc_siginfo PARAMS ((struct procinfo *, int));
+/*
+ * Function: close_procinfo_files
+ *
+ * Close all file descriptors associated with the procinfo
+ */
-static void info_proc_syscalls PARAMS ((struct procinfo *, int));
+static void
+close_procinfo_files (pi)
+ procinfo *pi;
+{
+ if (pi->ctl_fd > 0)
+ close (pi->ctl_fd);
+#ifdef NEW_PROC_API
+ if (pi->as_fd > 0)
+ close (pi->as_fd);
+ if (pi->status_fd > 0)
+ close (pi->status_fd);
+#endif
+ pi->ctl_fd = pi->as_fd = pi->status_fd = 0;
+}
-static void info_proc_mappings PARAMS ((struct procinfo *, int));
+/*
+ * Function: destroy_procinfo
+ *
+ * Destructor function. Close, unlink and deallocate the object.
+ */
-static void info_proc_signals PARAMS ((struct procinfo *, int));
+static void
+destroy_one_procinfo (list, pi)
+ procinfo **list;
+ procinfo *pi;
+{
+ procinfo *ptr;
+
+ /* Step one: unlink the procinfo from its list */
+ if (pi == *list)
+ *list = pi->next;
+ else
+ for (ptr = *list; ptr; ptr = ptr->next)
+ if (ptr->next == pi)
+ {
+ ptr->next = pi->next;
+ break;
+ }
-static void info_proc_faults PARAMS ((struct procinfo *, int));
+ /* Step two: close any open file descriptors */
+ close_procinfo_files (pi);
-static char *mappingflags PARAMS ((long));
+ /* Step three: free the memory. */
+ free (pi);
+}
-static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
+static void
+destroy_procinfo (pi)
+ procinfo *pi;
+{
+ procinfo *tmp;
-static char *lookupdesc PARAMS ((struct trans *, unsigned int));
+ if (pi->tid != 0) /* destroy a thread procinfo */
+ {
+ tmp = find_procinfo (pi->pid, 0); /* find the parent process */
+ destroy_one_procinfo (&tmp->thread_list, pi);
+ }
+ else /* destroy a process procinfo and all its threads */
+ {
+ /* First destroy the children, if any; */
+ while (pi->thread_list != NULL)
+ destroy_one_procinfo (&pi->thread_list, pi->thread_list);
+ /* Then destroy the parent. Genocide!!! */
+ destroy_one_procinfo (&procinfo_list, pi);
+ }
+}
-static int do_attach PARAMS ((int pid));
+enum { NOKILL, KILL };
-static void do_detach PARAMS ((int siggnal));
+/*
+ * Function: dead_procinfo
+ *
+ * To be called on a non_recoverable error for a procinfo.
+ * Prints error messages, optionally sends a SIGKILL to the process,
+ * then destroys the data structure.
+ */
-static void procfs_create_inferior PARAMS ((char *, char *, char **));
+static void
+dead_procinfo (pi, msg, kill_p)
+ procinfo *pi;
+ char *msg;
+ int kill_p;
+{
+ char procfile[80];
-static void procfs_notice_signals PARAMS ((int pid));
+ if (pi->pathname)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ }
+ else
+ {
+ sprintf (procfile, "process %d", pi->pid);
+ print_sys_errmsg (procfile, errno);
+ }
+ if (kill_p == KILL)
+ kill (pi->pid, SIGKILL);
-static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
+ destroy_procinfo (pi);
+ error (msg);
+}
-static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
+/* =================== END, STRUCT PROCINFO "MODULE" =================== */
-static int procfs_write_pcwstop PARAMS ((struct procinfo *));
-static int procfs_read_status PARAMS ((struct procinfo *));
-static void procfs_write_pckill PARAMS ((struct procinfo *));
+/* =================== /proc "MODULE" =================== */
-typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
- int why, int *rtnval, int *statval));
+/*
+ * This "module" is the interface layer between the /proc system API
+ * and the gdb target vector functions. This layer consists of
+ * access functions that encapsulate each of the basic operations
+ * that we need to use from the /proc API.
+ *
+ * The main motivation for this layer is to hide the fact that
+ * there are two very different implementations of the /proc API.
+ * Rather than have a bunch of #ifdefs all thru the gdb target vector
+ * functions, we do our best to hide them all in here.
+ */
-static void procfs_set_syscall_trap PARAMS ((struct procinfo *pi,
- int syscall_num, int flags,
- syscall_func_t *func));
+int proc_get_status PARAMS ((procinfo *pi));
+long proc_flags PARAMS ((procinfo *pi));
+int proc_why PARAMS ((procinfo *pi));
+int proc_what PARAMS ((procinfo *pi));
+int proc_set_run_on_last_close PARAMS ((procinfo *pi));
+int proc_unset_run_on_last_close PARAMS ((procinfo *pi));
+int proc_set_inherit_on_fork PARAMS ((procinfo *pi));
+int proc_unset_inherit_on_fork PARAMS ((procinfo *pi));
+int proc_set_async PARAMS ((procinfo *pi));
+int proc_unset_async PARAMS ((procinfo *pi));
+int proc_stop_process PARAMS ((procinfo *pi));
+int proc_trace_signal PARAMS ((procinfo *pi, int signo));
+int proc_ignore_signal PARAMS ((procinfo *pi, int signo));
+int proc_clear_current_fault PARAMS ((procinfo *pi));
+int proc_set_current_signal PARAMS ((procinfo *pi, int signo));
+int proc_clear_current_signal PARAMS ((procinfo *pi));
+int proc_set_gregs PARAMS ((procinfo *pi));
+int proc_set_fpregs PARAMS ((procinfo *pi));
+int proc_wait_for_stop PARAMS ((procinfo *pi));
+int proc_run_process PARAMS ((procinfo *pi, int step, int signo));
+int proc_kill PARAMS ((procinfo *pi, int signo));
+int proc_parent_pid PARAMS ((procinfo *pi));
+int proc_get_nthreads PARAMS ((procinfo *pi));
+int proc_get_current_thread PARAMS ((procinfo *pi));
+int proc_set_held_signals PARAMS ((procinfo *pi, sigset_t *sighold));
+int proc_set_traced_sysexit PARAMS ((procinfo *pi, sysset_t *sysset));
+int proc_set_traced_sysentry PARAMS ((procinfo *pi, sysset_t *sysset));
+int proc_set_traced_faults PARAMS ((procinfo *pi, fltset_t *fltset));
+int proc_set_traced_signals PARAMS ((procinfo *pi, sigset_t *sigset));
+
+int proc_update_threads PARAMS ((procinfo *pi));
+int proc_iterate_over_threads PARAMS ((procinfo *pi,
+ int (*func) PARAMS ((procinfo *,
+ procinfo *,
+ void *)),
+ void *ptr));
+
+gdb_gregset_t *proc_get_gregs PARAMS ((procinfo *pi));
+gdb_fpregset_t *proc_get_fpregs PARAMS ((procinfo *pi));
+sysset_t *proc_get_traced_sysexit PARAMS ((procinfo *pi, sysset_t *save));
+sysset_t *proc_get_traced_sysentry PARAMS ((procinfo *pi, sysset_t *save));
+fltset_t *proc_get_traced_faults PARAMS ((procinfo *pi, fltset_t *save));
+sigset_t *proc_get_traced_signals PARAMS ((procinfo *pi, sigset_t *save));
+sigset_t *proc_get_held_signals PARAMS ((procinfo *pi, sigset_t *save));
+sigset_t *proc_get_pending_signals PARAMS ((procinfo *pi, sigset_t *save));
+struct sigaction *proc_get_signal_actions PARAMS ((procinfo *pi,
+ struct sigaction *save));
+
+void proc_warn PARAMS ((procinfo *pi, char *func, int line));
+void proc_error PARAMS ((procinfo *pi, char *func, int line));
-static void procfs_clear_syscall_trap PARAMS ((struct procinfo *pi,
- int syscall_num, int errok));
+void
+proc_warn (pi, func, line)
+ procinfo *pi;
+ char *func;
+ int line;
+{
+ sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
+ print_sys_errmsg (errmsg, errno);
+}
-#define PROCFS_SYSCALL_ENTRY 0x1 /* Trap on entry to sys call */
-#define PROCFS_SYSCALL_EXIT 0x2 /* Trap on exit from sys call */
+void
+proc_error (pi, func, line)
+ procinfo *pi;
+ char *func;
+ int line;
+{
+ sprintf (errmsg, "procfs: %s line %d, %s", func, line, pi->pathname);
+ perror_with_name (errmsg);
+}
-static syscall_func_t procfs_exit_handler;
+/*
+ * Function: proc_get_status
+ *
+ * Updates the status struct in the procinfo.
+ * There is a 'valid' flag, to let other functions know when
+ * this function needs to be called (so the status is only
+ * read when it is needed). The status file descriptor is
+ * also only opened when it is needed.
+ *
+ * Return: non-zero for success, zero for failure.
+ */
-static syscall_func_t procfs_exec_handler;
+int
+proc_get_status (pi)
+ procinfo *pi;
+{
+ /* Status file descriptor is opened "lazily" */
+ if (pi->status_fd == 0 &&
+ open_procinfo_files (pi, FD_STATUS) == 0)
+ {
+ pi->status_valid = 0;
+ return 0;
+ }
-#ifdef SYS_sproc
-static syscall_func_t procfs_sproc_handler;
-static syscall_func_t procfs_fork_handler;
+#ifdef NEW_PROC_API
+ if (lseek (pi->status_fd, 0, SEEK_SET) < 0)
+ pi->status_valid = 0; /* fail */
+ else
+ {
+ /* Sigh... I have to read a different data structure,
+ depending on whether this is a main process or an LWP. */
+ if (pi->tid)
+ pi->status_valid = (read (pi->status_fd,
+ (char *) &pi->prstatus.pr_lwp,
+ sizeof (lwpstatus_t))
+ == sizeof (lwpstatus_t));
+ else
+ {
+ pi->status_valid = (read (pi->status_fd,
+ (char *) &pi->prstatus,
+ sizeof (gdb_prstatus_t))
+ == sizeof (gdb_prstatus_t));
+#if 0 /*def UNIXWARE*/
+ if (pi->status_valid &&
+ (pi->prstatus.pr_lwp.pr_flags & PR_ISTOP) &&
+ pi->prstatus.pr_lwp.pr_why == PR_REQUESTED)
+ /* Unixware peculiarity -- read the damn thing again! */
+ pi->status_valid = (read (pi->status_fd,
+ (char *) &pi->prstatus,
+ sizeof (gdb_prstatus_t))
+ == sizeof (gdb_prstatus_t));
+#endif /* UNIXWARE */
+ }
+ }
+#else /* ioctl method */
+#ifdef PIOCTSTATUS /* osf */
+ if (pi->tid == 0) /* main process */
+ {
+ /* Just read the danged status. Now isn't that simple? */
+ pi->status_valid =
+ (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) >= 0);
+ }
+ else
+ {
+ int win;
+ struct {
+ long pr_count;
+ tid_t pr_error_thread;
+ struct prstatus status;
+ } thread_status;
+
+ thread_status.pr_count = 1;
+ thread_status.status.pr_tid = pi->tid;
+ win = (ioctl (pi->status_fd, PIOCTSTATUS, &thread_status) >= 0);
+ if (win)
+ {
+ memcpy (&pi->prstatus, &thread_status.status,
+ sizeof (pi->prstatus));
+ pi->status_valid = 1;
+ }
+ }
+#else
+ /* Just read the danged status. Now isn't that simple? */
+ pi->status_valid = (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) >= 0);
#endif
-
-#ifdef SYS_lwp_create
-static syscall_func_t procfs_lwp_creation_handler;
#endif
-static void modify_inherit_on_fork_flag PARAMS ((int fd, int flag));
-static void modify_run_on_last_close_flag PARAMS ((int fd, int flag));
+ if (pi->status_valid)
+ {
+ PROC_PRETTYFPRINT_STATUS (proc_flags (pi),
+ proc_why (pi),
+ proc_what (pi),
+ proc_get_current_thread (pi));
+ }
-/* */
+ /* The status struct includes general regs, so mark them valid too */
+ pi->gregs_valid = pi->status_valid;
+#ifdef NEW_PROC_API
+ /* In the read/write multiple-fd model,
+ the status struct includes the fp regs too, so mark them valid too */
+ pi->fpregs_valid = pi->status_valid;
+#endif
+ return pi->status_valid; /* True if success, false if failure. */
+}
-struct procfs_syscall_handler
+/*
+ * Function: proc_flags
+ *
+ * returns the process flags (pr_flags field).
+ */
+
+long
+proc_flags (pi)
+ procinfo *pi;
{
- int syscall_num; /* The number of the system call being handled */
- /* The function to be called */
- syscall_func_t *func;
-};
-
-static void procfs_resume PARAMS ((int pid, int step,
- enum target_signal signo));
-
-static void init_procfs_ops PARAMS ((void));
-
-/* External function prototypes that can't be easily included in any
- header file because the args are typedefs in system include files. */
-
-extern void supply_gregset PARAMS ((gdb_gregset_t *));
-
-extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
-
-#ifdef FP0_REGNUM
-extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
-
-extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0; /* FIXME: not a good failure value (but what is?) */
+
+#ifdef NEW_PROC_API
+# ifdef UNIXWARE
+ /* UnixWare 7.1 puts process status flags, e.g. PR_ASYNC, in
+ pstatus_t and LWP status flags, e.g. PR_STOPPED, in lwpstatus_t.
+ The two sets of flags don't overlap. */
+ return pi->prstatus.pr_flags | pi->prstatus.pr_lwp.pr_flags;
+# else
+ return pi->prstatus.pr_lwp.pr_flags;
+# endif
+#else
+ return pi->prstatus.pr_flags;
#endif
+}
/*
-
-LOCAL FUNCTION
-
- find_procinfo -- convert a process id to a struct procinfo
-
-SYNOPSIS
-
- static struct procinfo * find_procinfo (pid_t pid, int okfail);
-
-DESCRIPTION
-
- Given a process id, look it up in the procinfo chain. Returns
- a struct procinfo *. If can't find pid, then call error(),
- unless okfail is set, in which case, return NULL;
+ * Function: proc_why
+ *
+ * returns the pr_why field (why the process stopped).
*/
-static struct procinfo *
-find_procinfo (pid, okfail)
- pid_t pid;
- int okfail;
+int
+proc_why (pi)
+ procinfo *pi;
{
- struct procinfo *procinfo;
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0; /* FIXME: not a good failure value (but what is?) */
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
- if (procinfo->pid == pid)
- return procinfo;
-
- if (okfail)
- return NULL;
-
- error ("procfs (find_procinfo): Couldn't locate pid %d", pid);
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_why;
+#else
+ return pi->prstatus.pr_why;
+#endif
}
/*
-
-LOCAL MACRO
-
- current_procinfo -- convert inferior_pid to a struct procinfo
-
-SYNOPSIS
-
- static struct procinfo * current_procinfo;
-
-DESCRIPTION
-
- Looks up inferior_pid in the procinfo chain. Always returns a
- struct procinfo *. If process can't be found, we error() out.
+ * Function: proc_what
+ *
+ * returns the pr_what field (details of why the process stopped).
*/
-#define current_procinfo find_procinfo (inferior_pid, 0)
-
-/*
-
-LOCAL FUNCTION
-
- add_fd -- Add the fd to the poll/select list
-
-SYNOPSIS
-
- static void add_fd (struct procinfo *);
-
-DESCRIPTION
-
- Add the fd of the supplied procinfo to the list of fds used for
- poll/select operations.
- */
-
-static void
-add_fd (pi)
- struct procinfo *pi;
+int
+proc_what (pi)
+ procinfo *pi;
{
- if (num_poll_list <= 0)
- poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
- else
- poll_list = (struct pollfd *) xrealloc (poll_list,
- (num_poll_list + 1)
- * sizeof (struct pollfd));
- poll_list[num_poll_list].fd = pi->ctl_fd;
-#ifdef UNIXWARE
- poll_list[num_poll_list].events = POLLWRNORM;
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0; /* FIXME: not a good failure value (but what is?) */
+
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_what;
#else
- poll_list[num_poll_list].events = POLLPRI;
+ return pi->prstatus.pr_what;
#endif
-
- num_poll_list++;
}
+#ifndef PIOCSSPCACT /* The following is not supported on OSF. */
/*
-
-LOCAL FUNCTION
-
- remove_fd -- Remove the fd from the poll/select list
-
-SYNOPSIS
-
- static void remove_fd (struct procinfo *);
-
-DESCRIPTION
-
- Remove the fd of the supplied procinfo from the list of fds used
- for poll/select operations.
+ * Function: proc_nsysarg
+ *
+ * returns the pr_nsysarg field (number of args to the current syscall).
*/
-static void
-remove_fd (pi)
- struct procinfo *pi;
+int
+proc_nsysarg (pi)
+ procinfo *pi;
{
- int i;
-
- for (i = 0; i < num_poll_list; i++)
- {
- if (poll_list[i].fd == pi->ctl_fd)
- {
- if (i != num_poll_list - 1)
- memcpy (poll_list + i, poll_list + i + 1,
- (num_poll_list - i - 1) * sizeof (struct pollfd));
-
- num_poll_list--;
-
- if (num_poll_list == 0)
- free (poll_list);
- else
- poll_list = (struct pollfd *) xrealloc (poll_list,
- num_poll_list
- * sizeof (struct pollfd));
- return;
- }
- }
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0;
+
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_nsysarg;
+#else
+ return pi->prstatus.pr_nsysarg;
+#endif
}
/*
-
-LOCAL FUNCTION
-
- procfs_read_status - get procfs fd status
-
-SYNOPSIS
-
- static int procfs_read_status (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, get the status of
- the status_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
+ * Function: proc_sysargs
+ *
+ * returns the pr_sysarg field (pointer to the arguments of current syscall).
*/
-static int
-procfs_read_status (pi)
- struct procinfo *pi;
+long *
+proc_sysargs (pi)
+ procinfo *pi;
{
-#ifdef PROCFS_USE_READ_WRITE
- if ((lseek (pi->status_fd, 0, SEEK_SET) < 0) ||
- (read (pi->status_fd, (char *) &pi->prstatus,
- sizeof (gdb_prstatus_t)) != sizeof (gdb_prstatus_t)))
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
+
+#ifdef NEW_PROC_API
+ return (long *) &pi->prstatus.pr_lwp.pr_sysarg;
#else
- if (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) < 0)
+ return (long *) &pi->prstatus.pr_sysarg;
#endif
- return 0;
- else
- return 1;
}
/*
-
-LOCAL FUNCTION
-
- procfs_write_pcwstop - send a PCWSTOP to procfs fd
-
-SYNOPSIS
-
- static int procfs_write_pcwstop (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, send a PCWSTOP to
- the ctl_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
+ * Function: proc_syscall
+ *
+ * returns the pr_syscall field (id of current syscall if we are in one).
*/
-static int
-procfs_write_pcwstop (pi)
- struct procinfo *pi;
+int
+proc_syscall (pi)
+ procinfo *pi;
{
-#ifdef PROCFS_USE_READ_WRITE
- long cmd = PCWSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0;
+
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_syscall;
#else
- if (ioctl (pi->ctl_fd, PIOCWSTOP, &pi->prstatus) < 0)
+ return pi->prstatus.pr_syscall;
#endif
- return 0;
- else
- return 1;
}
+#endif /* PIOCSSPCACT */
/*
-
-LOCAL FUNCTION
-
- procfs_write_pckill - send a kill to procfs fd
-
-SYNOPSIS
-
- static void procfs_write_pckill (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, send a kill to
- the ctl_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
+ * Function: proc_cursig:
+ *
+ * returns the pr_cursig field (current signal).
*/
-static void
-procfs_write_pckill (pi)
- struct procinfo *pi;
+long
+proc_cursig (struct procinfo *pi)
{
-#ifdef PROCFS_USE_READ_WRITE
- struct proc_ctl pctl;
- pctl.cmd = PCKILL;
- pctl.data = SIGKILL;
- write (pi->ctl_fd, &pctl, sizeof (struct proc_ctl));
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0; /* FIXME: not a good failure value (but what is?) */
+
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_cursig;
#else
- int signo = SIGKILL;
- ioctl (pi->ctl_fd, PIOCKILL, &signo);
+ return pi->prstatus.pr_cursig;
#endif
}
-static struct procinfo *
-wait_fd ()
+/*
+ * Function: proc_modify_flag
+ *
+ * === I appologize for the messiness of this function.
+ * === This is an area where the different versions of
+ * === /proc are more inconsistent than usual. MVS
+ *
+ * Set or reset any of the following process flags:
+ * PR_FORK -- forked child will inherit trace flags
+ * PR_RLC -- traced process runs when last /proc file closed.
+ * PR_KLC -- traced process is killed when last /proc file closed.
+ * PR_ASYNC -- LWP's get to run/stop independently.
+ *
+ * There are three methods for doing this function:
+ * 1) Newest: read/write [PCSET/PCRESET/PCUNSET]
+ * [Sol6, Sol7, UW]
+ * 2) Middle: PIOCSET/PIOCRESET
+ * [Irix, Sol5]
+ * 3) Oldest: PIOCSFORK/PIOCRFORK/PIOCSRLC/PIOCRRLC
+ * [OSF, Sol5]
+ *
+ * Note: Irix does not define PR_ASYNC.
+ * Note: OSF does not define PR_KLC.
+ * Note: OSF is the only one that can ONLY use the oldest method.
+ *
+ * Arguments:
+ * pi -- the procinfo
+ * flag -- one of PR_FORK, PR_RLC, or PR_ASYNC
+ * mode -- 1 for set, 0 for reset.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
+
+enum { FLAG_RESET, FLAG_SET };
+
+static int
+proc_modify_flag (pi, flag, mode)
+ procinfo *pi;
+ long flag;
+ long mode;
{
- struct procinfo *pi, *next_pi;
-#ifndef LOSING_POLL
- int num_fds;
- int i;
+ long win = 0; /* default to fail */
+
+ /*
+ * These operations affect the process as a whole, and applying
+ * them to an individual LWP has the same meaning as applying them
+ * to the main process. Therefore, if we're ever called with a
+ * pointer to an LWP's procinfo, let's substitute the process's
+ * procinfo and avoid opening the LWP's file descriptor
+ * unnecessarily.
+ */
+
+ if (pi->pid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
+
+#ifdef NEW_PROC_API /* Newest method: UnixWare and newer Solarii */
+ /* First normalize the PCUNSET/PCRESET command opcode
+ (which for no obvious reason has a different definition
+ from one operating system to the next...) */
+#ifdef PCUNSET
+#define GDBRESET PCUNSET
+#endif
+#ifdef PCRESET
+#define GDBRESET PCRESET
#endif
+ {
+ long arg[2];
- set_sigint_trap (); /* Causes SIGINT to be passed on to the
- attached process. */
- set_sigio_trap ();
+ if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC) */
+ arg[0] = PCSET;
+ else /* Reset the flag */
+ arg[0] = GDBRESET;
- wait_again:
-#ifndef LOSING_POLL
- while (1)
+ arg[1] = flag;
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else
+#ifdef PIOCSET /* Irix/Sol5 method */
+ if (mode == FLAG_SET) /* Set the flag (hopefully RLC, FORK, or ASYNC) */
{
- num_fds = poll (poll_list, num_poll_list, -1);
- if (num_fds > 0)
- break;
- if (num_fds < 0 && errno == EINTR)
- continue;
- print_sys_errmsg ("poll failed", errno);
- error ("Poll failed, returned %d", num_fds);
+ win = (ioctl (pi->ctl_fd, PIOCSET, &flag) >= 0);
}
-#else /* LOSING_POLL */
- pi = current_procinfo;
-
- while (!procfs_write_pcwstop (pi))
+ else /* Reset the flag */
{
- if (errno == ENOENT)
- {
- /* Process exited. */
- pi->prstatus.pr_flags = 0;
- break;
- }
- else if (errno != EINTR)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("procfs_write_pcwstop failed");
- }
+ win = (ioctl (pi->ctl_fd, PIOCRESET, &flag) >= 0);
}
- pi->had_event = 1;
-#endif /* LOSING_POLL */
-
- clear_sigint_trap ();
- clear_sigio_trap ();
-#ifndef LOSING_POLL
+#else
+#ifdef PIOCSRLC /* Oldest method: OSF */
+ switch (flag) {
+ case PR_RLC:
+ if (mode == FLAG_SET) /* Set run-on-last-close */
+ {
+ win = (ioctl (pi->ctl_fd, PIOCSRLC, NULL) >= 0);
+ }
+ else /* Clear run-on-last-close */
+ {
+ win = (ioctl (pi->ctl_fd, PIOCRRLC, NULL) >= 0);
+ }
+ break;
+ case PR_FORK:
+ if (mode == FLAG_SET) /* Set inherit-on-fork */
+ {
+ win = (ioctl (pi->ctl_fd, PIOCSFORK, NULL) >= 0);
+ }
+ else /* Clear inherit-on-fork */
+ {
+ win = (ioctl (pi->ctl_fd, PIOCRFORK, NULL) >= 0);
+ }
+ break;
+ default:
+ win = 0; /* fail -- unknown flag (can't do PR_ASYNC) */
+ break;
+ }
+#endif
+#endif
+#endif
+#undef GDBRESET
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
- for (i = 0; i < num_poll_list && num_fds > 0; i++)
- {
- if (0 == (poll_list[i].revents &
- (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
- continue;
- for (pi = procinfo_list; pi; pi = next_pi)
- {
- next_pi = pi->next;
- if (poll_list[i].fd == pi->ctl_fd)
- {
- num_fds--;
- if ((poll_list[i].revents & POLLHUP) != 0 ||
- !procfs_read_status(pi))
- { /* The LWP has apparently terminated. */
- if (num_poll_list <= 1)
- {
- pi->prstatus.pr_flags = 0;
- pi->had_event = 1;
- break;
- }
- if (info_verbose)
- printf_filtered ("LWP %d exited.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- i--; /* don't skip deleted entry */
- if (num_fds != 0)
- break; /* already another event to process */
- else
- goto wait_again; /* wait for another event */
- }
- pi->had_event = 1;
- break;
- }
- }
- if (!pi)
- error ("wait_fd: Couldn't find procinfo for fd %d\n",
- poll_list[i].fd);
- }
-#endif /* LOSING_POLL */
+ if (!win)
+ warning ("procfs: modify_flag failed to turn %s %s",
+ flag == PR_FORK ? "PR_FORK" :
+ flag == PR_RLC ? "PR_RLC" :
+#ifdef PR_ASYNC
+ flag == PR_ASYNC ? "PR_ASYNC" :
+#endif
+#ifdef PR_KLC
+ flag == PR_KLC ? "PR_KLC" :
+#endif
+ "<unknown flag>",
+ mode == FLAG_RESET ? "off" : "on");
- return pi;
+ return win;
}
/*
+ * Function: proc_set_run_on_last_close
+ *
+ * Set the run_on_last_close flag.
+ * Process with all threads will become runnable
+ * when debugger closes all /proc fds.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
+int
+proc_set_run_on_last_close (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_RLC, FLAG_SET);
+}
- lookupdesc -- translate a value to a summary desc string
+/*
+ * Function: proc_unset_run_on_last_close
+ *
+ * Reset the run_on_last_close flag.
+ * Process will NOT become runnable
+ * when debugger closes its file handles.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-SYNOPSIS
+int
+proc_unset_run_on_last_close (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_RLC, FLAG_RESET);
+}
- static char *lookupdesc (struct trans *transp, unsigned int val);
+#ifdef PR_KLC
+/*
+ * Function: proc_set_kill_on_last_close
+ *
+ * Set the kill_on_last_close flag.
+ * Process with all threads will be killed when debugger
+ * closes all /proc fds (or debugger exits or dies).
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-DESCRIPTION
-
- Given a pointer to a translation table and a value to be translated,
- lookup the desc string and return it.
+int
+proc_set_kill_on_last_close (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_KLC, FLAG_SET);
+}
+
+/*
+ * Function: proc_unset_kill_on_last_close
+ *
+ * Reset the kill_on_last_close flag.
+ * Process will NOT be killed when debugger
+ * closes its file handles (or exits or dies).
+ *
+ * Returns non-zero for success, zero for failure.
*/
-static char *
-lookupdesc (transp, val)
- struct trans *transp;
- unsigned int val;
+int
+proc_unset_kill_on_last_close (pi)
+ procinfo *pi;
{
- char *desc;
-
- for (desc = NULL; transp -> name != NULL; transp++)
- {
- if (transp -> value == val)
- {
- desc = transp -> desc;
- break;
- }
- }
+ return proc_modify_flag (pi, PR_KLC, FLAG_RESET);
+}
+#endif /* PR_KLC */
- /* Didn't find a translation for the specified value, set a default one. */
+/*
+ * Function: proc_set_inherit_on_fork
+ *
+ * Set inherit_on_fork flag.
+ * If the process forks a child while we are registered for events
+ * in the parent, then we will also recieve events from the child.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
- if (desc == NULL)
- {
- desc = "Unknown";
- }
- return (desc);
+int
+proc_set_inherit_on_fork (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_FORK, FLAG_SET);
}
/*
+ * Function: proc_unset_inherit_on_fork
+ *
+ * Reset inherit_on_fork flag.
+ * If the process forks a child while we are registered for events
+ * in the parent, then we will NOT recieve events from the child.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
+int
+proc_unset_inherit_on_fork (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_FORK, FLAG_RESET);
+}
- lookupname -- translate a value to symbolic name
+#ifdef PR_ASYNC
+/*
+ * Function: proc_set_async
+ *
+ * Set PR_ASYNC flag.
+ * If one LWP stops because of a debug event (signal etc.),
+ * the remaining LWPs will continue to run.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-SYNOPSIS
+int
+proc_set_async (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_ASYNC, FLAG_SET);
+}
- static char *lookupname (struct trans *transp, unsigned int val,
- char *prefix);
+/*
+ * Function: proc_unset_async
+ *
+ * Reset PR_ASYNC flag.
+ * If one LWP stops because of a debug event (signal etc.),
+ * then all other LWPs will stop as well.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-DESCRIPTION
-
- Given a pointer to a translation table, a value to be translated,
- and a default prefix to return if the value can't be translated,
- match the value with one of the translation table entries and
- return a pointer to the symbolic name.
+int
+proc_unset_async (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_ASYNC, FLAG_RESET);
+}
+#endif /* PR_ASYNC */
- If no match is found it just returns the value as a printable string,
- with the given prefix. The previous such value, if any, is freed
- at this time.
+/*
+ * Function: proc_stop_process
+ *
+ * Request the process/LWP to stop. Does not wait.
+ * Returns non-zero for success, zero for failure.
*/
-static char *
-lookupname (transp, val, prefix)
- struct trans *transp;
- unsigned int val;
- char *prefix;
+int
+proc_stop_process (pi)
+ procinfo *pi;
{
- static char *locbuf;
- char *name;
-
- for (name = NULL; transp -> name != NULL; transp++)
- {
- if (transp -> value == val)
- {
- name = transp -> name;
- break;
- }
- }
+ int win;
- /* Didn't find a translation for the specified value, build a default
- one using the specified prefix and return it. The lifetime of
- the value is only until the next one is needed. */
+ /*
+ * We might conceivably apply this operation to an LWP, and
+ * the LWP's ctl file descriptor might not be open.
+ */
- if (name == NULL)
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
+ return 0;
+ else
{
- if (locbuf != NULL)
+#ifdef NEW_PROC_API
+ int cmd = PCSTOP;
+ win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) >= 0);
+ /* Note: the call also reads the prstatus. */
+ if (win)
{
- free (locbuf);
+ pi->status_valid = 1;
+ PROC_PRETTYFPRINT_STATUS (proc_flags (pi),
+ proc_why (pi),
+ proc_what (pi),
+ proc_get_current_thread (pi));
}
- locbuf = xmalloc (strlen (prefix) + 16);
- sprintf (locbuf, "%s %u", prefix, val);
- name = locbuf;
+#endif
}
- return (name);
-}
-static char *
-sigcodename (sip)
- siginfo_t *sip;
-{
- struct sigcode *scp;
- char *name = NULL;
- static char locbuf[32];
-
- for (scp = siginfo_table; scp -> codename != NULL; scp++)
- {
- if ((scp -> signo == sip -> si_signo) &&
- (scp -> code == sip -> si_code))
- {
- name = scp -> codename;
- break;
- }
- }
- if (name == NULL)
- {
- sprintf (locbuf, "sigcode %u", sip -> si_signo);
- name = locbuf;
- }
- return (name);
+ return win;
}
-static char *
-sigcodedesc (sip)
- siginfo_t *sip;
+/*
+ * Function: proc_wait_for_stop
+ *
+ * Wait for the process or LWP to stop (block until it does).
+ * Returns non-zero for success, zero for failure.
+ */
+
+int
+proc_wait_for_stop (pi)
+ procinfo *pi;
{
- struct sigcode *scp;
- char *desc = NULL;
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
- for (scp = siginfo_table; scp -> codename != NULL; scp++)
- {
- if ((scp -> signo == sip -> si_signo) &&
- (scp -> code == sip -> si_code))
- {
- desc = scp -> desc;
- break;
- }
- }
- if (desc == NULL)
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
+
+#ifdef NEW_PROC_API
+ {
+ int cmd = PCWSTOP;
+ win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
+ /* We been runnin' and we stopped -- need to update status. */
+ pi->status_valid = 0;
+ }
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCWSTOP, &pi->prstatus) >= 0);
+ /* Above call also refreshes the prstatus. */
+ if (win)
{
- desc = "Unrecognized signal or trap use";
+ pi->status_valid = 1;
+ PROC_PRETTYFPRINT_STATUS (proc_flags (pi),
+ proc_why (pi),
+ proc_what (pi),
+ proc_get_current_thread (pi));
}
- return (desc);
+#endif
+
+ return win;
}
/*
-
-LOCAL FUNCTION
-
- syscallname - translate a system call number into a system call name
-
-SYNOPSIS
-
- char *syscallname (int syscallnum)
-
-DESCRIPTION
-
- Given a system call number, translate it into the printable name
- of a system call, or into "syscall <num>" if it is an unknown
- number.
+ * Function: proc_run_process
+ *
+ * Make the process or LWP runnable.
+ * Options (not all are implemented):
+ * - single-step
+ * - clear current fault
+ * - clear current signal
+ * - abort the current system call
+ * - stop as soon as finished with system call
+ * - (ioctl): set traced signal set
+ * - (ioctl): set held signal set
+ * - (ioctl): set traced fault set
+ * - (ioctl): set start pc (vaddr)
+ * Always clear the current fault.
+ * Clear the current signal if 'signo' is zero.
+ *
+ * Arguments:
+ * pi the process or LWP to operate on.
+ * step if true, set the process or LWP to trap after one instr.
+ * signo if zero, clear the current signal if any.
+ * if non-zero, set the current signal to this one.
+ *
+ * Returns non-zero for success, zero for failure.
*/
-static char *
-syscallname (syscallnum)
- int syscallnum;
+int
+proc_run_process (pi, step, signo)
+ procinfo *pi;
+ int step;
+ int signo;
{
- static char locbuf[32];
+ int win;
+ int runflags;
+
+ /*
+ * We will probably have to apply this operation to individual threads,
+ * so make sure the control file descriptor is open.
+ */
- if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS
- && syscall_table[syscallnum] != NULL)
- return syscall_table[syscallnum];
- else
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
{
- sprintf (locbuf, "syscall %u", syscallnum);
- return locbuf;
+ return 0;
}
-}
-/*
+ runflags = PRCFAULT; /* always clear current fault */
+ if (step)
+ runflags |= PRSTEP;
+ if (signo == 0)
+ runflags |= PRCSIG;
+ else if (signo != -1) /* -1 means do nothing W.R.T. signals */
+ proc_set_current_signal (pi, signo);
-LOCAL FUNCTION
+#ifdef NEW_PROC_API
+ {
+ int cmd[2];
- init_syscall_table - initialize syscall translation table
+ cmd[0] = PCRUN;
+ cmd[1] = runflags;
+ win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
+ }
+#else /* ioctl method */
+ {
+ prrun_t prrun;
-SYNOPSIS
+ memset (&prrun, 0, sizeof (prrun));
+ prrun.pr_flags = runflags;
+ win = (ioctl (pi->ctl_fd, PIOCRUN, &prrun) >= 0);
+ }
+#endif
- void init_syscall_table (void)
+ return win;
+}
-DESCRIPTION
+/*
+ * Function: proc_set_traced_signals
+ *
+ * Register to trace signals in the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
- Dynamically initialize the translation table to convert system
- call numbers into printable system call names. Done once per
- gdb run, on initialization.
+int
+proc_set_traced_signals (pi, sigset)
+ procinfo *pi;
+ sigset_t *sigset;
+{
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-NOTES
+#ifdef NEW_PROC_API
+ {
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char sigset[sizeof (sigset_t)];
+ } arg;
- This is awfully ugly, but preprocessor tricks to make it prettier
- tend to be nonportable.
- */
+ arg.cmd = PCSTRACE;
+ memcpy (&arg.sigset, sigset, sizeof (sigset_t));
-static void
-init_syscall_table ()
-{
-#if defined (SYS_exit)
- syscall_table[SYS_exit] = "exit";
-#endif
-#if defined (SYS_fork)
- syscall_table[SYS_fork] = "fork";
-#endif
-#if defined (SYS_read)
- syscall_table[SYS_read] = "read";
-#endif
-#if defined (SYS_write)
- syscall_table[SYS_write] = "write";
-#endif
-#if defined (SYS_open)
- syscall_table[SYS_open] = "open";
-#endif
-#if defined (SYS_close)
- syscall_table[SYS_close] = "close";
-#endif
-#if defined (SYS_wait)
- syscall_table[SYS_wait] = "wait";
-#endif
-#if defined (SYS_creat)
- syscall_table[SYS_creat] = "creat";
-#endif
-#if defined (SYS_link)
- syscall_table[SYS_link] = "link";
-#endif
-#if defined (SYS_unlink)
- syscall_table[SYS_unlink] = "unlink";
-#endif
-#if defined (SYS_exec)
- syscall_table[SYS_exec] = "exec";
-#endif
-#if defined (SYS_execv)
- syscall_table[SYS_execv] = "execv";
-#endif
-#if defined (SYS_execve)
- syscall_table[SYS_execve] = "execve";
-#endif
-#if defined (SYS_chdir)
- syscall_table[SYS_chdir] = "chdir";
-#endif
-#if defined (SYS_time)
- syscall_table[SYS_time] = "time";
-#endif
-#if defined (SYS_mknod)
- syscall_table[SYS_mknod] = "mknod";
-#endif
-#if defined (SYS_chmod)
- syscall_table[SYS_chmod] = "chmod";
-#endif
-#if defined (SYS_chown)
- syscall_table[SYS_chown] = "chown";
-#endif
-#if defined (SYS_brk)
- syscall_table[SYS_brk] = "brk";
-#endif
-#if defined (SYS_stat)
- syscall_table[SYS_stat] = "stat";
-#endif
-#if defined (SYS_lseek)
- syscall_table[SYS_lseek] = "lseek";
-#endif
-#if defined (SYS_getpid)
- syscall_table[SYS_getpid] = "getpid";
-#endif
-#if defined (SYS_mount)
- syscall_table[SYS_mount] = "mount";
-#endif
-#if defined (SYS_umount)
- syscall_table[SYS_umount] = "umount";
-#endif
-#if defined (SYS_setuid)
- syscall_table[SYS_setuid] = "setuid";
-#endif
-#if defined (SYS_getuid)
- syscall_table[SYS_getuid] = "getuid";
-#endif
-#if defined (SYS_stime)
- syscall_table[SYS_stime] = "stime";
-#endif
-#if defined (SYS_ptrace)
- syscall_table[SYS_ptrace] = "ptrace";
-#endif
-#if defined (SYS_alarm)
- syscall_table[SYS_alarm] = "alarm";
-#endif
-#if defined (SYS_fstat)
- syscall_table[SYS_fstat] = "fstat";
-#endif
-#if defined (SYS_pause)
- syscall_table[SYS_pause] = "pause";
-#endif
-#if defined (SYS_utime)
- syscall_table[SYS_utime] = "utime";
-#endif
-#if defined (SYS_stty)
- syscall_table[SYS_stty] = "stty";
-#endif
-#if defined (SYS_gtty)
- syscall_table[SYS_gtty] = "gtty";
-#endif
-#if defined (SYS_access)
- syscall_table[SYS_access] = "access";
-#endif
-#if defined (SYS_nice)
- syscall_table[SYS_nice] = "nice";
-#endif
-#if defined (SYS_statfs)
- syscall_table[SYS_statfs] = "statfs";
-#endif
-#if defined (SYS_sync)
- syscall_table[SYS_sync] = "sync";
-#endif
-#if defined (SYS_kill)
- syscall_table[SYS_kill] = "kill";
-#endif
-#if defined (SYS_fstatfs)
- syscall_table[SYS_fstatfs] = "fstatfs";
-#endif
-#if defined (SYS_pgrpsys)
- syscall_table[SYS_pgrpsys] = "pgrpsys";
-#endif
-#if defined (SYS_xenix)
- syscall_table[SYS_xenix] = "xenix";
-#endif
-#if defined (SYS_dup)
- syscall_table[SYS_dup] = "dup";
-#endif
-#if defined (SYS_pipe)
- syscall_table[SYS_pipe] = "pipe";
-#endif
-#if defined (SYS_times)
- syscall_table[SYS_times] = "times";
-#endif
-#if defined (SYS_profil)
- syscall_table[SYS_profil] = "profil";
-#endif
-#if defined (SYS_plock)
- syscall_table[SYS_plock] = "plock";
-#endif
-#if defined (SYS_setgid)
- syscall_table[SYS_setgid] = "setgid";
-#endif
-#if defined (SYS_getgid)
- syscall_table[SYS_getgid] = "getgid";
-#endif
-#if defined (SYS_signal)
- syscall_table[SYS_signal] = "signal";
-#endif
-#if defined (SYS_msgsys)
- syscall_table[SYS_msgsys] = "msgsys";
-#endif
-#if defined (SYS_sys3b)
- syscall_table[SYS_sys3b] = "sys3b";
-#endif
-#if defined (SYS_sysi86)
- syscall_table[SYS_sysi86] = "sysi86";
-#endif
-#if defined (SYS_acct)
- syscall_table[SYS_acct] = "acct";
-#endif
-#if defined (SYS_shmsys)
- syscall_table[SYS_shmsys] = "shmsys";
-#endif
-#if defined (SYS_semsys)
- syscall_table[SYS_semsys] = "semsys";
-#endif
-#if defined (SYS_ioctl)
- syscall_table[SYS_ioctl] = "ioctl";
-#endif
-#if defined (SYS_uadmin)
- syscall_table[SYS_uadmin] = "uadmin";
-#endif
-#if defined (SYS_utssys)
- syscall_table[SYS_utssys] = "utssys";
-#endif
-#if defined (SYS_fsync)
- syscall_table[SYS_fsync] = "fsync";
-#endif
-#if defined (SYS_umask)
- syscall_table[SYS_umask] = "umask";
-#endif
-#if defined (SYS_chroot)
- syscall_table[SYS_chroot] = "chroot";
-#endif
-#if defined (SYS_fcntl)
- syscall_table[SYS_fcntl] = "fcntl";
-#endif
-#if defined (SYS_ulimit)
- syscall_table[SYS_ulimit] = "ulimit";
-#endif
-#if defined (SYS_rfsys)
- syscall_table[SYS_rfsys] = "rfsys";
-#endif
-#if defined (SYS_rmdir)
- syscall_table[SYS_rmdir] = "rmdir";
-#endif
-#if defined (SYS_mkdir)
- syscall_table[SYS_mkdir] = "mkdir";
-#endif
-#if defined (SYS_getdents)
- syscall_table[SYS_getdents] = "getdents";
-#endif
-#if defined (SYS_sysfs)
- syscall_table[SYS_sysfs] = "sysfs";
-#endif
-#if defined (SYS_getmsg)
- syscall_table[SYS_getmsg] = "getmsg";
-#endif
-#if defined (SYS_putmsg)
- syscall_table[SYS_putmsg] = "putmsg";
-#endif
-#if defined (SYS_poll)
- syscall_table[SYS_poll] = "poll";
-#endif
-#if defined (SYS_lstat)
- syscall_table[SYS_lstat] = "lstat";
-#endif
-#if defined (SYS_symlink)
- syscall_table[SYS_symlink] = "symlink";
-#endif
-#if defined (SYS_readlink)
- syscall_table[SYS_readlink] = "readlink";
-#endif
-#if defined (SYS_setgroups)
- syscall_table[SYS_setgroups] = "setgroups";
-#endif
-#if defined (SYS_getgroups)
- syscall_table[SYS_getgroups] = "getgroups";
-#endif
-#if defined (SYS_fchmod)
- syscall_table[SYS_fchmod] = "fchmod";
-#endif
-#if defined (SYS_fchown)
- syscall_table[SYS_fchown] = "fchown";
-#endif
-#if defined (SYS_sigprocmask)
- syscall_table[SYS_sigprocmask] = "sigprocmask";
-#endif
-#if defined (SYS_sigsuspend)
- syscall_table[SYS_sigsuspend] = "sigsuspend";
-#endif
-#if defined (SYS_sigaltstack)
- syscall_table[SYS_sigaltstack] = "sigaltstack";
-#endif
-#if defined (SYS_sigaction)
- syscall_table[SYS_sigaction] = "sigaction";
-#endif
-#if defined (SYS_sigpending)
- syscall_table[SYS_sigpending] = "sigpending";
-#endif
-#if defined (SYS_context)
- syscall_table[SYS_context] = "context";
-#endif
-#if defined (SYS_evsys)
- syscall_table[SYS_evsys] = "evsys";
-#endif
-#if defined (SYS_evtrapret)
- syscall_table[SYS_evtrapret] = "evtrapret";
-#endif
-#if defined (SYS_statvfs)
- syscall_table[SYS_statvfs] = "statvfs";
-#endif
-#if defined (SYS_fstatvfs)
- syscall_table[SYS_fstatvfs] = "fstatvfs";
-#endif
-#if defined (SYS_nfssys)
- syscall_table[SYS_nfssys] = "nfssys";
-#endif
-#if defined (SYS_waitsys)
- syscall_table[SYS_waitsys] = "waitsys";
-#endif
-#if defined (SYS_sigsendsys)
- syscall_table[SYS_sigsendsys] = "sigsendsys";
-#endif
-#if defined (SYS_hrtsys)
- syscall_table[SYS_hrtsys] = "hrtsys";
-#endif
-#if defined (SYS_acancel)
- syscall_table[SYS_acancel] = "acancel";
-#endif
-#if defined (SYS_async)
- syscall_table[SYS_async] = "async";
-#endif
-#if defined (SYS_priocntlsys)
- syscall_table[SYS_priocntlsys] = "priocntlsys";
-#endif
-#if defined (SYS_pathconf)
- syscall_table[SYS_pathconf] = "pathconf";
-#endif
-#if defined (SYS_mincore)
- syscall_table[SYS_mincore] = "mincore";
-#endif
-#if defined (SYS_mmap)
- syscall_table[SYS_mmap] = "mmap";
-#endif
-#if defined (SYS_mprotect)
- syscall_table[SYS_mprotect] = "mprotect";
-#endif
-#if defined (SYS_munmap)
- syscall_table[SYS_munmap] = "munmap";
-#endif
-#if defined (SYS_fpathconf)
- syscall_table[SYS_fpathconf] = "fpathconf";
-#endif
-#if defined (SYS_vfork)
- syscall_table[SYS_vfork] = "vfork";
-#endif
-#if defined (SYS_fchdir)
- syscall_table[SYS_fchdir] = "fchdir";
-#endif
-#if defined (SYS_readv)
- syscall_table[SYS_readv] = "readv";
-#endif
-#if defined (SYS_writev)
- syscall_table[SYS_writev] = "writev";
-#endif
-#if defined (SYS_xstat)
- syscall_table[SYS_xstat] = "xstat";
-#endif
-#if defined (SYS_lxstat)
- syscall_table[SYS_lxstat] = "lxstat";
-#endif
-#if defined (SYS_fxstat)
- syscall_table[SYS_fxstat] = "fxstat";
-#endif
-#if defined (SYS_xmknod)
- syscall_table[SYS_xmknod] = "xmknod";
-#endif
-#if defined (SYS_clocal)
- syscall_table[SYS_clocal] = "clocal";
-#endif
-#if defined (SYS_setrlimit)
- syscall_table[SYS_setrlimit] = "setrlimit";
-#endif
-#if defined (SYS_getrlimit)
- syscall_table[SYS_getrlimit] = "getrlimit";
-#endif
-#if defined (SYS_lchown)
- syscall_table[SYS_lchown] = "lchown";
-#endif
-#if defined (SYS_memcntl)
- syscall_table[SYS_memcntl] = "memcntl";
-#endif
-#if defined (SYS_getpmsg)
- syscall_table[SYS_getpmsg] = "getpmsg";
-#endif
-#if defined (SYS_putpmsg)
- syscall_table[SYS_putpmsg] = "putpmsg";
-#endif
-#if defined (SYS_rename)
- syscall_table[SYS_rename] = "rename";
-#endif
-#if defined (SYS_uname)
- syscall_table[SYS_uname] = "uname";
-#endif
-#if defined (SYS_setegid)
- syscall_table[SYS_setegid] = "setegid";
-#endif
-#if defined (SYS_sysconfig)
- syscall_table[SYS_sysconfig] = "sysconfig";
-#endif
-#if defined (SYS_adjtime)
- syscall_table[SYS_adjtime] = "adjtime";
-#endif
-#if defined (SYS_systeminfo)
- syscall_table[SYS_systeminfo] = "systeminfo";
-#endif
-#if defined (SYS_seteuid)
- syscall_table[SYS_seteuid] = "seteuid";
-#endif
-#if defined (SYS_sproc)
- syscall_table[SYS_sproc] = "sproc";
-#endif
-#if defined (SYS_keyctl)
- syscall_table[SYS_keyctl] = "keyctl";
-#endif
-#if defined (SYS_secsys)
- syscall_table[SYS_secsys] = "secsys";
-#endif
-#if defined (SYS_filepriv)
- syscall_table[SYS_filepriv] = "filepriv";
-#endif
-#if defined (SYS_procpriv)
- syscall_table[SYS_procpriv] = "procpriv";
-#endif
-#if defined (SYS_devstat)
- syscall_table[SYS_devstat] = "devstat";
-#endif
-#if defined (SYS_aclipc)
- syscall_table[SYS_aclipc] = "aclipc";
-#endif
-#if defined (SYS_fdevstat)
- syscall_table[SYS_fdevstat] = "fdevstat";
-#endif
-#if defined (SYS_flvlfile)
- syscall_table[SYS_flvlfile] = "flvlfile";
-#endif
-#if defined (SYS_lvlfile)
- syscall_table[SYS_lvlfile] = "lvlfile";
-#endif
-#if defined (SYS_lvlequal)
- syscall_table[SYS_lvlequal] = "lvlequal";
-#endif
-#if defined (SYS_lvlproc)
- syscall_table[SYS_lvlproc] = "lvlproc";
-#endif
-#if defined (SYS_lvlipc)
- syscall_table[SYS_lvlipc] = "lvlipc";
-#endif
-#if defined (SYS_acl)
- syscall_table[SYS_acl] = "acl";
-#endif
-#if defined (SYS_auditevt)
- syscall_table[SYS_auditevt] = "auditevt";
-#endif
-#if defined (SYS_auditctl)
- syscall_table[SYS_auditctl] = "auditctl";
-#endif
-#if defined (SYS_auditdmp)
- syscall_table[SYS_auditdmp] = "auditdmp";
-#endif
-#if defined (SYS_auditlog)
- syscall_table[SYS_auditlog] = "auditlog";
-#endif
-#if defined (SYS_auditbuf)
- syscall_table[SYS_auditbuf] = "auditbuf";
-#endif
-#if defined (SYS_lvldom)
- syscall_table[SYS_lvldom] = "lvldom";
-#endif
-#if defined (SYS_lvlvfs)
- syscall_table[SYS_lvlvfs] = "lvlvfs";
-#endif
-#if defined (SYS_mkmld)
- syscall_table[SYS_mkmld] = "mkmld";
-#endif
-#if defined (SYS_mldmode)
- syscall_table[SYS_mldmode] = "mldmode";
-#endif
-#if defined (SYS_secadvise)
- syscall_table[SYS_secadvise] = "secadvise";
-#endif
-#if defined (SYS_online)
- syscall_table[SYS_online] = "online";
-#endif
-#if defined (SYS_setitimer)
- syscall_table[SYS_setitimer] = "setitimer";
-#endif
-#if defined (SYS_getitimer)
- syscall_table[SYS_getitimer] = "getitimer";
-#endif
-#if defined (SYS_gettimeofday)
- syscall_table[SYS_gettimeofday] = "gettimeofday";
-#endif
-#if defined (SYS_settimeofday)
- syscall_table[SYS_settimeofday] = "settimeofday";
-#endif
-#if defined (SYS_lwp_create)
- syscall_table[SYS_lwp_create] = "_lwp_create";
-#endif
-#if defined (SYS_lwp_exit)
- syscall_table[SYS_lwp_exit] = "_lwp_exit";
-#endif
-#if defined (SYS_lwp_wait)
- syscall_table[SYS_lwp_wait] = "_lwp_wait";
-#endif
-#if defined (SYS_lwp_self)
- syscall_table[SYS_lwp_self] = "_lwp_self";
-#endif
-#if defined (SYS_lwp_info)
- syscall_table[SYS_lwp_info] = "_lwp_info";
-#endif
-#if defined (SYS_lwp_private)
- syscall_table[SYS_lwp_private] = "_lwp_private";
-#endif
-#if defined (SYS_processor_bind)
- syscall_table[SYS_processor_bind] = "processor_bind";
-#endif
-#if defined (SYS_processor_exbind)
- syscall_table[SYS_processor_exbind] = "processor_exbind";
-#endif
-#if defined (SYS_prepblock)
- syscall_table[SYS_prepblock] = "prepblock";
-#endif
-#if defined (SYS_block)
- syscall_table[SYS_block] = "block";
-#endif
-#if defined (SYS_rdblock)
- syscall_table[SYS_rdblock] = "rdblock";
-#endif
-#if defined (SYS_unblock)
- syscall_table[SYS_unblock] = "unblock";
-#endif
-#if defined (SYS_cancelblock)
- syscall_table[SYS_cancelblock] = "cancelblock";
-#endif
-#if defined (SYS_pread)
- syscall_table[SYS_pread] = "pread";
-#endif
-#if defined (SYS_pwrite)
- syscall_table[SYS_pwrite] = "pwrite";
-#endif
-#if defined (SYS_truncate)
- syscall_table[SYS_truncate] = "truncate";
-#endif
-#if defined (SYS_ftruncate)
- syscall_table[SYS_ftruncate] = "ftruncate";
-#endif
-#if defined (SYS_lwp_kill)
- syscall_table[SYS_lwp_kill] = "_lwp_kill";
-#endif
-#if defined (SYS_sigwait)
- syscall_table[SYS_sigwait] = "sigwait";
-#endif
-#if defined (SYS_fork1)
- syscall_table[SYS_fork1] = "fork1";
-#endif
-#if defined (SYS_forkall)
- syscall_table[SYS_forkall] = "forkall";
-#endif
-#if defined (SYS_modload)
- syscall_table[SYS_modload] = "modload";
-#endif
-#if defined (SYS_moduload)
- syscall_table[SYS_moduload] = "moduload";
-#endif
-#if defined (SYS_modpath)
- syscall_table[SYS_modpath] = "modpath";
-#endif
-#if defined (SYS_modstat)
- syscall_table[SYS_modstat] = "modstat";
-#endif
-#if defined (SYS_modadm)
- syscall_table[SYS_modadm] = "modadm";
-#endif
-#if defined (SYS_getksym)
- syscall_table[SYS_getksym] = "getksym";
-#endif
-#if defined (SYS_lwp_suspend)
- syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
-#endif
-#if defined (SYS_lwp_continue)
- syscall_table[SYS_lwp_continue] = "_lwp_continue";
-#endif
-#if defined (SYS_priocntllst)
- syscall_table[SYS_priocntllst] = "priocntllst";
-#endif
-#if defined (SYS_sleep)
- syscall_table[SYS_sleep] = "sleep";
-#endif
-#if defined (SYS_lwp_sema_wait)
- syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
-#endif
-#if defined (SYS_lwp_sema_post)
- syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
-#endif
-#if defined (SYS_lwp_sema_trywait)
- syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
-#endif
-#if defined(SYS_fstatvfs64)
- syscall_table[SYS_fstatvfs64] = "fstatvfs64";
-#endif
-#if defined(SYS_statvfs64)
- syscall_table[SYS_statvfs64] = "statvfs64";
-#endif
-#if defined(SYS_ftruncate64)
- syscall_table[SYS_ftruncate64] = "ftruncate64";
-#endif
-#if defined(SYS_truncate64)
- syscall_table[SYS_truncate64] = "truncate64";
-#endif
-#if defined(SYS_getrlimit64)
- syscall_table[SYS_getrlimit64] = "getrlimit64";
-#endif
-#if defined(SYS_setrlimit64)
- syscall_table[SYS_setrlimit64] = "setrlimit64";
-#endif
-#if defined(SYS_lseek64)
- syscall_table[SYS_lseek64] = "lseek64";
-#endif
-#if defined(SYS_mmap64)
- syscall_table[SYS_mmap64] = "mmap64";
-#endif
-#if defined(SYS_pread64)
- syscall_table[SYS_pread64] = "pread64";
-#endif
-#if defined(SYS_creat64)
- syscall_table[SYS_creat64] = "creat64";
-#endif
-#if defined(SYS_dshmsys)
- syscall_table[SYS_dshmsys] = "dshmsys";
-#endif
-#if defined(SYS_invlpg)
- syscall_table[SYS_invlpg] = "invlpg";
-#endif
-#if defined(SYS_cg_ids)
- syscall_table[SYS_cg_ids] = "cg_ids";
-#endif
-#if defined(SYS_cg_processors)
- syscall_table[SYS_cg_processors] = "cg_processors";
-#endif
-#if defined(SYS_cg_info)
- syscall_table[SYS_cg_info] = "cg_info";
-#endif
-#if defined(SYS_cg_bind)
- syscall_table[SYS_cg_bind] = "cg_bind";
-#endif
-#if defined(SYS_cg_current)
- syscall_table[SYS_cg_current] = "cg_current";
-#endif
-#if defined(SYS_cg_memloc)
- syscall_table[SYS_cg_memloc] = "cg_memloc";
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCSTRACE, sigset) >= 0);
#endif
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
+
+ if (!win)
+ warning ("procfs: set_traced_signals failed");
+ return win;
}
/*
+ * Function: proc_set_traced_faults
+ *
+ * Register to trace hardware faults in the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
+int
+proc_set_traced_faults (pi, fltset)
+ procinfo *pi;
+ fltset_t *fltset;
+{
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- procfs_kill_inferior - kill any currently inferior
+#ifdef NEW_PROC_API
+ {
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char fltset[sizeof (fltset_t)];
+ } arg;
-SYNOPSIS
+ arg.cmd = PCSFAULT;
+ memcpy (&arg.fltset, fltset, sizeof (fltset_t));
- void procfs_kill_inferior (void)
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCSFAULT, fltset) >= 0);
+#endif
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
-DESCRIPTION
+ return win;
+}
- Kill any current inferior.
+/*
+ * Function: proc_set_traced_sysentry
+ *
+ * Register to trace entry to system calls in the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-NOTES
+int
+proc_set_traced_sysentry (pi, sysset)
+ procinfo *pi;
+ sysset_t *sysset;
+{
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- Kills even attached inferiors. Presumably the user has already
- been prompted that the inferior is an attached one rather than
- one started by gdb. (FIXME?)
+#ifdef NEW_PROC_API
+ {
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char sysset[sizeof (sysset_t)];
+ } arg;
-*/
+ arg.cmd = PCSENTRY;
+ memcpy (&arg.sysset, sysset, sizeof (sysset_t));
-static void
-procfs_kill_inferior ()
-{
- target_mourn_inferior ();
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCSENTRY, sysset) >= 0);
+#endif
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
+
+ return win;
}
/*
+ * Function: proc_set_traced_sysexit
+ *
+ * Register to trace exit from system calls in the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
-
- unconditionally_kill_inferior - terminate the inferior
-
-SYNOPSIS
-
- static void unconditionally_kill_inferior (struct procinfo *)
+int
+proc_set_traced_sysexit (pi, sysset)
+ procinfo *pi;
+ sysset_t *sysset;
+{
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-DESCRIPTION
+#ifdef NEW_PROC_API
+ {
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char sysset[sizeof (sysset_t)];
+ } arg;
- Kill the specified inferior.
+ arg.cmd = PCSEXIT;
+ memcpy (&arg.sysset, sysset, sizeof (sysset_t));
-NOTE
+ win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else /* ioctl method */
+ win = (ioctl (pi->ctl_fd, PIOCSEXIT, sysset) >= 0);
+#endif
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
- A possibly useful enhancement would be to first try sending
- the inferior a terminate signal, politely asking it to commit
- suicide, before we murder it (we could call that
- politely_kill_inferior()).
+ return win;
+}
-*/
+/*
+ * Function: proc_set_held_signals
+ *
+ * Specify the set of blocked / held signals in the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-static void
-unconditionally_kill_inferior (pi)
- struct procinfo *pi;
+int
+proc_set_held_signals (pi, sighold)
+ procinfo *pi;
+ sigset_t *sighold;
{
- int ppid;
- struct proc_ctl pctl;
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
- ppid = pi->prstatus.pr_ppid;
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
- /* Alpha OSF/1-3.x procfs needs a clear of the current signal
- before the PIOCKILL, otherwise it might generate a corrupted core
- file for the inferior. */
- ioctl (pi->ctl_fd, PIOCSSIG, NULL);
-#endif
-#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
- /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
- to kill the inferior, otherwise it might remain stopped with a
- pending SIGKILL.
- We do not check the result of the PIOCSSIG, the inferior might have
- died already. */
+#ifdef NEW_PROC_API
{
- struct siginfo newsiginfo;
-
- memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
- newsiginfo.si_signo = SIGKILL;
- newsiginfo.si_code = 0;
- newsiginfo.si_errno = 0;
- newsiginfo.si_pid = getpid ();
- newsiginfo.si_uid = getuid ();
- ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo);
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char hold[sizeof (sigset_t)];
+ } arg;
+
+ arg.cmd = PCSHOLD;
+ memcpy (&arg.hold, sighold, sizeof (sigset_t));
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
}
-#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
- procfs_write_pckill (pi);
-#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
-
- close_proc_file (pi);
-
-/* Only wait() for our direct children. Our grandchildren zombies are killed
- by the death of their parents. */
+#else
+ win = (ioctl (pi->ctl_fd, PIOCSHOLD, sighold) >= 0);
+#endif
+ /* The above operation renders the procinfo's cached pstatus obsolete. */
+ pi->status_valid = 0;
- if (ppid == getpid())
- wait ((int *) 0);
+ return win;
}
/*
+ * Function: proc_get_pending_signals
+ *
+ * returns the set of signals that are pending in the process or LWP.
+ * Will also copy the sigset if 'save' is non-zero.
+ */
-LOCAL FUNCTION
-
- procfs_xfer_memory -- copy data to or from inferior memory space
-
-SYNOPSIS
-
- int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
- int dowrite, struct target_ops target)
+sigset_t *
+proc_get_pending_signals (pi, save)
+ procinfo *pi;
+ sigset_t *save;
+{
+ sigset_t *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-DESCRIPTION
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- Copy LEN bytes to/from inferior's memory starting at MEMADDR
- from/to debugger memory starting at MYADDR. Copy from inferior
- if DOWRITE is zero or to inferior if DOWRITE is nonzero.
-
- Returns the length copied, which is either the LEN argument or
- zero. This xfer function does not do partial moves, since procfs_ops
- doesn't allow memory operations to cross below us in the target stack
- anyway.
+#ifdef NEW_PROC_API
+ ret = &pi->prstatus.pr_lwp.pr_lwppend;
+#else
+ ret = &pi->prstatus.pr_sigpend;
+#endif
+ if (save && ret)
+ memcpy (save, ret, sizeof (sigset_t));
-NOTES
+ return ret;
+}
- The /proc interface makes this an almost trivial task.
+/*
+ * Function: proc_get_signal_actions
+ *
+ * returns the set of signal actions.
+ * Will also copy the sigactionset if 'save' is non-zero.
*/
-static int
-procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int dowrite;
- struct target_ops *target; /* ignored */
+struct sigaction *
+proc_get_signal_actions (pi, save)
+ procinfo *pi;
+ struct sigaction *save;
{
- int nbytes = 0;
- struct procinfo *pi;
+ struct sigaction *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- pi = current_procinfo;
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- if (lseek(pi->as_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
- {
- if (dowrite)
- {
- nbytes = write (pi->as_fd, myaddr, len);
- }
- else
- {
- nbytes = read (pi->as_fd, myaddr, len);
- }
- if (nbytes < 0)
- {
- nbytes = 0;
- }
- }
- return (nbytes);
+#ifdef NEW_PROC_API
+ ret = &pi->prstatus.pr_lwp.pr_action;
+#else
+ ret = &pi->prstatus.pr_action;
+#endif
+ if (save && ret)
+ memcpy (save, ret, sizeof (struct sigaction));
+
+ return ret;
}
/*
+ * Function: proc_get_held_signals
+ *
+ * returns the set of signals that are held / blocked.
+ * Will also copy the sigset if 'save' is non-zero.
+ */
-LOCAL FUNCTION
+sigset_t *
+proc_get_held_signals (pi, save)
+ procinfo *pi;
+ sigset_t *save;
+{
+ sigset_t *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- procfs_store_registers -- copy register values back to inferior
+#ifdef NEW_PROC_API
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
+
+#ifdef UNIXWARE
+ ret = &pi->prstatus.pr_lwp.pr_context.uc_sigmask;
+#else
+ ret = &pi->prstatus.pr_lwp.pr_lwphold;
+#endif /* UNIXWARE */
+#else /* not NEW_PROC_API */
+ {
+ static sigset_t sigheld;
-SYNOPSIS
+ if (ioctl (pi->ctl_fd, PIOCGHOLD, &sigheld) >= 0)
+ ret = &sigheld;
+ }
+#endif /* NEW_PROC_API */
+ if (save && ret)
+ memcpy (save, ret, sizeof (sigset_t));
- void procfs_store_registers (int regno)
+ return ret;
+}
-DESCRIPTION
+/*
+ * Function: proc_get_traced_signals
+ *
+ * returns the set of signals that are traced / debugged.
+ * Will also copy the sigset if 'save' is non-zero.
+ */
- Store our current register values back into the inferior. If
- REGNO is -1 then store all the register, otherwise store just
- the value specified by REGNO.
+sigset_t *
+proc_get_traced_signals (pi, save)
+ procinfo *pi;
+ sigset_t *save;
+{
+ sigset_t *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-NOTES
+#ifdef NEW_PROC_API
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- If we are storing only a single register, we first have to get all
- the current values from the process, overwrite the desired register
- in the gregset with the one we want from gdb's registers, and then
- send the whole set back to the process. For writing all the
- registers, all we have to do is generate the gregset and send it to
- the process.
+ ret = &pi->prstatus.pr_sigtrace;
+#else
+ {
+ static sigset_t sigtrace;
- Also note that the process has to be stopped on an event of interest
- for this to work, which basically means that it has to have been
- run under the control of one of the other /proc ioctl calls and not
- ptrace. Since we don't use ptrace anyway, we don't worry about this
- fine point, but it is worth noting for future reference.
+ if (ioctl (pi->ctl_fd, PIOCGTRACE, &sigtrace) >= 0)
+ ret = &sigtrace;
+ }
+#endif
+ if (save && ret)
+ memcpy (save, ret, sizeof (sigset_t));
- Gdb is confused about what this function is supposed to return.
- Some versions return a value, others return nothing. Some are
- declared to return a value and actually return nothing. Gdb ignores
- anything returned. (FIXME)
+ return ret;
+}
+/*
+ * Function: proc_trace_signal
+ *
+ * Add 'signo' to the set of signals that are traced.
+ * Returns non-zero for success, zero for failure.
*/
-static void
-procfs_store_registers (regno)
- int regno;
+int
+proc_trace_signal (pi, signo)
+ procinfo *pi;
+ int signo;
{
- struct procinfo *pi;
-#ifdef PROCFS_USE_READ_WRITE
- struct greg_ctl greg;
- struct fpreg_ctl fpreg;
-#endif
-
- pi = current_procinfo;
+ sigset_t temp;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-#ifdef PROCFS_USE_READ_WRITE
- if (regno != -1)
- {
- procfs_read_status (pi);
- memcpy ((char *) &greg.gregset,
- (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
- sizeof (gdb_gregset_t));
- }
- fill_gregset (&greg.gregset, regno);
- greg.cmd = PCSREG;
- write (pi->ctl_fd, &greg, sizeof (greg));
-#else /* PROCFS_USE_READ_WRITE */
- if (regno != -1)
+ if (pi)
{
- ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset);
+ if (proc_get_traced_signals (pi, &temp))
+ {
+ praddset (&temp, signo);
+ return proc_set_traced_signals (pi, &temp);
+ }
}
- fill_gregset (&pi->gregset.gregset, regno);
- ioctl (pi->ctl_fd, PIOCSREG, &pi->gregset.gregset);
-#endif /* PROCFS_USE_READ_WRITE */
-#if defined (FP0_REGNUM)
+ return 0; /* failure */
+}
- /* Now repeat everything using the floating point register set, if the
- target has floating point hardware. Since we ignore the returned value,
- we'll never know whether it worked or not anyway. */
+/*
+ * Function: proc_ignore_signal
+ *
+ * Remove 'signo' from the set of signals that are traced.
+ * Returns non-zero for success, zero for failure.
+ */
-#ifdef PROCFS_USE_READ_WRITE
- if (regno != -1)
- {
- procfs_read_status (pi);
- memcpy ((char *) &fpreg.fpregset,
- (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
- sizeof (gdb_fpregset_t));
- }
- fill_fpregset (&fpreg.fpregset, regno);
- fpreg.cmd = PCSFPREG;
- write (pi->ctl_fd, &fpreg, sizeof (fpreg));
-#else /* PROCFS_USE_READ_WRITE */
- if (regno != -1)
+int
+proc_ignore_signal (pi, signo)
+ procinfo *pi;
+ int signo;
+{
+ sigset_t temp;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
+
+ if (pi)
{
- ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset);
+ if (proc_get_traced_signals (pi, &temp))
+ {
+ prdelset (&temp, signo);
+ return proc_set_traced_signals (pi, &temp);
+ }
}
- fill_fpregset (&pi->fpregset.fpregset, regno);
- ioctl (pi->ctl_fd, PIOCSFPREG, &pi->fpregset.fpregset);
-#endif /* PROCFS_USE_READ_WRITE */
-
-#endif /* FP0_REGNUM */
+ return 0; /* failure */
}
/*
+ * Function: proc_get_traced_faults
+ *
+ * returns the set of hardware faults that are traced /debugged.
+ * Will also copy the faultset if 'save' is non-zero.
+ */
-LOCAL FUNCTION
-
- init_procinfo - setup a procinfo struct and connect it to a process
-
-SYNOPSIS
-
- struct procinfo * init_procinfo (int pid)
+fltset_t *
+proc_get_traced_faults (pi, save)
+ procinfo *pi;
+ fltset_t *save;
+{
+ fltset_t *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-DESCRIPTION
+#ifdef NEW_PROC_API
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- Allocate a procinfo structure, open the /proc file and then set up the
- set of signals and faults that are to be traced. Returns a pointer to
- the new procinfo structure.
+ ret = &pi->prstatus.pr_flttrace;
+#else
+ {
+ static fltset_t flttrace;
-NOTES
+ if (ioctl (pi->ctl_fd, PIOCGFAULT, &flttrace) >= 0)
+ ret = &flttrace;
+ }
+#endif
+ if (save && ret)
+ memcpy (save, ret, sizeof (fltset_t));
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
+ return ret;
+}
+/*
+ * Function: proc_get_traced_sysentry
+ *
+ * returns the set of syscalls that are traced /debugged on entry.
+ * Will also copy the syscall set if 'save' is non-zero.
*/
-static struct procinfo *
-init_procinfo (pid, kill)
- int pid;
- int kill;
+sysset_t *
+proc_get_traced_sysentry (pi, save)
+ procinfo *pi;
+ sysset_t *save;
{
- struct procinfo *pi = (struct procinfo *)
- xmalloc (sizeof (struct procinfo));
- struct sig_ctl sctl;
- struct flt_ctl fctl;
-
- memset ((char *) pi, 0, sizeof (*pi));
- if (!open_proc_file (pid, pi, O_RDWR, 1))
- proc_init_failed (pi, "can't open process file", kill);
-
- /* open_proc_file may modify pid. */
-
- pid = pi -> pid;
-
- /* Add new process to process info list */
+ sysset_t *ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- pi->next = procinfo_list;
- procinfo_list = pi;
+#ifdef NEW_PROC_API
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- add_fd (pi); /* Add to list for poll/select */
+ ret = &pi->prstatus.pr_sysentry;
+#else
+ {
+ static sysset_t sysentry;
- /* Remember some things about the inferior that we will, or might, change
- so that we can restore them when we detach. */
-#ifdef UNIXWARE
- memcpy ((char *) &pi->saved_trace.sigset,
- (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
- memcpy ((char *) &pi->saved_fltset.fltset,
- (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
- memcpy ((char *) &pi->saved_entryset.sysset,
- (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
- memcpy ((char *) &pi->saved_exitset.sysset,
- (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- prfillset (&sctl.sigset);
- notice_signals (pi, &sctl);
- prfillset (&fctl.fltset);
- prdelset (&fctl.fltset, FLTPAGE);
-
-#else /* ! UNIXWARE */
- ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
- ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
- ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
- ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
- ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
- prfillset (&pi->prrun.pr_trace);
- procfs_notice_signals (pid);
- prfillset (&pi->prrun.pr_fault);
- prdelset (&pi->prrun.pr_fault, FLTPAGE);
-#ifdef PROCFS_DONT_TRACE_FAULTS
- premptyset (&pi->prrun.pr_fault);
+ if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysentry) >= 0)
+ ret = &sysentry;
+ }
#endif
-#endif /* UNIXWARE */
+ if (save && ret)
+ memcpy (save, ret, sizeof (sysset_t));
- if (!procfs_read_status (pi))
- proc_init_failed (pi, "procfs_read_status failed", kill);
-
- return pi;
+ return ret;
}
/*
+ * Function: proc_get_traced_sysexit
+ *
+ * returns the set of syscalls that are traced /debugged on exit.
+ * Will also copy the syscall set if 'save' is non-zero.
+ */
-LOCAL FUNCTION
-
- create_procinfo - initialize access to a /proc entry
-
-SYNOPSIS
-
- struct procinfo * create_procinfo (int pid)
+sysset_t *
+proc_get_traced_sysexit (pi, save)
+ procinfo *pi;
+ sysset_t *save;
+{
+ sysset_t * ret = NULL;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-DESCRIPTION
+#ifdef NEW_PROC_API
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- Allocate a procinfo structure, open the /proc file and then set up the
- set of signals and faults that are to be traced. Returns a pointer to
- the new procinfo structure.
+ ret = &pi->prstatus.pr_sysexit;
+#else
+ {
+ static sysset_t sysexit;
-NOTES
+ if (ioctl (pi->ctl_fd, PIOCGEXIT, &sysexit) >= 0)
+ ret = &sysexit;
+ }
+#endif
+ if (save && ret)
+ memcpy (save, ret, sizeof (sysset_t));
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
+ return ret;
+}
+/*
+ * Function: proc_clear_current_fault
+ *
+ * The current fault (if any) is cleared; the associated signal
+ * will not be sent to the process or LWP when it resumes.
+ * Returns non-zero for success, zero for failure.
*/
-static struct procinfo *
-create_procinfo (pid)
- int pid;
+int
+proc_clear_current_fault (pi)
+ procinfo *pi;
{
- struct procinfo *pi;
- struct sig_ctl sctl;
- struct flt_ctl fctl;
-
- pi = find_procinfo (pid, 1);
- if (pi != NULL)
- return pi; /* All done! It already exists */
-
- pi = init_procinfo (pid, 1);
-
-#ifndef UNIXWARE
-/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
- already stopped, even if they all have PR_ASYNC set. */
- if (!(pi->prstatus.pr_flags & PR_STOPPED))
-#endif
- if (!procfs_write_pcwstop (pi))
- proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-#ifdef PROCFS_USE_READ_WRITE
- fctl.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- proc_init_failed (pi, "PCSFAULT failed", 1);
+#ifdef NEW_PROC_API
+ {
+ int cmd = PCCFAULT;
+ win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd));
+ }
#else
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
- proc_init_failed (pi, "PIOCSFAULT failed", 1);
+ win = (ioctl (pi->ctl_fd, PIOCCFAULT, 0) >= 0);
#endif
- return pi;
+ return win;
}
/*
-
-LOCAL FUNCTION
-
- procfs_exit_handler - handle entry into the _exit syscall
-
-SYNOPSIS
-
- int procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called when an inferior process enters the _exit()
- system call. It continues the process, and then collects the exit
- status and pid which are returned in *statvalp and *rtnvalp. After
- that it returns non-zero to indicate that procfs_wait should wake up.
-
-NOTES
- There is probably a better way to do this.
-
+ * Function: proc_set_current_signal
+ *
+ * Set the "current signal" that will be delivered next to the process.
+ * NOTE: semantics are different from those of KILL.
+ * This signal will be delivered to the process or LWP
+ * immediately when it is resumed (even if the signal is held/blocked);
+ * it will NOT immediately cause another event of interest, and will NOT
+ * first trap back to the debugger.
+ *
+ * Returns non-zero for success, zero for failure.
*/
-static int
-procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
+int
+proc_set_current_signal (pi, signo)
+ procinfo *pi;
+ int signo;
{
- struct procinfo *temp_pi, *next_pi;
- struct proc_ctl pctl;
-
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-#else
- pi->prrun.pr_flags = PRCFAULT;
-#endif
+ int win;
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char sinfo[sizeof (struct siginfo)];
+ } arg;
+ struct siginfo *mysinfo;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-#ifdef PROCFS_USE_READ_WRITE
- if (write (pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
+#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
+ /* With Alpha OSF/1 procfs, the kernel gets really confused if it
+ * receives a PIOCSSIG with a signal identical to the current signal,
+ * it messes up the current signal. Work around the kernel bug.
+ */
+ if (signo > 0 &&
+ signo == proc_cursig (pi))
+ return 1; /* I assume this is a success? */
+#endif
+
+ /* The pointer is just a type alias. */
+ mysinfo = (struct siginfo *) &arg.sinfo;
+ mysinfo->si_signo = signo;
+ mysinfo->si_code = 0;
+ mysinfo->si_pid = getpid (); /* ?why? */
+ mysinfo->si_uid = getuid (); /* ?why? */
+
+#ifdef NEW_PROC_API
+ arg.cmd = PCSSIG;
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
#else
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ win = (ioctl (pi->ctl_fd, PIOCSSIG, (void *) &arg.sinfo) >= 0);
#endif
- perror_with_name (pi->pathname);
- if (attach_flag)
- {
- /* Claim it exited (don't call wait). */
- if (info_verbose)
- printf_filtered ("(attached process has exited)\n");
- *statvalp = 0;
- *rtnvalp = inferior_pid;
- }
- else
- {
- *rtnvalp = wait (statvalp);
- if (*rtnvalp >= 0)
- *rtnvalp = pi->pid;
- }
-
- /* Close ALL open proc file handles,
- except the one that called SYS_exit. */
- for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
- {
- next_pi = temp_pi->next;
- if (temp_pi == pi)
- continue; /* Handled below */
- close_proc_file (temp_pi);
- }
- return 1;
+ return win;
}
/*
+ * Function: proc_clear_current_signal
+ *
+ * The current signal (if any) is cleared, and
+ * is not sent to the process or LWP when it resumes.
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
-
- procfs_exec_handler - handle exit from the exec family of syscalls
-
-SYNOPSIS
-
- int procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
+int
+proc_clear_current_signal (pi)
+ procinfo *pi;
+{
+ int win;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- This routine is called when an inferior process is about to finish any
- of the exec() family of system calls. It pretends that we got a
- SIGTRAP (for compatibility with ptrace behavior), and returns non-zero
- to tell procfs_wait to wake up.
+#ifdef NEW_PROC_API
+ {
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char sinfo[sizeof (struct siginfo)];
+ } arg;
+ struct siginfo *mysinfo;
+
+ arg.cmd = PCSSIG;
+ /* The pointer is just a type alias. */
+ mysinfo = (struct siginfo *) &arg.sinfo;
+ mysinfo->si_signo = 0;
+ mysinfo->si_code = 0;
+ mysinfo->si_errno = 0;
+ mysinfo->si_pid = getpid (); /* ?why? */
+ mysinfo->si_uid = getuid (); /* ?why? */
+
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+#else
+ win = (ioctl (pi->ctl_fd, PIOCSSIG, 0) >= 0);
+#endif
-NOTES
- This need for compatibility with ptrace is questionable. In the
- future, it shouldn't be necessary.
+ return win;
+}
+/*
+ * Function: proc_get_gregs
+ *
+ * Get the general registers for the process or LWP.
+ * Returns non-zero for success, zero for failure.
*/
-static int
-procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
+gdb_gregset_t *
+proc_get_gregs (pi)
+ procinfo *pi;
{
- *statvalp = (SIGTRAP << 8) | 0177;
-
- return 1;
+ if (!pi->status_valid || !pi->gregs_valid)
+ if (!proc_get_status (pi))
+ return NULL;
+
+ /*
+ * OK, sorry about the ifdef's.
+ * There's three cases instead of two, because
+ * in this instance Unixware and Solaris/RW differ.
+ */
+
+#ifdef NEW_PROC_API
+#ifdef UNIXWARE /* ugh, a true architecture dependency */
+ return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs;
+#else /* not Unixware */
+ return &pi->prstatus.pr_lwp.pr_reg;
+#endif /* Unixware */
+#else /* not NEW_PROC_API */
+ return &pi->prstatus.pr_reg;
+#endif /* NEW_PROC_API */
}
-#if defined(SYS_sproc) && !defined(UNIXWARE)
-/* IRIX lwp creation system call */
-
/*
+ * Function: proc_get_fpregs
+ *
+ * Get the floating point registers for the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
-
- procfs_sproc_handler - handle exit from the sproc syscall
-
-SYNOPSIS
-
- int procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
+gdb_fpregset_t *
+proc_get_fpregs (pi)
+ procinfo *pi;
+{
+#ifdef NEW_PROC_API
+ if (!pi->status_valid || !pi->fpregs_valid)
+ if (!proc_get_status (pi))
+ return NULL;
- This routine is called when an inferior process is about to finish an
- sproc() system call. This is the system call that IRIX uses to create
- a lightweight process. When the target process gets this event, we can
- look at rval1 to find the new child processes ID, and create a new
- procinfo struct from that.
+#ifdef UNIXWARE /* a true architecture dependency */
+ return &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs;
+#else
+ return &pi->prstatus.pr_lwp.pr_fpreg;
+#endif /* Unixware */
- After that, it pretends that we got a SIGTRAP, and returns non-zero
- to tell procfs_wait to wake up. Subsequently, wait_for_inferior gets
- woken up, sees the new process and continues it.
+#else /* not NEW_PROC_API */
+ if (pi->fpregs_valid)
+ return &pi->fpregset; /* already got 'em */
+ else
+ {
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
+ {
+ return NULL;
+ }
+ else
+ {
+#ifdef PIOCTGFPREG
+ struct {
+ long pr_count;
+ tid_t pr_error_thread;
+ tfpregset_t thread_1;
+ } thread_fpregs;
+
+ thread_fpregs.pr_count = 1;
+ thread_fpregs.thread_1.tid = pi->tid;
+
+ if (pi->tid == 0 &&
+ ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
+ {
+ pi->fpregs_valid = 1;
+ return &pi->fpregset; /* got 'em now! */
+ }
+ else if (pi->tid != 0 &&
+ ioctl (pi->ctl_fd, PIOCTGFPREG, &thread_fpregs) >= 0)
+ {
+ memcpy (&pi->fpregset, &thread_fpregs.thread_1.pr_fpregs,
+ sizeof (pi->fpregset));
+ pi->fpregs_valid = 1;
+ return &pi->fpregset; /* got 'em now! */
+ }
+ else
+ {
+ return NULL;
+ }
+#else
+ if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset) >= 0)
+ {
+ pi->fpregs_valid = 1;
+ return &pi->fpregset; /* got 'em now! */
+ }
+ else
+ {
+ return NULL;
+ }
+#endif
+ }
+ }
+#endif
+}
-NOTES
- We actually never see the child exiting from sproc because we will
- shortly stop the child with PIOCSTOP, which is then registered as the
- event of interest.
+/*
+ * Function: proc_set_gregs
+ *
+ * Write the general registers back to the process or LWP.
+ * Returns non-zero for success, zero for failure.
*/
-static int
-procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
+int
+proc_set_gregs (pi)
+ procinfo *pi;
{
-/* We've just detected the completion of an sproc system call. Now we need to
- setup a procinfo struct for this thread, and notify the thread system of the
- new arrival. */
+ gdb_gregset_t *gregs;
+ int win;
-/* If sproc failed, then nothing interesting happened. Continue the process
- and go back to sleep. */
+ if ((gregs = proc_get_gregs (pi)) == NULL)
+ return 0; /* get_regs has already warned */
- if (pi->prstatus.pr_errno != 0)
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
{
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
-
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
-
return 0;
}
+ else
+ {
+#ifdef NEW_PROC_API
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char gregs[sizeof (gdb_gregset_t)];
+ } arg;
+
+ arg.cmd = PCSREG;
+ memcpy (&arg.gregs, gregs, sizeof (arg.gregs));
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
+#else
+ win = (ioctl (pi->ctl_fd, PIOCSREG, gregs) >= 0);
+#endif
+ }
- /* At this point, the new thread is stopped at it's first instruction, and
- the parent is stopped at the exit from sproc. */
-
- /* Notify the caller of the arrival of a new thread. */
- create_procinfo (pi->prstatus.pr_rval1);
-
- *rtnvalp = pi->prstatus.pr_rval1;
- *statvalp = (SIGTRAP << 8) | 0177;
-
- return 1;
+ /* Policy: writing the regs invalidates our cache. */
+ pi->gregs_valid = 0;
+ return win;
}
/*
+ * Function: proc_set_fpregs
+ *
+ * Modify the floating point register set of the process or LWP.
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
-
- procfs_fork_handler - handle exit from the fork syscall
-
-SYNOPSIS
-
- int procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
+int
+proc_set_fpregs (pi)
+ procinfo *pi;
+{
+ gdb_fpregset_t *fpregs;
+ int win;
-DESCRIPTION
+ if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ return 0; /* get_fpregs has already warned */
- This routine is called when an inferior process is about to finish a
- fork() system call. We will open up the new process, and then close
- it, which releases it from the clutches of the debugger.
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+#ifdef NEW_PROC_API
+ struct {
+ int cmd;
+ /* Use char array to avoid alignment issues. */
+ char fpregs[sizeof (gdb_fpregset_t)];
+ } arg;
+
+ arg.cmd = PCSFPREG;
+ memcpy (&arg.fpregs, fpregs, sizeof (arg.fpregs));
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
+#else
+#ifdef PIOCTSFPREG
+ if (pi->tid == 0)
+ win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
+ else
+ {
+ struct {
+ long pr_count;
+ tid_t pr_error_thread;
+ tfpregset_t thread_1;
+ } thread_fpregs;
+
+ thread_fpregs.pr_count = 1;
+ thread_fpregs.thread_1.tid = pi->tid;
+ memcpy (&thread_fpregs.thread_1.pr_fpregs, fpregs,
+ sizeof (*fpregs));
+ win = (ioctl (pi->ctl_fd, PIOCTSFPREG, &thread_fpregs) >= 0);
+ }
+#else
+ win = (ioctl (pi->ctl_fd, PIOCSFPREG, fpregs) >= 0);
+#endif /* osf PIOCTSFPREG */
+#endif /* NEW_PROC_API */
+ }
- After that, we continue the target process as though nothing had
- happened.
+ /* Policy: writing the regs invalidates our cache. */
+ pi->fpregs_valid = 0;
+ return win;
+}
-NOTES
- This is necessary for IRIX because we have to set PR_FORK in order
- to catch the creation of lwps (via sproc()). When an actual fork
- occurs, it becomes necessary to reset the forks debugger flags and
- continue it because we can't hack multiple processes yet.
+/*
+ * Function: proc_kill
+ *
+ * Send a signal to the proc or lwp with the semantics of "kill()".
+ * Returns non-zero for success, zero for failure.
*/
-static int
-procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
+int
+proc_kill (pi, signo)
+ procinfo *pi;
+ int signo;
{
- struct procinfo *pitemp;
-
-/* At this point, we've detected the completion of a fork (or vfork) call in
- our child. The grandchild is also stopped because we set inherit-on-fork
- earlier. (Note that nobody has the grandchilds' /proc file open at this
- point.) We will release the grandchild from the debugger by opening it's
- /proc file and then closing it. Since run-on-last-close is set, the
- grandchild continues on its' merry way. */
+ int win;
+ /*
+ * We might conceivably apply this operation to an LWP, and
+ * the LWP's ctl file descriptor might not be open.
+ */
- pitemp = create_procinfo (pi->prstatus.pr_rval1);
- if (pitemp)
- close_proc_file (pitemp);
+ if (pi->ctl_fd == 0 &&
+ open_procinfo_files (pi, FD_CTL) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+#ifdef NEW_PROC_API
+ int cmd[2];
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
+ cmd[0] = PCKILL;
+ cmd[1] = signo;
+ win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
+#else /* ioctl method */
+ /* FIXME: do I need the Alpha OSF fixups present in
+ procfs.c/unconditionally_kill_inferior? Perhaps only for SIGKILL? */
+ win = (ioctl (pi->ctl_fd, PIOCKILL, &signo) >= 0);
+#endif
+ }
- return 0;
+ return win;
}
-#endif /* SYS_sproc && !UNIXWARE */
/*
+ * Function: proc_parent_pid
+ *
+ * Find the pid of the process that started this one.
+ * Returns the parent process pid, or zero.
+ */
-LOCAL FUNCTION
-
- procfs_set_inferior_syscall_traps - setup the syscall traps
-
-SYNOPSIS
+int
+proc_parent_pid (pi)
+ procinfo *pi;
+{
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- void procfs_set_inferior_syscall_traps (struct procinfo *pip)
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0;
-DESCRIPTION
+ return pi->prstatus.pr_ppid;
+}
- Called for each "procinfo" (process, thread, or LWP) in the
- inferior, to register for notification of and handlers for
- syscall traps in the inferior.
+/*
+ * Function: proc_set_watchpoint
+ *
*/
-static void
-procfs_set_inferior_syscall_traps (pip)
- struct procinfo *pip;
+int
+proc_set_watchpoint (pi, addr, len, wflags)
+ procinfo *pi;
+ CORE_ADDR addr;
+ int len;
+ int wflags;
{
- procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
- procfs_exit_handler);
-
-#ifndef PRFS_STOPEXEC
-#ifdef SYS_exec
- procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
+#if !defined (TARGET_HAS_HARDWARE_WATCHPOINTS)
+ return 0;
+#else
+/* Horrible hack! Detect Solaris 2.5, because this doesn't work on 2.5 */
+#if defined (PIOCOPENLWP) || defined (UNIXWARE) /* Solaris 2.5: bail out */
+ return 0;
+#else
+ struct {
+ int cmd;
+ char watch[sizeof (prwatch_t)];
+ } arg;
+ prwatch_t *pwatch;
+
+ pwatch = (prwatch_t *) &arg.watch;
+ pwatch->pr_vaddr = addr;
+ pwatch->pr_size = len;
+ pwatch->pr_wflags = wflags;
+#if defined(NEW_PROC_API) && defined (PCWATCH)
+ arg.cmd = PCWATCH;
+ return (write (pi->ctl_fd, &arg, sizeof (arg)) == sizeof (arg));
+#else
+#if defined (PIOCSWATCH)
+ return (ioctl (pi->ctl_fd, PIOCSWATCH, pwatch) >= 0);
+#else
+ return 0; /* Fail */
#endif
-#ifdef SYS_execv
- procfs_set_syscall_trap (pip, SYS_execv, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
#endif
-#ifdef SYS_execve
- procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
#endif
-#endif /* PRFS_STOPEXEC */
+#endif
+}
- /* Setup traps on exit from sproc() */
+/*
+ * Function: proc_iterate_over_mappings
+ *
+ * Given a pointer to a function, call that function once for every
+ * mapped address space in the process. The callback function
+ * receives an open file descriptor for the file corresponding to
+ * that mapped address space (if there is one), and the base address
+ * of the mapped space. Quit when the callback function returns a
+ * nonzero value, or at teh end of the mappings.
+ *
+ * Returns: the first non-zero return value of the callback function,
+ * or zero.
+ */
-#ifdef SYS_sproc
- procfs_set_syscall_trap (pip, SYS_sproc, PROCFS_SYSCALL_EXIT,
- procfs_sproc_handler);
- procfs_set_syscall_trap (pip, SYS_fork, PROCFS_SYSCALL_EXIT,
- procfs_fork_handler);
-#ifdef SYS_vfork
- procfs_set_syscall_trap (pip, SYS_vfork, PROCFS_SYSCALL_EXIT,
- procfs_fork_handler);
+/* FIXME: it's probably a waste to cache this FD.
+ It doesn't get called that often... and if I open it
+ every time, I don't need to lseek it. */
+int
+proc_iterate_over_mappings (func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ struct prmap *map;
+ procinfo *pi;
+#ifndef NEW_PROC_API /* avoid compiler warning */
+ int nmaps = 0;
+ int i;
+#else
+ int map_fd;
+ char pathname[MAX_PROC_NAME_SIZE];
#endif
-/* Turn on inherit-on-fork flag so that all children of the target process
- start with tracing flags set. This allows us to trap lwp creation. Note
- that we also have to trap on fork and vfork in order to disable all tracing
- in the targets child processes. */
+ int funcstat = 0;
+ int fd;
- modify_inherit_on_fork_flag (pip->ctl_fd, 1);
-#endif
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
-#ifdef SYS_lwp_create
- procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
- procfs_lwp_creation_handler);
-#endif
-}
+#ifdef NEW_PROC_API
+ /* Open map fd. */
+ sprintf (pathname, "/proc/%d/map", pi->pid);
+ if ((map_fd = open (pathname, O_RDONLY)) < 0)
+ proc_error (pi, "proc_iterate_over_mappings (open)", __LINE__);
-/*
+ /* Make sure it gets closed again. */
+ make_cleanup ((make_cleanup_func) close, (void *) map_fd);
-LOCAL FUNCTION
+ /* Allocate space for mapping (lifetime only for this function). */
+ map = alloca (sizeof (struct prmap));
- procfs_init_inferior - initialize target vector and access to a
- /proc entry
+ /* Now read the mappings from the file,
+ open a file descriptor for those that have a name,
+ and call the callback function. */
+ while (read (map_fd,
+ (void *) map,
+ sizeof (struct prmap)) == sizeof (struct prmap))
+ {
+ char name[MAX_PROC_NAME_SIZE + sizeof (map->pr_mapname)];
-SYNOPSIS
+ if (map->pr_vaddr == 0 && map->pr_size == 0)
+ break; /* sanity */
- void procfs_init_inferior (int pid)
+ if (map->pr_mapname[0] == 0)
+ {
+ fd = -1; /* no map file */
+ }
+ else
+ {
+ sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
+ /* Note: caller's responsibility to close this fd! */
+ fd = open (name, O_RDONLY);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the ioctl may return failure, but that's
+ not a problem. */
+ }
-DESCRIPTION
+ /* Stop looping if the callback returns non-zero. */
+ if ((funcstat = (*func) (fd, (CORE_ADDR) map->pr_vaddr)) != 0)
+ break;
+ }
+#else
+ /* Get the number of mapping entries. */
+ if (ioctl (pi->ctl_fd, PIOCNMAP, &nmaps) < 0)
+ proc_error (pi, "proc_iterate_over_mappings (PIOCNMAP)", __LINE__);
+
+ /* Allocate space for mappings (lifetime only this function). */
+ map = (struct prmap *) alloca ((nmaps + 1) * sizeof (struct prmap));
+
+ /* Read in all the mappings. */
+ if (ioctl (pi->ctl_fd, PIOCMAP, map) < 0)
+ proc_error (pi, "proc_iterate_over_mappings (PIOCMAP)", __LINE__);
+
+ /* Now loop through the mappings, open an fd for each, and
+ call the callback function. */
+ for (i = 0;
+ i < nmaps && map[i].pr_size != 0;
+ i++)
+ {
+ /* Note: caller's responsibility to close this fd! */
+ fd = ioctl (pi->ctl_fd, PIOCOPENM, &map[i].pr_vaddr);
+ /* Note: we don't test the above call for failure;
+ we just pass the FD on as given. Sometimes there is
+ no file, so the ioctl may return failure, but that's
+ not a problem. */
+
+ /* Stop looping if the callback returns non-zero. */
+ if ((funcstat = (*func) (fd, (CORE_ADDR) map[i].pr_vaddr)) != 0)
+ break;
+ }
+#endif
- When gdb starts an inferior, this function is called in the parent
- process immediately after the fork. It waits for the child to stop
- on the return from the exec system call (the child itself takes care
- of ensuring that this is set up), then sets up the set of signals
- and faults that are to be traced. Returns the pid, which may have had
- the thread-id added to it.
+ return funcstat;
+}
-NOTES
+#ifdef TM_I386SOL2_H /* Is it hokey to use this? */
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
+#include <sys/sysi86.h>
+/*
+ * Function: proc_get_LDT_entry
+ *
+ * Inputs:
+ * procinfo *pi;
+ * int key;
+ *
+ * The 'key' is actually the value of the lower 16 bits of
+ * the GS register for the LWP that we're interested in.
+ *
+ * Return: matching ssh struct (LDT entry).
*/
-static void
-procfs_init_inferior (pid)
- int pid;
+struct ssd *
+proc_get_LDT_entry (pi, key)
+ procinfo *pi;
+ int key;
{
- struct procinfo *pip;
-
- push_target (&procfs_ops);
-
- pip = create_procinfo (pid);
+ static struct ssd *ldt_entry = NULL;
+#ifdef NEW_PROC_API
+ char pathname[MAX_PROC_NAME_SIZE];
+ struct cleanup *old_chain = NULL;
+ int fd;
+
+ /* Allocate space for one LDT entry.
+ This alloc must persist, because we return a pointer to it. */
+ if (ldt_entry == NULL)
+ ldt_entry = (struct ssd *) xmalloc (sizeof (struct ssd));
+
+ /* Open the file descriptor for the LDT table. */
+ sprintf (pathname, "/proc/%d/ldt", pi->pid);
+ if ((fd = open (pathname, O_RDONLY)) < 0)
+ {
+ proc_warn (pi, "proc_get_LDT_entry (open)", __LINE__);
+ return NULL;
+ }
+ /* Make sure it gets closed again! */
+ old_chain = make_cleanup ((make_cleanup_func) close, (void *) fd);
- procfs_set_inferior_syscall_traps (pip);
+ /* Now 'read' thru the table, find a match and return it. */
+ while (read (fd, ldt_entry, sizeof (struct ssd)) == sizeof (struct ssd))
+ {
+ if (ldt_entry->sel == 0 &&
+ ldt_entry->bo == 0 &&
+ ldt_entry->acc1 == 0 &&
+ ldt_entry->acc2 == 0)
+ break; /* end of table */
+ /* If key matches, return this entry. */
+ if (ldt_entry->sel == key)
+ return ldt_entry;
+ }
+ /* Loop ended, match not found. */
+ return NULL;
+#else
+ int nldt, i;
+ static int nalloc = 0;
- /* create_procinfo may change the pid, so we have to update inferior_pid
- here before calling other gdb routines that need the right pid. */
+ /* Get the number of LDT entries. */
+ if (ioctl (pi->ctl_fd, PIOCNLDT, &nldt) < 0)
+ {
+ proc_warn (pi, "proc_get_LDT_entry (PIOCNLDT)", __LINE__);
+ return NULL;
+ }
- pid = pip -> pid;
- inferior_pid = pid;
+ /* Allocate space for the number of LDT entries. */
+ /* This alloc has to persist, 'cause we return a pointer to it. */
+ if (nldt > nalloc)
+ {
+ ldt_entry = (struct ssd *)
+ xrealloc (ldt_entry, (nldt + 1) * sizeof (struct ssd));
+ nalloc = nldt;
+ }
+
+ /* Read the whole table in one gulp. */
+ if (ioctl (pi->ctl_fd, PIOCLDT, ldt_entry) < 0)
+ {
+ proc_warn (pi, "proc_get_LDT_entry (PIOCLDT)", __LINE__);
+ return NULL;
+ }
- add_thread (pip -> pid); /* Setup initial thread */
+ /* Search the table and return the (first) entry matching 'key'. */
+ for (i = 0; i < nldt; i++)
+ if (ldt_entry[i].sel == key)
+ return &ldt_entry[i];
-#ifdef START_INFERIOR_TRAPS_EXPECTED
- startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
-#else
- /* One trap to exec the shell, one to exec the program being debugged. */
- startup_inferior (2);
+ /* Loop ended, match not found. */
+ return NULL;
#endif
}
-/*
-
-GLOBAL FUNCTION
-
- procfs_notice_signals
+#endif /* TM_I386SOL2_H */
-SYNOPSIS
+/* =============== END, non-thread part of /proc "MODULE" =============== */
- static void procfs_notice_signals (int pid);
+/* =================== Thread "MODULE" =================== */
-DESCRIPTION
+/* NOTE: you'll see more ifdefs and duplication of functions here,
+ since there is a different way to do threads on every OS. */
- When the user changes the state of gdb's signal handling via the
- "handle" command, this function gets called to see if any change
- in the /proc interface is required. It is also called internally
- by other /proc interface functions to initialize the state of
- the traced signal set.
-
- One thing it does is that signals for which the state is "nostop",
- "noprint", and "pass", have their trace bits reset in the pr_trace
- field, so that they are no longer traced. This allows them to be
- delivered directly to the inferior without the debugger ever being
- involved.
+/*
+ * Function: proc_get_nthreads
+ *
+ * Return the number of threads for the process
*/
-static void
-procfs_notice_signals (pid)
- int pid;
+#if defined (PIOCNTHR) && defined (PIOCTLIST)
+/*
+ * OSF version
+ */
+int
+proc_get_nthreads (pi)
+ procinfo *pi;
{
- struct procinfo *pi;
- struct sig_ctl sctl;
+ int nthreads = 0;
- pi = find_procinfo (pid, 0);
+ if (ioctl (pi->ctl_fd, PIOCNTHR, &nthreads) < 0)
+ proc_warn (pi, "procfs: PIOCNTHR failed", __LINE__);
-#ifndef HAVE_PRRUN_T
- premptyset (&sctl.sigset);
-#else
- sctl.sigset = pi->prrun.pr_trace;
-#endif
-
- notice_signals (pi, &sctl);
-
-#ifdef HAVE_PRRUN_T
- pi->prrun.pr_trace = sctl.sigset;
-#endif
+ return nthreads;
}
-static void
-notice_signals (pi, sctl)
- struct procinfo *pi;
- struct sig_ctl *sctl;
+#else
+#if defined (SYS_lwpcreate) || defined (SYS_lwp_create) /* FIXME: multiple */
+/*
+ * Solaris and Unixware version
+ */
+int
+proc_get_nthreads (pi)
+ procinfo *pi;
{
- int signo;
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0;
- for (signo = 0; signo < NSIG; signo++)
- {
- if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
- signal_print_state (target_signal_from_host (signo)) == 0 &&
- signal_pass_state (target_signal_from_host (signo)) == 1)
- {
- prdelset (&sctl->sigset, signo);
- }
- else
- {
- praddset (&sctl->sigset, signo);
- }
- }
-#ifdef PROCFS_USE_READ_WRITE
- sctl->cmd = PCSTRACE;
- if (write (pi->ctl_fd, (char *) sctl, sizeof (struct sig_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &sctl->sigset))
+ /*
+ * NEW_PROC_API: only works for the process procinfo,
+ * because the LWP procinfos do not get prstatus filled in.
+ */
+#ifdef NEW_PROC_API
+ if (pi->tid != 0) /* find the parent process procinfo */
+ pi = find_procinfo_or_die (pi->pid, 0);
#endif
- {
- print_sys_errmsg ("PIOCSTRACE failed", errno);
- }
+ return pi->prstatus.pr_nlwp;
}
+#else
/*
+ * Default version
+ */
+int
+proc_get_nthreads (pi)
+ procinfo *pi;
+{
+ return 0;
+}
+#endif
+#endif
-LOCAL FUNCTION
-
- proc_set_exec_trap -- arrange for exec'd child to halt at startup
-
-SYNOPSIS
-
- void proc_set_exec_trap (void)
-
-DESCRIPTION
+/*
+ * Function: proc_get_current_thread (LWP version)
+ *
+ * Return the ID of the thread that had an event of interest.
+ * (ie. the one that hit a breakpoint or other traced event).
+ * All other things being equal, this should be the ID of a
+ * thread that is currently executing.
+ */
- This function is called in the child process when starting up
- an inferior, prior to doing the exec of the actual inferior.
- It sets the child process's exitset to make exit from the exec
- system call an event of interest to stop on, and then simply
- returns. The child does the exec, the system call returns, and
- the child stops at the first instruction, ready for the gdb
- parent process to take control of it.
+#if defined (SYS_lwpcreate) || defined (SYS_lwp_create) /* FIXME: multiple */
+/*
+ * Solaris and Unixware version
+ */
+int
+proc_get_current_thread (pi)
+ procinfo *pi;
+{
+ /*
+ * Note: this should be applied to the root procinfo for the process,
+ * not to the procinfo for an LWP. If applied to the procinfo for
+ * an LWP, it will simply return that LWP's ID. In that case,
+ * find the parent process procinfo.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-NOTE
+ if (!pi->status_valid)
+ if (!proc_get_status (pi))
+ return 0;
- We need to use all local variables since the child may be sharing
- it's data space with the parent, if vfork was used rather than
- fork.
+#ifdef NEW_PROC_API
+ return pi->prstatus.pr_lwp.pr_lwpid;
+#else
+ return pi->prstatus.pr_who;
+#endif
+}
- Also note that we want to turn off the inherit-on-fork flag in
- the child process so that any grand-children start with all
- tracing flags cleared.
+#else
+#if defined (PIOCNTHR) && defined (PIOCTLIST)
+/*
+ * OSF version
*/
-
-static void
-proc_set_exec_trap ()
+int
+proc_get_current_thread (pi)
+ procinfo *pi;
{
- struct sys_ctl exitset;
- struct sys_ctl entryset;
- char procname[MAX_PROC_NAME_SIZE];
- int fd;
-
- sprintf (procname, CTL_PROC_NAME_FMT, getpid ());
-#ifdef UNIXWARE
- if ((fd = open (procname, O_WRONLY)) < 0)
+#if 0 /* FIXME: not ready for prime time? */
+ return pi->prstatus.pr_tid;
#else
- if ((fd = open (procname, O_RDWR)) < 0)
+ return 0;
#endif
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
- premptyset (&exitset.sysset);
- premptyset (&entryset.sysset);
-
-#ifdef PRFS_STOPEXEC
- /* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
- exits from exec system calls because of the user level loader. */
- {
- int prfs_flags;
+}
- if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
- prfs_flags |= PRFS_STOPEXEC;
- if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
- }
-#else /* PRFS_STOPEXEC */
- /* GW: Rationale...
- Not all systems with /proc have all the exec* syscalls with the same
- names. On the SGI, for example, there is no SYS_exec, but there
- *is* a SYS_execv. So, we try to account for that. */
+#else
+/*
+ * Default version
+ */
+int
+proc_get_current_thread (pi)
+ procinfo *pi;
+{
+ return 0;
+}
-#ifdef SYS_exec
- praddset (&exitset.sysset, SYS_exec);
#endif
-#ifdef SYS_execve
- praddset (&exitset.sysset, SYS_execve);
-#endif
-#ifdef SYS_execv
- praddset (&exitset.sysset, SYS_execv);
#endif
-#ifdef PROCFS_USE_READ_WRITE
- exitset.cmd = PCSEXIT;
- if (write (fd, (char *) &exitset, sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (fd, PIOCSEXIT, &exitset.sysset) < 0)
-#endif
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
-#endif /* PRFS_STOPEXEC */
-
- praddset (&entryset.sysset, SYS_exit);
+/*
+ * Function: proc_update_threads
+ *
+ * Discover the IDs of all the threads within the process, and
+ * create a procinfo for each of them (chained to the parent).
+ *
+ * This unfortunately requires a different method on every OS.
+ *
+ * Return: non-zero for success, zero for failure.
+ */
-#ifdef PROCFS_USE_READ_WRITE
- entryset.cmd = PCSENTRY;
- if (write (fd, (char *) &entryset, sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (fd, PIOCSENTRY, &entryset.sysset) < 0)
-#endif
+int
+proc_delete_dead_threads (parent, thread, ignore)
+ procinfo *parent;
+ procinfo *thread;
+ void *ignore;
+{
+ if (thread && parent) /* sanity */
{
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (126);
+ thread->status_valid = 0;
+ if (!proc_get_status (thread))
+ destroy_one_procinfo (&parent->thread_list, thread);
}
-
- /* Turn off inherit-on-fork flag so that all grand-children of gdb
- start with tracing flags cleared. */
-
- modify_inherit_on_fork_flag (fd, 0);
-
- /* Turn on run-on-last-close flag so that this process will not hang
- if GDB goes away for some reason. */
-
- modify_run_on_last_close_flag (fd, 1);
-
-#ifndef UNIXWARE /* since this is a solaris-ism, we don't want it */
- /* NOTE: revisit when doing thread support for UW */
-#ifdef PR_ASYNC
- {
- long pr_flags;
- struct proc_ctl pctl;
-
-/* Solaris needs this to make procfs treat all threads seperately. Without
- this, all threads halt whenever something happens to any thread. Since
- GDB wants to control all this itself, it needs to set PR_ASYNC. */
-
- pr_flags = PR_ASYNC;
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_FORK|PR_ASYNC;
- write (fd, (char *) &pctl, sizeof (struct proc_ctl));
-#else
- ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
-#endif /* PR_ASYNC */
-#endif /* !UNIXWARE */
+ return 0; /* keep iterating */
}
+#if defined (PIOCLSTATUS)
/*
+ * Solaris 2.5 (ioctl) version
+ */
+int
+proc_update_threads (pi)
+ procinfo *pi;
+{
+ gdb_prstatus_t *prstatus;
+ struct cleanup *old_chain = NULL;
+ procinfo *thread;
+ int nlwp, i;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
-GLOBAL FUNCTION
+ proc_iterate_over_threads (pi, proc_delete_dead_threads, NULL);
- proc_iterate_over_mappings -- call function for every mapped space
+ if ((nlwp = proc_get_nthreads (pi)) <= 1)
+ return 1; /* Process is not multi-threaded; nothing to do. */
-SYNOPSIS
+ if ((prstatus = (gdb_prstatus_t *)
+ malloc (sizeof (gdb_prstatus_t) * (nlwp + 1))) == 0)
+ perror_with_name ("procfs: malloc failed in update_threads");
- int proc_iterate_over_mappings (int (*func)())
+ old_chain = make_cleanup (free, prstatus);
+ if (ioctl (pi->ctl_fd, PIOCLSTATUS, prstatus) < 0)
+ proc_error (pi, "update_threads (PIOCLSTATUS)", __LINE__);
-DESCRIPTION
+ /* Skip element zero, which represents the process as a whole. */
+ for (i = 1; i < nlwp + 1; i++)
+ {
+ if ((thread = create_procinfo (pi->pid, prstatus[i].pr_who)) == NULL)
+ proc_error (pi, "update_threads, create_procinfo", __LINE__);
- Given a pointer to a function, call that function for every
- mapped address space, passing it an open file descriptor for
- the file corresponding to that mapped address space (if any)
- and the base address of the mapped space. Quit when we hit
- the end of the mappings or the function returns nonzero.
+ memcpy (&thread->prstatus, &prstatus[i], sizeof (*prstatus));
+ thread->status_valid = 1;
+ }
+ pi->threads_valid = 1;
+ do_cleanups (old_chain);
+ return 1;
+}
+#else
+#ifdef NEW_PROC_API
+/*
+ * Unixware and Solaris 6 (and later) version
*/
-
-#ifdef UNIXWARE
int
-proc_iterate_over_mappings (func)
- int (*func) PARAMS ((int, CORE_ADDR));
+proc_update_threads (pi)
+ procinfo *pi;
{
- int nmap;
- int fd;
- int funcstat = 0;
- prmap_t *prmaps;
- prmap_t *prmap;
- struct procinfo *pi;
- struct stat sbuf;
+ char pathname[MAX_PROC_NAME_SIZE + 16];
+ struct dirent *direntry;
+ struct cleanup *old_chain = NULL;
+ procinfo *thread;
+ DIR *dirp;
+ int lwpid;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
+
+ proc_iterate_over_threads (pi, proc_delete_dead_threads, NULL);
+
+ /*
+ * Unixware
+ *
+ * Note: this brute-force method is the only way I know of
+ * to accomplish this task on Unixware. This method will
+ * also work on Solaris 2.6 and 2.7. There is a much simpler
+ * and more elegant way to do this on Solaris, but the margins
+ * of this manuscript are too small to write it here... ;-)
+ */
+
+ strcpy (pathname, pi->pathname);
+ strcat (pathname, "/lwp");
+ if ((dirp = opendir (pathname)) == NULL)
+ proc_error (pi, "update_threads, opendir", __LINE__);
+
+ old_chain = make_cleanup ((make_cleanup_func) closedir, dirp);
+ while ((direntry = readdir (dirp)) != NULL)
+ if (direntry->d_name[0] != '.') /* skip '.' and '..' */
+ {
+ lwpid = atoi (&direntry->d_name[0]);
+ if ((thread = create_procinfo (pi->pid, lwpid)) == NULL)
+ proc_error (pi, "update_threads, create_procinfo", __LINE__);
+ }
+ pi->threads_valid = 1;
+ do_cleanups (old_chain);
+ return 1;
+}
+#else
+#ifdef PIOCTLIST
+/*
+ * OSF version
+ */
+int
+proc_update_threads (pi)
+ procinfo *pi;
+{
+ int nthreads, i;
+ tid_t *threads;
+
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
- pi = current_procinfo;
+ proc_iterate_over_threads (pi, proc_delete_dead_threads, NULL);
- if (fstat (pi->map_fd, &sbuf) < 0)
- return 0;
+ nthreads = proc_get_nthreads (pi);
+ if (nthreads < 2)
+ return 0; /* nothing to do for 1 or fewer threads */
- nmap = sbuf.st_size / sizeof (prmap_t);
- prmaps = (prmap_t *) alloca (nmap * sizeof(prmap_t));
- if ((lseek (pi->map_fd, 0, SEEK_SET) == 0) &&
- (read (pi->map_fd, (char *) prmaps, nmap * sizeof (prmap_t)) ==
- (nmap * sizeof (prmap_t))))
+ if ((threads = malloc (nthreads * sizeof (tid_t))) == NULL)
+ proc_error (pi, "update_threads, malloc", __LINE__);
+
+ if (ioctl (pi->ctl_fd, PIOCTLIST, threads) < 0)
+ proc_error (pi, "procfs: update_threads (PIOCTLIST)", __LINE__);
+
+ for (i = 0; i < nthreads; i++)
{
- int i = 0;
- for (prmap = prmaps; i < nmap && funcstat == 0; ++prmap, ++i)
- {
- char name[sizeof ("/proc/1234567890/object") +
- sizeof (prmap->pr_mapname)];
- sprintf (name, "/proc/%d/object/%s", pi->pid, prmap->pr_mapname);
- if ((fd = open (name, O_RDONLY)) == -1)
- {
- funcstat = 1;
- break;
- }
- funcstat = (*func) (fd, (CORE_ADDR) prmap->pr_vaddr);
- close (fd);
- }
+ if (!find_procinfo (pi->pid, threads[i]))
+ if (!create_procinfo (pi->pid, threads[i]))
+ proc_error (pi, "update_threads, create_procinfo", __LINE__);
}
- return (funcstat);
+ pi->threads_valid = 1;
+ return 1;
}
-#else /* UNIXWARE */
+#else
+/*
+ * Default version
+ */
int
-proc_iterate_over_mappings (func)
- int (*func) PARAMS ((int, CORE_ADDR));
+proc_update_threads (pi)
+ procinfo *pi;
{
- int nmap;
- int fd;
- int funcstat = 0;
- struct prmap *prmaps;
- struct prmap *prmap;
- struct procinfo *pi;
+ return 0;
+}
+#endif /* OSF PIOCTLIST */
+#endif /* NEW_PROC_API */
+#endif /* SOL 2.5 PIOCLSTATUS */
- pi = current_procinfo;
+/*
+ * Function: proc_iterate_over_threads
+ *
+ * Description:
+ * Given a pointer to a function, call that function once
+ * for each lwp in the procinfo list, until the function
+ * returns non-zero, in which event return the value
+ * returned by the function.
+ *
+ * Note: this function does NOT call update_threads.
+ * If you want to discover new threads first, you must
+ * call that function explicitly. This function just makes
+ * a quick pass over the currently-known procinfos.
+ *
+ * Arguments:
+ * pi - parent process procinfo
+ * func - per-thread function
+ * ptr - opaque parameter for function.
+ *
+ * Return:
+ * First non-zero return value from the callee, or zero.
+ */
+
+int
+proc_iterate_over_threads (pi, func, ptr)
+ procinfo *pi;
+ int (*func) PARAMS ((procinfo *, procinfo *, void *));
+ void *ptr;
+{
+ procinfo *thread, *next;
+ int retval = 0;
- if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
+ /*
+ * We should never have to apply this operation to any procinfo
+ * except the one for the main process. If that ever changes
+ * for any reason, then take out the following clause and
+ * replace it with one that makes sure the ctl_fd is open.
+ */
+
+ if (pi->tid != 0)
+ pi = find_procinfo_or_die (pi->pid, 0);
+
+ for (thread = pi->thread_list; thread != NULL; thread = next)
{
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
- {
- fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
- funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
- close (fd);
- }
- }
+ next = thread->next; /* in case thread is destroyed */
+ if ((retval = (*func) (pi, thread, ptr)) != 0)
+ break;
}
- return (funcstat);
-}
-#endif /* UNIXWARE */
-#if 0 /* Currently unused */
-/*
-
-GLOBAL FUNCTION
+ return retval;
+}
- proc_base_address -- find base address for segment containing address
+/* =================== END, Thread "MODULE" =================== */
-SYNOPSIS
+/* =================== END, /proc "MODULE" =================== */
- CORE_ADDR proc_base_address (CORE_ADDR addr)
+/* =================== GDB "MODULE" =================== */
-DESCRIPTION
+/*
+ * Here are all of the gdb target vector functions and their friends.
+ */
- Given an address of a location in the inferior, find and return
- the base address of the mapped segment containing that address.
+static int do_attach PARAMS ((int pid));
+static void do_detach PARAMS ((int signo));
+static int register_gdb_signals PARAMS ((procinfo *, sigset_t *));
- This is used for example, by the shared library support code,
- where we have the pc value for some location in the shared library
- where we are stopped, and need to know the base address of the
- segment containing that address.
-*/
+/*
+ * Function: procfs_debug_inferior
+ *
+ * Sets up the inferior to be debugged.
+ * Registers to trace signals, hardware faults, and syscalls.
+ * Note: does not set RLC flag: caller may want to customize that.
+ *
+ * Returns: zero for success (note! unlike most functions in this module)
+ * On failure, returns the LINE NUMBER where it failed!
+ */
-CORE_ADDR
-proc_base_address (addr)
- CORE_ADDR addr;
+static int
+procfs_debug_inferior (pi)
+ procinfo *pi;
{
- int nmap;
- struct prmap *prmaps;
- struct prmap *prmap;
- CORE_ADDR baseaddr = 0;
- struct procinfo *pi;
+ fltset_t traced_faults;
+ sigset_t traced_signals;
+ sysset_t traced_syscall_entries;
+ sysset_t traced_syscall_exits;
- pi = current_procinfo;
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ /* On some systems (OSF), we don't trace hardware faults.
+ Apparently it's enough that we catch them as signals.
+ Wonder why we don't just do that in general? */
+ premptyset (&traced_faults); /* don't trace faults. */
+#else
+ /* Register to trace hardware faults in the child. */
+ prfillset (&traced_faults); /* trace all faults... */
+ prdelset (&traced_faults, FLTPAGE); /* except page fault. */
+#endif
+ if (!proc_set_traced_faults (pi, &traced_faults))
+ return __LINE__;
- if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
- {
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size; ++prmap)
- {
- if ((prmap -> pr_vaddr <= (caddr_t) addr) &&
- (prmap -> pr_vaddr + prmap -> pr_size > (caddr_t) addr))
- {
- baseaddr = (CORE_ADDR) prmap -> pr_vaddr;
- break;
- }
- }
- }
- }
- return (baseaddr);
-}
+ /* Register to trace selected signals in the child. */
+ premptyset (&traced_signals);
+ if (!register_gdb_signals (pi, &traced_signals))
+ return __LINE__;
-#endif /* 0 */
+ /* Register to trace the 'exit' system call (on entry). */
+ premptyset (&traced_syscall_entries);
+ praddset (&traced_syscall_entries, SYS_exit);
+#ifdef SYS_lwpexit
+ praddset (&traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */
+#endif
+#ifdef SYS_lwp_exit
+ praddset (&traced_syscall_entries, SYS_lwp_exit);
+#endif
-#ifndef UNIXWARE
-/*
+ if (!proc_set_traced_sysentry (pi, &traced_syscall_entries))
+ return __LINE__;
-LOCAL FUNCTION
+#ifdef PRFS_STOPEXEC /* defined on OSF */
+ /* OSF method for tracing exec syscalls. Quoting:
+ Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
+ exits from exec system calls because of the user level loader. */
+ /* FIXME: make nice and maybe move into an access function. */
+ {
+ int prfs_flags;
- proc_address_to_fd -- return open fd for file mapped to address
+ if (ioctl (pi->ctl_fd, PIOCGSPCACT, &prfs_flags) < 0)
+ return __LINE__;
-SYNOPSIS
+ prfs_flags |= PRFS_STOPEXEC;
- int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
+ if (ioctl (pi->ctl_fd, PIOCSSPCACT, &prfs_flags) < 0)
+ return __LINE__;
+ }
+#else /* not PRFS_STOPEXEC */
+ /* Everyone else's (except OSF) method for tracing exec syscalls */
+ /* GW: Rationale...
+ Not all systems with /proc have all the exec* syscalls with the same
+ names. On the SGI, for example, there is no SYS_exec, but there
+ *is* a SYS_execv. So, we try to account for that. */
-DESCRIPTION
+ premptyset (&traced_syscall_exits);
+#ifdef SYS_exec
+ praddset (&traced_syscall_exits, SYS_exec);
+#endif
+#ifdef SYS_execve
+ praddset (&traced_syscall_exits, SYS_execve);
+#endif
+#ifdef SYS_execv
+ praddset (&traced_syscall_exits, SYS_execv);
+#endif
- Given an address in the current inferior's address space, use the
- /proc interface to find an open file descriptor for the file that
- this address was mapped in from. Return -1 if there is no current
- inferior. Print a warning message if there is an inferior but
- the address corresponds to no file (IE a bogus address).
+#ifdef SYS_lwpcreate
+ praddset (&traced_syscall_exits, SYS_lwpcreate);
+ praddset (&traced_syscall_exits, SYS_lwpexit);
+#endif
-*/
+#ifdef SYS_lwp_create /* FIXME: once only, please */
+ praddset (&traced_syscall_exits, SYS_lwp_create);
+ praddset (&traced_syscall_exits, SYS_lwp_exit);
+#endif
-static int
-proc_address_to_fd (pi, addr, complain)
- struct procinfo *pi;
- CORE_ADDR addr;
- int complain;
-{
- int fd = -1;
- if ((fd = ioctl (pi->ctl_fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
- {
- if (complain)
- {
- print_sys_errmsg (pi->pathname, errno);
- warning ("can't find mapped file for address 0x%x", addr);
- }
- }
- return (fd);
-}
-#endif /* !UNIXWARE */
+ if (!proc_set_traced_sysexit (pi, &traced_syscall_exits))
+ return __LINE__;
-/* Attach to process PID, then initialize for debugging it
- and wait for the trace-trap that results from attaching. */
+#endif /* PRFS_STOPEXEC */
+ return 0;
+}
-static void
+static void
procfs_attach (args, from_tty)
char *args;
int from_tty;
{
char *exec_file;
- int pid;
+ int pid;
if (!args)
error_no_arg ("process-id to attach");
pid = atoi (args);
-
- if (pid == getpid()) /* Trying to masturbate? */
- error ("I refuse to debug myself!");
+ if (pid == getpid ())
+ error ("Attaching GDB to itself is not a good idea...");
if (from_tty)
{
- exec_file = (char *) get_exec_file (0);
+ exec_file = get_exec_file (0);
if (exec_file)
- printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+ printf_filtered ("Attaching to program `%s', %s\n",
+ exec_file, target_pid_to_str (pid));
else
- printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
+ printf_filtered ("Attaching to %s\n", target_pid_to_str (pid));
- gdb_flush (gdb_stdout);
+ fflush (stdout);
}
-
- inferior_pid = pid = do_attach (pid);
+ inferior_pid = do_attach (pid);
push_target (&procfs_ops);
}
-
-/* Take a program previously attached to and detaches it.
- The program resumes execution and will no longer stop
- on signals, etc. We'd better not have left any breakpoints
- in the program or it'll die when it hits one. For this
- to work, it may be necessary for the process to have been
- previously attached. It *might* work if the program was
- started via the normal ptrace (PTRACE_TRACEME). */
-
-static void
+static void
procfs_detach (args, from_tty)
char *args;
int from_tty;
{
- int siggnal = 0;
+ char *exec_file;
+ int signo = 0;
if (from_tty)
{
- char *exec_file = get_exec_file (0);
+ exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
- printf_unfiltered ("Detaching from program: %s %s\n",
+ printf_filtered ("Detaching from program: %s %s\n",
exec_file, target_pid_to_str (inferior_pid));
- gdb_flush (gdb_stdout);
+ fflush (stdout);
}
if (args)
- siggnal = atoi (args);
+ signo = atoi (args);
- do_detach (siggnal);
+ do_detach (signo);
inferior_pid = 0;
unpush_target (&procfs_ops); /* Pop out of handling an inferior */
}
-/* Get ready to modify the registers array. On machines which store
- individual registers, this doesn't need to do anything. On machines
- which store all the registers in one fell swoop, this makes sure
- that registers contains all the registers from the program being
- debugged. */
-
-static void
-procfs_prepare_to_store ()
-{
-#ifdef CHILD_PREPARE_TO_STORE
- CHILD_PREPARE_TO_STORE ();
-#endif
-}
-
-/* Print status information about what we're accessing. */
-
-static void
-procfs_files_info (ignore)
- struct target_ops *ignore;
-{
- printf_unfiltered ("\tUsing the running image of %s %s via /proc.\n",
- attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
-}
-
-/* ARGSUSED */
-static void
-procfs_open (arg, from_tty)
- char *arg;
- int from_tty;
-{
- error ("Use the \"run\" command to start a Unix child process.");
-}
-
-/*
-
-LOCAL FUNCTION
-
- do_attach -- attach to an already existing process
-
-SYNOPSIS
-
- int do_attach (int pid)
-
-DESCRIPTION
-
- Attach to an already existing process with the specified process
- id. If the process is not already stopped, query whether to
- stop it or not.
-
-NOTES
-
- The option of stopping at attach time is specific to the /proc
- versions of gdb. Versions using ptrace force the attachee
- to stop. (I have changed this version to do so, too. All you
- have to do is "continue" to make it go on. -- gnu@cygnus.com)
-
-*/
-
static int
do_attach (pid)
int pid;
{
- struct procinfo *pi;
- struct sig_ctl sctl;
- struct flt_ctl fctl;
- int nlwp, *lwps;
+ procinfo *pi;
+ int fail;
- pi = init_procinfo (pid, 0);
+ if ((pi = create_procinfo (pid, 0)) == NULL)
+ perror ("procfs: out of memory in 'attach'");
-#ifdef PIOCLWPIDS
- nlwp = pi->prstatus.pr_nlwp;
- lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+ if (!open_procinfo_files (pi, FD_CTL))
+ {
+ fprintf_filtered (gdb_stderr, "procfs:%d -- ", __LINE__);
+ sprintf (errmsg, "do_attach: couldn't open /proc file for process %d",
+ pid);
+ dead_procinfo (pi, errmsg, NOKILL);
+ }
- if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
+ /* Stop the process (if it isn't already stopped). */
+ if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
{
- print_sys_errmsg (pi -> pathname, errno);
- error ("PIOCLWPIDS failed");
+ pi->was_stopped = 1;
+ proc_prettyprint_why (proc_why (pi), proc_what (pi), 1);
}
-#else /* PIOCLWPIDS */
- nlwp = 1;
- lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
- lwps[0] = 0;
-#endif
- for (; nlwp > 0; nlwp--, lwps++)
+ else
{
- /* First one has already been created above. */
- if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
- pi = init_procinfo ((*lwps << 16) | pid, 0);
-
- if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
- {
- pi->was_stopped = 1;
- }
- else
- {
- pi->was_stopped = 0;
- if (1 || query ("Process is currently running, stop it? "))
- {
- long cmd;
- /* Make it run again when we close it. */
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
-#ifdef PROCFS_USE_READ_WRITE
- cmd = PCSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("PIOCSTOP failed");
- }
-#ifdef UNIXWARE
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("procfs_read_status failed");
- }
-#endif
- pi->nopass_next_sigstop = 1;
- }
- else
- {
- printf_unfiltered ("Ok, gdb will wait for %s to stop.\n",
- target_pid_to_str (pi->pid));
- }
- }
-
-#ifdef PROCFS_USE_READ_WRITE
- fctl.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- print_sys_errmsg ("PCSFAULT failed", errno);
-#else /* PROCFS_USE_READ_WRITE */
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
- {
- print_sys_errmsg ("PIOCSFAULT failed", errno);
- }
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
- {
- print_sys_errmsg ("PIOCSTRACE failed", errno);
- }
- add_thread (pi->pid);
- procfs_set_inferior_syscall_traps (pi);
-#endif /* PROCFS_USE_READ_WRITE */
+ pi->was_stopped = 0;
+ /* Set the process to run again when we close it. */
+ if (!proc_set_run_on_last_close (pi))
+ dead_procinfo (pi, "do_attach: couldn't set RLC.", NOKILL);
+
+ /* Now stop the process. */
+ if (!proc_stop_process (pi))
+ dead_procinfo (pi, "do_attach: couldn't stop the process.", NOKILL);
+ pi->ignore_next_sigstop = 1;
}
+ /* Save some of the /proc state to be restored if we detach. */
+ if (!proc_get_traced_faults (pi, &pi->saved_fltset))
+ dead_procinfo (pi, "do_attach: couldn't save traced faults.", NOKILL);
+ if (!proc_get_traced_signals (pi, &pi->saved_sigset))
+ dead_procinfo (pi, "do_attach: couldn't save traced signals.", NOKILL);
+ if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ dead_procinfo (pi, "do_attach: couldn't save traced syscall entries.",
+ NOKILL);
+ if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.",
+ NOKILL);
+ if (!proc_get_held_signals (pi, &pi->saved_sighold))
+ dead_procinfo (pi, "do_attach: couldn't save held signals.", NOKILL);
+
+ if ((fail = procfs_debug_inferior (pi)) != 0)
+ dead_procinfo (pi, "do_attach: failed in procfs_debug_inferior", NOKILL);
+
+ /* Let GDB know that the inferior was attached. */
attach_flag = 1;
- return (pi->pid);
+ return MERGEPID (pi->pid, proc_get_current_thread (pi));
}
-/*
-
-LOCAL FUNCTION
-
- do_detach -- detach from an attached-to process
-
-SYNOPSIS
-
- void do_detach (int signal)
-
-DESCRIPTION
-
- Detach from the current attachee.
-
- If signal is non-zero, the attachee is started running again and sent
- the specified signal.
-
- If signal is zero and the attachee was not already stopped when we
- attached to it, then we make it runnable again when we detach.
-
- Otherwise, we query whether or not to make the attachee runnable
- again, since we may simply want to leave it in the state it was in
- when we attached.
-
- We report any problems, but do not consider them errors, since we
- MUST detach even if some things don't seem to go right. This may not
- be the ideal situation. (FIXME).
- */
-
static void
-do_detach (signal)
- int signal;
-{
- struct procinfo *pi;
-
- for (pi = procinfo_list; pi; pi = pi->next)
- {
- if (signal)
- {
- set_proc_siginfo (pi, signal);
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_exitset.cmd = PCSEXIT;
- if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
- sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSEXIT failed.\n");
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_entryset.cmd = PCSENTRY;
- if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
- sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSENTRY failed.\n");
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_trace.cmd = PCSTRACE;
- if (write (pi->ctl_fd, (char *) &pi->saved_trace,
- sizeof (struct sig_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSTRACE failed.\n");
- }
-#ifndef UNIXWARE
- if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOSCHOLD failed.\n");
- }
-#endif
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_fltset.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
- sizeof (struct flt_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSFAULT failed.\n");
- }
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("procfs_read_status failed.\n");
- }
- else
- {
- if (signal
- || (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
- {
- long cmd;
- struct proc_ctl pctl;
-
- if (signal || !pi->was_stopped ||
- query ("Was stopped when attached, make it runnable again? "))
- {
- /* Clear any pending signal if we want to detach without
- a signal. */
- if (signal == 0)
- set_proc_siginfo (pi, signal);
-
- /* Clear any fault that might have stopped it. */
-#ifdef PROCFS_USE_READ_WRITE
- cmd = PCCFAULT;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCCFAULT failed.\n");
- }
-
- /* Make it run again when we close it. */
-
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
- }
- }
- }
- close_proc_file (pi);
- }
- attach_flag = 0;
-}
-
-/* emulate wait() as much as possible.
- Wait for child to do something. Return pid of child, or -1 in case
- of error; store status in *OURSTATUS.
-
- Not sure why we can't
- just use wait(), but it seems to have problems when applied to a
- process being controlled with the /proc interface.
-
- We have a race problem here with no obvious solution. We need to let
- the inferior run until it stops on an event of interest, which means
- that we need to use the PIOCWSTOP ioctl. However, we cannot use this
- ioctl if the process is already stopped on something that is not an
- event of interest, or the call will hang indefinitely. Thus we first
- use PIOCSTATUS to see if the process is not stopped. If not, then we
- use PIOCWSTOP. But during the window between the two, if the process
- stops for any reason that is not an event of interest (such as a job
- control signal) then gdb will hang. One possible workaround is to set
- an alarm to wake up every minute of so and check to see if the process
- is still running, and if so, then reissue the PIOCWSTOP. But this is
- a real kludge, so has not been implemented. FIXME: investigate
- alternatives.
-
- FIXME: Investigate why wait() seems to have problems with programs
- being control by /proc routines. */
-static int
-procfs_wait (pid, ourstatus)
- int pid;
- struct target_waitstatus *ourstatus;
+do_detach (signo)
+ int signo;
{
- short what;
- short why;
- int statval = 0;
- int checkerr = 0;
- int rtnval = -1;
- struct procinfo *pi;
- struct proc_ctl pctl;
+ procinfo *pi;
-scan_again:
+ /* Find procinfo for the main process */
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0); /* FIXME: threads */
+ if (signo)
+ if (!proc_set_current_signal (pi, signo))
+ proc_warn (pi, "do_detach, set_current_signal", __LINE__);
- /* handle all syscall events first, otherwise we might not
- notice a thread was created until too late. */
+ if (!proc_set_traced_signals (pi, &pi->saved_sigset))
+ proc_warn (pi, "do_detach, set_traced_signal", __LINE__);
- for (pi = procinfo_list; pi; pi = pi->next)
- {
- if (!pi->had_event)
- continue;
-
- if (! (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)) )
- continue;
-
- why = THE_PR_LWP(pi->prstatus).pr_why;
- what = THE_PR_LWP(pi->prstatus).pr_what;
- if (why == PR_SYSENTRY || why == PR_SYSEXIT)
- {
- int i;
- int found_handler = 0;
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == what)
- {
- found_handler = 1;
- pi->saved_rtnval = pi->pid;
- pi->saved_statval = 0;
- if (!pi->syscall_handlers[i].func
- (pi, what, why, &pi->saved_rtnval, &pi->saved_statval))
- pi->had_event = 0;
- break;
- }
+ if (!proc_set_traced_faults (pi, &pi->saved_fltset))
+ proc_warn (pi, "do_detach, set_traced_faults", __LINE__);
- if (!found_handler)
- {
- if (why == PR_SYSENTRY)
- error ("PR_SYSENTRY, unhandled system call %d", what);
- else
- error ("PR_SYSEXIT, unhandled system call %d", what);
- }
- }
- }
+ if (!proc_set_traced_sysentry (pi, &pi->saved_entryset))
+ proc_warn (pi, "do_detach, set_traced_sysentry", __LINE__);
- /* find a relevant process with an event */
-
- for (pi = procinfo_list; pi; pi = pi->next)
- if (pi->had_event && (pid == -1 || pi->pid == pid))
- break;
-
- if (!pi)
- {
- wait_fd ();
- goto scan_again;
- }
-
- if (!checkerr
- && !(THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
- {
- if (!procfs_write_pcwstop (pi))
- {
- checkerr++;
- }
- }
- if (checkerr)
- {
- if (errno == ENOENT)
- {
- /* XXX Fixme -- what to do if attached? Can't call wait... */
- rtnval = wait (&statval);
- if ((rtnval) != (PIDGET (inferior_pid)))
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("procfs_wait: wait failed, returned %d", rtnval);
- /* NOTREACHED */
- }
- }
- else
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSTATUS or PIOCWSTOP failed.");
- /* NOTREACHED */
- }
- }
- else if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
- {
-#ifdef UNIXWARE
- rtnval = pi->prstatus.pr_pid;
-#else
- rtnval = pi->pid;
-#endif
- why = THE_PR_LWP(pi->prstatus).pr_why;
- what = THE_PR_LWP(pi->prstatus).pr_what;
+ if (!proc_set_traced_sysexit (pi, &pi->saved_exitset))
+ proc_warn (pi, "do_detach, set_traced_sysexit", __LINE__);
- switch (why)
- {
- case PR_SIGNALLED:
- statval = (what << 8) | 0177;
- break;
- case PR_SYSENTRY:
- case PR_SYSEXIT:
- rtnval = pi->saved_rtnval;
- statval = pi->saved_statval;
- break;
- case PR_REQUESTED:
- statval = (SIGSTOP << 8) | 0177;
- break;
- case PR_JOBCONTROL:
- statval = (what << 8) | 0177;
- break;
- case PR_FAULTED:
- switch (what)
- {
-#ifdef FLTWATCH
- case FLTWATCH:
- statval = (SIGTRAP << 8) | 0177;
- break;
-#endif
-#ifdef FLTKWATCH
- case FLTKWATCH:
- statval = (SIGTRAP << 8) | 0177;
- break;
-#endif
-#ifndef FAULTED_USE_SIGINFO
- /* Irix, contrary to the documentation, fills in 0 for si_signo.
- Solaris fills in si_signo. I'm not sure about others. */
- case FLTPRIV:
- case FLTILL:
- statval = (SIGILL << 8) | 0177;
- break;
- case FLTBPT:
- case FLTTRACE:
- statval = (SIGTRAP << 8) | 0177;
- break;
- case FLTSTACK:
- case FLTACCESS:
- case FLTBOUNDS:
- statval = (SIGSEGV << 8) | 0177;
- break;
- case FLTIOVF:
- case FLTIZDIV:
- case FLTFPE:
- statval = (SIGFPE << 8) | 0177;
- break;
- case FLTPAGE: /* Recoverable page fault */
-#endif /* not FAULTED_USE_SIGINFO */
- default:
- /* Use the signal which the kernel assigns. This is better than
- trying to second-guess it from the fault. In fact, I suspect
- that FLTACCESS can be either SIGSEGV or SIGBUS. */
- statval =
- ((THE_PR_LWP(pi->prstatus).pr_info.si_signo) << 8) | 0177;
- break;
- }
- break;
- default:
- error ("PIOCWSTOP, unknown why %d, what %d", why, what);
- }
- /* Stop all the other threads when any of them stops. */
+ if (!proc_set_held_signals (pi, &pi->saved_sighold))
+ proc_warn (pi, "do_detach, set_held_signals", __LINE__);
+ if (signo || (proc_flags (pi) & (PR_STOPPED | PR_ISTOP)))
+ if (signo || !(pi->was_stopped) ||
+ query ("Was stopped when attached, make it runnable again? "))
{
- struct procinfo *procinfo, *next_pi;
-
- for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
- {
- next_pi = procinfo->next;
- if (!procinfo->had_event)
- {
-#ifdef PROCFS_USE_READ_WRITE
- long cmd = PCSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
- {
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PCSTOP failed");
- }
-#else
- /* A bug in Solaris (2.5) causes us to hang when trying to
- stop a stopped process. So, we have to check first in
- order to avoid the hang. */
- if (!procfs_read_status (procinfo))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (procinfo->pid >> 16) & 0xffff);
- close_proc_file (procinfo);
- continue;
- }
+ /* Clear any pending signal. */
+ if (!proc_clear_current_fault (pi))
+ proc_warn (pi, "do_detach, clear_current_fault", __LINE__);
- if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
- if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
- < 0)
- {
- print_sys_errmsg (procinfo->pathname, errno);
- warning ("PIOCSTOP failed");
- }
-#endif
- }
- }
+ if (!proc_set_run_on_last_close (pi))
+ proc_warn (pi, "do_detach, set_rlc", __LINE__);
}
- }
- else
- {
- error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
- THE_PR_LWP(pi->prstatus).pr_flags);
- }
-
- store_waitstatus (ourstatus, statval);
-
- if (rtnval == -1) /* No more children to wait for */
- {
- warning ("Child process unexpectedly missing");
- /* Claim it exited with unknown signal. */
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
- return rtnval;
- }
- pi->had_event = 0; /* Indicate that we've seen this one */
- return (rtnval);
+ attach_flag = 0;
+ destroy_procinfo (pi);
}
/*
-
-LOCAL FUNCTION
-
- set_proc_siginfo - set a process's current signal info
-
-SYNOPSIS
-
- void set_proc_siginfo (struct procinfo *pip, int signo);
-
-DESCRIPTION
-
- Given a pointer to a process info struct in PIP and a signal number
- in SIGNO, set the process's current signal and its associated signal
- information. The signal will be delivered to the process immediately
- after execution is resumed, even if it is being held. In addition,
- this particular delivery will not cause another PR_SIGNALLED stop
- even if the signal is being traced.
-
- If we are not delivering the same signal that the prstatus siginfo
- struct contains information about, then synthesize a siginfo struct
- to match the signal we are doing to deliver, make it of the type
- "generated by a user process", and send this synthesized copy. When
- used to set the inferior's signal state, this will be required if we
- are not currently stopped because of a traced signal, or if we decide
- to continue with a different signal.
-
- Note that when continuing the inferior from a stop due to receipt
- of a traced signal, we either have set PRCSIG to clear the existing
- signal, or we have to call this function to do a PIOCSSIG with either
- the existing siginfo struct from pr_info, or one we have synthesized
- appropriately for the signal we want to deliver. Otherwise if the
- signal is still being traced, the inferior will immediately stop
- again.
-
- See siginfo(5) for more details.
-*/
+ * fetch_registers
+ *
+ * Since the /proc interface cannot give us individual registers,
+ * we pay no attention to the (regno) argument, and just fetch them all.
+ * This results in the possibility that we will do unnecessarily many
+ * fetches, since we may be called repeatedly for individual registers.
+ * So we cache the results, and mark the cache invalid when the process
+ * is resumed.
+ */
static void
-set_proc_siginfo (pip, signo)
- struct procinfo *pip;
- int signo;
+procfs_fetch_registers (regno)
+ int regno;
{
- struct siginfo newsiginfo;
- struct siginfo *sip;
- struct sigi_ctl sictl;
-
-#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
- /* With Alpha OSF/1 procfs, the kernel gets really confused if it
- receives a PIOCSSIG with a signal identical to the current signal,
- it messes up the current signal. Work around the kernel bug. */
- if (signo == THE_PR_LWP(pip->prstatus).pr_cursig)
- return;
-#endif
-
-#ifdef UNIXWARE
- if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
- {
- memcpy ((char *) &sictl.siginfo, (char *) &pip->prstatus.pr_lwp.pr_info,
- sizeof (siginfo_t));
- }
-#else
- if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
- {
- sip = &pip -> prstatus.pr_info;
- }
-#endif
- else
- {
-#ifdef UNIXWARE
- siginfo_t *sip = &sictl.siginfo;
- memset ((char *) sip, 0, sizeof (siginfo_t));
-#else
- memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
- sip = &newsiginfo;
-#endif
- sip -> si_signo = signo;
- sip -> si_code = 0;
- sip -> si_errno = 0;
- sip -> si_pid = getpid ();
- sip -> si_uid = getuid ();
- }
-#ifdef PROCFS_USE_READ_WRITE
- sictl.cmd = PCSSIG;
- if (write (pip->ctl_fd, (char *) &sictl, sizeof (struct sigi_ctl)) < 0)
-#else
- if (ioctl (pip->ctl_fd, PIOCSSIG, sip) < 0)
-#endif
- {
- print_sys_errmsg (pip -> pathname, errno);
- warning ("PIOCSSIG failed");
- }
-}
+ gdb_fpregset_t *fpregs;
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid;
+ int tid;
-/* Resume execution of process PID. If STEP is nozero, then
- just single step it. If SIGNAL is nonzero, restart it with that
- signal activated. */
+ pid = PIDGET (inferior_pid);
+ tid = TIDGET (inferior_pid);
-static void
-procfs_resume (pid, step, signo)
- int pid;
- int step;
- enum target_signal signo;
-{
- int signal_to_pass;
- struct procinfo *pi, *procinfo, *next_pi;
- struct proc_ctl pctl;
+ /* First look up procinfo for the main process. */
+ pi = find_procinfo_or_die (pid, 0);
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+ /* If the event thread is not the same as GDB's requested thread
+ (ie. inferior_pid), then look up procinfo for the requested
+ thread. */
+ if ((tid != 0) &&
+ (tid != proc_get_current_thread (pi)))
+ pi = find_procinfo_or_die (pid, tid);
- errno = 0;
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-#else
- pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
-#endif
+ if (pi == NULL)
+ error ("procfs: fetch_registers failed to find procinfo for %s",
+ target_pid_to_str (inferior_pid));
-#if 0
- /* It should not be necessary. If the user explicitly changes the value,
- value_assign calls write_register_bytes, which writes it. */
-/* It may not be absolutely necessary to specify the PC value for
- restarting, but to be safe we use the value that gdb considers
- to be current. One case where this might be necessary is if the
- user explicitly changes the PC value that gdb considers to be
- current. FIXME: Investigate if this is necessary or not. */
-
-#ifdef PRSVADDR_BROKEN
-/* Can't do this under Solaris running on a Sparc, as there seems to be no
- place to put nPC. In fact, if you use this, nPC seems to be set to some
- random garbage. We have to rely on the fact that PC and nPC have been
- written previously via PIOCSREG during a register flush. */
-
- pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
- pi->prrun.pr_flags != PRSVADDR;
-#endif
-#endif
+ if ((gregs = proc_get_gregs (pi)) == NULL)
+ proc_error (pi, "fetch_registers, get_gregs", __LINE__);
- if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
- /* When attaching to a child process, if we forced it to stop with
- a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
- Upon resuming the first time after such a stop, we explicitly
- inhibit sending it another SIGSTOP, which would be the normal
- result of default signal handling. One potential drawback to
- this is that we will also ignore any attempt to by the user
- to explicitly continue after the attach with a SIGSTOP. Ultimately
- this problem should be dealt with by making the routines that
- deal with the inferior a little smarter, and possibly even allow
- an inferior to continue running at the same time as gdb. (FIXME?) */
- signal_to_pass = 0;
- else if (signo == TARGET_SIGNAL_TSTP
- && THE_PR_LWP(pi->prstatus).pr_cursig == SIGTSTP
- && THE_PR_LWP(pi->prstatus).pr_action.sa_handler == SIG_DFL
- )
-
- /* We are about to pass the inferior a SIGTSTP whose action is
- SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
- (notifying the parent via wait()), and then keep going from the
- same place when the parent is ready for you to keep going. So
- under the debugger, it should do nothing (as if the program had
- been stopped and then later resumed. Under ptrace, this
- happens for us, but under /proc, the system obligingly stops
- the process, and wait_for_inferior would have no way of
- distinguishing that type of stop (which indicates that we
- should just start it again), with a stop due to the pr_trace
- field of the prrun_t struct.
-
- Note that if the SIGTSTP is being caught, we *do* need to pass it,
- because the handler needs to get executed. */
- signal_to_pass = 0;
- else
- signal_to_pass = target_signal_to_host (signo);
+ supply_gregset (gregs);
- if (signal_to_pass)
- {
- set_proc_siginfo (pi, signal_to_pass);
- }
- else
- {
-#ifdef UNIXWARE
- pctl.data |= PRCSIG;
-#else
- pi->prrun.pr_flags |= PRCSIG;
-#endif
- }
- pi->nopass_next_sigstop = 0;
- if (step)
- {
-#ifdef UNIXWARE
- pctl.data |= PRSTEP;
-#else
- pi->prrun.pr_flags |= PRSTEP;
-#endif
- }
- pi->had_event = 0;
- /* Don't try to start a process unless it's stopped on an
- `event of interest'. Doing so will cause errors. */
-
- if (!procfs_read_status (pi))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
-#else
- if ((pi->prstatus.pr_flags & PR_ISTOP)
- && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+#if defined (FP0_REGNUM) /* need floating point? */
+ if ((regno >= 0 && regno < FP0_REGNUM) ||
+ regno == PC_REGNUM ||
+#ifdef NPC_REGNUM
+ regno == NPC_REGNUM ||
#endif
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- }
- }
-
- /* Continue all the other threads that haven't had an event of interest.
- Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
- set by do_attach, and means this is the first resume after an attach.
- All threads were CSTOP'd by do_attach, and should be resumed now. */
-
- if (pid == -1)
- for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
- {
- next_pi = procinfo->next;
- if (pi != procinfo)
- if (!procinfo->had_event ||
- (procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
- {
- procinfo->had_event = procinfo->nopass_next_sigstop = 0;
-#ifdef PROCFS_USE_READ_WRITE
- pctl.data = PRCFAULT | PRCSIG;
- if (write (procinfo->ctl_fd, (char *) &pctl,
- sizeof (struct proc_ctl)) < 0)
- {
- if (!procfs_read_status (procinfo))
- fprintf_unfiltered(gdb_stderr,
- "procfs_read_status failed, errno=%d\n",
- errno);
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PCRUN failed");
- }
-#else
- procinfo->prrun.pr_flags &= PRSTEP;
- procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
- if (!procfs_read_status (procinfo))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (procinfo->pid >> 16) & 0xffff);
- close_proc_file (procinfo);
- continue;
- }
+ regno == FP_REGNUM ||
+ regno == SP_REGNUM)
+ return; /* not a floating point register */
- /* Don't try to start a process unless it's stopped on an
- `event of interest'. Doing so will cause errors. */
+ if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ proc_error (pi, "fetch_registers, get_fpregs", __LINE__);
- if ((procinfo->prstatus.pr_flags & PR_ISTOP)
- && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
- {
- if (!procfs_read_status (procinfo))
- fprintf_unfiltered(gdb_stderr,
- "procfs_read_status failed, errno=%d\n",
- errno);
- print_sys_errmsg (procinfo->pathname, errno);
- warning ("PIOCRUN failed");
- }
+ supply_fpregset (fpregs);
#endif
- }
- procfs_read_status (procinfo);
- }
}
-/*
-
-LOCAL FUNCTION
-
- procfs_fetch_registers -- fetch current registers from inferior
-
-SYNOPSIS
-
- void procfs_fetch_registers (int regno)
-
-DESCRIPTION
-
- Read the current values of the inferior's registers, both the
- general register set and floating point registers (if supported)
- and update gdb's idea of their current values.
-
-*/
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On
+ machines which store all the registers in one fell swoop, such as
+ /proc, this makes sure that registers contains all the registers
+ from the program being debugged. */
static void
-procfs_fetch_registers (regno)
- int regno;
+procfs_prepare_to_store ()
{
- struct procinfo *pi;
-
- pi = current_procinfo;
-
-#ifdef UNIXWARE
- if (procfs_read_status (pi))
- {
- supply_gregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
-#if defined (FP0_REGNUM)
- supply_fpregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs);
-#endif
- }
-#else /* UNIXWARE */
- if (ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset) != -1)
- {
- supply_gregset (&pi->gregset.gregset);
- }
-#if defined (FP0_REGNUM)
- if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset) != -1)
- {
- supply_fpregset (&pi->fpregset.fpregset);
- }
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
#endif
-#endif /* UNIXWARE */
}
/*
-
-LOCAL FUNCTION
-
- proc_init_failed - called when /proc access initialization fails
-fails
-
-SYNOPSIS
-
- static void proc_init_failed (struct procinfo *pi,
- char *why, int kill_p)
-
-DESCRIPTION
-
- This function is called whenever initialization of access to a /proc
- entry fails. It prints a suitable error message, does some cleanup,
- and then invokes the standard error processing routine which dumps
- us back into the command loop. If KILL_P is true, sends SIGKILL.
+ * store_registers
+ *
+ * Since the /proc interface will not read individual registers,
+ * we will cache these requests until the process is resumed, and
+ * only then write them back to the inferior process.
+ *
+ * FIXME: is that a really bad idea? Have to think about cases
+ * where writing one register might affect the value of others, etc.
*/
static void
-proc_init_failed (pi, why, kill_p)
- struct procinfo *pi;
- char *why;
- int kill_p;
+procfs_store_registers (regno)
+ int regno;
{
- print_sys_errmsg (pi->pathname, errno);
- if (kill_p)
- kill (pi->pid, SIGKILL);
- close_proc_file (pi);
- error (why);
- /* NOTREACHED */
-}
-
-/*
+ gdb_fpregset_t *fpregs;
+ gdb_gregset_t *gregs;
+ procinfo *pi;
+ int pid;
+ int tid;
-LOCAL FUNCTION
+ pid = PIDGET (inferior_pid);
+ tid = TIDGET (inferior_pid);
- close_proc_file - close any currently open /proc entry
+ /* First find procinfo for main process */
+ pi = find_procinfo_or_die (pid, 0);
-SYNOPSIS
+ /* If current lwp for process is not the same as requested thread
+ (ie. inferior_pid), then find procinfo for the requested thread. */
- static void close_proc_file (struct procinfo *pip)
+ if ((tid != 0) &&
+ (tid != proc_get_current_thread (pi)))
+ pi = find_procinfo_or_die (pid, tid);
-DESCRIPTION
-
- Close any currently open /proc entry and mark the process information
- entry as invalid. In order to ensure that we don't try to reuse any
- stale information, the pid, fd, and pathnames are explicitly
- invalidated, which may be overkill.
+ if (pi == NULL)
+ error ("procfs: store_registers: failed to find procinfo for %s",
+ target_pid_to_str (inferior_pid));
- */
+ if ((gregs = proc_get_gregs (pi)) == NULL)
+ proc_error (pi, "store_registers, get_gregs", __LINE__);
-static void
-close_proc_file (pip)
- struct procinfo *pip;
-{
- struct procinfo *procinfo;
+ fill_gregset (gregs, regno);
+ if (!proc_set_gregs (pi))
+ proc_error (pi, "store_registers, set_gregs", __LINE__);
- delete_thread (pip->pid); /* remove thread from GDB's thread list */
- remove_fd (pip); /* Remove fd from poll/select list */
-
- close (pip->ctl_fd);
-#ifdef HAVE_MULTIPLE_PROC_FDS
- close (pip->as_fd);
- close (pip->status_fd);
- close (pip->map_fd);
+#if defined (FP0_REGNUM) /* need floating point? */
+ if ((regno >= 0 && regno < FP0_REGNUM) ||
+ regno == PC_REGNUM ||
+#ifdef NPC_REGNUM
+ regno == NPC_REGNUM ||
#endif
+ regno == FP_REGNUM ||
+ regno == SP_REGNUM)
+ return; /* not a floating point register */
- free (pip -> pathname);
-
- /* Unlink pip from the procinfo chain. Note pip might not be on the list. */
+ if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ proc_error (pi, "store_registers, get_fpregs", __LINE__);
- if (procinfo_list == pip)
- procinfo_list = pip->next;
- else
- {
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
- {
- if (procinfo->next == pip)
- {
- procinfo->next = pip->next;
- break;
- }
- }
- free (pip);
- }
+ fill_fpregset (fpregs, regno);
+ if (!proc_set_fpregs (pi))
+ proc_error (pi, "store_registers, set_fpregs", __LINE__);
+#endif
}
/*
-
-LOCAL FUNCTION
-
- open_proc_file - open a /proc entry for a given process id
-
-SYNOPSIS
-
- static int open_proc_file (int pid, struct procinfo *pip, int mode)
-
-DESCRIPTION
-
- Given a process id and a mode, close the existing open /proc
- entry (if any) and open one for the new process id, in the
- specified mode. Once it is open, then mark the local process
- information structure as valid, which guarantees that the pid,
- fd, and pathname fields match an open /proc entry. Returns
- zero if the open fails, nonzero otherwise.
-
- Note that the pathname is left intact, even when the open fails,
- so that callers can use it to construct meaningful error messages
- rather than just "file open failed".
-
- Note that for Solaris, the process-id also includes an LWP-id, so we
- actually attempt to open that. If we are handed a pid with a 0 LWP-id,
- then we will ask the kernel what it is and add it to the pid. Hence,
- the pid can be changed by us.
+ * Function: target_wait
+ *
+ * Retrieve the next stop event from the child process.
+ * If child has not stopped yet, wait for it to stop.
+ * Translate /proc eventcodes (or possibly wait eventcodes)
+ * into gdb internal event codes.
+ *
+ * Return: id of process (and possibly thread) that incurred the event.
+ * event codes are returned thru a pointer parameter.
*/
-static int
-open_proc_file (pid, pip, mode, control)
+static int
+procfs_wait (pid, status)
int pid;
- struct procinfo *pip;
- int mode;
- int control;
+ struct target_waitstatus *status;
{
- int tmp, tmpfd;
-
- pip -> next = NULL;
- pip -> had_event = 0;
- pip -> pathname = xmalloc (MAX_PROC_NAME_SIZE);
- pip -> pid = pid;
-
-#ifndef PIOCOPENLWP
- tmp = pid;
-#else
- tmp = pid & 0xffff;
-#endif
-
-#ifdef HAVE_MULTIPLE_PROC_FDS
- sprintf (pip->pathname, STATUS_PROC_NAME_FMT, tmp);
- if ((pip->status_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- return 0;
- }
-
- sprintf (pip->pathname, AS_PROC_NAME_FMT, tmp);
- if ((pip->as_fd = open (pip->pathname, O_RDWR)) < 0)
- {
- close (pip->status_fd);
- return 0;
- }
-
- sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
- if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- close (pip->status_fd);
- close (pip->as_fd);
- return 0;
- }
-
- if (control)
+ /* First cut: loosely based on original version 2.1 */
+ procinfo *pi;
+ int temp, wstat;
+ int retval;
+ int why, what, flags;
+ int retry = 0;
+
+wait_again:
+
+ retry++;
+ wstat = 0;
+ retval = -1;
+
+ /* Find procinfo for main process */
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ if (pi)
{
- sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
- if ((pip->ctl_fd = open (pip->pathname, O_WRONLY)) < 0)
+ /* We must assume that the status is stale now... */
+ pi->status_valid = 0;
+ pi->gregs_valid = 0;
+ pi->fpregs_valid = 0;
+
+#if 0 /* just try this out... */
+ flags = proc_flags (pi);
+ why = proc_why (pi);
+ if ((flags & PR_STOPPED) && (why == PR_REQUESTED))
+ pi->status_valid = 0; /* re-read again, IMMEDIATELY... */
+#endif
+ /* If child is not stopped, wait for it to stop. */
+ if (!(proc_flags (pi) & (PR_STOPPED | PR_ISTOP)) &&
+ !proc_wait_for_stop (pi))
{
- close (pip->status_fd);
- close (pip->as_fd);
- close (pip->map_fd);
- return 0;
- }
- }
-
-#else /* HAVE_MULTIPLE_PROC_FDS */
- sprintf (pip -> pathname, CTL_PROC_NAME_FMT, tmp);
-
- if ((tmpfd = open (pip -> pathname, mode)) < 0)
- return 0;
-
-#ifndef PIOCOPENLWP
- pip -> ctl_fd = tmpfd;
- pip -> as_fd = tmpfd;
- pip -> map_fd = tmpfd;
- pip -> status_fd = tmpfd;
-#else
- tmp = (pid >> 16) & 0xffff; /* Extract thread id */
-
- if (tmp == 0)
- { /* Don't know thread id yet */
- if (ioctl (tmpfd, PIOCSTATUS, &pip -> prstatus) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- close (tmpfd);
- error ("open_proc_file: PIOCSTATUS failed");
+ /* wait_for_stop failed: has the child terminated? */
+ if (errno == ENOENT)
+ {
+ /* /proc file not found; presumably child has terminated. */
+ retval = wait (&wstat); /* "wait" for the child's exit */
+
+ if (retval != PIDGET (inferior_pid)) /* wrong child? */
+ error ("procfs: couldn't stop process %d: wait returned %d\n",
+ inferior_pid, retval);
+ /* FIXME: might I not just use waitpid?
+ Or try find_procinfo to see if I know about this child? */
+ }
+ else
+ {
+ /* Unknown error from wait_for_stop. */
+ proc_error (pi, "target_wait (wait_for_stop)", __LINE__);
+ }
}
+ else
+ {
+ /* This long block is reached if either:
+ a) the child was already stopped, or
+ b) we successfully waited for the child with wait_for_stop.
+ This block will analyze the /proc status, and translate it
+ into a waitstatus for GDB.
- tmp = pip -> prstatus.pr_who; /* Get thread id from prstatus_t */
- pip -> pid = (tmp << 16) | pid; /* Update pip */
- }
+ If we actually had to call wait because the /proc file
+ is gone (child terminated), then we skip this block,
+ because we already have a waitstatus. */
- if ((pip -> ctl_fd = ioctl (tmpfd, PIOCOPENLWP, &tmp)) < 0)
- {
- close (tmpfd);
- return 0;
- }
+ flags = proc_flags (pi);
+ why = proc_why (pi);
+ what = proc_what (pi);
-#ifdef PIOCSET /* New method */
- {
- long pr_flags;
- pr_flags = PR_ASYNC;
- ioctl (pip -> ctl_fd, PIOCSET, &pr_flags);
- }
+ if (flags & (PR_STOPPED | PR_ISTOP))
+ {
+#ifdef PR_ASYNC
+ /* If it's running async (for single_thread control),
+ set it back to normal again. */
+ if (flags & PR_ASYNC)
+ if (!proc_unset_async (pi))
+ proc_error (pi, "target_wait, unset_async", __LINE__);
#endif
- /* keep extra fds in sync */
- pip->as_fd = pip->ctl_fd;
- pip->map_fd = pip->ctl_fd;
- pip->status_fd = pip->ctl_fd;
+ if (info_verbose)
+ proc_prettyprint_why (why, what, 1);
- close (tmpfd); /* All done with main pid */
-#endif /* PIOCOPENLWP */
+ /* The 'pid' we will return to GDB is composed of
+ the process ID plus the lwp ID. */
+ retval = MERGEPID (pi->pid, proc_get_current_thread (pi));
-#endif /* HAVE_MULTIPLE_PROC_FDS */
+ switch (why) {
+ case PR_SIGNALLED:
+ wstat = (what << 8) | 0177;
+ break;
+ case PR_SYSENTRY:
+ switch (what) {
+#ifdef SYS_lwp_exit
+ case SYS_lwp_exit:
+#endif
+#ifdef SYS_lwpexit
+ case SYS_lwpexit:
+#endif
+#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+#endif /* _lwp_exit */
+
+ case SYS_exit:
+ /* Handle SYS_exit call only */
+ /* Stopped at entry to SYS_exit.
+ Make it runnable, resume it, then use
+ the wait system call to get its exit code.
+ Proc_run_process always clears the current
+ fault and signal.
+ Then return its exit status. */
+ pi->status_valid = 0;
+ wstat = 0;
+ /* FIXME: what we should do is return
+ TARGET_WAITKIND_SPURIOUS. */
+ if (!proc_run_process (pi, 0, 0))
+ proc_error (pi, "target_wait, run_process", __LINE__);
+ if (attach_flag)
+ {
+ /* Don't call wait: simulate waiting for exit,
+ return a "success" exit code. Bogus: what if
+ it returns something else? */
+ wstat = 0;
+ retval = inferior_pid; /* ??? */
+ }
+ else
+ {
+ int temp = wait (&wstat);
+
+ /* FIXME: shouldn't I make sure I get the right
+ event from the right process? If (for
+ instance) I have killed an earlier inferior
+ process but failed to clean up after it
+ somehow, I could get its termination event
+ here. */
+
+ /* If wait returns -1, that's what we return to GDB. */
+ if (temp < 0)
+ retval = temp;
+ }
+ break;
+ default:
+ printf_filtered ("procfs: trapped on entry to ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
+ {
+ long i, nsysargs, *sysargs;
- return 1;
-}
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08x\n",
+ i, sysargs[i]);
+ }
-static char *
-mappingflags (flags)
- long flags;
-{
- static char asciiflags[8];
-
- strcpy (asciiflags, "-------");
-#if defined (MA_PHYS)
- if (flags & MA_PHYS) asciiflags[0] = 'd';
+ }
#endif
- if (flags & MA_STACK) asciiflags[1] = 's';
- if (flags & MA_BREAK) asciiflags[2] = 'b';
- if (flags & MA_SHARED) asciiflags[3] = 's';
- if (flags & MA_READ) asciiflags[4] = 'r';
- if (flags & MA_WRITE) asciiflags[5] = 'w';
- if (flags & MA_EXEC) asciiflags[6] = 'x';
- return (asciiflags);
-}
-
-static void
-info_proc_flags (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
-#ifdef UNIXWARE
- long flags = pip->prstatus.pr_flags | pip->prstatus.pr_lwp.pr_flags;
-#else
- long flags = pip->prstatus.pr_flags;
+ if (status)
+ {
+ /* How to exit gracefully, returning "unknown event" */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
+ }
+ else
+ {
+ /* How to keep going without returning to wfi: */
+ target_resume (pid, 0, TARGET_SIGNAL_0);
+ goto wait_again;
+ }
+ break;
+ }
+ break;
+ case PR_SYSEXIT:
+ switch (what) {
+#ifdef SYS_exec
+ case SYS_exec:
#endif
+#ifdef SYS_execv
+ case SYS_execv:
+#endif
+#ifdef SYS_execve
+ case SYS_execve:
+#endif
+ /* Hopefully this is our own "fork-child" execing
+ the real child. Hoax this event into a trap, and
+ GDB will see the child about to execute its start
+ address. */
+ wstat = (SIGTRAP << 8) | 0177;
+ break;
+#ifdef SYS_lwp_create
+ case SYS_lwp_create:
+#endif
+#ifdef SYS_lwpcreate
+ case SYS_lwpcreate:
+#endif
+#if defined(SYS_lwp_create) || defined(SYS_lwpcreate)
+ /*
+ * This syscall is somewhat like fork/exec.
+ * We will get the event twice: once for the parent LWP,
+ * and once for the child. We should already know about
+ * the parent LWP, but the child will be new to us. So,
+ * whenever we get this event, if it represents a new
+ * thread, simply add the thread to the list.
+ */
+
+ /* If not in procinfo list, add it. */
+ temp = proc_get_current_thread (pi);
+ if (!find_procinfo (pi->pid, temp))
+ create_procinfo (pi->pid, temp);
+
+ temp = MERGEPID (pi->pid, temp);
+ /* If not in GDB's thread list, add it. */
+ if (!in_thread_list (temp))
+ {
+ printf_filtered ("[New %s]\n", target_pid_to_str (temp));
+ add_thread (temp);
+ }
+ /* Return to WFI, but tell it to immediately resume. */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
+#endif /* _lwp_create */
- printf_filtered ("%-32s", "Process status flags:");
- if (!summary)
- {
- printf_filtered ("\n\n");
- }
- for (transp = pr_flag_table; transp -> name != NULL; transp++)
- {
- if (flags & transp -> value)
- {
- if (summary)
- {
- printf_filtered ("%s ", transp -> name);
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
- }
- }
- }
- printf_filtered ("\n");
-}
-
-static void
-info_proc_stop (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
- int why;
- int what;
-
- why = THE_PR_LWP(pip->prstatus).pr_why;
- what = THE_PR_LWP(pip->prstatus).pr_what;
+#ifdef SYS_lwp_exit
+ case SYS_lwp_exit:
+#endif
+#ifdef SYS_lwpexit
+ case SYS_lwpexit:
+#endif
+#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+#endif /* _lwp_exit */
- if (THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED)
- {
- printf_filtered ("%-32s", "Reason for stopping:");
- if (!summary)
- {
- printf_filtered ("\n\n");
- }
- for (transp = pr_why_table; transp -> name != NULL; transp++)
- {
- if (why == transp -> value)
- {
- if (summary)
- {
- printf_filtered ("%s ", transp -> name);
+#ifdef SYS_sproc
+ case SYS_sproc:
+ /* Nothing to do here for now. The old procfs
+ seemed to use this event to handle threads on
+ older (non-LWP) systems, where I'm assuming that
+ threads were actually separate processes. Irix,
+ maybe? Anyway, low priority for now. */
+#endif
+#ifdef SYS_fork
+ case SYS_fork:
+ /* FIXME: do we need to handle this? Investigate. */
+#endif
+#ifdef SYS_vfork
+ case SYS_vfork:
+ /* FIXME: see above. */
+#endif
+ default:
+ printf_filtered ("procfs: trapped on exit from ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
+ {
+ long i, nsysargs, *sysargs;
+
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08x\n",
+ i, sysargs[i]);
+ }
+ }
+#endif
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
}
- else
- {
- printf_filtered ("\t%-16s %s.\n",
- transp -> name, transp -> desc);
+ break;
+ case PR_REQUESTED:
+#if 0 /* FIXME */
+ wstat = (SIGSTOP << 8) | 0177;
+ break;
+#else
+ if (retry < 5)
+ {
+ printf_filtered ("Retry #%d:\n", retry);
+ pi->status_valid = 0;
+ goto wait_again;
+ }
+ else
+ {
+ /* If not in procinfo list, add it. */
+ temp = proc_get_current_thread (pi);
+ if (!find_procinfo (pi->pid, temp))
+ create_procinfo (pi->pid, temp);
+
+ /* If not in GDB's thread list, add it. */
+ temp = MERGEPID (pi->pid, temp);
+ if (!in_thread_list (temp))
+ {
+ printf_filtered ("[New %s]\n",
+ target_pid_to_str (temp));
+ add_thread (temp);
+ }
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = 0;
+ return retval;
+ }
+#endif
+ case PR_JOBCONTROL:
+ wstat = (what << 8) | 0177;
+ break;
+ case PR_FAULTED:
+ switch (what) { /* FIXME: FAULTED_USE_SIGINFO */
+#ifdef FLTWATCH
+ case FLTWATCH:
+ wstat = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+#ifdef FLTKWATCH
+ case FLTKWATCH:
+ wstat = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+ /* FIXME: use si_signo where possible. */
+ case FLTPRIV:
+#if (FLTILL != FLTPRIV) /* avoid "duplicate case" error */
+ case FLTILL:
+#endif
+ wstat = (SIGILL << 8) | 0177;
+ break;
+ case FLTBPT:
+#if (FLTTRACE != FLTBPT) /* avoid "duplicate case" error */
+ case FLTTRACE:
+#endif
+ wstat = (SIGTRAP << 8) | 0177;
+ break;
+ case FLTSTACK:
+ case FLTACCESS:
+#if (FLTBOUNDS != FLTSTACK) /* avoid "duplicate case" error */
+ case FLTBOUNDS:
+#endif
+ wstat = (SIGSEGV << 8) | 0177;
+ break;
+ case FLTIOVF:
+ case FLTIZDIV:
+#if (FLTFPE != FLTIOVF) /* avoid "duplicate case" error */
+ case FLTFPE:
+#endif
+ wstat = (SIGFPE << 8) | 0177;
+ break;
+ case FLTPAGE: /* Recoverable page fault */
+ default: /* FIXME: use si_signo if possible for fault */
+ retval = -1;
+ printf_filtered ("procfs:%d -- ", __LINE__);
+ printf_filtered ("child stopped for unknown reason:\n");
+ proc_prettyprint_why (why, what, 1);
+ error ("... giving up...");
+ break;
}
- break;
- }
- }
-
- /* Use the pr_why field to determine what the pr_what field means, and
- print more information. */
-
- switch (why)
- {
- case PR_REQUESTED:
- /* pr_what is unused for this case */
- break;
- case PR_JOBCONTROL:
- case PR_SIGNALLED:
- if (summary)
- {
- printf_filtered ("%s ", signalname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", signalname (what),
- safe_strsignal (what));
- }
- break;
- case PR_SYSENTRY:
- if (summary)
- {
- printf_filtered ("%s ", syscallname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", syscallname (what),
- "Entered this system call");
- }
- break;
- case PR_SYSEXIT:
- if (summary)
- {
- printf_filtered ("%s ", syscallname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", syscallname (what),
- "Returned from this system call");
- }
- break;
- case PR_FAULTED:
- if (summary)
- {
- printf_filtered ("%s ",
- lookupname (faults_table, what, "fault"));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n",
- lookupname (faults_table, what, "fault"),
- lookupdesc (faults_table, what));
+ break; /* case PR_FAULTED: */
+ default: /* switch (why) unmatched */
+ printf_filtered ("procfs:%d -- ", __LINE__);
+ printf_filtered ("child stopped for unknown reason:\n");
+ proc_prettyprint_why (why, what, 1);
+ error ("... giving up...");
+ break;
}
- break;
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_siginfo (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct siginfo *sip;
-
- if ((THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED) &&
- (THE_PR_LWP(pip->prstatus).pr_why == PR_SIGNALLED ||
- THE_PR_LWP(pip->prstatus).pr_why == PR_FAULTED))
- {
- printf_filtered ("%-32s", "Additional signal/fault info:");
- sip = &(THE_PR_LWP(pip->prstatus).pr_info);
- if (summary)
- {
- printf_filtered ("%s ", signalname (sip -> si_signo));
- if (sip -> si_errno > 0)
- {
- printf_filtered ("%s ", errnoname (sip -> si_errno));
- }
- if (sip -> si_code <= 0)
- {
- printf_filtered ("sent by %s, uid %d ",
- target_pid_to_str (sip -> si_pid),
- sip -> si_uid);
- }
- else
- {
- printf_filtered ("%s ", sigcodename (sip));
- if ((sip -> si_signo == SIGILL) ||
- (sip -> si_signo == SIGFPE) ||
- (sip -> si_signo == SIGSEGV) ||
- (sip -> si_signo == SIGBUS))
- {
- printf_filtered ("addr=%#lx ",
- (unsigned long) sip -> si_addr);
- }
- else if ((sip -> si_signo == SIGCHLD))
- {
- printf_filtered ("child %s, status %u ",
- target_pid_to_str (sip -> si_pid),
- sip -> si_status);
- }
- else if ((sip -> si_signo == SIGPOLL))
+ /*
+ * Got this far without error:
+ * If retval isn't in the threads database, add it.
+ */
+ if (retval > 0 &&
+ retval != inferior_pid &&
+ !in_thread_list (retval))
{
- printf_filtered ("band %u ", sip -> si_band);
+ /*
+ * We have a new thread.
+ * We need to add it both to GDB's list and to our own.
+ * If we don't create a procinfo, resume may be unhappy
+ * later.
+ */
+ printf_filtered ("[New %s]\n", target_pid_to_str (retval));
+ add_thread (retval);
+ if (find_procinfo (PIDGET (retval), TIDGET (retval)) == NULL)
+ create_procinfo (PIDGET (retval), TIDGET (retval));
+
+ /* In addition, it's possible that this is the first
+ * new thread we've seen, in which case we may not
+ * have created entries for inferior_pid yet.
+ */
+ if (TIDGET (inferior_pid) != 0)
+ {
+ if (!in_thread_list (inferior_pid))
+ add_thread (inferior_pid);
+ if (find_procinfo (PIDGET (inferior_pid),
+ TIDGET (inferior_pid)) == NULL)
+ create_procinfo (PIDGET (inferior_pid),
+ TIDGET (inferior_pid));
+ }
}
}
- }
- else
- {
- printf_filtered ("\n\n");
- printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo),
- safe_strsignal (sip -> si_signo));
- if (sip -> si_errno > 0)
- {
- printf_filtered ("\t%-16s %s.\n",
- errnoname (sip -> si_errno),
- safe_strerror (sip -> si_errno));
- }
- if (sip -> si_code <= 0)
+ else /* flags do not indicate STOPPED */
{
- printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */
- "PID of process sending signal");
- printf_filtered ("\t%-16u %s\n", sip -> si_uid,
- "UID of process sending signal");
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
- sigcodedesc (sip));
- if ((sip -> si_signo == SIGILL) ||
- (sip -> si_signo == SIGFPE))
- {
- printf_filtered ("\t%#-16lx %s.\n",
- (unsigned long) sip -> si_addr,
- "Address of faulting instruction");
- }
- else if ((sip -> si_signo == SIGSEGV) ||
- (sip -> si_signo == SIGBUS))
- {
- printf_filtered ("\t%#-16lx %s.\n",
- (unsigned long) sip -> si_addr,
- "Address of faulting memory reference");
- }
- else if ((sip -> si_signo == SIGCHLD))
- {
- printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */
- "Child process ID");
- printf_filtered ("\t%-16u %s.\n", sip -> si_status,
- "Child process exit value or signal");
- }
- else if ((sip -> si_signo == SIGPOLL))
- {
- printf_filtered ("\t%-16u %s.\n", sip -> si_band,
- "Band event for POLL_{IN,OUT,MSG}");
- }
+ /* surely this can't happen... */
+ printf_filtered ("procfs:%d -- process not stopped.\n",
+ __LINE__);
+ proc_prettyprint_flags (flags, 1);
+ error ("procfs: ...giving up...");
}
}
- printf_filtered ("\n");
+
+ if (status)
+ store_waitstatus (status, wstat);
}
+
+ return retval;
}
-static void
-info_proc_syscalls (pip, summary)
- struct procinfo *pip;
- int summary;
+static int
+procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int dowrite;
+ struct target_ops *target; /* ignored */
{
- int syscallnum;
+ procinfo *pi;
+ int nbytes = 0;
- if (!summary)
+ /* Find procinfo for main process */
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ if (pi->as_fd == 0 &&
+ open_procinfo_files (pi, FD_AS) == 0)
{
+ proc_warn (pi, "xfer_memory, open_proc_files", __LINE__);
+ return 0;
+ }
-#if 0 /* FIXME: Needs to use gdb-wide configured info about system calls. */
- if (pip -> prstatus.pr_flags & PR_ASLEEP)
+ if (lseek (pi->as_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
+ {
+ if (dowrite)
{
- int syscallnum = pip -> prstatus.pr_reg[R_D0];
- if (summary)
- {
- printf_filtered ("%-32s", "Sleeping in system call:");
- printf_filtered ("%s", syscallname (syscallnum));
- }
- else
- {
- printf_filtered ("Sleeping in system call '%s'.\n",
- syscallname (syscallnum));
- }
- }
+#ifdef NEW_PROC_API
+ PROCFS_NOTE ("write memory: ");
+#else
+ PROCFS_NOTE ("write memory: \n");
#endif
-
-#ifndef UNIXWARE
- if (ioctl (pip -> ctl_fd, PIOCGENTRY, &pip -> entryset) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGENTRY failed");
+ nbytes = write (pi->as_fd, myaddr, len);
}
-
- if (ioctl (pip -> ctl_fd, PIOCGEXIT, &pip -> exitset) < 0)
+ else
{
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGEXIT failed");
+ PROCFS_NOTE ("read memory: \n");
+ nbytes = read (pi->as_fd, myaddr, len);
}
-#endif
-
- printf_filtered ("System call tracing information:\n\n");
-
- printf_filtered ("\t%-12s %-8s %-8s\n",
- "System call",
- "Entry",
- "Exit");
- for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
+ if (nbytes < 0)
{
- QUIT;
- if (syscall_table[syscallnum] != NULL)
- printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
- else
- printf_filtered ("\t%-12d ", syscallnum);
-
-#ifdef UNIXWARE
- printf_filtered ("%-8s ",
- prismember (&pip->prstatus.pr_sysentry, syscallnum)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip->prstatus.pr_sysexit, syscallnum)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s ",
- prismember (&pip -> entryset, syscallnum)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> exitset, syscallnum)
- ? "on" : "off");
-#endif
- printf_filtered ("\n");
+ nbytes = 0;
}
- printf_filtered ("\n");
}
+ return nbytes;
}
-static char *
-signalname (signo)
- int signo;
-{
- const char *name;
- static char locbuf[32];
-
- name = strsigno (signo);
- if (name == NULL)
- {
- sprintf (locbuf, "Signal %d", signo);
- }
- else
- {
- sprintf (locbuf, "%s (%d)", name, signo);
- }
- return (locbuf);
-}
-
-static char *
-errnoname (errnum)
- int errnum;
-{
- const char *name;
- static char locbuf[32];
+/*
+ * Function: invalidate_cache
+ *
+ * Called by target_resume before making child runnable.
+ * Mark cached registers and status's invalid.
+ * If there are "dirty" caches that need to be written back
+ * to the child process, do that.
+ *
+ * File descriptors are also cached.
+ * As they are a limited resource, we cannot hold onto them indefinitely.
+ * However, as they are expensive to open, we don't want to throw them
+ * away indescriminately either. As a compromise, we will keep the
+ * file descriptors for the parent process, but discard any file
+ * descriptors we may have accumulated for the threads.
+ *
+ * Return value:
+ * As this function is called by iterate_over_threads, it always
+ * returns zero (so that iterate_over_threads will keep iterating).
+ */
- name = strerrno (errnum);
- if (name == NULL)
- {
- sprintf (locbuf, "Errno %d", errnum);
- }
- else
- {
- sprintf (locbuf, "%s (%d)", name, errnum);
- }
- return (locbuf);
-}
-static void
-info_proc_signals (pip, summary)
- struct procinfo *pip;
- int summary;
+static int
+invalidate_cache (parent, pi, ptr)
+ procinfo *parent;
+ procinfo *pi;
+ void *ptr;
{
- int signo;
+ /*
+ * About to run the child; invalidate caches and do any other cleanup.
+ */
- if (!summary)
- {
-#ifndef PROCFS_USE_READ_WRITE
- if (ioctl (pip -> ctl_fd, PIOCGTRACE, &pip -> trace) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGTRACE failed");
- }
+#if 0
+ if (pi->gregs_dirty)
+ if (parent == NULL ||
+ proc_get_current_thread (parent) != pi->tid)
+ if (!proc_set_gregs (pi)) /* flush gregs cache */
+ proc_warn (pi, "target_resume, set_gregs",
+ __LINE__);
+#ifdef FP0_REGNUM
+ if (pi->fpregs_dirty)
+ if (parent == NULL ||
+ proc_get_current_thread (parent) != pi->tid)
+ if (!proc_set_fpregs (pi)) /* flush fpregs cache */
+ proc_warn (pi, "target_resume, set_fpregs",
+ __LINE__);
#endif
-
- printf_filtered ("Disposition of signals:\n\n");
- printf_filtered ("\t%-15s %-8s %-8s %-8s %s\n\n",
- "Signal", "Trace", "Hold", "Pending", "Description");
- for (signo = 0; signo < NSIG; signo++)
- {
- QUIT;
- printf_filtered ("\t%-15s ", signalname (signo));
-#ifdef UNIXWARE
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_sigtrace, signo)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_lwp.pr_context.uc_sigmask, signo)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s ",
- prismember (&pip -> trace, signo)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_sighold, signo)
- ? "on" : "off");
#endif
-#ifdef UNIXWARE
- if (prismember (&pip->prstatus.pr_sigpend, signo) ||
- prismember (&pip->prstatus.pr_lwp.pr_lwppend, signo))
- printf_filtered("%-8s ", "yes");
- else
- printf_filtered("%-8s ", "no");
-#else /* UNIXWARE */
-#ifdef PROCFS_SIGPEND_OFFSET
- /* Alpha OSF/1 numbers the pending signals from 1. */
- printf_filtered ("%-8s ",
- (signo ? prismember (&pip -> prstatus.pr_sigpend,
- signo - 1)
- : 0)
- ? "yes" : "no");
-#else
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_sigpend, signo)
- ? "yes" : "no");
-#endif
-#endif /* UNIXWARE */
- printf_filtered (" %s\n", safe_strsignal (signo));
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_faults (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
-
- if (!summary)
+ if (parent != NULL)
{
-#ifndef UNIXWARE
- if (ioctl (pip -> ctl_fd, PIOCGFAULT, &pip->fltset.fltset) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGFAULT failed");
- }
-#endif
-
- printf_filtered ("Current traced hardware fault set:\n\n");
- printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
+ /* The presence of a parent indicates that this is an LWP.
+ Close any file descriptors that it might have open.
+ We don't do this to the master (parent) procinfo. */
- for (transp = faults_table; transp -> name != NULL; transp++)
- {
- QUIT;
- printf_filtered ("\t%-12s ", transp -> name);
-#ifdef UNIXWARE
- printf_filtered ("%-8s", prismember (&pip->prstatus.pr_flttrace, transp -> value)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s", prismember (&pip->fltset.fltset, transp -> value)
- ? "on" : "off");
-#endif
- printf_filtered ("\n");
- }
- printf_filtered ("\n");
+ close_procinfo_files (pi);
}
+ pi->gregs_valid = 0;
+ pi->fpregs_valid = 0;
+#if 0
+ pi->gregs_dirty = 0;
+ pi->fpregs_dirty = 0;
+#endif
+ pi->status_valid = 0;
+ pi->threads_valid = 0;
+
+ return 0;
}
-static void
-info_proc_mappings (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- int nmap;
- struct prmap *prmaps;
- struct prmap *prmap;
- struct stat sbuf;
+#if 0
+/*
+ * Function: make_signal_thread_runnable
+ *
+ * A callback function for iterate_over_threads.
+ * Find the asynchronous signal thread, and make it runnable.
+ * See if that helps matters any.
+ */
- if (!summary)
+static int
+make_signal_thread_runnable (process, pi, ptr)
+ procinfo *process;
+ procinfo *pi;
+ void *ptr;
+{
+#ifdef PR_ASLWP
+ if (proc_flags (pi) & PR_ASLWP)
{
- printf_filtered ("Mapped address spaces:\n\n");
-#ifdef BFD_HOST_64_BIT
- printf_filtered (" %18s %18s %10s %10s %7s\n",
-#else
- printf_filtered ("\t%10s %10s %10s %10s %7s\n",
-#endif
- "Start Addr",
- " End Addr",
- " Size",
- " Offset",
- "Flags");
-#ifdef PROCFS_USE_READ_WRITE
- if (fstat (pip->map_fd, &sbuf) == 0)
- {
- nmap = sbuf.st_size / sizeof (prmap_t);
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if ((lseek (pip->map_fd, 0, SEEK_SET) == 0) &&
- (read (pip->map_fd, (char *) prmaps,
- nmap * sizeof (*prmaps)) == (nmap * sizeof (*prmaps))))
- {
- int i = 0;
- for (prmap = prmaps; i < nmap; ++prmap, ++i)
-#else
- if (ioctl (pip -> ctl_fd, PIOCNMAP, &nmap) == 0)
- {
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pip -> ctl_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size; ++prmap)
-#endif /* PROCFS_USE_READ_WRITE */
- {
-#ifdef BFD_HOST_64_BIT
- printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
-#else
- printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
-#endif
- (unsigned long)prmap -> pr_vaddr,
- (unsigned long)prmap -> pr_vaddr
- + prmap -> pr_size - 1,
- prmap -> pr_size,
- prmap -> pr_off,
- mappingflags (prmap -> pr_mflags));
- }
- }
- }
- printf_filtered ("\n");
+ if (!proc_run_process (pi, 0, -1))
+ proc_error (pi, "make_signal_thread_runnable", __LINE__);
+ return 1;
}
+#endif
+ return 0;
}
+#endif
/*
-
-LOCAL FUNCTION
-
- info_proc -- implement the "info proc" command
-
-SYNOPSIS
-
- void info_proc (char *args, int from_tty)
-
-DESCRIPTION
-
- Implement gdb's "info proc" command by using the /proc interface
- to print status information about any currently running process.
-
- Examples of the use of "info proc" are:
-
- info proc (prints summary info for current inferior)
- info proc 123 (prints summary info for process with pid 123)
- info proc mappings (prints address mappings)
- info proc times (prints process/children times)
- info proc id (prints pid, ppid, gid, sid, etc)
- FIXME: i proc id not implemented.
- info proc status (prints general process state info)
- FIXME: i proc status not implemented.
- info proc signals (prints info about signal handling)
- info proc all (prints all info)
-
+ * Function: target_resume
+ *
+ * Make the child process runnable. Normally we will then call
+ * procfs_wait and wait for it to stop again (unles gdb is async).
+ *
+ * Arguments:
+ * step: if true, then arrange for the child to stop again
+ * after executing a single instruction.
+ * signo: if zero, then cancel any pending signal.
+ * If non-zero, then arrange for the indicated signal
+ * to be delivered to the child when it runs.
+ * pid: if -1, then allow any child thread to run.
+ * if non-zero, then allow only the indicated thread to run.
+ ******* (not implemented yet)
*/
static void
-info_proc (args, from_tty)
- char *args;
- int from_tty;
+procfs_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
{
- int pid;
- struct procinfo *pip;
- struct cleanup *old_chain;
- char **argv;
- int argsize;
- int summary = 1;
- int flags = 0;
- int syscalls = 0;
- int signals = 0;
- int faults = 0;
- int mappings = 0;
- int times = 0;
- int id = 0;
- int status = 0;
- int all = 0;
- int nlwp;
- int *lwps;
+ procinfo *pi, *thread;
+ int native_signo;
+
+ /* 2.1:
+ prrun.prflags |= PRSVADDR;
+ prrun.pr_vaddr = $PC; set resume address
+ prrun.prflags |= PRSTRACE; trace signals in pr_trace (all)
+ prrun.prflags |= PRSFAULT; trace faults in pr_fault (all but PAGE)
+ prrun.prflags |= PRCFAULT; clear current fault.
+
+ PRSTRACE and PRSFAULT can be done by other means
+ (proc_trace_signals, proc_trace_faults)
+ PRSVADDR is unnecessary.
+ PRCFAULT may be replaced by a PIOCCFAULT call (proc_clear_current_fault)
+ This basically leaves PRSTEP and PRCSIG.
+ PRCSIG is like PIOCSSIG (proc_clear_current_signal).
+ So basically PR_STEP is the sole argument that must be passed
+ to proc_run_process (for use in the prrun struct by ioctl). */
+
+ /* Find procinfo for main process */
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+
+ /* First cut: ignore pid argument */
+ errno = 0;
- old_chain = make_cleanup (null_cleanup, 0);
+ /* Convert signal to host numbering. */
+ if (signo == 0 ||
+ (signo == TARGET_SIGNAL_STOP && pi->ignore_next_sigstop))
+ native_signo = 0;
+ else
+ native_signo = target_signal_to_host (signo);
- /* Default to using the current inferior if no pid specified. Note
- that inferior_pid may be 0, hence we set okerr. */
+ pi->ignore_next_sigstop = 0;
- pid = inferior_pid & 0x7fffffff; /* strip off sol-thread bit */
- if (!(pip = find_procinfo (pid, 1))) /* inferior_pid no good? */
- pip = procinfo_list; /* take first available */
- pid = pid & 0xffff; /* extract "real" pid */
+ /* Running the process voids all cached registers and status. */
+ /* Void the threads' caches first */
+ proc_iterate_over_threads (pi, invalidate_cache, NULL);
+ /* Void the process procinfo's caches. */
+ invalidate_cache (NULL, pi, NULL);
- if (args != NULL)
+ if (pid != -1)
{
- if ((argv = buildargv (args)) == NULL)
- {
- nomem (0);
- }
- make_cleanup (freeargv, (char *) argv);
-
- while (*argv != NULL)
+ /* Resume a specific thread, presumably suppressing the others. */
+ thread = find_procinfo (PIDGET (pid), TIDGET (pid));
+ if (thread == NULL)
+ warning ("procfs: resume can't find thread %d -- resuming all.",
+ TIDGET (pid));
+ else
{
- argsize = strlen (*argv);
- if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
- {
- summary = 0;
- all = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
- {
- summary = 0;
- faults = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
- {
- summary = 0;
- flags = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
- {
- summary = 0;
- id = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
+ if (thread->tid != 0)
{
- summary = 0;
- mappings = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
- {
- summary = 0;
- signals = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
- {
- summary = 0;
- status = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
- {
- summary = 0;
- syscalls = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
- {
- summary = 0;
- times = 1;
- }
- else if ((pid = atoi (*argv)) > 0)
- {
- pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
- memset (pip, 0, sizeof (*pip));
-
- pip->pid = pid;
- if (!open_proc_file (pid, pip, O_RDONLY, 0))
- {
- perror_with_name (pip -> pathname);
- /* NOTREACHED */
- }
- pid = pip->pid;
- make_cleanup (close_proc_file, pip);
- }
- else if (**argv != '\000')
- {
- error ("Unrecognized or ambiguous keyword `%s'.", *argv);
+ /* We're to resume a specific thread, and not the others.
+ * Set the child process's PR_ASYNC flag.
+ */
+#ifdef PR_ASYNC
+ if (!proc_set_async (pi))
+ proc_error (pi, "target_resume, set_async", __LINE__);
+#endif
+#if 0
+ proc_iterate_over_threads (pi,
+ make_signal_thread_runnable,
+ NULL);
+#endif
+ pi = thread; /* substitute the thread's procinfo for run */
}
- argv++;
}
}
- /* If we don't have a valid open process at this point, then we have no
- inferior or didn't specify a specific pid. */
-
- if (!pip)
- {
- error ("\
-No process. Start debugging a program or specify an explicit process ID.");
- }
-
- if (!procfs_read_status (pip))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("procfs_read_status failed");
- }
-
-#ifndef PROCFS_USE_READ_WRITE
-#ifdef PIOCLWPIDS
- nlwp = pip->prstatus.pr_nlwp;
- lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
-
- if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCLWPIDS failed");
- }
-#else /* PIOCLWPIDS */
- nlwp = 1;
- lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
- lwps[0] = 0;
-#endif /* PIOCLWPIDS */
-
- for (; nlwp > 0; nlwp--, lwps++)
+ if (!proc_run_process (pi, step, native_signo))
{
- pip = find_procinfo ((*lwps << 16) | pid, 1);
-
- if (!pip)
- {
- pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
- memset (pip, 0, sizeof (*pip));
- if (!open_proc_file ((*lwps << 16) | pid, pip, O_RDONLY, 0))
- continue;
-
- make_cleanup (close_proc_file, pip);
-
- if (!procfs_read_status (pip))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("procfs_read_status failed");
- }
- }
-
-#endif /* PROCFS_USE_READ_WRITE */
-
- /* Print verbose information of the requested type(s), or just a summary
- of the information for all types. */
-
- printf_filtered ("\nInformation for %s.%d:\n\n", pip -> pathname, *lwps);
- if (summary || all || flags)
- {
- info_proc_flags (pip, summary);
- }
- if (summary || all)
- {
- info_proc_stop (pip, summary);
-#ifdef UNIXWARE
- supply_gregset (&pip->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
-#else
- supply_gregset (&pip->prstatus.pr_reg);
-#endif
- printf_filtered ("PC: ");
- print_address (read_pc (), gdb_stdout);
- printf_filtered ("\n");
- }
- if (summary || all || signals || faults)
- {
- info_proc_siginfo (pip, summary);
- }
- if (summary || all || syscalls)
- {
- info_proc_syscalls (pip, summary);
- }
- if (summary || all || mappings)
- {
- info_proc_mappings (pip, summary);
- }
- if (summary || all || signals)
- {
- info_proc_signals (pip, summary);
- }
- if (summary || all || faults)
- {
- info_proc_faults (pip, summary);
- }
- printf_filtered ("\n");
-
- /* All done, deal with closing any temporary process info structure,
- freeing temporary memory , etc. */
-
- do_cleanups (old_chain);
-#ifndef PROCFS_USE_READ_WRITE
+ if (errno == EBUSY)
+ warning ("resume: target already running. Pretend to resume, and hope for the best!\n");
+ else
+ proc_error (pi, "target_resume", __LINE__);
}
-#endif
}
/*
+ * Function: register_gdb_signals
+ *
+ * Traverse the list of signals that GDB knows about
+ * (see "handle" command), and arrange for the target
+ * to be stopped or not, according to these settings.
+ *
+ * Returns non-zero for success, zero for failure.
+ */
-LOCAL FUNCTION
-
- modify_inherit_on_fork_flag - Change the inherit-on-fork flag
-
-SYNOPSIS
-
- void modify_inherit_on_fork_flag (fd, flag)
+static int
+register_gdb_signals (pi, signals)
+ procinfo *pi;
+ sigset_t *signals;
+{
+ int signo;
-DESCRIPTION
+ for (signo = 0; signo < NSIG; signo ++)
+ if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
+ signal_print_state (target_signal_from_host (signo)) == 0 &&
+ signal_pass_state (target_signal_from_host (signo)) == 1)
+ prdelset (signals, signo);
+ else
+ praddset (signals, signo);
- Call this routine to modify the inherit-on-fork flag. This routine is
- just a nice wrapper to hide the #ifdefs needed by various systems to
- control this flag.
+ return proc_set_traced_signals (pi, signals);
+}
+/*
+ * Function: target_notice_signals
+ *
+ * Set up to trace signals in the child process.
*/
static void
-modify_inherit_on_fork_flag (fd, flag)
- int fd;
- int flag;
+procfs_notice_signals (pid)
+ int pid;
{
-#if defined (PIOCSET) || defined (PCSET)
- long pr_flags;
-#endif
- int retval = 0;
- struct proc_ctl pctl;
+ sigset_t signals;
+ procinfo *pi = find_procinfo_or_die (PIDGET (pid), 0);
-#if defined (PIOCSET) || defined (PCSET) /* New method */
- pr_flags = PR_FORK;
- if (flag)
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_FORK;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCRESET;
- pctl.data = PR_FORK;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCRESET, &pr_flags);
-#endif
- }
-
-#else
-#ifdef PIOCSFORK /* Original method */
- if (flag)
- {
- retval = ioctl (fd, PIOCSFORK, NULL);
- }
+ if (proc_get_traced_signals (pi, &signals) &&
+ register_gdb_signals (pi, &signals))
+ return;
else
- {
- retval = ioctl (fd, PIOCRFORK, NULL);
- }
-#else
- Neither PR_FORK nor PIOCSFORK exist!!!
-#endif
-#endif
+ proc_error (pi, "notice_signals", __LINE__);
+}
- if (!retval)
- return;
+/*
+ * Function: target_files_info
+ *
+ * Print status information about the child process.
+ */
- print_sys_errmsg ("modify_inherit_on_fork_flag", errno);
- error ("PIOCSFORK or PR_FORK modification failed");
+static void
+procfs_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_filtered ("\tUsing the running image of %s %s via /proc.\n",
+ attach_flag? "attached": "child",
+ target_pid_to_str (inferior_pid));
}
/*
+ * Function: target_open
+ *
+ * A dummy: you don't open procfs.
+ */
-LOCAL FUNCTION
+static void
+procfs_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
- modify_run_on_last_close_flag - Change the run-on-last-close flag
+/*
+ * Function: target_can_run
+ *
+ * This tells GDB that this target vector can be invoked
+ * for "run" or "attach".
+ */
-SYNOPSIS
+int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to
+ be a runnable target. Used by targets
+ that can sit atop procfs, such as solaris
+ thread support. */
- void modify_run_on_last_close_flag (fd, flag)
-DESCRIPTION
+static int
+procfs_can_run ()
+{
+ /* This variable is controlled by modules that sit atop procfs that
+ may layer their own process structure atop that provided here.
+ sol-thread.c does this because of the Solaris two-level thread
+ model. */
+
+ /* NOTE: possibly obsolete -- use the thread_stratum approach instead. */
- Call this routine to modify the run-on-last-close flag. This routine
- is just a nice wrapper to hide the #ifdefs needed by various systems to
- control this flag.
+ return !procfs_suppress_run;
+}
+/*
+ * Function: target_stop
+ *
+ * Stop the child process asynchronously, as when the
+ * gdb user types control-c or presses a "stop" button.
+ *
+ * Works by sending kill(SIGINT) to the child's process group.
*/
static void
-modify_run_on_last_close_flag (fd, flag)
- int fd;
- int flag;
+procfs_stop ()
{
-#if defined (PIOCSET) || defined (PCSET)
- long pr_flags;
-#endif
- int retval = 0;
- struct proc_ctl pctl;
-
-#if defined (PIOCSET) || defined (PCSET) /* New method */
- pr_flags = PR_RLC;
- if (flag)
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_RLC;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCRESET;
- pctl.data = PR_RLC;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCRESET, &pr_flags);
-#endif
- }
-
-#else
-#ifdef PIOCSRLC /* Original method */
- if (flag)
- retval = ioctl (fd, PIOCSRLC, NULL);
- else
- retval = ioctl (fd, PIOCRRLC, NULL);
-#else
- Neither PR_RLC nor PIOCSRLC exist!!!
-#endif
-#endif
-
- if (!retval)
- return;
+ extern pid_t inferior_process_group;
- print_sys_errmsg ("modify_run_on_last_close_flag", errno);
- error ("PIOCSRLC or PR_RLC modification failed");
+ kill (-inferior_process_group, SIGINT);
}
/*
-
-LOCAL FUNCTION
-
- procfs_clear_syscall_trap -- Deletes the trap for the specified system call.
-
-SYNOPSIS
-
- void procfs_clear_syscall_trap (struct procinfo *, int syscall_num, int errok)
-
-DESCRIPTION
-
- This function function disables traps for the specified system call.
- errok is non-zero if errors should be ignored.
+ * Function: unconditionally_kill_inferior
+ *
+ * Make it die. Wait for it to die. Clean up after it.
+ * Note: this should only be applied to the real process,
+ * not to an LWP, because of the check for parent-process.
+ * If we need this to work for an LWP, it needs some more logic.
*/
static void
-procfs_clear_syscall_trap (pi, syscall_num, errok)
- struct procinfo *pi;
- int syscall_num;
- int errok;
+unconditionally_kill_inferior (pi)
+ procinfo *pi;
{
- sysset_t sysset;
- int goterr, i;
-
-#ifndef UNIXWARE
- goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
+ int parent_pid;
- if (goterr && !errok)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGENTRY failed");
- }
-
- if (!goterr)
+ parent_pid = proc_parent_pid (pi);
+#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
+ /* FIXME: use access functions */
+ /* Alpha OSF/1-3.x procfs needs a clear of the current signal
+ before the PIOCKILL, otherwise it might generate a corrupted core
+ file for the inferior. */
+ if (ioctl (pi->ctl_fd, PIOCSSIG, NULL) < 0)
{
- prdelset (&sysset, syscall_num);
-
- if ((ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0) && !errok)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSENTRY failed");
- }
+ printf_filtered ("unconditionally_kill: SSIG failed!\n");
}
+#endif
+#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
+ /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
+ to kill the inferior, otherwise it might remain stopped with a
+ pending SIGKILL.
+ We do not check the result of the PIOCSSIG, the inferior might have
+ died already. */
+ {
+ struct siginfo newsiginfo;
- goterr = ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0;
-
- if (goterr && !errok)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGEXIT failed");
- }
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ newsiginfo.si_signo = SIGKILL;
+ newsiginfo.si_code = 0;
+ newsiginfo.si_errno = 0;
+ newsiginfo.si_pid = getpid ();
+ newsiginfo.si_uid = getuid ();
+ /* FIXME: use proc_set_current_signal */
+ ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo);
+ }
+#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+ if (!proc_kill (pi, SIGKILL))
+ proc_warn (pi, "unconditionally_kill, proc_kill", __LINE__);
+#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
+ destroy_procinfo (pi);
- if (!goterr)
+ /* If pi is GDB's child, wait for it to die. */
+ if (parent_pid == getpid ())
+ /* FIXME: should we use waitpid to make sure we get the right event?
+ Should we check the returned event? */
{
- praddset (&sysset, syscall_num);
+#if 0
+ int status, ret;
- if ((ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0) && !errok)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSEXIT failed");
- }
- }
+ ret = waitpid (pi->pid, &status, 0);
+#else
+ wait (NULL);
#endif
-
- if (!pi->syscall_handlers)
- {
- if (!errok)
- error ("procfs_clear_syscall_trap: syscall_handlers is empty");
- return;
}
-
- /* Remove handler func from the handler list */
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == syscall_num)
- {
- if (i + 1 != pi->num_syscall_handlers)
- { /* Not the last entry.
- Move subsequent entries fwd. */
- memcpy (&pi->syscall_handlers[i], &pi->syscall_handlers[i + 1],
- (pi->num_syscall_handlers - i - 1)
- * sizeof (struct procfs_syscall_handler));
- }
-
- pi->syscall_handlers = xrealloc (pi->syscall_handlers,
- (pi->num_syscall_handlers - 1)
- * sizeof (struct procfs_syscall_handler));
- pi->num_syscall_handlers--;
- return;
- }
-
- if (!errok)
- error ("procfs_clear_syscall_trap: Couldn't find handler for sys call %d",
- syscall_num);
}
/*
-
-LOCAL FUNCTION
-
- procfs_set_syscall_trap -- arrange for a function to be called when the
- child executes the specified system call.
-
-SYNOPSIS
-
- void procfs_set_syscall_trap (struct procinfo *, int syscall_num, int flags,
- syscall_func_t *function)
-
-DESCRIPTION
-
- This function sets up an entry and/or exit trap for the specified system
- call. When the child executes the specified system call, your function
- will be called with the call #, a flag that indicates entry or exit, and
- pointers to rtnval and statval (which are used by procfs_wait). The
- function should return non-zero if something interesting happened, zero
- otherwise.
+ * Function: target_kill_inferior
+ *
+ * We're done debugging it, and we want it to go away.
+ * Then we want GDB to forget all about it.
*/
-static void
-procfs_set_syscall_trap (pi, syscall_num, flags, func)
- struct procinfo *pi;
- int syscall_num;
- int flags;
- syscall_func_t *func;
+static void
+procfs_kill_inferior ()
{
- sysset_t sysset;
-
-#ifndef UNIXWARE
- if (flags & PROCFS_SYSCALL_ENTRY)
+ if (inferior_pid != 0) /* ? */
{
- if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGENTRY failed");
- }
+ /* Find procinfo for main process */
+ procinfo *pi = find_procinfo (PIDGET (inferior_pid), 0);
- praddset (&sysset, syscall_num);
-
- if (ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSENTRY failed");
- }
+ if (pi)
+ unconditionally_kill_inferior (pi);
+ target_mourn_inferior ();
}
+}
- if (flags & PROCFS_SYSCALL_EXIT)
- {
- if (ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGEXIT failed");
- }
-
- praddset (&sysset, syscall_num);
+/*
+ * Function: target_mourn_inferior
+ *
+ * Forget we ever debugged this thing!
+ */
- if (ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSEXIT failed");
- }
- }
-#endif
+static void
+procfs_mourn_inferior ()
+{
+ procinfo *pi;
- if (!pi->syscall_handlers)
- {
- pi->syscall_handlers = xmalloc (sizeof (struct procfs_syscall_handler));
- pi->syscall_handlers[0].syscall_num = syscall_num;
- pi->syscall_handlers[0].func = func;
- pi->num_syscall_handlers = 1;
- }
- else
+ if (inferior_pid != 0)
{
- int i;
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == syscall_num)
- {
- pi->syscall_handlers[i].func = func;
- return;
- }
-
- pi->syscall_handlers = xrealloc (pi->syscall_handlers, (i + 1)
- * sizeof (struct procfs_syscall_handler));
- pi->syscall_handlers[i].syscall_num = syscall_num;
- pi->syscall_handlers[i].func = func;
- pi->num_syscall_handlers++;
+ /* Find procinfo for main process */
+ pi = find_procinfo (PIDGET (inferior_pid), 0);
+ if (pi)
+ destroy_procinfo (pi);
}
+ unpush_target (&procfs_ops);
+ generic_mourn_inferior ();
}
-#ifdef SYS_lwp_create
-
/*
-
-LOCAL FUNCTION
-
- procfs_lwp_creation_handler - handle exit from the _lwp_create syscall
-
-SYNOPSIS
-
- int procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called both when an inferior process and it's new lwp
- are about to finish a _lwp_create() system call. This is the system
- call that Solaris uses to create a lightweight process. When the
- target process gets this event, we can look at sysarg[2] to find the
- new childs lwp ID, and create a procinfo struct from that. After that,
- we pretend that we got a SIGTRAP, and return non-zero to tell
- procfs_wait to wake up. Subsequently, wait_for_inferior gets woken up,
- sees the new process and continues it.
-
- When we see the child exiting from lwp_create, we just contine it,
- since everything was handled when the parent trapped.
-
-NOTES
- In effect, we are only paying attention to the parent's completion of
- the lwp_create syscall. If we only paid attention to the child
- instead, then we wouldn't detect the creation of a suspended thread.
+ * Function: init_inferior
+ *
+ * When GDB forks to create a runnable inferior process,
+ * this function is called on the parent side of the fork.
+ * It's job is to do whatever is necessary to make the child
+ * ready to be debugged, and then wait for the child to synchronize.
*/
-static int
-procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
+static void
+procfs_init_inferior (pid)
+ int pid;
{
- int lwp_id;
- struct procinfo *childpi;
- struct proc_ctl pctl;
-
- /* We've just detected the completion of an lwp_create system call. Now we
- need to setup a procinfo struct for this thread, and notify the thread
- system of the new arrival. */
+ procinfo *pi;
+ sigset_t signals;
+ int fail;
- /* If lwp_create failed, then nothing interesting happened. Continue the
- process and go back to sleep. */
-
-#ifdef UNIXWARE
- /* Joel ... can you check this logic out please? JKJ */
- if (pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs[R_EFL] & 1)
- { /* _lwp_create failed */
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- perror_with_name (pi->pathname);
-
- return 0;
- }
-#else /* UNIXWARE */
- if (PROCFS_GET_CARRY (pi->prstatus.pr_reg))
- { /* _lwp_create failed */
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
+ /* This routine called on the parent side (GDB side)
+ after GDB forks the inferior. */
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
+ push_target (&procfs_ops);
- return 0;
- }
-#endif
+ if ((pi = create_procinfo (pid, 0)) == NULL)
+ perror ("procfs: out of memory in 'init_inferior'");
+
+ if (!open_procinfo_files (pi, FD_CTL))
+ proc_error (pi, "init_inferior, open_proc_files", __LINE__);
+
+ /*
+ xmalloc // done
+ open_procinfo_files // done
+ link list // done
+ prfillset (trace)
+ procfs_notice_signals
+ prfillset (fault)
+ prdelset (FLTPAGE)
+ PIOCWSTOP
+ PIOCSFAULT
+ */
+
+ /* If not stopped yet, wait for it to stop. */
+ if (!(proc_flags (pi) & PR_STOPPED) &&
+ !(proc_wait_for_stop (pi)))
+ dead_procinfo (pi, "init_inferior: wait_for_stop failed", KILL);
+
+ /* Save some of the /proc state to be restored if we detach. */
+ /* FIXME: Why? In case another debugger was debugging it?
+ We're it's parent, for Ghu's sake! */
+ if (!proc_get_traced_signals (pi, &pi->saved_sigset))
+ proc_error (pi, "init_inferior, get_traced_signals", __LINE__);
+ if (!proc_get_held_signals (pi, &pi->saved_sighold))
+ proc_error (pi, "init_inferior, get_held_signals", __LINE__);
+ if (!proc_get_traced_faults (pi, &pi->saved_fltset))
+ proc_error (pi, "init_inferior, get_traced_faults", __LINE__);
+ if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ proc_error (pi, "init_inferior, get_traced_sysentry", __LINE__);
+ if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__);
+
+ /* Register to trace selected signals in the child. */
+ prfillset (&signals);
+ if (!register_gdb_signals (pi, &signals))
+ proc_error (pi, "init_inferior, register_signals", __LINE__);
+
+ if ((fail = procfs_debug_inferior (pi)) != 0)
+ proc_error (pi, "init_inferior (procfs_debug_inferior)", fail);
+
+ /* FIXME: logically, we should really be turning OFF run-on-last-close,
+ and possibly even turning ON kill-on-last-close at this point. But
+ I can't make that change without careful testing which I don't have
+ time to do right now... */
+ /* Turn on run-on-last-close flag so that the child
+ will die if GDB goes away for some reason. */
+ if (!proc_set_run_on_last_close (pi))
+ proc_error (pi, "init_inferior, set_RLC", __LINE__);
+
+ /* The 'process ID' we return to GDB is composed of
+ the actual process ID plus the lwp ID. */
+ inferior_pid = MERGEPID (pi->pid, proc_get_current_thread (pi));
- /* At this point, the new thread is stopped at it's first instruction, and
- the parent is stopped at the exit from lwp_create. */
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+ startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+#else
+ /* One trap to exec the shell, one to exec the program being debugged. */
+ startup_inferior (2);
+#endif /* START_INFERIOR_TRAPS_EXPECTED */
+}
- if (pi->new_child) /* Child? */
- { /* Yes, just continue it */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
+/*
+ * Function: set_exec_trap
+ *
+ * When GDB forks to create a new process, this function is called
+ * on the child side of the fork before GDB exec's the user program.
+ * Its job is to make the child minimally debuggable, so that the
+ * parent GDB process can connect to the child and take over.
+ * This function should do only the minimum to make that possible,
+ * and to synchronize with the parent process. The parent process
+ * should take care of the details.
+ */
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else /* !UNIXWARE */
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
+static void
+procfs_set_exec_trap ()
+{
+ /* This routine called on the child side (inferior side)
+ after GDB forks the inferior. It must use only local variables,
+ because it may be sharing data space with its parent. */
- if ((pi->prstatus.pr_flags & PR_ISTOP)
- && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif /* !UNIXWARE */
- perror_with_name (pi->pathname);
+ procinfo *pi;
+ sysset_t exitset;
- pi->new_child = 0; /* No longer new */
+ if ((pi = create_procinfo (getpid (), 0)) == NULL)
+ perror_with_name ("procfs: create_procinfo failed in child.");
- return 0;
+ if (open_procinfo_files (pi, FD_CTL) == 0)
+ {
+ proc_warn (pi, "set_exec_trap, open_proc_files", __LINE__);
+ gdb_flush (gdb_stderr);
+ /* no need to call "dead_procinfo", because we're going to exit. */
+ _exit (127);
}
- /* We're the proud parent of a new thread. Setup an exit trap for lwp_create
- in the child and continue the parent. */
-
- /* Third arg is pointer to new thread id. */
- lwp_id = read_memory_integer (
- THE_PR_LWP(pi->prstatus).pr_sysarg[2], sizeof (int));
-
- lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
-
- childpi = create_procinfo (lwp_id);
-
- /* The new process has actually inherited the lwp_create syscall trap from
- it's parent, but we still have to call this to register handlers for
- that child. */
+#ifdef PRFS_STOPEXEC /* defined on OSF */
+ /* OSF method for tracing exec syscalls. Quoting:
+ Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
+ exits from exec system calls because of the user level loader. */
+ /* FIXME: make nice and maybe move into an access function. */
+ {
+ int prfs_flags;
- procfs_set_inferior_syscall_traps (childpi);
- add_thread (lwp_id);
- printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
+ if (ioctl (pi->ctl_fd, PIOCGSPCACT, &prfs_flags) < 0)
+ {
+ proc_warn (pi, "set_exec_trap (PIOCGSPCACT)", __LINE__);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ prfs_flags |= PRFS_STOPEXEC;
- /* Continue the parent */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
+ if (ioctl (pi->ctl_fd, PIOCSSPCACT, &prfs_flags) < 0)
+ {
+ proc_warn (pi, "set_exec_trap (PIOCSSPCACT)", __LINE__);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ }
+#else /* not PRFS_STOPEXEC */
+ /* Everyone else's (except OSF) method for tracing exec syscalls */
+ /* GW: Rationale...
+ Not all systems with /proc have all the exec* syscalls with the same
+ names. On the SGI, for example, there is no SYS_exec, but there
+ *is* a SYS_execv. So, we try to account for that. */
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
+ premptyset (&exitset);
+#ifdef SYS_exec
+ praddset (&exitset, SYS_exec);
+#endif
+#ifdef SYS_execve
+ praddset (&exitset, SYS_execve);
+#endif
+#ifdef SYS_execv
+ praddset (&exitset, SYS_execv);
#endif
- perror_with_name (pi->pathname);
-
- /* The new child may have been created in one of two states:
- SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
- If suspended, we flag it to be continued later, when it has an event. */
- if (THE_PR_LWP(childpi->prstatus).pr_why == PR_SUSPENDED)
- childpi->new_child = 1; /* Flag this as an unseen child process */
- else
+ if (!proc_set_traced_sysexit (pi, &exitset))
{
- /* Continue the child */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else
- childpi->prrun.pr_flags &= PRSTEP;
- childpi->prrun.pr_flags |= PRCFAULT;
-
- if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
-#endif
- perror_with_name (childpi->pathname);
+ proc_warn (pi, "set_exec_trap, set_traced_sysexit", __LINE__);
+ gdb_flush (gdb_stderr);
+ _exit (127);
}
- return 0;
+#endif /* PRFS_STOPEXEC */
+
+ /* FIXME: should this be done in the parent instead? */
+ /* Turn off inherit on fork flag so that all grand-children
+ of gdb start with tracing flags cleared. */
+ if (!proc_unset_inherit_on_fork (pi))
+ proc_warn (pi, "set_exec_trap, unset_inherit", __LINE__);
+
+ /* Turn off run on last close flag, so that the child process
+ cannot run away just because we close our handle on it.
+ We want it to wait for the parent to attach. */
+ if (!proc_unset_run_on_last_close (pi))
+ proc_warn (pi, "set_exec_trap, unset_RLC", __LINE__);
+
+ /* FIXME: No need to destroy the procinfo --
+ we have our own address space, and we're about to do an exec! */
+ /*destroy_procinfo (pi);*/
}
-#endif /* SYS_lwp_create */
-/* Fork an inferior process, and start debugging it with /proc. */
+/*
+ * Function: create_inferior
+ *
+ * This function is called BEFORE gdb forks the inferior process.
+ * Its only real responsibility is to set things up for the fork,
+ * and tell GDB which two functions to call after the fork (one
+ * for the parent, and one for the child).
+ *
+ * This function does a complicated search for a unix shell program,
+ * which it then uses to parse arguments and environment variables
+ * to be sent to the child. I wonder whether this code could not
+ * be abstracted out and shared with other unix targets such as
+ * infptrace?
+ */
static void
procfs_create_inferior (exec_file, allargs, env)
@@ -5508,13 +4785,14 @@ procfs_create_inferior (exec_file, allargs, env)
/* Not found. This must be an error rather than merely passing
the file to execlp(), because execlp() would try all the
exec()s, causing GDB to get confused. */
- error ("Can't find shell %s in PATH", shell_file);
+ error ("procfs:%d -- Can't find shell %s in PATH",
+ __LINE__, shell_file);
shell_file = tryname;
}
- fork_inferior (exec_file, allargs, env,
- proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
+ fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
+ procfs_init_inferior, NULL, shell_file);
/* We are at the first instruction we care about. */
/* Pedal to the metal... */
@@ -5522,243 +4800,459 @@ procfs_create_inferior (exec_file, allargs, env)
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
}
-/* Clean up after the inferior dies. */
+/*
+ * Function: notice_thread
+ *
+ * Callback for find_new_threads.
+ * Calls "add_thread".
+ */
-static void
-procfs_mourn_inferior ()
+static int
+procfs_notice_thread (pi, thread, ptr)
+ procinfo *pi;
+ procinfo *thread;
+ void *ptr;
{
- struct procinfo *pi;
- struct procinfo *next_pi;
+ int gdb_threadid = MERGEPID (pi->pid, thread->tid);
- for (pi = procinfo_list; pi; pi = next_pi)
- {
- next_pi = pi->next;
- unconditionally_kill_inferior (pi);
- }
+ if (!in_thread_list (gdb_threadid))
+ add_thread (gdb_threadid);
- unpush_target (&procfs_ops);
- generic_mourn_inferior ();
+ return 0;
+}
+
+/*
+ * Function: target_find_new_threads
+ *
+ * Query all the threads that the target knows about,
+ * and give them back to GDB to add to its list.
+ */
+
+void
+procfs_find_new_threads ()
+{
+ procinfo *pi;
+
+ /* Find procinfo for main process */
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ proc_update_threads (pi);
+ proc_iterate_over_threads (pi, procfs_notice_thread, NULL);
}
+/*
+ * Function: target_thread_alive
+ *
+ * Return true if the thread is still 'alive'.
+ *
+ * This guy doesn't really seem to be doing his job.
+ * Got to investigate how to tell when a thread is really gone.
+ */
-/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
static int
-procfs_can_run ()
+procfs_thread_alive (pid)
+ int pid;
{
- /* This variable is controlled by modules that sit atop procfs that may layer
- their own process structure atop that provided here. sol-thread.c does
- this because of the Solaris two-level thread model. */
+ int proc, thread;
+ procinfo *pi;
- return !procfs_suppress_run;
+ proc = PIDGET (pid);
+ thread = TIDGET (pid);
+ /* If I don't know it, it ain't alive! */
+ if ((pi = find_procinfo (proc, thread)) == NULL)
+ return 0;
+
+ /* If I can't get its status, it ain't alive!
+ What's more, I need to forget about it! */
+ if (!proc_get_status (pi))
+ {
+ destroy_procinfo (pi);
+ return 0;
+ }
+ /* I couldn't have got its status if it weren't alive, so it's alive. */
+ return 1;
}
-#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
-#ifndef UNIXWARE
-
-/* Insert a watchpoint */
-int
-procfs_set_watchpoint(pid, addr, len, rw)
- int pid;
- CORE_ADDR addr;
- int len;
- int rw;
+
+/*
+ * Function: target_pid_to_str
+ *
+ * Return a string to be used to identify the thread in
+ * the "info threads" display.
+ */
+
+char *
+procfs_pid_to_str (pid)
+ int pid;
{
- struct procinfo *pi;
- prwatch_t wpt;
-
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
- wpt.pr_vaddr = (caddr_t)addr;
- wpt.pr_size = len;
- wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
- if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
+ static char buf[80];
+ int proc, thread;
+ procinfo *pi;
+
+ proc = PIDGET (pid);
+ thread = TIDGET (pid);
+ pi = find_procinfo (proc, thread);
+
+ if (thread == 0)
+ sprintf (buf, "Process %d", proc);
+ else
+ sprintf (buf, "LWP %d", thread);
+ return &buf[0];
+}
+
+/*
+ * Function: procfs_set_watchpoint
+ * Insert a watchpoint
+ */
+
+int
+procfs_set_watchpoint (pid, addr, len, rwflag, after)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+ int rwflag;
+ int after;
+{
+#ifndef UNIXWARE
+ int pflags = 0;
+ procinfo *pi;
+
+ pi = find_procinfo_or_die (pid == -1 ?
+ PIDGET (inferior_pid) : PIDGET (pid), 0);
+
+ /* Translate from GDB's flags to /proc's */
+ if (len > 0) /* len == 0 means delete watchpoint */
{
- if (errno == E2BIG)
+ switch (rwflag) { /* FIXME: need an enum! */
+ case hw_write: /* default watchpoint (write) */
+ pflags = WRITE_WATCHFLAG;
+ break;
+ case hw_read: /* read watchpoint */
+ pflags = READ_WATCHFLAG;
+ break;
+ case hw_access: /* access watchpoint */
+ pflags = READ_WATCHFLAG | WRITE_WATCHFLAG;
+ break;
+ case hw_execute: /* execution HW breakpoint */
+ pflags = EXEC_WATCHFLAG;
+ break;
+ default: /* Something weird. Return error. */
return -1;
- /* Currently it sometimes happens that the same watchpoint gets
- deleted twice - don't die in this case (FIXME please) */
+ }
+ if (after) /* Stop after r/w access is completed. */
+ pflags |= AFTER_WATCHFLAG;
+ }
+
+ if (!proc_set_watchpoint (pi, addr, len, pflags))
+ {
+ if (errno == E2BIG) /* Typical error for no resources */
+ return -1; /* fail */
+ /* GDB may try to remove the same watchpoint twice.
+ If a remove request returns no match, don't error. */
if (errno == ESRCH && len == 0)
- return 0;
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSWATCH failed");
+ return 0; /* ignore */
+ proc_error (pi, "set_watchpoint", __LINE__);
}
+#endif
return 0;
}
+/*
+ * Function: stopped_by_watchpoint
+ *
+ * Returns non-zero if process is stopped on a hardware watchpoint fault,
+ * else returns zero.
+ */
+
int
-procfs_stopped_by_watchpoint(pid)
- int pid;
+procfs_stopped_by_watchpoint (pid)
+ int pid;
{
- struct procinfo *pi;
- short what;
- short why;
+ procinfo *pi;
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
- if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ pi = find_procinfo_or_die (pid == -1 ?
+ PIDGET (inferior_pid) : PIDGET (pid), 0);
+ if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
{
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
- if (why == PR_FAULTED
-#if defined (FLTWATCH) && defined (FLTKWATCH)
- && (what == FLTWATCH || what == FLTKWATCH)
-#else
+ if (proc_why (pi) == PR_FAULTED)
+ {
#ifdef FLTWATCH
- && (what == FLTWATCH)
+ if (proc_what (pi) == FLTWATCH)
+ return 1;
#endif
#ifdef FLTKWATCH
- && (what == FLTKWATCH)
-#endif
+ if (proc_what (pi) == FLTKWATCH)
+ return 1;
#endif
- )
- return what;
+ }
}
return 0;
}
-#endif /* !UNIXWARE */
-#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
-/* Why is this necessary? Shouldn't dead threads just be removed from the
- thread database? */
+#ifdef TM_I386SOL2_H
+/*
+ * Function: procfs_find_LDT_entry
+ *
+ * Input:
+ * int pid; // The GDB-style pid-plus-LWP.
+ *
+ * Return:
+ * pointer to the corresponding LDT entry.
+ */
-static int
-procfs_thread_alive (pid)
+struct ssd *
+procfs_find_LDT_entry (pid)
int pid;
{
- struct procinfo *pi, *next_pi;
+ gdb_gregset_t *gregs;
+ int key;
+ procinfo *pi;
- for (pi = procinfo_list; pi; pi = next_pi)
+ /* Find procinfo for the lwp. */
+ if ((pi = find_procinfo (PIDGET (pid), TIDGET (pid))) == NULL)
{
- next_pi = pi->next;
- if (pi -> pid == pid)
- if (procfs_read_status (pi)) /* alive */
- return 1;
- else /* defunct (exited) */
- {
- close_proc_file (pi);
- return 0;
- }
+ warning ("procfs_find_LDT_entry: could not find procinfi for %d.",
+ pid);
+ return NULL;
}
- return 0;
+ /* get its general registers. */
+ if ((gregs = proc_get_gregs (pi)) == NULL)
+ {
+ warning ("procfs_find_LDT_entry: could not read gregs for %d.",
+ pid);
+ return NULL;
+ }
+ /* Now extract the GS register's lower 16 bits. */
+ key = (*gregs)[GS] & 0xffff;
+
+ /* Find the matching entry and return it. */
+ return proc_get_LDT_entry (pi, key);
}
+#endif /* TM_I386SOL2_H */
-int
-procfs_first_available ()
+
+
+static void
+info_proc_cmd (args, from_tty)
+ char *args;
+ int from_tty;
{
- struct procinfo *pi;
+ struct cleanup *old_chain;
+ procinfo *process = NULL;
+ procinfo *thread = NULL;
+ char **argv = NULL;
+ char *tmp = NULL;
+ int pid = 0;
+ int tid = 0;
- for (pi = procinfo_list; pi; pi = pi->next)
+ old_chain = make_cleanup (null_cleanup, 0);
+ if (args)
+ {
+ if ((argv = buildargv (args)) == NULL)
+ nomem (0);
+ else
+ make_cleanup ((make_cleanup_func) freeargv, argv);
+ }
+ while (argv != NULL && *argv != NULL)
+ {
+ if (isdigit (argv[0][0]))
+ {
+ pid = strtoul (argv[0], &tmp, 10);
+ if (*tmp == '/')
+ tid = strtoul (++tmp, NULL, 10);
+ }
+ else if (argv[0][0] == '/')
+ {
+ tid = strtoul (argv[0] + 1, NULL, 10);
+ }
+ else
+ {
+ /* [...] */
+ }
+ argv++;
+ }
+ if (pid == 0)
+ pid = PIDGET (inferior_pid);
+ if (pid == 0)
+ error ("No current process: you must name one.");
+ else
+ {
+ /* Have pid, will travel.
+ First see if it's a process we're already debugging. */
+ process = find_procinfo (pid, 0);
+ if (process == NULL)
+ {
+ /* No. So open a procinfo for it, but
+ remember to close it again when finished. */
+ process = create_procinfo (pid, 0);
+ make_cleanup ((make_cleanup_func) destroy_procinfo, process);
+ if (!open_procinfo_files (process, FD_CTL))
+ proc_error (process, "info proc, open_procinfo_files", __LINE__);
+ }
+ }
+ if (tid != 0)
+ thread = create_procinfo (pid, tid);
+
+ if (process)
+ {
+ printf_filtered ("process %d flags:\n", process->pid);
+ proc_prettyprint_flags (proc_flags (process), 1);
+ if (proc_flags (process) & (PR_STOPPED | PR_ISTOP))
+ proc_prettyprint_why (proc_why (process), proc_what (process), 1);
+ if (proc_get_nthreads (process) > 1)
+ printf_filtered ("Process has %d threads.\n",
+ proc_get_nthreads (process));
+ }
+ if (thread)
{
- if (procfs_read_status (pi))
- return pi->pid;
+ printf_filtered ("thread %d flags:\n", thread->tid);
+ proc_prettyprint_flags (proc_flags (thread), 1);
+ if (proc_flags (thread) & (PR_STOPPED | PR_ISTOP))
+ proc_prettyprint_why (proc_why (thread), proc_what (thread), 1);
}
- return -1;
+
+ do_cleanups (old_chain);
}
-int
-procfs_get_pid_fd (pid)
- int pid;
+static void
+proc_trace_syscalls (args, from_tty, entry_or_exit, mode)
+ char *args;
+ int from_tty;
+ int entry_or_exit;
+ int mode;
{
- struct procinfo *pi = find_procinfo (pid, 1);
+ procinfo *pi;
+ sysset_t *sysset;
+ int syscallnum = 0;
- if (pi == NULL)
- return -1;
+ if (inferior_pid <= 0)
+ error ("you must be debugging a process to use this command.");
- return pi->ctl_fd;
-}
+ if (args == NULL || args[0] == 0)
+ error_no_arg ("system call to trace");
-/* Send a SIGINT to the process group. This acts just like the user typed a
- ^C on the controlling terminal.
+ pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ if (isdigit (args[0]))
+ {
+ syscallnum = atoi (args);
+ if (entry_or_exit == PR_SYSENTRY)
+ sysset = proc_get_traced_sysentry (pi, NULL);
+ else
+ sysset = proc_get_traced_sysexit (pi, NULL);
- XXX - This may not be correct for all systems. Some may want to use
- killpg() instead of kill (-pgrp). */
+ if (sysset == NULL)
+ proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
-static void
-procfs_stop ()
+ if (mode == FLAG_SET)
+ praddset (sysset, syscallnum);
+ else
+ prdelset (sysset, syscallnum);
+
+ if (entry_or_exit == PR_SYSENTRY)
+ {
+ if (!proc_set_traced_sysentry (pi, sysset))
+ proc_error (pi, "proc-trace, set_traced_sysentry", __LINE__);
+ }
+ else
+ {
+ if (!proc_set_traced_sysexit (pi, sysset))
+ proc_error (pi, "proc-trace, set_traced_sysexit", __LINE__);
+ }
+ }
+}
+
+static void
+proc_trace_sysentry_cmd (args, from_tty)
+ char *args;
+ int from_tty;
{
- extern pid_t inferior_process_group;
+ proc_trace_syscalls (args, from_tty, PR_SYSENTRY, FLAG_SET);
+}
- kill (-inferior_process_group, SIGINT);
+static void
+proc_trace_sysexit_cmd (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_SET);
}
-
-/* Convert a pid to printable form. */
-#ifdef TIDGET
-char *
-procfs_pid_to_str (pid)
- int pid;
+static void
+proc_untrace_sysentry_cmd (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ proc_trace_syscalls (args, from_tty, PR_SYSENTRY, FLAG_RESET);
+}
+
+static void
+proc_untrace_sysexit_cmd (args, from_tty)
+ char *args;
+ int from_tty;
{
- static char buf[100];
+ proc_trace_syscalls (args, from_tty, PR_SYSEXIT, FLAG_RESET);
+}
- sprintf (buf, "Kernel thread %d", TIDGET (pid));
- return buf;
+int
+mapping_test (fd, core_addr)
+ int fd;
+ CORE_ADDR core_addr;
+{
+ printf ("File descriptor %d, base address 0x%08x\n", fd, core_addr);
+ if (fd > 0)
+ close (fd);
+ return 0;
}
-#endif /* TIDGET */
-
-static void
-init_procfs_ops ()
+void
+test_mapping_cmd (args, from_tty)
+ char *args;
+ int from_tty;
{
- procfs_ops.to_shortname = "procfs";
- procfs_ops.to_longname = "Unix /proc child process";
- procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
- procfs_ops.to_open = procfs_open;
- procfs_ops.to_attach = procfs_attach;
- procfs_ops.to_detach = procfs_detach;
- procfs_ops.to_resume = procfs_resume;
- procfs_ops.to_wait = procfs_wait;
- procfs_ops.to_fetch_registers = procfs_fetch_registers;
- procfs_ops.to_store_registers = procfs_store_registers;
- procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
- procfs_ops.to_xfer_memory = procfs_xfer_memory;
- procfs_ops.to_files_info = procfs_files_info;
- procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
- procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
- procfs_ops.to_terminal_init = terminal_init_inferior;
- procfs_ops.to_terminal_inferior = terminal_inferior;
- procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
- procfs_ops.to_terminal_ours = terminal_ours;
- procfs_ops.to_terminal_info = child_terminal_info;
- procfs_ops.to_kill = procfs_kill_inferior;
- procfs_ops.to_create_inferior = procfs_create_inferior;
- procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
- procfs_ops.to_can_run = procfs_can_run;
- procfs_ops.to_notice_signals = procfs_notice_signals;
- procfs_ops.to_thread_alive = procfs_thread_alive;
- procfs_ops.to_stop = procfs_stop;
- procfs_ops.to_stratum = process_stratum;
- procfs_ops.to_has_all_memory = 1;
- procfs_ops.to_has_memory = 1;
- procfs_ops.to_has_stack = 1;
- procfs_ops.to_has_registers = 1;
- procfs_ops.to_has_execution = 1;
- procfs_ops.to_magic = OPS_MAGIC;
+ int ret;
+ ret = proc_iterate_over_mappings (mapping_test);
+ printf ("iterate_over_mappings returned %d.\n", ret);
}
void
_initialize_procfs ()
{
-#ifdef HAVE_OPTIONAL_PROC_FS
- char procname[MAX_PROC_NAME_SIZE];
- int fd;
-
- /* If we have an optional /proc filesystem (e.g. under OSF/1),
- don't add procfs support if we cannot access the running
- GDB via /proc. */
- sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
- if ((fd = open (procname, O_RDONLY)) < 0)
- return;
- close (fd);
-#endif
-
init_procfs_ops ();
add_target (&procfs_ops);
+ add_info ("proc", info_proc_cmd,
+ "Show /proc process information about any running process.\
+Default is the process being debugged.");
+ add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd,
+ "Give a trace of entries into the syscall.");
+ add_com ("proc-trace-exit", no_class, proc_trace_sysexit_cmd,
+ "Give a trace of exits from the syscall.");
+ add_com ("proc-untrace-entry", no_class, proc_untrace_sysentry_cmd,
+ "Cancel a trace of entries into the syscall.");
+ add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd,
+ "Cancel a trace of exits from the syscall.");
+
+ add_com ("test-mapping", no_class, test_mapping_cmd,
+ "test iterate-over-mappings");
+}
+
+/* =================== END, GDB "MODULE" =================== */
+
- add_info ("processes", info_proc,
-"Show process status information using /proc entry.\n\
-Specify process id or use current inferior by default.\n\
-Specify keywords for detailed information; default is summary.\n\
-Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\
-`status', `syscalls', and `times'.\n\
-Unambiguous abbreviations may be used.");
- init_syscall_table ();
+/* miscelaneous stubs: */
+/* The following satisfy a few random symbols mostly created by */
+/* the solaris threads implementation, which I will chase down */
+/* later. */
+
+/*
+ * Return a pid for which we guarantee
+ * we will be able to find a 'live' procinfo.
+ */
+
+int
+procfs_first_available ()
+{
+ if (procinfo_list)
+ return procinfo_list->pid;
+ else
+ return -1;
}
diff --git a/contrib/gdb/gdb/remote-mips.c b/contrib/gdb/gdb/remote-mips.c
index c92f8b7..efafd6d 100644
--- a/contrib/gdb/gdb/remote-mips.c
+++ b/contrib/gdb/gdb/remote-mips.c
@@ -1,29 +1,30 @@
/* Remote debugging interface for MIPS remote debugging protocol.
- Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1993-1995, 2000 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Ian Lance Taylor
<ian@cygnus.com>.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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 "bfd.h"
#include "symfile.h"
-#include "wait.h"
+#include "gdb_wait.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "serial.h"
@@ -34,31 +35,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
/* Microsoft C's stat.h doesn't define all the POSIX file modes. */
#ifndef S_IROTH
#define S_IROTH S_IREAD
#endif
-extern void mips_set_processor_type_command PARAMS ((char *, int));
-
+
/* Breakpoint types. Values 0, 1, and 2 must agree with the watch
types passed by breakpoint.c to target_insert_watchpoint.
Value 3 is our own invention, and is used for ordinary instruction
breakpoints. Value 4 is used to mark an unused watchpoint in tables. */
-enum break_type {
- BREAK_WRITE, /* 0 */
- BREAK_READ, /* 1 */
- BREAK_ACCESS, /* 2 */
- BREAK_FETCH, /* 3 */
- BREAK_UNUSED /* 4 */
-};
+enum break_type
+ {
+ BREAK_WRITE, /* 0 */
+ BREAK_READ, /* 1 */
+ BREAK_ACCESS, /* 2 */
+ BREAK_FETCH, /* 3 */
+ BREAK_UNUSED /* 4 */
+ };
/* Prototypes for local functions. */
@@ -82,8 +78,8 @@ static int mips_receive_packet PARAMS ((char *buff, int throw_error,
int timeout));
static CORE_ADDR mips_request PARAMS ((int cmd, CORE_ADDR addr,
- CORE_ADDR data, int *perr, int timeout,
- char *buff));
+ CORE_ADDR data, int *perr, int timeout,
+ char *buff));
static void mips_initialize PARAMS ((void));
@@ -102,7 +98,7 @@ static void mips_detach PARAMS ((char *args, int from_tty));
static void mips_resume PARAMS ((int pid, int step,
enum target_signal siggnal));
-static int mips_wait PARAMS ((int pid, struct target_waitstatus *status));
+static int mips_wait PARAMS ((int pid, struct target_waitstatus * status));
static int mips_map_regno PARAMS ((int regno));
@@ -118,9 +114,9 @@ static int mips_store_word PARAMS ((CORE_ADDR addr, unsigned int value,
char *old_contents));
static int mips_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
- int write, struct target_ops *ignore));
+ int write, struct target_ops * ignore));
-static void mips_files_info PARAMS ((struct target_ops *ignore));
+static void mips_files_info PARAMS ((struct target_ops * ignore));
static void mips_create_inferior PARAMS ((char *execfile, char *args,
char **env));
@@ -130,13 +126,13 @@ static void mips_mourn_inferior PARAMS ((void));
static int pmon_makeb64 PARAMS ((unsigned long v, char *p, int n, int *chksum));
static int pmon_zeroset PARAMS ((int recsize, char **buff, int *amount,
- unsigned int *chksum));
+ unsigned int *chksum));
static int pmon_checkset PARAMS ((int recsize, char **buff, int *value));
static void pmon_make_fastrec PARAMS ((char **outbuf, unsigned char *inbuf,
- int *inptr, int inamount, int *recsize,
- unsigned int *csum, unsigned int *zerofill));
+ int *inptr, int inamount, int *recsize,
+ unsigned int *csum, unsigned int *zerofill));
static int pmon_check_ack PARAMS ((char *mesg));
@@ -166,70 +162,72 @@ static int common_breakpoint PARAMS ((int set, CORE_ADDR addr, int len,
extern struct target_ops mips_ops;
extern struct target_ops pmon_ops;
extern struct target_ops ddb_ops;
-
+ /* *INDENT-OFF* */
/* The MIPS remote debugging interface is built on top of a simple
packet protocol. Each packet is organized as follows:
- SYN The first character is always a SYN (ASCII 026, or ^V). SYN
- may not appear anywhere else in the packet. Any time a SYN is
- seen, a new packet should be assumed to have begun.
+ SYN The first character is always a SYN (ASCII 026, or ^V). SYN
+ may not appear anywhere else in the packet. Any time a SYN is
+ seen, a new packet should be assumed to have begun.
TYPE_LEN
- This byte contains the upper five bits of the logical length
- of the data section, plus a single bit indicating whether this
- is a data packet or an acknowledgement. The documentation
- indicates that this bit is 1 for a data packet, but the actual
- board uses 1 for an acknowledgement. The value of the byte is
- 0x40 + (ack ? 0x20 : 0) + (len >> 6)
- (we always have 0 <= len < 1024). Acknowledgement packets do
- not carry data, and must have a data length of 0.
+ This byte contains the upper five bits of the logical length
+ of the data section, plus a single bit indicating whether this
+ is a data packet or an acknowledgement. The documentation
+ indicates that this bit is 1 for a data packet, but the actual
+ board uses 1 for an acknowledgement. The value of the byte is
+ 0x40 + (ack ? 0x20 : 0) + (len >> 6)
+ (we always have 0 <= len < 1024). Acknowledgement packets do
+ not carry data, and must have a data length of 0.
LEN1 This byte contains the lower six bits of the logical length of
- the data section. The value is
- 0x40 + (len & 0x3f)
-
- SEQ This byte contains the six bit sequence number of the packet.
- The value is
- 0x40 + seq
- An acknowlegment packet contains the sequence number of the
- packet being acknowledged plus 1 modulo 64. Data packets are
- transmitted in sequence. There may only be one outstanding
- unacknowledged data packet at a time. The sequence numbers
- are independent in each direction. If an acknowledgement for
- the previous packet is received (i.e., an acknowledgement with
- the sequence number of the packet just sent) the packet just
- sent should be retransmitted. If no acknowledgement is
- received within a timeout period, the packet should be
- retransmitted. This has an unfortunate failure condition on a
- high-latency line, as a delayed acknowledgement may lead to an
- endless series of duplicate packets.
-
- DATA The actual data bytes follow. The following characters are
- escaped inline with DLE (ASCII 020, or ^P):
- SYN (026) DLE S
- DLE (020) DLE D
- ^C (003) DLE C
- ^S (023) DLE s
- ^Q (021) DLE q
- The additional DLE characters are not counted in the logical
- length stored in the TYPE_LEN and LEN1 bytes.
+ the data section. The value is
+ 0x40 + (len & 0x3f)
+
+ SEQ This byte contains the six bit sequence number of the packet.
+ The value is
+ 0x40 + seq
+ An acknowlegment packet contains the sequence number of the
+ packet being acknowledged plus 1 modulo 64. Data packets are
+ transmitted in sequence. There may only be one outstanding
+ unacknowledged data packet at a time. The sequence numbers
+ are independent in each direction. If an acknowledgement for
+ the previous packet is received (i.e., an acknowledgement with
+ the sequence number of the packet just sent) the packet just
+ sent should be retransmitted. If no acknowledgement is
+ received within a timeout period, the packet should be
+ retransmitted. This has an unfortunate failure condition on a
+ high-latency line, as a delayed acknowledgement may lead to an
+ endless series of duplicate packets.
+
+ DATA The actual data bytes follow. The following characters are
+ escaped inline with DLE (ASCII 020, or ^P):
+ SYN (026) DLE S
+ DLE (020) DLE D
+ ^C (003) DLE C
+ ^S (023) DLE s
+ ^Q (021) DLE q
+ The additional DLE characters are not counted in the logical
+ length stored in the TYPE_LEN and LEN1 bytes.
CSUM1
CSUM2
CSUM3
- These bytes contain an 18 bit checksum of the complete
- contents of the packet excluding the SEQ byte and the
- CSUM[123] bytes. The checksum is simply the twos complement
- addition of all the bytes treated as unsigned characters. The
- values of the checksum bytes are:
- CSUM1: 0x40 + ((cksum >> 12) & 0x3f)
- CSUM2: 0x40 + ((cksum >> 6) & 0x3f)
- CSUM3: 0x40 + (cksum & 0x3f)
+ These bytes contain an 18 bit checksum of the complete
+ contents of the packet excluding the SEQ byte and the
+ CSUM[123] bytes. The checksum is simply the twos complement
+ addition of all the bytes treated as unsigned characters. The
+ values of the checksum bytes are:
+ CSUM1: 0x40 + ((cksum >> 12) & 0x3f)
+ CSUM2: 0x40 + ((cksum >> 6) & 0x3f)
+ CSUM3: 0x40 + (cksum & 0x3f)
It happens that the MIPS remote debugging protocol always
communicates with ASCII strings. Because of this, this
implementation doesn't bother to handle the DLE quoting mechanism,
since it will never be required. */
+/* *INDENT-ON* */
+
/* The SYN character which starts each packet. */
#define SYN '\026'
@@ -311,16 +309,17 @@ extern struct target_ops ddb_ops;
vector later. */
struct target_ops mips_ops, pmon_ops, ddb_ops, lsi_ops;
-enum mips_monitor_type {
- /* IDT/SIM monitor being used: */
- MON_IDT,
- /* PMON monitor being used: */
- MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] Algorithmics Ltd. Nov 9 1995 17:19:50 */
- MON_DDB, /* 2.7.473 [DDBVR4300,EL,FP,NET] Risq Modular Systems, Thu Jun 6 09:28:40 PDT 1996 */
- MON_LSI, /* 4.3.12 [EB,FP], LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */
- /* Last and unused value, for sizing vectors, etc. */
- MON_LAST
-};
+enum mips_monitor_type
+ {
+ /* IDT/SIM monitor being used: */
+ MON_IDT,
+ /* PMON monitor being used: */
+ MON_PMON, /* 3.0.83 [COGENT,EB,FP,NET] Algorithmics Ltd. Nov 9 1995 17:19:50 */
+ MON_DDB, /* 2.7.473 [DDBVR4300,EL,FP,NET] Risq Modular Systems, Thu Jun 6 09:28:40 PDT 1996 */
+ MON_LSI, /* 4.3.12 [EB,FP], LSI LOGIC Corp. Tue Feb 25 13:22:14 1997 */
+ /* Last and unused value, for sizing vectors, etc. */
+ MON_LAST
+ };
static enum mips_monitor_type mips_monitor = MON_LAST;
/* The monitor prompt text. If the user sets the PMON prompt
@@ -329,12 +328,12 @@ static enum mips_monitor_type mips_monitor = MON_LAST;
will not be able to connect to PMON in mips_initialize().
If the `set monitor-prompt' command is not used, the expected
default prompt will be set according the target:
- target prompt
- ----- -----
- pmon PMON>
- ddb NEC010>
- lsi PMON>
-*/
+ target prompt
+ ----- -----
+ pmon PMON>
+ ddb NEC010>
+ lsi PMON>
+ */
static char *mips_monitor_prompt;
/* Set to 1 if the target is open. */
@@ -394,11 +393,11 @@ static int interrupt_count;
static int mips_wait_flag = 0;
/* If non-zero, monitor supports breakpoint commands. */
-static monitor_supports_breakpoints = 0;
+static int monitor_supports_breakpoints = 0;
/* Data cache header. */
-#if 0 /* not used (yet?) */
+#if 0 /* not used (yet?) */
static DCACHE *mips_dcache;
#endif
@@ -408,52 +407,53 @@ static int hit_watchpoint;
/* Table of breakpoints/watchpoints (used only on LSI PMON target).
The table is indexed by a breakpoint number, which is an integer
from 0 to 255 returned by the LSI PMON when a breakpoint is set.
-*/
+ */
#define MAX_LSI_BREAKPOINTS 256
struct lsi_breakpoint_info
-{
- enum break_type type; /* type of breakpoint */
- CORE_ADDR addr; /* address of breakpoint */
- int len; /* length of region being watched */
- unsigned long value; /* value to watch */
-} lsi_breakpoints [MAX_LSI_BREAKPOINTS];
+ {
+ enum break_type type; /* type of breakpoint */
+ CORE_ADDR addr; /* address of breakpoint */
+ int len; /* length of region being watched */
+ unsigned long value; /* value to watch */
+ }
+lsi_breakpoints[MAX_LSI_BREAKPOINTS];
/* Error/warning codes returned by LSI PMON for breakpoint commands.
Warning values may be ORed together; error values may not. */
-#define W_WARN 0x100 /* This bit is set if the error code is a warning */
-#define W_MSK 0x101 /* warning: Range feature is supported via mask */
-#define W_VAL 0x102 /* warning: Value check is not supported in hardware */
-#define W_QAL 0x104 /* warning: Requested qualifiers are not supported in hardware */
-
-#define E_ERR 0x200 /* This bit is set if the error code is an error */
-#define E_BPT 0x200 /* error: No such breakpoint number */
-#define E_RGE 0x201 /* error: Range is not supported */
-#define E_QAL 0x202 /* error: The requested qualifiers can not be used */
-#define E_OUT 0x203 /* error: Out of hardware resources */
-#define E_NON 0x204 /* error: Hardware breakpoint not supported */
+#define W_WARN 0x100 /* This bit is set if the error code is a warning */
+#define W_MSK 0x101 /* warning: Range feature is supported via mask */
+#define W_VAL 0x102 /* warning: Value check is not supported in hardware */
+#define W_QAL 0x104 /* warning: Requested qualifiers are not supported in hardware */
+
+#define E_ERR 0x200 /* This bit is set if the error code is an error */
+#define E_BPT 0x200 /* error: No such breakpoint number */
+#define E_RGE 0x201 /* error: Range is not supported */
+#define E_QAL 0x202 /* error: The requested qualifiers can not be used */
+#define E_OUT 0x203 /* error: Out of hardware resources */
+#define E_NON 0x204 /* error: Hardware breakpoint not supported */
struct lsi_error
-{
- int code; /* error code */
- char *string; /* string associated with this code */
-};
+ {
+ int code; /* error code */
+ char *string; /* string associated with this code */
+ };
struct lsi_error lsi_warning_table[] =
{
- { W_MSK, "Range feature is supported via mask" },
- { W_VAL, "Value check is not supported in hardware" },
- { W_QAL, "Requested qualifiers are not supported in hardware" },
- { 0, NULL }
+ {W_MSK, "Range feature is supported via mask"},
+ {W_VAL, "Value check is not supported in hardware"},
+ {W_QAL, "Requested qualifiers are not supported in hardware"},
+ {0, NULL}
};
struct lsi_error lsi_error_table[] =
-{
- { E_BPT, "No such breakpoint number" },
- { E_RGE, "Range is not supported" },
- { E_QAL, "The requested qualifiers can not be used" },
- { E_OUT, "Out of hardware resources" },
- { E_NON, "Hardware breakpoint not supported" },
- { 0, NULL }
+{
+ {E_BPT, "No such breakpoint number"},
+ {E_RGE, "Range is not supported"},
+ {E_QAL, "The requested qualifiers can not be used"},
+ {E_OUT, "Out of hardware resources"},
+ {E_NON, "Hardware breakpoint not supported"},
+ {0, NULL}
};
/* Set to 1 with the 'set monitor-warnings' command to enable printing
@@ -462,7 +462,7 @@ static int monitor_warnings;
static void
-close_ports()
+close_ports ()
{
mips_is_open = 0;
SERIAL_CLOSE (mips_desc);
@@ -474,32 +474,21 @@ close_ports()
}
tftp_in_use = 0;
}
-
+
/* Handle low-level error that we can't recover from. Note that just
error()ing out from target_wait or some such low-level place will cause
all hell to break loose--the rest of GDB will tend to get left in an
inconsistent state. */
static NORETURN void
-#ifdef ANSI_PROTOTYPES
-mips_error (char *string, ...)
-#else
-mips_error (va_alist)
- va_dcl
-#endif
+mips_error (char *string,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, string);
-#else
- char *string;
- va_start (args);
- string = va_arg (args, char *);
-#endif
-
+
target_terminal_ours ();
- wrap_here(""); /* Force out any buffered output */
+ wrap_here (""); /* Force out any buffered output */
gdb_flush (gdb_stdout);
if (error_pre_print)
fprintf_filtered (gdb_stderr, error_pre_print);
@@ -523,19 +512,20 @@ mips_error (va_alist)
^x notation or in hex. */
static void
-putc_readable (ch)
+fputc_readable (ch, file)
int ch;
+ struct ui_file *file;
{
if (ch == '\n')
- putchar_unfiltered ('\n');
+ fputc_unfiltered ('\n', file);
else if (ch == '\r')
- printf_unfiltered ("\\r");
- else if (ch < 0x20) /* ASCII control character */
- printf_unfiltered ("^%c", ch + '@');
- else if (ch >= 0x7f) /* non-ASCII characters (rubout or greater) */
- printf_unfiltered ("[%02x]", ch & 0xff);
+ fprintf_unfiltered (file, "\\r");
+ else if (ch < 0x20) /* ASCII control character */
+ fprintf_unfiltered (file, "^%c", ch + '@');
+ else if (ch >= 0x7f) /* non-ASCII characters (rubout or greater) */
+ fprintf_unfiltered (file, "[%02x]", ch & 0xff);
else
- putchar_unfiltered (ch);
+ fputc_unfiltered (ch, file);
}
@@ -543,19 +533,20 @@ putc_readable (ch)
^x notation or in hex. */
static void
-puts_readable (string)
+fputs_readable (string, file)
char *string;
+ struct ui_file *file;
{
int c;
while ((c = *string++) != '\0')
- putc_readable (c);
+ fputc_readable (c, file);
}
/* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if
timed out. TIMEOUT specifies timeout value in seconds.
-*/
+ */
int
mips_expect_timeout (string, timeout)
@@ -566,9 +557,9 @@ mips_expect_timeout (string, timeout)
if (remote_debug)
{
- printf_unfiltered ("Expected \"");
- puts_readable (string);
- printf_unfiltered ("\", got \"");
+ fprintf_unfiltered (gdb_stdlog, "Expected \"");
+ fputs_readable (string, gdb_stdlog);
+ fprintf_unfiltered (gdb_stdlog, "\", got \"");
}
immediate_quit = 1;
@@ -584,20 +575,20 @@ mips_expect_timeout (string, timeout)
if (c == SERIAL_TIMEOUT)
{
if (remote_debug)
- printf_unfiltered ("\": FAIL\n");
+ fprintf_unfiltered (gdb_stdlog, "\": FAIL\n");
return 0;
}
if (remote_debug)
- putc_readable (c);
+ fputc_readable (c, gdb_stdlog);
if (c == *p++)
- {
+ {
if (*p == '\0')
{
immediate_quit = 0;
if (remote_debug)
- printf_unfiltered ("\": OK\n");
+ fprintf_unfiltered (gdb_stdlog, "\": OK\n");
return 1;
}
}
@@ -613,13 +604,13 @@ mips_expect_timeout (string, timeout)
/* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if
timed out. The timeout value is hard-coded to 2 seconds. Use
mips_expect_timeout if a different timeout value is needed.
-*/
+ */
int
mips_expect (string)
char *string;
{
- return mips_expect_timeout (string, 2);
+ return mips_expect_timeout (string, 2);
}
/* Read the required number of characters into the given buffer (which
@@ -637,11 +628,12 @@ mips_getstring (string, n)
{
c = SERIAL_READCHAR (mips_desc, 2);
- if (c == SERIAL_TIMEOUT) {
- fprintf_unfiltered (gdb_stderr,
- "Failed to read %d characters from target (TIMEOUT)\n", n);
- return 0;
- }
+ if (c == SERIAL_TIMEOUT)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Failed to read %d characters from target (TIMEOUT)\n", n);
+ return 0;
+ }
*p++ = c;
n--;
@@ -672,26 +664,24 @@ mips_readchar (timeout)
static int state = 0;
int mips_monitor_prompt_len = strlen (mips_monitor_prompt);
-#ifdef MAINTENANCE_CMDS
{
int i;
i = timeout;
if (i == -1 && watchdog > 0)
- i = watchdog;
+ i = watchdog;
}
-#endif
if (state == mips_monitor_prompt_len)
timeout = 1;
ch = SERIAL_READCHAR (mips_desc, timeout);
-#ifdef MAINTENANCE_CMDS
- if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */
+
+ if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */
{
target_mourn_inferior ();
error ("Watchdog has expired. Target detached.\n");
}
-#endif
+
if (ch == SERIAL_EOF)
mips_error ("End of file from remote");
if (ch == SERIAL_ERROR)
@@ -699,11 +689,11 @@ mips_readchar (timeout)
if (remote_debug > 1)
{
/* Don't use _filtered; we can't deal with a QUIT out of
- target_wait, and I think this might be called from there. */
+ target_wait, and I think this might be called from there. */
if (ch != SERIAL_TIMEOUT)
- printf_unfiltered ("Read '%c' %d 0x%x\n", ch, ch, ch);
+ fprintf_unfiltered (gdb_stdlog, "Read '%c' %d 0x%x\n", ch, ch, ch);
else
- printf_unfiltered ("Timed out in read\n");
+ fprintf_unfiltered (gdb_stdlog, "Timed out in read\n");
}
/* If we have seen mips_monitor_prompt and we either time out, or
@@ -713,13 +703,13 @@ mips_readchar (timeout)
more than 64 characters long, which ours never are. */
if ((ch == SERIAL_TIMEOUT || ch == '@')
&& state == mips_monitor_prompt_len
- && ! mips_initializing
- && ! mips_exiting)
+ && !mips_initializing
+ && !mips_exiting)
{
if (remote_debug > 0)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
- printf_unfiltered ("Reinitializing MIPS debugging mode\n");
+ fprintf_unfiltered (gdb_stdlog, "Reinitializing MIPS debugging mode\n");
mips_need_reply = 0;
mips_initialize ();
@@ -727,7 +717,7 @@ mips_readchar (timeout)
state = 0;
/* At this point, about the only thing we can do is abort the command
- in progress and get back to command level as quickly as possible. */
+ in progress and get back to command level as quickly as possible. */
error ("Remote board reset, debug protocol re-initialized.");
}
@@ -757,30 +747,30 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
while (1)
{
/* Wait for a SYN. mips_syn_garbage is intended to prevent
- sitting here indefinitely if the board sends us one garbage
- character per second. ch may already have a value from the
- last time through the loop. */
+ sitting here indefinitely if the board sends us one garbage
+ character per second. ch may already have a value from the
+ last time through the loop. */
while (ch != SYN)
{
ch = mips_readchar (timeout);
if (ch == SERIAL_TIMEOUT)
- return -1;
+ return -1;
if (ch != SYN)
{
/* Printing the character here lets the user of gdb see
- what the program is outputting, if the debugging is
- being done on the console port. Don't use _filtered;
- we can't deal with a QUIT out of target_wait. */
- if (! mips_initializing || remote_debug > 0)
+ what the program is outputting, if the debugging is
+ being done on the console port. Don't use _filtered;
+ we can't deal with a QUIT out of target_wait. */
+ if (!mips_initializing || remote_debug > 0)
{
- putc_readable (ch);
- gdb_flush (gdb_stdout);
+ fputc_readable (ch, gdb_stdlog);
+ gdb_flush (gdb_stdlog);
}
++*pgarbage;
if (mips_syn_garbage > 0
&& *pgarbage > mips_syn_garbage)
- mips_error ("Debug protocol failure: more than %d characters before a sync.",
+ mips_error ("Debug protocol failure: more than %d characters before a sync.",
mips_syn_garbage);
}
}
@@ -790,18 +780,18 @@ mips_receive_header (hdr, pgarbage, ch, timeout)
{
ch = mips_readchar (timeout);
if (ch == SERIAL_TIMEOUT)
- return -1;
+ return -1;
/* Make sure this is a header byte. */
- if (ch == SYN || ! HDR_CHECK (ch))
+ if (ch == SYN || !HDR_CHECK (ch))
break;
hdr[i] = ch;
}
/* If we got the complete header, we can return. Otherwise we
- loop around and keep looking for SYN. */
+ loop around and keep looking for SYN. */
if (i >= HDR_LENGTH)
- return 0;
+ return 0;
}
}
@@ -826,7 +816,7 @@ mips_receive_trailer (trlr, pgarbage, pch, timeout)
*pch = ch;
if (ch == SERIAL_TIMEOUT)
return -1;
- if (! TRLR_CHECK (ch))
+ if (!TRLR_CHECK (ch))
return -2;
trlr[i] = ch;
}
@@ -853,7 +843,7 @@ mips_cksum (hdr, data, len)
p = hdr + 1;
while (c-- != 0)
cksum += *p++;
-
+
c = len;
p = data;
while (c-- != 0)
@@ -909,14 +899,14 @@ mips_send_packet (s, get_ack)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
packet[HDR_LENGTH + len + TRLR_LENGTH] = '\0';
- printf_unfiltered ("Writing \"%s\"\n", packet + 1);
+ fprintf_unfiltered (gdb_stdlog, "Writing \"%s\"\n", packet + 1);
}
if (SERIAL_WRITE (mips_desc, packet,
HDR_LENGTH + len + TRLR_LENGTH) != 0)
mips_error ("write to target failed: %s", safe_strerror (errno));
- if (! get_ack)
+ if (!get_ack)
return;
garbage = 0;
@@ -940,36 +930,37 @@ mips_send_packet (s, get_ack)
ignore it. FIXME: If the acknowledgement is lost, this
data packet may be the packet the remote sends after the
acknowledgement. */
- if (HDR_IS_DATA (hdr)) {
- int i;
-
- /* Ignore any errors raised whilst attempting to ignore
- packet. */
-
- len = HDR_GET_LEN (hdr);
-
- for (i = 0; i < len; i++)
- {
- int rch;
-
- rch = mips_readchar (2);
- if (rch == SYN)
- {
- ch = SYN;
- break;
- }
- if (rch == SERIAL_TIMEOUT)
- break;
- /* ignore the character */
- }
-
- if (i == len)
- (void) mips_receive_trailer (trlr, &garbage, &ch, 2);
-
- /* We don't bother checking the checksum, or providing an
- ACK to the packet. */
- continue;
- }
+ if (HDR_IS_DATA (hdr))
+ {
+ int i;
+
+ /* Ignore any errors raised whilst attempting to ignore
+ packet. */
+
+ len = HDR_GET_LEN (hdr);
+
+ for (i = 0; i < len; i++)
+ {
+ int rch;
+
+ rch = mips_readchar (2);
+ if (rch == SYN)
+ {
+ ch = SYN;
+ break;
+ }
+ if (rch == SERIAL_TIMEOUT)
+ break;
+ /* ignore the character */
+ }
+
+ if (i == len)
+ (void) mips_receive_trailer (trlr, &garbage, &ch, 2);
+
+ /* We don't bother checking the checksum, or providing an
+ ACK to the packet. */
+ continue;
+ }
/* If the length is not 0, this is a garbled packet. */
if (HDR_GET_LEN (hdr) != 0)
@@ -998,9 +989,9 @@ mips_send_packet (s, get_ack)
hdr[HDR_LENGTH] = '\0';
trlr[TRLR_LENGTH] = '\0';
/* Don't use _filtered; we can't deal with a QUIT out of
- target_wait, and I think this might be called from there. */
- printf_unfiltered ("Got ack %d \"%s%s\"\n",
- HDR_GET_SEQ (hdr), hdr + 1, trlr);
+ target_wait, and I think this might be called from there. */
+ fprintf_unfiltered (gdb_stdlog, "Got ack %d \"%s%s\"\n",
+ HDR_GET_SEQ (hdr), hdr + 1, trlr);
}
/* If this ack is for the current packet, we're done. */
@@ -1062,21 +1053,21 @@ mips_receive_packet (buff, throw_error, timeout)
ch = 0;
/* An acknowledgement is probably a duplicate; ignore it. */
- if (! HDR_IS_DATA (hdr))
+ if (!HDR_IS_DATA (hdr))
{
- len = HDR_GET_LEN (hdr);
- /* Check if the length is valid for an ACK, we may aswell
- try and read the remainder of the packet: */
- if (len == 0)
- {
- /* Ignore the error condition, since we are going to
- ignore the packet anyway. */
- (void) mips_receive_trailer (trlr, &garbage, &ch, timeout);
- }
+ len = HDR_GET_LEN (hdr);
+ /* Check if the length is valid for an ACK, we may aswell
+ try and read the remainder of the packet: */
+ if (len == 0)
+ {
+ /* Ignore the error condition, since we are going to
+ ignore the packet anyway. */
+ (void) mips_receive_trailer (trlr, &garbage, &ch, timeout);
+ }
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
if (remote_debug > 0)
- printf_unfiltered ("Ignoring unexpected ACK\n");
+ fprintf_unfiltered (gdb_stdlog, "Ignoring unexpected ACK\n");
continue;
}
@@ -1106,8 +1097,9 @@ mips_receive_packet (buff, throw_error, timeout)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
if (remote_debug > 0)
- printf_unfiltered ("Got new SYN after %d chars (wanted %d)\n",
- i, len);
+ fprintf_unfiltered (gdb_stdlog,
+ "Got new SYN after %d chars (wanted %d)\n",
+ i, len);
continue;
}
@@ -1124,7 +1116,7 @@ mips_receive_packet (buff, throw_error, timeout)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
if (remote_debug > 0)
- printf_unfiltered ("Got SYN when wanted trailer\n");
+ fprintf_unfiltered (gdb_stdlog, "Got SYN when wanted trailer\n");
continue;
}
@@ -1134,23 +1126,24 @@ mips_receive_packet (buff, throw_error, timeout)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
if (remote_debug > 0)
- printf_unfiltered ("Ignoring sequence number %d (want %d)\n",
- HDR_GET_SEQ (hdr), mips_receive_seq);
+ fprintf_unfiltered (gdb_stdlog,
+ "Ignoring sequence number %d (want %d)\n",
+ HDR_GET_SEQ (hdr), mips_receive_seq);
continue;
}
if (mips_cksum (hdr, buff, len) == TRLR_GET_CKSUM (trlr))
- break;
+ break;
if (remote_debug > 0)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
printf_unfiltered ("Bad checksum; data %d, trailer %d\n",
- mips_cksum (hdr, buff, len),
- TRLR_GET_CKSUM (trlr));
+ mips_cksum (hdr, buff, len),
+ TRLR_GET_CKSUM (trlr));
/* The checksum failed. Send an acknowledgement for the
- previous packet to tell the remote to resend the packet. */
+ previous packet to tell the remote to resend the packet. */
ack[HDR_INDX_SYN] = HDR_SET_SYN (0, 0, mips_receive_seq);
ack[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (0, 0, mips_receive_seq);
ack[HDR_INDX_LEN1] = HDR_SET_LEN1 (0, 0, mips_receive_seq);
@@ -1168,7 +1161,7 @@ mips_receive_packet (buff, throw_error, timeout)
/* Don't use _filtered; we can't deal with a QUIT out of
target_wait, and I think this might be called from there. */
printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
- ack + 1);
+ ack + 1);
}
if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
@@ -1184,7 +1177,7 @@ mips_receive_packet (buff, throw_error, timeout)
{
buff[len] = '\0';
/* Don't use _filtered; we can't deal with a QUIT out of
- target_wait, and I think this might be called from there. */
+ target_wait, and I think this might be called from there. */
printf_unfiltered ("Got packet \"%s\"\n", buff);
}
@@ -1206,9 +1199,9 @@ mips_receive_packet (buff, throw_error, timeout)
{
ack[HDR_LENGTH + TRLR_LENGTH] = '\0';
/* Don't use _filtered; we can't deal with a QUIT out of
- target_wait, and I think this might be called from there. */
+ target_wait, and I think this might be called from there. */
printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
- ack + 1);
+ ack + 1);
}
if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
@@ -1228,15 +1221,15 @@ mips_receive_packet (buff, throw_error, timeout)
request has an ADDR argument and a DATA argument. The following
requests are defined:
- \0 don't send a request; just wait for a reply
- i read word from instruction space at ADDR
- d read word from data space at ADDR
- I write DATA to instruction space at ADDR
- D write DATA to data space at ADDR
- r read register number ADDR
- R set register number ADDR to value DATA
- c continue execution (if ADDR != 1, set pc to ADDR)
- s single step (if ADDR != 1, set pc to ADDR)
+ \0 don't send a request; just wait for a reply
+ i read word from instruction space at ADDR
+ d read word from data space at ADDR
+ I write DATA to instruction space at ADDR
+ D write DATA to data space at ADDR
+ r read register number ADDR
+ R set register number ADDR to value DATA
+ c continue execution (if ADDR != 1, set pc to ADDR)
+ s single step (if ADDR != 1, set pc to ADDR)
The read requests return the value requested. The write requests
return the previous value in the changed location. The execution
@@ -1247,7 +1240,7 @@ mips_receive_packet (buff, throw_error, timeout)
occurs, it sets *PERR to 1 and sets errno according to what the
target board reports. */
-static CORE_ADDR
+static CORE_ADDR
mips_request (cmd, addr, data, perr, timeout, buff)
int cmd;
CORE_ADDR addr;
@@ -1269,7 +1262,7 @@ mips_request (cmd, addr, data, perr, timeout, buff)
if (cmd != '\0')
{
if (mips_need_reply)
- fatal ("mips_request: Trying to send command before reply");
+ internal_error ("mips_request: Trying to send command before reply");
sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr_nz (addr), paddr_nz (data));
mips_send_packet (buff, 1);
mips_need_reply = 1;
@@ -1278,8 +1271,8 @@ mips_request (cmd, addr, data, perr, timeout, buff)
if (perr == (int *) NULL)
return 0;
- if (! mips_need_reply)
- fatal ("mips_request: Trying to get reply before command");
+ if (!mips_need_reply)
+ internal_error ("mips_request: Trying to get reply before command");
mips_need_reply = 0;
@@ -1296,9 +1289,9 @@ mips_request (cmd, addr, data, perr, timeout, buff)
*perr = 1;
/* FIXME: This will returns MIPS errno numbers, which may or may
- not be the same as errno values used on other systems. If
- they stick to common errno values, they will be the same, but
- if they don't, they must be translated. */
+ not be the same as errno values used on other systems. If
+ they stick to common errno values, they will be the same, but
+ if they don't, they must be translated. */
errno = rresponse;
return 0;
@@ -1327,7 +1320,7 @@ mips_send_command (cmd, prompt)
const char *cmd;
int prompt;
{
- SERIAL_WRITE (mips_desc, cmd, strlen(cmd));
+ SERIAL_WRITE (mips_desc, cmd, strlen (cmd));
mips_expect (cmd);
mips_expect ("\n");
if (prompt)
@@ -1344,10 +1337,10 @@ mips_enter_debug ()
if (mips_monitor != MON_IDT)
mips_send_command ("debug\r", 0);
- else /* assume IDT monitor by default */
+ else /* assume IDT monitor by default */
mips_send_command ("db tty0\r", 0);
- sleep(1);
+ sleep (1);
SERIAL_WRITE (mips_desc, "\r", sizeof "\r" - 1);
/* We don't need to absorb any spurious characters here, since the
@@ -1356,7 +1349,7 @@ mips_enter_debug ()
being displayed to the user. */
if (mips_monitor != MON_IDT)
mips_expect ("\r");
-
+
{
char buff[DATA_MAXLEN + 1];
if (mips_receive_packet (buff, 1, 3) < 0)
@@ -1378,14 +1371,14 @@ mips_exit_debug ()
/* The DDB (NEC) and MiniRISC (LSI) versions of PMON exit immediately,
so we do not get a reply to this command: */
mips_request ('x', (unsigned int) 0, (unsigned int) 0, NULL,
- mips_receive_wait, NULL);
+ mips_receive_wait, NULL);
mips_need_reply = 0;
if (!mips_expect (" break!"))
- return -1;
+ return -1;
}
else
mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
- mips_receive_wait, NULL);
+ mips_receive_wait, NULL);
if (!mips_expect (mips_monitor_prompt))
return -1;
@@ -1424,65 +1417,65 @@ mips_initialize ()
/* Force the system into the monitor. After this we *should* be at
the mips_monitor_prompt. */
if (mips_monitor != MON_IDT)
- j = 0; /* start by checking if we are already at the prompt */
+ j = 0; /* start by checking if we are already at the prompt */
else
- j = 1; /* start by sending a break */
+ j = 1; /* start by sending a break */
for (; j <= 4; j++)
{
switch (j)
{
- case 0: /* First, try sending a CR */
- SERIAL_FLUSH_INPUT (mips_desc);
+ case 0: /* First, try sending a CR */
+ SERIAL_FLUSH_INPUT (mips_desc);
SERIAL_WRITE (mips_desc, "\r", 1);
- break;
- case 1: /* First, try sending a break */
+ break;
+ case 1: /* First, try sending a break */
SERIAL_SEND_BREAK (mips_desc);
break;
- case 2: /* Then, try a ^C */
+ case 2: /* Then, try a ^C */
SERIAL_WRITE (mips_desc, "\003", 1);
break;
- case 3: /* Then, try escaping from download */
+ case 3: /* Then, try escaping from download */
{
- if (mips_monitor != MON_IDT)
- {
- char tbuff[7];
-
- /* We shouldn't need to send multiple termination
- sequences, since the target performs line (or
- block) reads, and then processes those
- packets. In-case we were downloading a large packet
- we flush the output buffer before inserting a
- termination sequence. */
- SERIAL_FLUSH_OUTPUT (mips_desc);
- sprintf (tbuff, "\r/E/E\r");
- SERIAL_WRITE (mips_desc, tbuff, 6);
- }
- else
- {
- char srec[10];
- int i;
-
- /* We are possibly in binary download mode, having
- aborted in the middle of an S-record. ^C won't
- work because of binary mode. The only reliable way
- out is to send enough termination packets (8 bytes)
- to fill up and then overflow the largest size
- S-record (255 bytes in this case). This amounts to
- 256/8 + 1 packets.
- */
-
- mips_make_srec (srec, '7', 0, NULL, 0);
-
- for (i = 1; i <= 33; i++)
- {
- SERIAL_WRITE (mips_desc, srec, 8);
-
- if (SERIAL_READCHAR (mips_desc, 0) >= 0)
- break; /* Break immediatly if we get something from
+ if (mips_monitor != MON_IDT)
+ {
+ char tbuff[7];
+
+ /* We shouldn't need to send multiple termination
+ sequences, since the target performs line (or
+ block) reads, and then processes those
+ packets. In-case we were downloading a large packet
+ we flush the output buffer before inserting a
+ termination sequence. */
+ SERIAL_FLUSH_OUTPUT (mips_desc);
+ sprintf (tbuff, "\r/E/E\r");
+ SERIAL_WRITE (mips_desc, tbuff, 6);
+ }
+ else
+ {
+ char srec[10];
+ int i;
+
+ /* We are possibly in binary download mode, having
+ aborted in the middle of an S-record. ^C won't
+ work because of binary mode. The only reliable way
+ out is to send enough termination packets (8 bytes)
+ to fill up and then overflow the largest size
+ S-record (255 bytes in this case). This amounts to
+ 256/8 + 1 packets.
+ */
+
+ mips_make_srec (srec, '7', 0, NULL, 0);
+
+ for (i = 1; i <= 33; i++)
+ {
+ SERIAL_WRITE (mips_desc, srec, 8);
+
+ if (SERIAL_READCHAR (mips_desc, 0) >= 0)
+ break; /* Break immediatly if we get something from
the board. */
- }
- }
- }
+ }
+ }
+ }
break;
case 4:
mips_error ("Failed to initialize.");
@@ -1496,7 +1489,7 @@ mips_initialize ()
{
/* Sometimes PMON ignores the first few characters in the first
command sent after a load. Sending a blank command gets
- around that. */
+ around that. */
mips_send_command ("\r", -1);
/* Ensure the correct target state: */
@@ -1548,26 +1541,26 @@ common_open (ops, name, from_tty, new_monitor, new_monitor_prompt)
if (name == 0)
error (
-"To open a MIPS remote debugging connection, you need to specify what serial\n\
+ "To open a MIPS remote debugging connection, you need to specify what serial\n\
device is attached to the target board (e.g., /dev/ttya).\n"
-"If you want to use TFTP to download to the board, specify the name of a\n"
-"temporary file to be used by GDB for downloads as the second argument.\n"
-"This filename must be in the form host:filename, where host is the name\n"
-"of the host running the TFTP server, and the file must be readable by the\n"
-"world. If the local name of the temporary file differs from the name as\n"
-"seen from the board via TFTP, specify that name as the third parameter.\n");
+ "If you want to use TFTP to download to the board, specify the name of a\n"
+ "temporary file to be used by GDB for downloads as the second argument.\n"
+ "This filename must be in the form host:filename, where host is the name\n"
+ "of the host running the TFTP server, and the file must be readable by the\n"
+ "world. If the local name of the temporary file differs from the name as\n"
+ "seen from the board via TFTP, specify that name as the third parameter.\n");
/* Parse the serial port name, the optional TFTP name, and the
optional local TFTP name. */
if ((argv = buildargv (name)) == NULL)
- nomem(0);
- make_cleanup ((make_cleanup_func) freeargv, argv);
+ nomem (0);
+ make_cleanup_freeargv (argv);
serial_port_name = strsave (argv[0]);
- if (argv[1]) /* remote TFTP name specified? */
+ if (argv[1]) /* remote TFTP name specified? */
{
remote_name = argv[1];
- if (argv[2]) /* local TFTP filename specified? */
+ if (argv[2]) /* local TFTP filename specified? */
local_name = argv[2];
}
@@ -1584,10 +1577,10 @@ device is attached to the target board (e.g., /dev/ttya).\n"
if (baud_rate != -1)
{
if (SERIAL_SETBAUDRATE (mips_desc, baud_rate))
- {
- SERIAL_CLOSE (mips_desc);
- perror_with_name (serial_port_name);
- }
+ {
+ SERIAL_CLOSE (mips_desc);
+ perror_with_name (serial_port_name);
+ }
}
SERIAL_RAW (mips_desc);
@@ -1615,8 +1608,8 @@ device is attached to the target board (e.g., /dev/ttya).\n"
if (tftp_localname)
free (tftp_localname);
if (local_name == NULL)
- if ((local_name = strchr (remote_name, ':')) != NULL)
- local_name++; /* skip over the colon */
+ if ((local_name = strchr (remote_name, ':')) != NULL)
+ local_name++; /* skip over the colon */
if (local_name == NULL)
local_name = remote_name; /* local name same as remote name */
tftp_name = strsave (remote_name);
@@ -1696,7 +1689,7 @@ lsi_open (name, from_tty)
/* Clear the LSI breakpoint table. */
for (i = 0; i < MAX_LSI_BREAKPOINTS; i++)
lsi_breakpoints[i].type = BREAK_UNUSED;
-
+
common_open (&lsi_ops, name, from_tty, MON_LSI, "PMON> ");
}
@@ -1794,7 +1787,7 @@ mips_wait (pid, status)
/* If we have not sent a single step or continue command, then the
board is waiting for us to do something. Return a status
indicating that it is stopped. */
- if (! mips_need_reply)
+ if (!mips_need_reply)
{
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
@@ -1835,7 +1828,7 @@ mips_wait (pid, status)
supply_register (PC_REGNUM, buf);
store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rfp);
- supply_register (30, buf); /* This register they are avoiding and so it is unnamed */
+ supply_register (30, buf); /* This register they are avoiding and so it is unnamed */
store_unsigned_integer (buf, REGISTER_RAW_SIZE (SP_REGNUM), rsp);
supply_register (SP_REGNUM, buf);
@@ -1859,13 +1852,13 @@ mips_wait (pid, status)
{
#if 0
/* If this is an LSI PMON target, see if we just hit a hardrdware watchpoint.
- Right now, PMON doesn't give us enough information to determine which
- breakpoint we hit. So we have to look up the PC in our own table
- of breakpoints, and if found, assume it's just a normal instruction
- fetch breakpoint, not a data watchpoint. FIXME when PMON
- provides some way to tell us what type of breakpoint it is. */
+ Right now, PMON doesn't give us enough information to determine which
+ breakpoint we hit. So we have to look up the PC in our own table
+ of breakpoints, and if found, assume it's just a normal instruction
+ fetch breakpoint, not a data watchpoint. FIXME when PMON
+ provides some way to tell us what type of breakpoint it is. */
int i;
- CORE_ADDR pc = read_pc();
+ CORE_ADDR pc = read_pc ();
hit_watchpoint = 1;
for (i = 0; i < MAX_LSI_BREAKPOINTS; i++)
@@ -1879,22 +1872,22 @@ mips_wait (pid, status)
}
#else
/* If a data breakpoint was hit, PMON returns the following packet:
- 0x1 c 0x0 0x57f 0x1
- The return packet from an ordinary breakpoint doesn't have the
- extra 0x01 field tacked onto the end. */
+ 0x1 c 0x0 0x57f 0x1
+ The return packet from an ordinary breakpoint doesn't have the
+ extra 0x01 field tacked onto the end. */
if (nfields == 1 && rpc == 1)
hit_watchpoint = 1;
#endif
}
/* NOTE: The following (sig) numbers are defined by PMON:
- SPP_SIGTRAP 5 breakpoint
- SPP_SIGINT 2
- SPP_SIGSEGV 11
- SPP_SIGBUS 10
- SPP_SIGILL 4
- SPP_SIGFPE 8
- SPP_SIGTERM 15 */
+ SPP_SIGTRAP 5 breakpoint
+ SPP_SIGINT 2
+ SPP_SIGSEGV 11
+ SPP_SIGBUS 10
+ SPP_SIGILL 4
+ SPP_SIGFPE 8
+ SPP_SIGTERM 15 */
/* Translate a MIPS waitstatus. We use constants here rather than WTERMSIG
and so on, because the constants we want here are determined by the
@@ -1911,12 +1904,12 @@ mips_wait (pid, status)
/* If the stop PC is in the _exit function, assume
we hit the 'break 0x3ff' instruction in _exit, so this
- is not a normal breakpoint. */
+ is not a normal breakpoint. */
if (strcmp (target_shortname, "lsi") == 0)
{
char *func_name;
CORE_ADDR func_start;
- CORE_ADDR pc = read_pc();
+ CORE_ADDR pc = read_pc ();
find_pc_partial_function (pc, &func_name, &func_start, NULL);
if (func_name != NULL && strcmp (func_name, "_exit") == 0
@@ -2000,11 +1993,11 @@ mips_fetch_registers (regno)
compiled without the 64bit register access commands. This
means we cannot get hold of the full register width. */
if (mips_monitor == MON_DDB)
- val = (unsigned)mips_request ('t', (unsigned int) pmon_reg,
- (unsigned int) 0, &err, mips_receive_wait, NULL);
+ val = (unsigned) mips_request ('t', (unsigned int) pmon_reg,
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
else
val = mips_request ('r', (unsigned int) pmon_reg,
- (unsigned int) 0, &err, mips_receive_wait, NULL);
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
if (err)
mips_error ("Can't read register %d: %s", regno,
safe_strerror (errno));
@@ -2053,7 +2046,7 @@ mips_store_registers (regno)
/* Fetch a word from the target board. */
-static unsigned int
+static unsigned int
mips_fetch_word (addr)
CORE_ADDR addr;
{
@@ -2070,8 +2063,8 @@ mips_fetch_word (addr)
val = mips_request ('i', addr, (unsigned int) 0, &err,
mips_receive_wait, NULL);
if (err)
- mips_error ("Can't read address 0x%s: %s",
- paddr_nz (addr), safe_strerror (errno));
+ mips_error ("Can't read address 0x%s: %s",
+ paddr_nz (addr), safe_strerror (errno));
}
return val;
}
@@ -2124,7 +2117,7 @@ mips_xfer_memory (memaddr, myaddr, len, write, ignore)
{
register int i;
/* Round starting address down to longword boundary. */
- register CORE_ADDR addr = memaddr &~ 3;
+ register CORE_ADDR addr = memaddr & ~3;
/* Round ending address up; get number of longwords that makes. */
register int count = (((memaddr + len) - addr) + 3) / 4;
/* Allocate buffer of that many longwords. */
@@ -2158,10 +2151,10 @@ mips_xfer_memory (memaddr, myaddr, len, write, ignore)
for (i = 0; i < count; i++, addr += 4)
{
status = mips_store_word (addr,
- extract_unsigned_integer (&buffer[i*4], 4),
+ extract_unsigned_integer (&buffer[i * 4], 4),
NULL);
/* Report each kilobyte (we download 32-bit words at a time) */
- if (i % 256 == 255)
+ if (i % 256 == 255)
{
printf_unfiltered ("*");
gdb_flush (gdb_stdout);
@@ -2181,7 +2174,7 @@ mips_xfer_memory (memaddr, myaddr, len, write, ignore)
/* Read all the longwords */
for (i = 0; i < count; i++, addr += 4)
{
- store_unsigned_integer (&buffer[i*4], 4, mips_fetch_word (addr));
+ store_unsigned_integer (&buffer[i * 4], 4, mips_fetch_word (addr));
QUIT;
}
@@ -2226,7 +2219,7 @@ Give up (and stop debugging it)? "))
board (it almost surely won't work since we weren't able to talk to
it). */
mips_wait_flag = 0;
- close_ports();
+ close_ports ();
printf_unfiltered ("Ending remote MIPS debugging.\n");
target_mourn_inferior ();
@@ -2329,14 +2322,14 @@ mips_remove_breakpoint (addr, contents_cache)
return memory_remove_breakpoint (addr, contents_cache);
}
-#if 0 /* currently not used */
+#if 0 /* currently not used */
/* PMON does not currently provide support for the debug mode 'b'
commands to manipulate breakpoints. However, if we wanted to use
the monitor breakpoints (rather than the GDB BREAK_INSN version)
then this code performs the work needed to leave debug mode,
set/clear the breakpoint, and then return to debug mode. */
-#define PMON_MAX_BP (33) /* 32 SW, 1 HW */
+#define PMON_MAX_BP (33) /* 32 SW, 1 HW */
static CORE_ADDR mips_pmon_bp_info[PMON_MAX_BP];
/* NOTE: The code relies on this vector being zero-initialised by the system */
@@ -2349,13 +2342,13 @@ pmon_insert_breakpoint (addr, contents_cache)
if (monitor_supports_breakpoints)
{
- char tbuff[12]; /* space for breakpoint command */
+ char tbuff[12]; /* space for breakpoint command */
int bpnum;
CORE_ADDR bpaddr;
/* PMON does not support debug level breakpoint set/remove: */
if (mips_exit_debug ())
- mips_error ("Failed to exit debug mode");
+ mips_error ("Failed to exit debug mode");
sprintf (tbuff, "b %08x\r", addr);
mips_send_command (tbuff, 0);
@@ -2363,14 +2356,14 @@ pmon_insert_breakpoint (addr, contents_cache)
mips_expect ("Bpt ");
if (!mips_getstring (tbuff, 2))
- return 1;
- tbuff[2] = '\0'; /* terminate the string */
+ return 1;
+ tbuff[2] = '\0'; /* terminate the string */
if (sscanf (tbuff, "%d", &bpnum) != 1)
- {
- fprintf_unfiltered (gdb_stderr,
- "Invalid decimal breakpoint number from target: %s\n", tbuff);
- return 1;
- }
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Invalid decimal breakpoint number from target: %s\n", tbuff);
+ return 1;
+ }
mips_expect (" = ");
@@ -2381,26 +2374,26 @@ pmon_insert_breakpoint (addr, contents_cache)
/* FIXME!! only 8 bytes! need to expand for Bfd64;
which targets return 64-bit addresses? PMON returns only 32! */
if (!mips_getstring (&tbuff[2], 8))
- return 1;
- tbuff[10] = '\0'; /* terminate the string */
+ return 1;
+ tbuff[10] = '\0'; /* terminate the string */
if (sscanf (tbuff, "0x%08x", &bpaddr) != 1)
- {
- fprintf_unfiltered (gdb_stderr,
- "Invalid hex address from target: %s\n", tbuff);
- return 1;
- }
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Invalid hex address from target: %s\n", tbuff);
+ return 1;
+ }
if (bpnum >= PMON_MAX_BP)
- {
- fprintf_unfiltered (gdb_stderr,
+ {
+ fprintf_unfiltered (gdb_stderr,
"Error: Returned breakpoint number %d outside acceptable range (0..%d)\n",
- bpnum, PMON_MAX_BP - 1);
- return 1;
- }
+ bpnum, PMON_MAX_BP - 1);
+ return 1;
+ }
if (bpaddr != addr)
- fprintf_unfiltered (gdb_stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr);
+ fprintf_unfiltered (gdb_stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr);
mips_pmon_bp_info[bpnum] = bpaddr;
@@ -2423,22 +2416,22 @@ pmon_remove_breakpoint (addr, contents_cache)
if (monitor_supports_breakpoints)
{
int bpnum;
- char tbuff[7]; /* enough for delete breakpoint command */
+ char tbuff[7]; /* enough for delete breakpoint command */
for (bpnum = 0; bpnum < PMON_MAX_BP; bpnum++)
- if (mips_pmon_bp_info[bpnum] == addr)
- break;
+ if (mips_pmon_bp_info[bpnum] == addr)
+ break;
if (bpnum >= PMON_MAX_BP)
- {
- fprintf_unfiltered (gdb_stderr,
- "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n",
- paddr_nz (addr));
- return 1;
- }
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n",
+ paddr_nz (addr));
+ return 1;
+ }
if (mips_exit_debug ())
- mips_error ("Failed to exit debug mode");
+ mips_error ("Failed to exit debug mode");
sprintf (tbuff, "db %02d\r", bpnum);
@@ -2464,7 +2457,7 @@ int
remote_mips_can_use_hardware_watchpoint (cnt)
int cnt;
{
- return cnt < MAX_LSI_BREAKPOINTS && strcmp (target_shortname, "lsi") == 0;
+ return cnt < MAX_LSI_BREAKPOINTS && strcmp (target_shortname, "lsi") == 0;
}
@@ -2551,7 +2544,7 @@ remote_mips_remove_watchpoint (addr, len, type)
}
int
-remote_mips_stopped_by_watchpoint ()
+remote_mips_stopped_by_watchpoint (void)
{
return hit_watchpoint;
}
@@ -2611,14 +2604,14 @@ check_lsi_error (addr, rerrflg)
{
found = 1;
fprintf_unfiltered (gdb_stderr,
- "common_breakpoint (0x%s): Warning: %s\n",
+ "common_breakpoint (0x%s): Warning: %s\n",
saddr,
err->string);
}
}
if (!found)
fprintf_unfiltered (gdb_stderr,
- "common_breakpoint (0x%s): Unknown warning: 0x%x\n",
+ "common_breakpoint (0x%s): Unknown warning: 0x%x\n",
saddr,
rerrflg);
}
@@ -2651,10 +2644,10 @@ check_lsi_error (addr, rerrflg)
<ADDR> is the address of the breakpoint.
<LEN> the length of the region to break on.
<TYPE> is the type of breakpoint:
- 0 = write (BREAK_WRITE)
- 1 = read (BREAK_READ)
- 2 = read/write (BREAK_ACCESS)
- 3 = instruction fetch (BREAK_FETCH)
+ 0 = write (BREAK_WRITE)
+ 1 = read (BREAK_READ)
+ 2 = read/write (BREAK_ACCESS)
+ 3 = instruction fetch (BREAK_FETCH)
Return 0 if successful; otherwise 1. */
@@ -2674,12 +2667,12 @@ common_breakpoint (set, addr, len, type)
if (mips_monitor == MON_LSI)
{
- if (set == 0) /* clear breakpoint */
+ if (set == 0) /* clear breakpoint */
{
/* The LSI PMON "clear breakpoint" has this form:
- <pid> 'b' <bptn> 0x0
- reply:
- <pid> 'b' 0x0 <code>
+ <pid> 'b' <bptn> 0x0
+ reply:
+ <pid> 'b' 0x0 <code>
<bptn> is a breakpoint number returned by an earlier 'B' command.
Possible return codes: OK, E_BPT. */
@@ -2714,42 +2707,44 @@ common_breakpoint (set, addr, len, type)
return (check_lsi_error (addr, rerrflg));
}
- else /* set a breakpoint */
+ else
+ /* set a breakpoint */
{
/* The LSI PMON "set breakpoint" command has this form:
- <pid> 'B' <addr> 0x0
- reply:
- <pid> 'B' <bptn> <code>
+ <pid> 'B' <addr> 0x0
+ reply:
+ <pid> 'B' <bptn> <code>
The "set data breakpoint" command has this form:
- <pid> 'A' <addr1> <type> [<addr2> [<value>]]
+ <pid> 'A' <addr1> <type> [<addr2> [<value>]]
- where: type= "0x1" = read
- "0x2" = write
- "0x3" = access (read or write)
+ where: type= "0x1" = read
+ "0x2" = write
+ "0x3" = access (read or write)
The reply returns two values:
- bptn - a breakpoint number, which is a small integer with
- possible values of zero through 255.
- code - an error return code, a value of zero indicates a
- succesful completion, other values indicate various
- errors and warnings.
-
+ bptn - a breakpoint number, which is a small integer with
+ possible values of zero through 255.
+ code - an error return code, a value of zero indicates a
+ succesful completion, other values indicate various
+ errors and warnings.
+
Possible return codes: OK, W_QAL, E_QAL, E_OUT, E_NON.
- */
+ */
if (type == BREAK_FETCH) /* instruction breakpoint */
{
cmd = 'B';
sprintf (buf, "0x0 B 0x%s 0x0", paddr_nz (addr));
}
- else /* watchpoint */
+ else
+ /* watchpoint */
{
cmd = 'A';
sprintf (buf, "0x0 A 0x%s 0x%x 0x%s", paddr_nz (addr),
- type == BREAK_READ ? 1 : (type == BREAK_WRITE ? 2 : 3),
+ type == BREAK_READ ? 1 : (type == BREAK_WRITE ? 2 : 3),
paddr_nz (addr + len - 1));
}
mips_send_packet (buf, 1);
@@ -2770,7 +2765,7 @@ common_breakpoint (set, addr, len, type)
information for this breakpoint so we can clear it later. */
lsi_breakpoints[rresponse].type = type;
lsi_breakpoints[rresponse].addr = addr;
- lsi_breakpoints[rresponse].len = len;
+ lsi_breakpoints[rresponse].len = len;
return 0;
}
@@ -2778,30 +2773,30 @@ common_breakpoint (set, addr, len, type)
else
{
/* On non-LSI targets, the breakpoint command has this form:
- 0x0 <CMD> <ADDR> <MASK> <FLAGS>
- <MASK> is a don't care mask for addresses.
- <FLAGS> is any combination of `r', `w', or `f' for read/write/fetch.
+ 0x0 <CMD> <ADDR> <MASK> <FLAGS>
+ <MASK> is a don't care mask for addresses.
+ <FLAGS> is any combination of `r', `w', or `f' for read/write/fetch.
*/
unsigned long mask;
mask = calculate_mask (addr, len);
addr &= ~mask;
- if (set) /* set a breakpoint */
- {
+ if (set) /* set a breakpoint */
+ {
char *flags;
switch (type)
{
- case BREAK_WRITE: /* write */
+ case BREAK_WRITE: /* write */
flags = "w";
break;
- case BREAK_READ: /* read */
+ case BREAK_READ: /* read */
flags = "r";
break;
- case BREAK_ACCESS: /* read/write */
+ case BREAK_ACCESS: /* read/write */
flags = "rw";
break;
- case BREAK_FETCH: /* fetch */
+ case BREAK_FETCH: /* fetch */
flags = "f";
break;
default:
@@ -2836,9 +2831,9 @@ common_breakpoint (set, addr, len, type)
Cogent returns "0x0 b 0xffffffff 0x16\000": */
if (mips_monitor == MON_DDB)
rresponse = rerrflg;
- if (rresponse != 22) /* invalid argument */
+ if (rresponse != 22) /* invalid argument */
fprintf_unfiltered (gdb_stderr,
- "common_breakpoint (0x%s): Got error: 0x%x\n",
+ "common_breakpoint (0x%s): Got error: 0x%x\n",
paddr_nz (addr), rresponse);
return 1;
}
@@ -2868,7 +2863,7 @@ send_srec (srec, len, addr)
case 0x6: /* ACK */
return;
case 0x15: /* NACK */
- fprintf_unfiltered (gdb_stderr, "Download got a NACK at byte %d! Retrying.\n", addr);
+ fprintf_unfiltered (gdb_stderr, "Download got a NACK at byte %s! Retrying.\n", paddr_u (addr));
continue;
default:
error ("Download got unexpected ack char: 0x%x, retrying.\n", ch);
@@ -2914,9 +2909,10 @@ mips_load_srec (args)
{
unsigned int numbytes;
- /* FIXME! vma too small?? */
- printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
- s->vma + s->_raw_size);
+ /* FIXME! vma too small????? */
+ printf_filtered ("%s\t: 0x%4lx .. 0x%4lx ", s->name,
+ (long) s->vma,
+ (long) (s->vma + s->_raw_size));
gdb_flush (gdb_stdout);
for (i = 0; i < s->_raw_size; i += numbytes)
@@ -2934,14 +2930,14 @@ mips_load_srec (args)
gdb_flush (gdb_stdout);
}
- } /* Per-packet (or S-record) loop */
-
+ } /* Per-packet (or S-record) loop */
+
putchar_unfiltered ('\n');
- } /* Loadable sections */
+ } /* Loadable sections */
}
- if (hashmark)
+ if (hashmark)
putchar_unfiltered ('\n');
-
+
/* Write a type 7 terminator record. no data for a type 7, and there
is no data, so len is 0. */
@@ -2954,19 +2950,19 @@ mips_load_srec (args)
/*
* mips_make_srec -- make an srecord. This writes each line, one at a
- * time, each with it's own header and trailer line.
- * An srecord looks like this:
+ * time, each with it's own header and trailer line.
+ * An srecord looks like this:
*
* byte count-+ address
* start ---+ | | data +- checksum
- * | | | |
- * S01000006F6B692D746573742E73726563E4
- * S315000448600000000000000000FC00005900000000E9
- * S31A0004000023C1400037DE00F023604000377B009020825000348D
- * S30B0004485A0000000000004E
- * S70500040000F6
+ * | | | |
+ * S01000006F6B692D746573742E73726563E4
+ * S315000448600000000000000000FC00005900000000E9
+ * S31A0004000023C1400037DE00F023604000377B009020825000348D
+ * S30B0004485A0000000000004E
+ * S70500040000F6
*
- * S<type><length><address><data><checksum>
+ * S<type><length><address><data><checksum>
*
* Where
* - length
@@ -2989,7 +2985,7 @@ mips_load_srec (args)
* - data
* is the data.
* - checksum
- * is the sum of all the raw byte data in the record, from the length
+ * is the sum of all the raw byte data in the record, from the length
* upwards, modulo 256 and subtracted from 255.
*
* This routine returns the length of the S-record.
@@ -3045,13 +3041,13 @@ mips_make_srec (buf, type, memaddr, myaddr, len)
3byte data packets (encoded as 4 printable ASCII characters), and
escape sequences (preceded by a '/'):
- 'K' clear checksum
- 'C' compare checksum (12bit value, not included in checksum calculation)
- 'S' define symbol name (for addr) terminated with "," and padded to 4char boundary
- 'Z' zero fill multiple of 3bytes
- 'B' byte (12bit encoded value, of 8bit data)
- 'A' address (36bit encoded value)
- 'E' define entry as original address, and exit load
+ 'K' clear checksum
+ 'C' compare checksum (12bit value, not included in checksum calculation)
+ 'S' define symbol name (for addr) terminated with "," and padded to 4char boundary
+ 'Z' zero fill multiple of 3bytes
+ 'B' byte (12bit encoded value, of 8bit data)
+ 'A' address (36bit encoded value)
+ 'E' define entry as original address, and exit load
The packets are processed in 4 character chunks, so the escape
sequences that do not have any data (or variable length data)
@@ -3077,32 +3073,41 @@ pmon_makeb64 (v, p, n, chksum)
{
int count = (n / 6);
- if ((n % 12) != 0) {
- fprintf_unfiltered(gdb_stderr,
- "Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s");
- return(0);
- }
- if (n > 36) {
- fprintf_unfiltered(gdb_stderr,
- "Fast encoding cannot process more than 36bits at the moment: %dbits\n",n);
- return(0);
- }
+ if ((n % 12) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n", n, (n == 1) ? "" : "s");
+ return (0);
+ }
+ if (n > 36)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Fast encoding cannot process more than 36bits at the moment: %dbits\n", n);
+ return (0);
+ }
/* Deal with the checksum: */
- if (chksum != NULL) {
- switch (n) {
- case 36: *chksum += ((v >> 24) & 0xFFF);
- case 24: *chksum += ((v >> 12) & 0xFFF);
- case 12: *chksum += ((v >> 0) & 0xFFF);
+ if (chksum != NULL)
+ {
+ switch (n)
+ {
+ case 36:
+ *chksum += ((v >> 24) & 0xFFF);
+ case 24:
+ *chksum += ((v >> 12) & 0xFFF);
+ case 12:
+ *chksum += ((v >> 0) & 0xFFF);
+ }
}
- }
- do {
- n -= 6;
- *p++ = encoding[(v >> n) & 0x3F];
- } while (n > 0);
+ do
+ {
+ n -= 6;
+ *p++ = encoding[(v >> n) & 0x3F];
+ }
+ while (n > 0);
- return(count);
+ return (count);
}
/* Shorthand function (that could be in-lined) to output the zero-fill
@@ -3116,11 +3121,11 @@ pmon_zeroset (recsize, buff, amount, chksum)
{
int count;
- sprintf(*buff,"/Z");
+ sprintf (*buff, "/Z");
count = pmon_makeb64 (*amount, (*buff + 2), 12, chksum);
*buff += (count + 2);
*amount = 0;
- return(recsize + count + 2);
+ return (recsize + count + 2);
}
static int
@@ -3136,10 +3141,10 @@ pmon_checkset (recsize, buff, value)
count = pmon_makeb64 (*value, (*buff + 2), 12, NULL);
*buff += (count + 2);
sprintf (*buff, "\n");
- *buff += 2; /* include zero terminator */
+ *buff += 2; /* include zero terminator */
/* Forcing a checksum validation clears the sum: */
*value = 0;
- return(recsize + count + 3);
+ return (recsize + count + 3);
}
/* Amount of padding we leave after at the end of the output buffer,
@@ -3173,46 +3178,53 @@ pmon_make_fastrec (outbuf, inbuf, inptr, inamount, recsize, csum, zerofill)
the maximum allowable record size. Each record output is 4bytes
in length. We must allow space for a pending zero fill command,
the record, and a checksum record. */
- while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0)) {
- /* Process the binary data: */
- if ((inamount - *inptr) < 3) {
- if (*zerofill != 0)
- *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
- sprintf (p, "/B");
- count = pmon_makeb64 (inbuf[*inptr], &p[2], 12, csum);
- p += (2 + count);
- *recsize += (2 + count);
- (*inptr)++;
- } else {
- unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]);
- /* Simple check for zero data. TODO: A better check would be
- to check the last, and then the middle byte for being zero
- (if the first byte is not). We could then check for
- following runs of zeros, and if above a certain size it is
- worth the 4 or 8 character hit of the byte insertions used
- to pad to the start of the zeroes. NOTE: This also depends
- on the alignment at the end of the zero run. */
- if (value == 0x00000000) {
- (*zerofill)++;
- if (*zerofill == 0xFFF) /* 12bit counter */
- *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
- }else {
- if (*zerofill != 0)
- *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
- count = pmon_makeb64 (value, p, 24, csum);
- p += count;
- *recsize += count;
- }
- *inptr += 3;
+ while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0))
+ {
+ /* Process the binary data: */
+ if ((inamount - *inptr) < 3)
+ {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ sprintf (p, "/B");
+ count = pmon_makeb64 (inbuf[*inptr], &p[2], 12, csum);
+ p += (2 + count);
+ *recsize += (2 + count);
+ (*inptr)++;
+ }
+ else
+ {
+ unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]);
+ /* Simple check for zero data. TODO: A better check would be
+ to check the last, and then the middle byte for being zero
+ (if the first byte is not). We could then check for
+ following runs of zeros, and if above a certain size it is
+ worth the 4 or 8 character hit of the byte insertions used
+ to pad to the start of the zeroes. NOTE: This also depends
+ on the alignment at the end of the zero run. */
+ if (value == 0x00000000)
+ {
+ (*zerofill)++;
+ if (*zerofill == 0xFFF) /* 12bit counter */
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ }
+ else
+ {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ count = pmon_makeb64 (value, p, 24, csum);
+ p += count;
+ *recsize += count;
+ }
+ *inptr += 3;
+ }
}
- }
*outbuf = p;
return;
}
static int
-pmon_check_ack(mesg)
+pmon_check_ack (mesg)
char *mesg;
{
#if defined(DOETXACK)
@@ -3225,11 +3237,11 @@ pmon_check_ack(mesg)
{
fprintf_unfiltered (gdb_stderr,
"Failed to receive valid ACK for %s\n", mesg);
- return(-1); /* terminate the download */
+ return (-1); /* terminate the download */
}
}
#endif /* DOETXACK */
- return(0);
+ return (0);
}
/* pmon_download - Send a sequence of characters to the PMON download port,
@@ -3272,7 +3284,7 @@ pmon_end_download (final, bintotal)
int final;
int bintotal;
{
- char hexnumber[9]; /* includes '\0' space */
+ char hexnumber[9]; /* includes '\0' space */
if (tftp_in_use)
{
@@ -3317,13 +3329,13 @@ pmon_end_download (final, bintotal)
else
mips_expect_timeout ("Entry Address = ", tftp_in_use ? 15 : 2);
- sprintf (hexnumber,"%x",final);
+ sprintf (hexnumber, "%x", final);
mips_expect (hexnumber);
mips_expect ("\r\n");
if (mips_monitor != MON_LSI)
pmon_check_ack ("termination");
mips_expect ("\r\ntotal = 0x");
- sprintf (hexnumber,"%x",bintotal);
+ sprintf (hexnumber, "%x", bintotal);
mips_expect (hexnumber);
if (!mips_expect_download (" bytes\r\n"))
return;
@@ -3358,21 +3370,21 @@ pmon_load_fast (file)
int final = 0;
int finished = 0;
- buffer = (char *)xmalloc(MAXRECSIZE + 1);
- binbuf = (unsigned char *)xmalloc(BINCHUNK);
+ buffer = (char *) xmalloc (MAXRECSIZE + 1);
+ binbuf = (unsigned char *) xmalloc (BINCHUNK);
- abfd = bfd_openr(file,0);
+ abfd = bfd_openr (file, 0);
if (!abfd)
- {
- printf_filtered ("Unable to open file %s\n",file);
- return;
- }
+ {
+ 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;
- }
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
/* Setup the required download state: */
mips_send_command ("set dlproto etxack\r", -1);
@@ -3381,101 +3393,110 @@ pmon_load_fast (file)
already defined to have the argument we give. The code doesn't
care, since it just scans to the next prompt anyway. */
/* Start the download: */
- pmon_start_download();
-
+ pmon_start_download ();
+
/* Zero the checksum */
- sprintf(buffer,"/Kxx\n");
- reclen = strlen(buffer);
+ sprintf (buffer, "/Kxx\n");
+ reclen = strlen (buffer);
pmon_download (buffer, reclen);
- finished = pmon_check_ack("/Kxx");
+ finished = pmon_check_ack ("/Kxx");
for (s = abfd->sections; s && !finished; s = s->next)
- if (s->flags & SEC_LOAD) /* only deal with loadable sections */
- {
- bintotal += s->_raw_size;
- final = (s->vma + s->_raw_size);
-
- printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, (unsigned int)s->vma,
- (unsigned int)(s->vma + s->_raw_size));
- gdb_flush (gdb_stdout);
-
- /* Output the starting address */
- sprintf(buffer,"/A");
- reclen = pmon_makeb64(s->vma,&buffer[2],36,&csum);
- buffer[2 + reclen] = '\n';
- buffer[3 + reclen] = '\0';
- reclen += 3; /* for the initial escape code and carriage return */
- pmon_download (buffer, reclen);
- finished = pmon_check_ack("/A");
-
- if (!finished)
- {
- unsigned int binamount;
- unsigned int zerofill = 0;
- char *bp = buffer;
- unsigned int i;
-
- reclen = 0;
-
- for (i = 0; ((i < s->_raw_size) && !finished); i += binamount) {
- int binptr = 0;
-
- binamount = min (BINCHUNK, s->_raw_size - i);
-
- bfd_get_section_contents (abfd, s, binbuf, i, binamount);
-
- /* This keeps a rolling checksum, until we decide to output
- the line: */
- for (; ((binamount - binptr) > 0);) {
- pmon_make_fastrec (&bp, binbuf, &binptr, binamount, &reclen, &csum, &zerofill);
- if (reclen >= (MAXRECSIZE - CHECKSIZE)) {
- reclen = pmon_checkset (reclen, &bp, &csum);
- pmon_download (buffer, reclen);
- finished = pmon_check_ack("data record");
- if (finished) {
- zerofill = 0; /* do not transmit pending zerofills */
- break;
- }
-
- if (hashmark) {
- putchar_unfiltered ('#');
- gdb_flush (gdb_stdout);
- }
-
- bp = buffer;
- reclen = 0; /* buffer processed */
- }
- }
- }
-
- /* Ensure no out-standing zerofill requests: */
- if (zerofill != 0)
- reclen = pmon_zeroset (reclen, &bp, &zerofill, &csum);
-
- /* and then flush the line: */
- if (reclen > 0) {
- reclen = pmon_checkset (reclen, &bp, &csum);
- /* Currently pmon_checkset outputs the line terminator by
- default, so we write out the buffer so far: */
- pmon_download (buffer, reclen);
- finished = pmon_check_ack("record remnant");
- }
- }
-
- putchar_unfiltered ('\n');
- }
+ if (s->flags & SEC_LOAD) /* only deal with loadable sections */
+ {
+ bintotal += s->_raw_size;
+ final = (s->vma + s->_raw_size);
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, (unsigned int) s->vma,
+ (unsigned int) (s->vma + s->_raw_size));
+ gdb_flush (gdb_stdout);
+
+ /* Output the starting address */
+ sprintf (buffer, "/A");
+ reclen = pmon_makeb64 (s->vma, &buffer[2], 36, &csum);
+ buffer[2 + reclen] = '\n';
+ buffer[3 + reclen] = '\0';
+ reclen += 3; /* for the initial escape code and carriage return */
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack ("/A");
+
+ if (!finished)
+ {
+ unsigned int binamount;
+ unsigned int zerofill = 0;
+ char *bp = buffer;
+ unsigned int i;
+
+ reclen = 0;
+
+ for (i = 0; ((i < s->_raw_size) && !finished); i += binamount)
+ {
+ int binptr = 0;
+
+ binamount = min (BINCHUNK, s->_raw_size - i);
+
+ bfd_get_section_contents (abfd, s, binbuf, i, binamount);
+
+ /* This keeps a rolling checksum, until we decide to output
+ the line: */
+ for (; ((binamount - binptr) > 0);)
+ {
+ pmon_make_fastrec (&bp, binbuf, &binptr, binamount, &reclen, &csum, &zerofill);
+ if (reclen >= (MAXRECSIZE - CHECKSIZE))
+ {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack ("data record");
+ if (finished)
+ {
+ zerofill = 0; /* do not transmit pending zerofills */
+ break;
+ }
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+
+ bp = buffer;
+ reclen = 0; /* buffer processed */
+ }
+ }
+ }
+
+ /* Ensure no out-standing zerofill requests: */
+ if (zerofill != 0)
+ reclen = pmon_zeroset (reclen, &bp, &zerofill, &csum);
+
+ /* and then flush the line: */
+ if (reclen > 0)
+ {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ /* Currently pmon_checkset outputs the line terminator by
+ default, so we write out the buffer so far: */
+ pmon_download (buffer, reclen);
+ finished = pmon_check_ack ("record remnant");
+ }
+ }
+
+ putchar_unfiltered ('\n');
+ }
/* Terminate the transfer. We know that we have an empty output
buffer at this point. */
- sprintf (buffer, "/E/E\n"); /* include dummy padding characters */
+ sprintf (buffer, "/E/E\n"); /* include dummy padding characters */
reclen = strlen (buffer);
pmon_download (buffer, reclen);
- if (finished) { /* Ignore the termination message: */
- SERIAL_FLUSH_INPUT (udp_in_use ? udp_desc : mips_desc);
- } else { /* Deal with termination message: */
- pmon_end_download (final, bintotal);
- }
+ if (finished)
+ { /* Ignore the termination message: */
+ SERIAL_FLUSH_INPUT (udp_in_use ? udp_desc : mips_desc);
+ }
+ else
+ { /* Deal with termination message: */
+ pmon_end_download (final, bintotal);
+ }
return;
}
@@ -3484,17 +3505,17 @@ pmon_load_fast (file)
static void
mips_load (file, from_tty)
- char *file;
- int from_tty;
+ char *file;
+ int from_tty;
{
/* Get the board out of remote debugging mode. */
if (mips_exit_debug ())
error ("mips_load: Couldn't get into monitor mode.");
if (mips_monitor != MON_IDT)
- pmon_load_fast (file);
+ pmon_load_fast (file);
else
- mips_load_srec (file);
+ mips_load_srec (file);
mips_initialize ();
@@ -3502,8 +3523,8 @@ mips_load (file, from_tty)
if (mips_monitor != MON_IDT)
{
/* Work around problem where PMON monitor updates the PC after a load
- to a different value than GDB thinks it has. The following ensures
- that the write_pc() WILL update the PC value: */
+ to a different value than GDB thinks it has. The following ensures
+ that the write_pc() WILL update the PC value: */
register_valid[PC_REGNUM] = 0;
}
if (exec_bfd)
@@ -3580,7 +3601,7 @@ HOST:PORT to access a board over a network";
mips_ops.to_wait = mips_wait;
pmon_ops.to_shortname = "pmon";
- pmon_ops.to_doc = "\
+ pmon_ops.to_doc = "\
Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
line. The argument is the device it is connected to or, if it contains a\n\
colon, HOST:PORT to access a board over a network";
@@ -3610,29 +3631,29 @@ of the TFTP temporary file, if it differs from the filename seen by the board.";
add_target (&lsi_ops);
add_show_from_set (
- add_set_cmd ("timeout", no_class, var_zinteger,
- (char *) &mips_receive_wait,
- "Set timeout in seconds for remote MIPS serial I/O.",
- &setlist),
- &showlist);
+ add_set_cmd ("timeout", no_class, var_zinteger,
+ (char *) &mips_receive_wait,
+ "Set timeout in seconds for remote MIPS serial I/O.",
+ &setlist),
+ &showlist);
add_show_from_set (
- add_set_cmd ("retransmit-timeout", no_class, var_zinteger,
- (char *) &mips_retransmit_wait,
- "Set retransmit timeout in seconds for remote MIPS serial I/O.\n\
+ add_set_cmd ("retransmit-timeout", no_class, var_zinteger,
+ (char *) &mips_retransmit_wait,
+ "Set retransmit timeout in seconds for remote MIPS serial I/O.\n\
This is the number of seconds to wait for an acknowledgement to a packet\n\
before resending the packet.", &setlist),
- &showlist);
+ &showlist);
add_show_from_set (
- add_set_cmd ("syn-garbage-limit", no_class, var_zinteger,
- (char *) &mips_syn_garbage,
-"Set the maximum number of characters to ignore when scanning for a SYN.\n\
+ add_set_cmd ("syn-garbage-limit", no_class, var_zinteger,
+ (char *) &mips_syn_garbage,
+ "Set the maximum number of characters to ignore when scanning for a SYN.\n\
This is the maximum number of characters GDB will ignore when trying to\n\
synchronize with the remote system. A value of -1 means that there is no limit\n\
(Note that these characters are printed out even though they are ignored.)",
- &setlist),
- &showlist);
+ &setlist),
+ &showlist);
add_show_from_set
(add_set_cmd ("monitor-prompt", class_obscure, var_string,
@@ -3642,14 +3663,14 @@ synchronize with the remote system. A value of -1 means that there is no limit\
&showlist);
add_show_from_set (
- add_set_cmd ("monitor-warnings", class_obscure, var_zinteger,
- (char *)&monitor_warnings,
- "Set printing of monitor warnings.\n"
- "When enabled, monitor warnings about hardware breakpoints "
- "will be displayed.",
- &setlist),
- &showlist);
+ add_set_cmd ("monitor-warnings", class_obscure, var_zinteger,
+ (char *) &monitor_warnings,
+ "Set printing of monitor warnings.\n"
+ "When enabled, monitor warnings about hardware breakpoints "
+ "will be displayed.",
+ &setlist),
+ &showlist);
add_com ("pmon <command>", class_obscure, pmon_command,
- "Send a packet to PMON (must be in debug mode).");
+ "Send a packet to PMON (must be in debug mode).");
}
diff --git a/contrib/gdb/gdb/remote-rdp.c b/contrib/gdb/gdb/remote-rdp.c
index 1d596a4..e193abb 100644
--- a/contrib/gdb/gdb/remote-rdp.c
+++ b/contrib/gdb/gdb/remote-rdp.c
@@ -15,7 +15,8 @@
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.
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
*/
@@ -37,25 +38,20 @@
#include "defs.h"
#include "inferior.h"
-#include "wait.h"
+#include "gdb_wait.h"
#include "value.h"
#include "callback.h"
#include "command.h"
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include <ctype.h>
#include <fcntl.h>
#include "symfile.h"
#include "remote-utils.h"
#include "gdb_string.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#include "gdbcore.h"
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
extern struct target_ops remote_rdp_ops;
static serial_t io;
@@ -168,7 +164,7 @@ ds;
static int timeout = 2;
-static char * commandline = NULL;
+static char *commandline = NULL;
static int
remote_rdp_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
@@ -186,7 +182,7 @@ get_byte ()
int c = SERIAL_READCHAR (io, timeout);
if (remote_debug)
- printf ("[%02x]\n", c);
+ fprintf_unfiltered (gdb_stdlog, "[%02x]\n", c);
if (c == SERIAL_TIMEOUT)
{
@@ -220,7 +216,7 @@ put_byte (val)
char val;
{
if (remote_debug)
- printf ("(%02x)\n", val);
+ fprintf_unfiltered (gdb_stdlog, "(%02x)\n", val);
SERIAL_WRITE (io, &val, 1);
}
@@ -236,7 +232,7 @@ put_word (val)
b[3] = val >> 24;
if (remote_debug)
- printf ("(%04x)", val);
+ fprintf_unfiltered (gdb_stdlog, "(%04x)", val);
SERIAL_WRITE (io, b, 4);
}
@@ -278,9 +274,9 @@ rdp_init (cold, tty)
printf_unfiltered ("Trying to connect at %d baud.\n", baudtry);
/*
- ** It seems necessary to reset an EmbeddedICE to get it going.
- ** This has the side benefit of displaying the startup banner.
- */
+ ** It seems necessary to reset an EmbeddedICE to get it going.
+ ** This has the side benefit of displaying the startup banner.
+ */
if (cold)
{
put_byte (RDP_RESET);
@@ -308,13 +304,13 @@ rdp_init (cold, tty)
put_byte (RDP_OPEN);
- put_byte (type | RDP_OPEN_TYPE_RETURN_SEX );
+ put_byte (type | RDP_OPEN_TYPE_RETURN_SEX);
put_word (0);
while (!sync && (restype = SERIAL_READCHAR (io, 1)) > 0)
{
if (remote_debug)
- printf_unfiltered ("[%02x]\n", restype);
+ fprintf_unfiltered (gdb_stdlog, "[%02x]\n", restype);
switch (restype)
{
@@ -349,7 +345,7 @@ rdp_init (cold, tty)
int resval = SERIAL_READCHAR (io, 1);
if (remote_debug)
- printf_unfiltered ("[%02x]\n", resval);
+ fprintf_unfiltered (gdb_stdlog, "[%02x]\n", resval);
switch (resval)
{
@@ -378,23 +374,13 @@ rdp_init (cold, tty)
}
-#ifdef ANSI_PROTOTYPES
void
send_rdp (char *template,...)
-#else
-void
-send_rdp (char *template, va_alist)
- va_dcl
-#endif
{
char buf[200];
char *dst = buf;
va_list alist;
-#ifdef ANSI_PROTOTYPES
va_start (alist, template);
-#else
- va_start (alist);
-#endif
while (*template)
{
@@ -494,7 +480,7 @@ send_rdp (char *template, va_alist)
abort ();
}
}
- va_end (args);
+ va_end (alist);
if (dst != buf)
abort ();
@@ -723,14 +709,14 @@ rdp_execute_start ()
static void
rdp_set_command_line (command, args)
- char * command;
- char * args;
+ char *command;
+ char *args;
{
/*
- ** We could use RDP_INFO_SET_CMDLINE to send this, but EmbeddedICE systems
- ** don't implement that, and get all confused at the unexpected text.
- ** Instead, just keep a copy, and send it when the target does a SWI_GetEnv
- */
+ ** We could use RDP_INFO_SET_CMDLINE to send this, but EmbeddedICE systems
+ ** don't implement that, and get all confused at the unexpected text.
+ ** Instead, just keep a copy, and send it when the target does a SWI_GetEnv
+ */
if (commandline != NULL)
free (commandline);
@@ -748,22 +734,22 @@ static void
rdp_catch_vectors ()
{
/*
- ** We want the target monitor to intercept the abort vectors
- ** i.e. stop the program if any of these are used.
- */
+ ** We want the target monitor to intercept the abort vectors
+ ** i.e. stop the program if any of these are used.
+ */
send_rdp ("bww-SZ", RDP_INFO, RDP_INFO_VECTOR_CATCH,
- /*
- ** Specify a bitmask including
- ** the reset vector
- ** the undefined instruction vector
- ** the prefetch abort vector
- ** the data abort vector
- ** the address exception vector
- */
- (1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<5)
- );
+ /*
+ ** Specify a bitmask including
+ ** the reset vector
+ ** the undefined instruction vector
+ ** the prefetch abort vector
+ ** the data abort vector
+ ** the address exception vector
+ */
+ (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5)
+ );
}
-
+
#define a_byte 1
@@ -817,18 +803,18 @@ argsin;
static int translate_open_mode[] =
{
- O_RDONLY, /* "r" */
- O_RDONLY+O_BINARY, /* "rb" */
- O_RDWR, /* "r+" */
- O_RDWR +O_BINARY, /* "r+b" */
- O_WRONLY +O_CREAT+O_TRUNC, /* "w" */
- O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb" */
- O_RDWR +O_CREAT+O_TRUNC, /* "w+" */
- O_RDWR +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
- O_WRONLY +O_APPEND+O_CREAT,/* "a" */
- O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab" */
- O_RDWR +O_APPEND+O_CREAT,/* "a+" */
- O_RDWR +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
+ O_RDONLY, /* "r" */
+ O_RDONLY + O_BINARY, /* "rb" */
+ O_RDWR, /* "r+" */
+ O_RDWR + O_BINARY, /* "r+b" */
+ O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
+ O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
+ O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
+ O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
+ O_WRONLY + O_APPEND + O_CREAT, /* "a" */
+ O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
+ O_RDWR + O_APPEND + O_CREAT, /* "a+" */
+ O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
};
static int
@@ -861,18 +847,18 @@ exec_swi (swi, args)
args->n = callback->time (callback, NULL);
return 1;
- case SWI_Clock :
- /* return number of centi-seconds... */
- args->n =
+ case SWI_Clock:
+ /* return number of centi-seconds... */
+ args->n =
#ifdef CLOCKS_PER_SEC
- (CLOCKS_PER_SEC >= 100)
- ? (clock() / (CLOCKS_PER_SEC / 100))
- : ((clock() * 100) / CLOCKS_PER_SEC) ;
+ (CLOCKS_PER_SEC >= 100)
+ ? (clock () / (CLOCKS_PER_SEC / 100))
+ : ((clock () * 100) / CLOCKS_PER_SEC);
#else
- /* presume unix... clock() returns microseconds */
- clock() / 10000 ;
+ /* presume unix... clock() returns microseconds */
+ clock () / 10000;
#endif
- return 1 ;
+ return 1;
case SWI_Remove:
args->n = callback->unlink (callback, args->s);
@@ -882,19 +868,19 @@ exec_swi (swi, args)
return 1;
case SWI_Open:
- /* Now we need to decode the Demon open mode */
- i = translate_open_mode[args[1].n];
-
- /* Filename ":tt" is special: it denotes stdin/out */
- if (strcmp(args->s,":tt")==0)
- {
- if (i == O_RDONLY ) /* opening tty "r" */
- args->n = 0 /* stdin */ ;
- else
- args->n = 1 /* stdout */ ;
- }
- else
- args->n = callback->open (callback, args->s, i);
+ /* Now we need to decode the Demon open mode */
+ i = translate_open_mode[args[1].n];
+
+ /* Filename ":tt" is special: it denotes stdin/out */
+ if (strcmp (args->s, ":tt") == 0)
+ {
+ if (i == O_RDONLY) /* opening tty "r" */
+ args->n = 0 /* stdin */ ;
+ else
+ args->n = 1 /* stdout */ ;
+ }
+ else
+ args->n = callback->open (callback, args->s, i);
return 1;
case SWI_Close:
@@ -913,7 +899,7 @@ exec_swi (swi, args)
int done = callback->read (callback, args[0].n, copy, args[2].n);
if (done > 0)
remote_rdp_xfer_inferior_memory (args[1].n, copy, done, 1, 0);
- args->n = args[2].n-done;
+ args->n = args[2].n - done;
return 1;
}
@@ -941,15 +927,15 @@ exec_swi (swi, args)
if (len > 255)
{
len = 255;
- commandline [255]='\0';
+ commandline[255] = '\0';
}
remote_rdp_xfer_inferior_memory (args[0].n,
- commandline, len+1, 1, 0);
+ commandline, len + 1, 1, 0);
}
else
remote_rdp_xfer_inferior_memory (args[0].n, "", 1, 1, 0);
return 1;
-
+
default:
return 0;
}
@@ -1177,32 +1163,32 @@ remote_rdp_open (args, from_tty)
rdp_info ();
/* Need to set up the vector interception state */
- rdp_catch_vectors();
+ rdp_catch_vectors ();
/*
- ** If it's an EmbeddedICE, we need to set the processor config.
- ** Assume we can always have ARM7TDI...
- */
- send_rdp ("bw-SB", RDP_INFO, RDP_INFO_ICEBREAKER, & not_icebreaker);
+ ** If it's an EmbeddedICE, we need to set the processor config.
+ ** Assume we can always have ARM7TDI...
+ */
+ send_rdp ("bw-SB", RDP_INFO, RDP_INFO_ICEBREAKER, &not_icebreaker);
if (!not_icebreaker)
{
- const char * CPU = "ARM7TDI";
+ const char *CPU = "ARM7TDI";
int ICEversion;
int len = strlen (CPU);
-
+
send_rdp ("bbbbw-p-SWZ",
RDP_SELECT_CONFIG,
RDI_ConfigCPU, /* Aspect: set the CPU */
len, /* The number of bytes in the name */
RDI_MatchAny, /* We'll take whatever we get */
0, /* We'll take whatever version's there */
- CPU,len,
- & ICEversion);
+ CPU, len,
+ &ICEversion);
}
- /* command line initialised on 'run'*/
+ /* command line initialised on 'run' */
- push_target (& remote_rdp_ops);
+ push_target (&remote_rdp_ops);
callback->init (callback);
flush_cached_frames ();
@@ -1386,18 +1372,18 @@ remote_rdp_files_info (target)
static void
remote_rdp_create_inferior (exec_file, allargs, env)
- char * exec_file;
- char * allargs;
- char ** env;
+ char *exec_file;
+ char *allargs;
+ char **env;
{
CORE_ADDR entry_point;
if (exec_file == 0 || exec_bfd == 0)
- error ("No executable file specified.");
+ error ("No executable file specified.");
entry_point = (CORE_ADDR) bfd_get_start_address (exec_bfd);
- remote_rdp_kill ();
+ remote_rdp_kill ();
remove_breakpoints ();
init_wait_for_inferior ();
@@ -1405,12 +1391,12 @@ remote_rdp_create_inferior (exec_file, allargs, env)
rdp_set_command_line (exec_file, allargs);
inferior_pid = 42;
- insert_breakpoints (); /* Needed to get correct instruction in cache */
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
/*
- ** RDP targets don't provide any facility to set the top of memory,
- ** so we don't bother to look for MEMSIZE in the environment.
- */
+ ** RDP targets don't provide any facility to set the top of memory,
+ ** so we don't bother to look for MEMSIZE in the environment.
+ */
/* Let's go! */
proceed (entry_point, TARGET_SIGNAL_DEFAULT, 0);
@@ -1418,56 +1404,56 @@ remote_rdp_create_inferior (exec_file, allargs, env)
/* Accept any stray run/attach commands */
static int
-remote_rdp_can_run()
+remote_rdp_can_run ()
{
return 1;
}
/* Attach doesn't need to do anything */
static void
-remote_rdp_attach(args, from_tty)
- char * args;
+remote_rdp_attach (args, from_tty)
+ char *args;
int from_tty;
{
return;
}
-
+
/* Define the target subroutine names */
-struct target_ops remote_rdp_ops ;
+struct target_ops remote_rdp_ops;
-static void
-init_remote_rdp_ops(void)
+static void
+init_remote_rdp_ops (void)
{
- remote_rdp_ops.to_shortname = "rdp";
- remote_rdp_ops.to_longname = "Remote Target using the RDProtocol";
- remote_rdp_ops.to_doc = "Use a remote ARM system which uses the ARM Remote Debugging Protocol";
- remote_rdp_ops.to_open = remote_rdp_open;
- remote_rdp_ops.to_close = remote_rdp_close;
- remote_rdp_ops.to_attach = remote_rdp_attach;
+ remote_rdp_ops.to_shortname = "rdp";
+ remote_rdp_ops.to_longname = "Remote Target using the RDProtocol";
+ remote_rdp_ops.to_doc = "Use a remote ARM system which uses the ARM Remote Debugging Protocol";
+ remote_rdp_ops.to_open = remote_rdp_open;
+ remote_rdp_ops.to_close = remote_rdp_close;
+ remote_rdp_ops.to_attach = remote_rdp_attach;
remote_rdp_ops.to_post_attach = NULL;
remote_rdp_ops.to_require_attach = NULL;
- remote_rdp_ops.to_detach = NULL;
- remote_rdp_ops.to_require_detach = NULL;
- remote_rdp_ops.to_resume = remote_rdp_resume;
- remote_rdp_ops.to_wait = remote_rdp_wait;
- remote_rdp_ops.to_post_wait = NULL;
- remote_rdp_ops.to_fetch_registers = remote_rdp_fetch_register;
- remote_rdp_ops.to_store_registers = remote_rdp_store_register;
- remote_rdp_ops.to_prepare_to_store = remote_rdp_prepare_to_store;
- remote_rdp_ops.to_xfer_memory = remote_rdp_xfer_inferior_memory;
- remote_rdp_ops.to_files_info = remote_rdp_files_info;
- remote_rdp_ops.to_insert_breakpoint = remote_rdp_insert_breakpoint;
- remote_rdp_ops.to_remove_breakpoint = remote_rdp_remove_breakpoint;
- remote_rdp_ops.to_terminal_init = NULL;
- remote_rdp_ops.to_terminal_inferior = NULL;
- remote_rdp_ops.to_terminal_ours_for_output = NULL;
- remote_rdp_ops.to_terminal_ours = NULL;
- remote_rdp_ops.to_terminal_info = NULL;
- remote_rdp_ops.to_kill = remote_rdp_kill;
- remote_rdp_ops.to_load = generic_load;
- remote_rdp_ops.to_lookup_symbol = NULL;
- remote_rdp_ops.to_create_inferior = remote_rdp_create_inferior;
+ remote_rdp_ops.to_detach = NULL;
+ remote_rdp_ops.to_require_detach = NULL;
+ remote_rdp_ops.to_resume = remote_rdp_resume;
+ remote_rdp_ops.to_wait = remote_rdp_wait;
+ remote_rdp_ops.to_post_wait = NULL;
+ remote_rdp_ops.to_fetch_registers = remote_rdp_fetch_register;
+ remote_rdp_ops.to_store_registers = remote_rdp_store_register;
+ remote_rdp_ops.to_prepare_to_store = remote_rdp_prepare_to_store;
+ remote_rdp_ops.to_xfer_memory = remote_rdp_xfer_inferior_memory;
+ remote_rdp_ops.to_files_info = remote_rdp_files_info;
+ remote_rdp_ops.to_insert_breakpoint = remote_rdp_insert_breakpoint;
+ remote_rdp_ops.to_remove_breakpoint = remote_rdp_remove_breakpoint;
+ remote_rdp_ops.to_terminal_init = NULL;
+ remote_rdp_ops.to_terminal_inferior = NULL;
+ remote_rdp_ops.to_terminal_ours_for_output = NULL;
+ remote_rdp_ops.to_terminal_ours = NULL;
+ remote_rdp_ops.to_terminal_info = NULL;
+ remote_rdp_ops.to_kill = remote_rdp_kill;
+ remote_rdp_ops.to_load = generic_load;
+ remote_rdp_ops.to_lookup_symbol = NULL;
+ remote_rdp_ops.to_create_inferior = remote_rdp_create_inferior;
remote_rdp_ops.to_post_startup_inferior = NULL;
remote_rdp_ops.to_acknowledge_created_inferior = NULL;
remote_rdp_ops.to_clone_and_follow_inferior = NULL;
@@ -1485,28 +1471,28 @@ init_remote_rdp_ops(void)
remote_rdp_ops.to_has_execd = NULL;
remote_rdp_ops.to_reported_exec_events_per_exec_call = NULL;
remote_rdp_ops.to_has_exited = NULL;
- remote_rdp_ops.to_mourn_inferior = generic_mourn_inferior;
- remote_rdp_ops.to_can_run = remote_rdp_can_run;
- remote_rdp_ops.to_notice_signals = 0;
- remote_rdp_ops.to_thread_alive = 0;
- remote_rdp_ops.to_stop = 0;
+ remote_rdp_ops.to_mourn_inferior = generic_mourn_inferior;
+ remote_rdp_ops.to_can_run = remote_rdp_can_run;
+ remote_rdp_ops.to_notice_signals = 0;
+ remote_rdp_ops.to_thread_alive = 0;
+ remote_rdp_ops.to_stop = 0;
remote_rdp_ops.to_pid_to_exec_file = NULL;
- remote_rdp_ops.to_core_file_to_sym_file = NULL;
- remote_rdp_ops.to_stratum = process_stratum;
- remote_rdp_ops.DONT_USE = NULL;
- remote_rdp_ops.to_has_all_memory = 1;
- remote_rdp_ops.to_has_memory = 1;
- remote_rdp_ops.to_has_stack = 1;
- remote_rdp_ops.to_has_registers = 1;
- remote_rdp_ops.to_has_execution = 1;
- remote_rdp_ops.to_sections = NULL;
- remote_rdp_ops.to_sections_end = NULL;
- remote_rdp_ops.to_magic = OPS_MAGIC;
+ remote_rdp_ops.to_core_file_to_sym_file = NULL;
+ remote_rdp_ops.to_stratum = process_stratum;
+ remote_rdp_ops.DONT_USE = NULL;
+ remote_rdp_ops.to_has_all_memory = 1;
+ remote_rdp_ops.to_has_memory = 1;
+ remote_rdp_ops.to_has_stack = 1;
+ remote_rdp_ops.to_has_registers = 1;
+ remote_rdp_ops.to_has_execution = 1;
+ remote_rdp_ops.to_sections = NULL;
+ remote_rdp_ops.to_sections_end = NULL;
+ remote_rdp_ops.to_magic = OPS_MAGIC;
}
void
_initialize_remote_rdp ()
{
- init_remote_rdp_ops() ;
+ init_remote_rdp_ops ();
add_target (&remote_rdp_ops);
}
diff --git a/contrib/gdb/gdb/remote-sim.c b/contrib/gdb/gdb/remote-sim.c
index e10fced..dd231ad 100644
--- a/contrib/gdb/gdb/remote-sim.c
+++ b/contrib/gdb/gdb/remote-sim.c
@@ -1,27 +1,28 @@
/* Generic remote debugging interface for simulators.
- Copyright 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1996, 1997, 2000 Free Software Foundation, Inc.
Contributed by Cygnus Support.
Steve Chamberlain (sac@cygnus.com).
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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 "wait.h"
+#include "gdb_wait.h"
#include "value.h"
#include "gdb_string.h"
#include <ctype.h>
@@ -39,6 +40,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Prototypes */
+extern void _initialize_remote_sim PARAMS ((void));
+
+extern int (*ui_loop_hook) PARAMS ((int signo));
+
static void dump_mem PARAMS ((char *buf, int len));
static void init_callbacks PARAMS ((void));
@@ -56,13 +61,13 @@ static void gdb_os_flush_stderr PARAMS ((host_callback *));
static int gdb_os_poll_quit PARAMS ((host_callback *));
/* printf_filtered is depreciated */
-static void gdb_os_printf_filtered PARAMS ((host_callback *, const char *, ...));
+static void gdb_os_printf_filtered PARAMS ((host_callback *, const char *,...));
static void gdb_os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
static void gdb_os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
-static void gdb_os_error PARAMS ((host_callback *, const char *, ...));
+static void gdb_os_error PARAMS ((host_callback *, const char *,...));
static void gdbsim_fetch_register PARAMS ((int regno));
@@ -82,16 +87,16 @@ static void gdbsim_detach PARAMS ((char *args, int from_tty));
static void gdbsim_resume PARAMS ((int pid, int step, enum target_signal siggnal));
-static int gdbsim_wait PARAMS ((int pid, struct target_waitstatus *status));
+static int gdbsim_wait PARAMS ((int pid, struct target_waitstatus * status));
static void gdbsim_prepare_to_store PARAMS ((void));
static int gdbsim_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
char *myaddr, int len,
int write,
- struct target_ops *target));
+ struct target_ops * target));
-static void gdbsim_files_info PARAMS ((struct target_ops *target));
+static void gdbsim_files_info PARAMS ((struct target_ops * target));
static void gdbsim_mourn_inferior PARAMS ((void));
@@ -126,7 +131,7 @@ dump_mem (buf, len)
{
long l[2];
memcpy (l, buf, len);
- printf_filtered ("\t0x%x", l[0]);
+ printf_filtered ("\t0x%lx", l[0]);
printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]);
}
else
@@ -148,7 +153,7 @@ static int callbacks_initialized = 0;
static void
init_callbacks ()
{
- if (! callbacks_initialized)
+ if (!callbacks_initialized)
{
gdb_callback = default_callback;
gdb_callback.init (&gdb_callback);
@@ -180,7 +185,7 @@ end_callbacks ()
/* GDB version of os_write_stdout callback. */
-static int
+static int
gdb_os_write_stdout (p, buf, len)
host_callback *p;
const char *buf;
@@ -189,15 +194,7 @@ gdb_os_write_stdout (p, buf, len)
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);
- }
+ ui_file_write (gdb_stdtarg, buf, len);
return len;
}
@@ -207,12 +204,12 @@ static void
gdb_os_flush_stdout (p)
host_callback *p;
{
- gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stdtarg);
}
/* GDB version of os_write_stderr callback. */
-static int
+static int
gdb_os_write_stderr (p, buf, len)
host_callback *p;
const char *buf;
@@ -221,14 +218,11 @@ gdb_os_write_stderr (p, buf, len)
int i;
char b[2];
- for (i = 0; i < len; i++)
+ 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_stderr);
+ fputs_unfiltered (b, gdb_stdtarg);
}
return len;
}
@@ -244,25 +238,11 @@ gdb_os_flush_stderr (p)
/* GDB version of printf_filtered callback. */
-/* VARARGS */
static void
-#ifdef ANSI_PROTOTYPES
-gdb_os_printf_filtered (host_callback *p, const char *format, ...)
-#else
-gdb_os_printf_filtered (p, va_alist)
- host_callback *p;
- va_dcl
-#endif
+gdb_os_printf_filtered (host_callback * p, const char *format,...)
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- char *format;
-
- va_start (args);
- format = va_arg (args, char *);
-#endif
vfprintf_filtered (gdb_stdout, format, args);
@@ -271,93 +251,72 @@ gdb_os_printf_filtered (p, va_alist)
/* GDB version of error vprintf_filtered. */
-/* VARARGS */
static void
-#ifdef ANSI_PROTOTYPES
-gdb_os_vprintf_filtered (host_callback *p, const char *format, va_list ap)
-#else
-gdb_os_vprintf_filtered (p, format, ap)
- host_callback *p;
- char *format;
- va_list ap;
-#endif
+gdb_os_vprintf_filtered (host_callback * p, const char *format, va_list ap)
{
vfprintf_filtered (gdb_stdout, format, ap);
}
/* GDB version of error evprintf_filtered. */
-/* VARARGS */
static void
-#ifdef ANSI_PROTOTYPES
-gdb_os_evprintf_filtered (host_callback *p, const char *format, va_list ap)
-#else
-gdb_os_evprintf_filtered (p, format, ap)
- host_callback *p;
- char *format;
- va_list ap;
-#endif
+gdb_os_evprintf_filtered (host_callback * p, const char *format, va_list ap)
{
vfprintf_filtered (gdb_stderr, format, ap);
}
/* GDB version of error callback. */
-/* VARARGS */
static void
-#ifdef ANSI_PROTOTYPES
-gdb_os_error (host_callback *p, const char *format, ...)
-#else
-gdb_os_error (p, va_alist)
- host_callback *p;
- va_dcl
-#endif
+gdb_os_error (host_callback * p, const char *format,...)
{
if (error_hook)
(*error_hook) ();
- else
+ else
{
va_list args;
-#ifdef ANSI_PROTOTYPES
va_start (args, format);
-#else
- char *format;
-
- va_start (args);
- format = va_arg (args, char *);
-#endif
-
- error_begin ();
- vfprintf_filtered (gdb_stderr, format, args);
- fprintf_filtered (gdb_stderr, "\n");
+ verror (format, args);
va_end (args);
- return_to_top_level (RETURN_ERROR);
}
}
+#ifndef REGISTER_SIM_REGNO
+#define REGISTER_SIM_REGNO(N) (N)
+#endif
+
static void
gdbsim_fetch_register (regno)
int regno;
{
static int warn_user = 1;
- if (regno == -1)
+ if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_fetch_register (regno);
}
- else if (REGISTER_NAME (regno) != NULL && *REGISTER_NAME (regno) != '\0')
+ else if (REGISTER_NAME (regno) != NULL
+ && *REGISTER_NAME (regno) != '\0')
{
char buf[MAX_REGISTER_RAW_SIZE];
- int nr_bytes = sim_fetch_register (gdbsim_desc, regno, buf, REGISTER_RAW_SIZE (regno));
+ int nr_bytes;
+ if (REGISTER_SIM_REGNO (regno) >= 0)
+ nr_bytes = sim_fetch_register (gdbsim_desc,
+ REGISTER_SIM_REGNO (regno),
+ buf, REGISTER_RAW_SIZE (regno));
+ else
+ nr_bytes = 0;
if (nr_bytes == 0)
/* register not applicable, supply zero's */
memset (buf, 0, MAX_REGISTER_RAW_SIZE);
else if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno)
&& warn_user)
{
- printf_unfiltered ("Size of register %s (%d) incorrect (%d instead of %d))",
- REGISTER_NAME (regno), regno,
- nr_bytes, REGISTER_RAW_SIZE (regno));
+ fprintf_unfiltered (gdb_stderr,
+ "Size of register %s (%d/%d) incorrect (%d instead of %d))",
+ REGISTER_NAME (regno),
+ regno, REGISTER_SIM_REGNO (regno),
+ nr_bytes, REGISTER_RAW_SIZE (regno));
warn_user = 0;
}
supply_register (regno, buf);
@@ -375,19 +334,23 @@ static void
gdbsim_store_register (regno)
int regno;
{
- if (regno == -1)
+ if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
gdbsim_store_register (regno);
}
- else if (REGISTER_NAME (regno) != NULL && *REGISTER_NAME (regno) != '\0')
+ else if (REGISTER_NAME (regno) != NULL
+ && *REGISTER_NAME (regno) != '\0'
+ && REGISTER_SIM_REGNO (regno) >= 0)
{
char tmp[MAX_REGISTER_RAW_SIZE];
int nr_bytes;
read_register_gen (regno, tmp);
- nr_bytes = sim_store_register (gdbsim_desc, regno, tmp, REGISTER_RAW_SIZE (regno));
+ nr_bytes = sim_store_register (gdbsim_desc,
+ REGISTER_SIM_REGNO (regno),
+ tmp, REGISTER_RAW_SIZE (regno));
if (nr_bytes > 0 && nr_bytes != REGISTER_RAW_SIZE (regno))
- fatal ("Register size different to expected");
+ internal_error ("Register size different to expected");
if (sr_get_debug ())
{
printf_filtered ("gdbsim_store_register: %d", regno);
@@ -453,44 +416,44 @@ gdbsim_create_inferior (exec_file, args, env)
char **env;
{
int len;
- char *arg_buf,**argv;
+ char *arg_buf, **argv;
if (exec_file == 0 || exec_bfd == 0)
warning ("No executable file specified.");
- if (! program_loaded)
+ if (!program_loaded)
warning ("No program loaded.");
if (sr_get_debug ())
printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
- (exec_file ? exec_file: "(NULL)"),
+ (exec_file ? exec_file : "(NULL)"),
args);
- gdbsim_kill ();
+ gdbsim_kill ();
remove_breakpoints ();
init_wait_for_inferior ();
if (exec_file != NULL)
{
- len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+ len = strlen (exec_file) + 1 + strlen (args) + 1 + /*slop */ 10;
arg_buf = (char *) alloca (len);
arg_buf[0] = '\0';
strcat (arg_buf, exec_file);
strcat (arg_buf, " ");
strcat (arg_buf, args);
argv = buildargv (arg_buf);
- make_cleanup ((make_cleanup_func) freeargv, argv);
+ make_cleanup_freeargv (argv);
}
else
argv = NULL;
sim_create_inferior (gdbsim_desc, exec_bfd, argv, env);
inferior_pid = 42;
- insert_breakpoints (); /* Needed to get correct instruction in cache */
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
clear_proceed_status ();
/* NB: Entry point already set by sim_create_inferior. */
- proceed ((CORE_ADDR)-1, TARGET_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
}
/* The open routine takes the rest of the parameters from the command,
@@ -519,13 +482,13 @@ gdbsim_open (args, from_tty)
if (gdbsim_desc != NULL)
unpush_target (&gdbsim_ops);
- len = (7 + 1 /* gdbsim */
+ len = (7 + 1 /* gdbsim */
+ strlen (" -E little")
+ strlen (" --architecture=xxxxxxxxxx")
+ (args ? strlen (args) : 0)
- + 50) /* slack */;
+ + 50) /* slack */ ;
arg_buf = (char *) alloca (len);
- strcpy (arg_buf, "gdbsim"); /* 7 */
+ strcpy (arg_buf, "gdbsim"); /* 7 */
/* Specify the byte order for the target when it is both selectable
and explicitly specified by the user (not auto detected). */
if (TARGET_BYTE_ORDER_SELECTABLE_P
@@ -540,7 +503,7 @@ gdbsim_open (args, from_tty)
strcat (arg_buf, " -E little");
break;
default:
- fatal ("Value of TARGET_BYTE_ORDER unknown");
+ internal_error ("Value of TARGET_BYTE_ORDER unknown");
}
}
/* Specify the architecture of the target when it has been
@@ -553,13 +516,13 @@ gdbsim_open (args, from_tty)
/* finally, any explicit args */
if (args)
{
- strcat (arg_buf, " "); /* 1 */
+ strcat (arg_buf, " "); /* 1 */
strcat (arg_buf, args);
}
argv = buildargv (arg_buf);
if (argv == NULL)
error ("Insufficient memory available to allocate simulator arg list.");
- make_cleanup ((make_cleanup_func) freeargv, argv);
+ make_cleanup_freeargv (argv);
init_callbacks ();
gdbsim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, argv);
@@ -597,6 +560,7 @@ gdbsim_close (quitting)
}
end_callbacks ();
+ generic_mourn_inferior ();
}
/* Takes a program previously attached to and detaches it.
@@ -609,7 +573,7 @@ gdbsim_close (quitting)
Use this when you want to detach and do something else with your gdb. */
static void
-gdbsim_detach (args,from_tty)
+gdbsim_detach (args, from_tty)
char *args;
int from_tty;
{
@@ -620,7 +584,7 @@ gdbsim_detach (args,from_tty)
if (from_tty)
printf_filtered ("Ending simulator %s debugging\n", target_shortname);
}
-
+
/* Resume execution of the target process. STEP says whether to single-step
or to run free; SIGGNAL is the signal value (e.g. SIGINT) to be given
to the target, or zero for no signal. */
@@ -644,7 +608,7 @@ gdbsim_resume (pid, step, siggnal)
}
/* Notify the simulator of an asynchronous request to stop.
-
+
The simulator shall ensure that the stop request is eventually
delivered to the simulator. If the call is made while the
simulator is not running then the stop request is processed when
@@ -655,7 +619,7 @@ gdbsim_resume (pid, step, siggnal)
static void
gdbsim_stop ()
{
- if (! sim_stop (gdbsim_desc))
+ if (!sim_stop (gdbsim_desc))
{
quit ();
}
@@ -668,10 +632,13 @@ static int
gdb_os_poll_quit (p)
host_callback *p;
{
+ if (ui_loop_hook != NULL)
+ ui_loop_hook (0);
+
notice_quit ();
- if (quit_flag) /* gdb's idea of quit */
+ if (quit_flag) /* gdb's idea of quit */
{
- quit_flag = 0; /* we've stolen it */
+ quit_flag = 0; /* we've stolen it */
return 1;
}
else if (immediate_quit)
@@ -748,7 +715,7 @@ gdbsim_wait (pid, status)
case sim_signalled:
status->kind = TARGET_WAITKIND_SIGNALLED;
/* The signal in sigrc is a host signal. That probably
- should be fixed. */
+ should be fixed. */
status->value.sig = target_signal_from_host (sigrc);
break;
case sim_running:
@@ -778,29 +745,32 @@ gdbsim_xfer_inferior_memory (memaddr, myaddr, len, write, target)
char *myaddr;
int len;
int write;
- struct target_ops *target; /* ignored */
+ struct target_ops *target; /* ignored */
{
- if (! program_loaded)
+ if (!program_loaded)
error ("No program loaded.");
if (sr_get_debug ())
{
- printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n",
- myaddr, memaddr, len, write);
+ /* FIXME: Send to something other than STDOUT? */
+ printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x");
+ gdb_print_host_address (myaddr, gdb_stdout);
+ printf_filtered (", memaddr 0x%s, len %d, write %d\n",
+ paddr_nz (memaddr), len, write);
if (sr_get_debug () && write)
- dump_mem(myaddr, len);
+ dump_mem (myaddr, len);
}
if (write)
{
len = sim_write (gdbsim_desc, memaddr, myaddr, len);
}
- else
+ else
{
len = sim_read (gdbsim_desc, memaddr, myaddr, len);
if (sr_get_debug () && len > 0)
- dump_mem(myaddr, len);
- }
+ dump_mem (myaddr, len);
+ }
return len;
}
@@ -827,8 +797,8 @@ gdbsim_files_info (target)
/* Clear the simulator's notion of what the break points are. */
static void
-gdbsim_mourn_inferior ()
-{
+gdbsim_mourn_inferior ()
+{
if (sr_get_debug ())
printf_filtered ("gdbsim_mourn_inferior:\n");
@@ -913,45 +883,45 @@ simulator_command (args, from_tty)
/* Invalidate the register cache, in case the simulator command does
something funny. */
- registers_changed ();
+ registers_changed ();
}
/* Define the target subroutine names */
-struct target_ops gdbsim_ops ;
-
-static void
-init_gdbsim_ops(void)
-{
- gdbsim_ops.to_shortname = "sim";
- gdbsim_ops.to_longname = "simulator";
- gdbsim_ops.to_doc = "Use the compiled-in simulator.";
- gdbsim_ops.to_open = gdbsim_open;
- gdbsim_ops.to_close = gdbsim_close;
- gdbsim_ops.to_attach = NULL;
- gdbsim_ops.to_post_attach = NULL;
- gdbsim_ops.to_require_attach = NULL;
- gdbsim_ops.to_detach = gdbsim_detach;
- gdbsim_ops.to_require_detach = NULL;
- gdbsim_ops.to_resume = gdbsim_resume;
- gdbsim_ops.to_wait = gdbsim_wait;
- gdbsim_ops.to_post_wait = NULL;
- gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
- gdbsim_ops.to_store_registers = gdbsim_store_register;
- gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
- gdbsim_ops.to_xfer_memory = gdbsim_xfer_inferior_memory;
- gdbsim_ops.to_files_info = gdbsim_files_info;
- gdbsim_ops.to_insert_breakpoint = gdbsim_insert_breakpoint;
- gdbsim_ops.to_remove_breakpoint = gdbsim_remove_breakpoint;
- gdbsim_ops.to_terminal_init = NULL;
- gdbsim_ops.to_terminal_inferior = NULL;
- gdbsim_ops.to_terminal_ours_for_output = NULL;
- gdbsim_ops.to_terminal_ours = NULL;
- gdbsim_ops.to_terminal_info = NULL;
- gdbsim_ops.to_kill = gdbsim_kill;
- gdbsim_ops.to_load = gdbsim_load;
- gdbsim_ops.to_lookup_symbol = NULL;
- gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
+struct target_ops gdbsim_ops;
+
+static void
+init_gdbsim_ops (void)
+{
+ gdbsim_ops.to_shortname = "sim";
+ gdbsim_ops.to_longname = "simulator";
+ gdbsim_ops.to_doc = "Use the compiled-in simulator.";
+ gdbsim_ops.to_open = gdbsim_open;
+ gdbsim_ops.to_close = gdbsim_close;
+ gdbsim_ops.to_attach = NULL;
+ gdbsim_ops.to_post_attach = NULL;
+ gdbsim_ops.to_require_attach = NULL;
+ gdbsim_ops.to_detach = gdbsim_detach;
+ gdbsim_ops.to_require_detach = NULL;
+ gdbsim_ops.to_resume = gdbsim_resume;
+ gdbsim_ops.to_wait = gdbsim_wait;
+ gdbsim_ops.to_post_wait = NULL;
+ gdbsim_ops.to_fetch_registers = gdbsim_fetch_register;
+ gdbsim_ops.to_store_registers = gdbsim_store_register;
+ gdbsim_ops.to_prepare_to_store = gdbsim_prepare_to_store;
+ gdbsim_ops.to_xfer_memory = gdbsim_xfer_inferior_memory;
+ gdbsim_ops.to_files_info = gdbsim_files_info;
+ gdbsim_ops.to_insert_breakpoint = gdbsim_insert_breakpoint;
+ gdbsim_ops.to_remove_breakpoint = gdbsim_remove_breakpoint;
+ gdbsim_ops.to_terminal_init = NULL;
+ gdbsim_ops.to_terminal_inferior = NULL;
+ gdbsim_ops.to_terminal_ours_for_output = NULL;
+ gdbsim_ops.to_terminal_ours = NULL;
+ gdbsim_ops.to_terminal_info = NULL;
+ gdbsim_ops.to_kill = gdbsim_kill;
+ gdbsim_ops.to_load = gdbsim_load;
+ gdbsim_ops.to_lookup_symbol = NULL;
+ gdbsim_ops.to_create_inferior = gdbsim_create_inferior;
gdbsim_ops.to_post_startup_inferior = NULL;
gdbsim_ops.to_acknowledge_created_inferior = NULL;
gdbsim_ops.to_clone_and_follow_inferior = NULL;
@@ -969,23 +939,23 @@ init_gdbsim_ops(void)
gdbsim_ops.to_has_execd = NULL;
gdbsim_ops.to_reported_exec_events_per_exec_call = NULL;
gdbsim_ops.to_has_exited = NULL;
- gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
- gdbsim_ops.to_can_run = 0;
- gdbsim_ops.to_notice_signals = 0;
- gdbsim_ops.to_thread_alive = 0;
- gdbsim_ops.to_stop = gdbsim_stop;
- gdbsim_ops.to_pid_to_exec_file = NULL;
- gdbsim_ops.to_core_file_to_sym_file = NULL;
- gdbsim_ops.to_stratum = process_stratum;
- gdbsim_ops.DONT_USE = NULL;
- gdbsim_ops.to_has_all_memory = 1;
- gdbsim_ops.to_has_memory = 1;
- gdbsim_ops.to_has_stack = 1;
- gdbsim_ops.to_has_registers = 1;
- gdbsim_ops.to_has_execution = 1;
- gdbsim_ops.to_sections = NULL;
- gdbsim_ops.to_sections_end = NULL;
- gdbsim_ops.to_magic = OPS_MAGIC;
+ gdbsim_ops.to_mourn_inferior = gdbsim_mourn_inferior;
+ gdbsim_ops.to_can_run = 0;
+ gdbsim_ops.to_notice_signals = 0;
+ gdbsim_ops.to_thread_alive = 0;
+ gdbsim_ops.to_stop = gdbsim_stop;
+ gdbsim_ops.to_pid_to_exec_file = NULL;
+ gdbsim_ops.to_core_file_to_sym_file = NULL;
+ gdbsim_ops.to_stratum = process_stratum;
+ gdbsim_ops.DONT_USE = NULL;
+ gdbsim_ops.to_has_all_memory = 1;
+ gdbsim_ops.to_has_memory = 1;
+ gdbsim_ops.to_has_stack = 1;
+ gdbsim_ops.to_has_registers = 1;
+ gdbsim_ops.to_has_execution = 1;
+ gdbsim_ops.to_sections = NULL;
+ gdbsim_ops.to_sections_end = NULL;
+ gdbsim_ops.to_magic = OPS_MAGIC;
#ifdef TARGET_REDEFINE_DEFAULT_OPS
TARGET_REDEFINE_DEFAULT_OPS (&gdbsim_ops);
@@ -995,9 +965,9 @@ init_gdbsim_ops(void)
void
_initialize_remote_sim ()
{
- init_gdbsim_ops() ;
+ init_gdbsim_ops ();
add_target (&gdbsim_ops);
add_com ("sim <command>", class_obscure, simulator_command,
- "Send a command to the simulator.");
+ "Send a command to the simulator.");
}
diff --git a/contrib/gdb/gdb/remote-st.c b/contrib/gdb/gdb/remote-st.c
index 1efdbfa..e820b28 100644
--- a/contrib/gdb/gdb/remote-st.c
+++ b/contrib/gdb/gdb/remote-st.c
@@ -2,27 +2,28 @@
Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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 was derived from remote-eb.c, which did a similar job, but for
an AMD-29K running EBMON. That file was in turn derived from remote.c
as mentioned in the following comment (left in for comic relief):
- "This is like remote.c but is for an esoteric situation--
+ "This is like remote.c but is for an esoteric situation--
having an a29k board in a PC hooked up to a unix machine with
a serial line, and running ctty com1 on the PC, through which
the unix machine can run ebmon. Not to mention that the PC
@@ -37,22 +38,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
-#include "wait.h"
-#ifdef ANSI_PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
+#include "gdb_wait.h"
#include <signal.h>
#include "gdb_string.h"
#include <sys/types.h>
#include "serial.h"
-extern struct target_ops st2000_ops; /* Forward declaration */
+extern struct target_ops st2000_ops; /* Forward declaration */
-static void st2000_close();
-static void st2000_fetch_register();
-static void st2000_store_register();
+static void st2000_close ();
+static void st2000_fetch_register ();
+static void st2000_store_register ();
#define LOG_FILE "st2000.log"
#if defined (LOG_FILE)
@@ -70,44 +66,33 @@ static serial_t st2000_desc;
/* Send data to stdebug. Works just like printf. */
static void
-#ifdef ANSI_PROTOTYPES
-printf_stdebug(char *pattern, ...)
-#else
-printf_stdebug(va_alist)
- va_dcl
-#endif
+printf_stdebug (char *pattern,...)
{
va_list args;
char buf[200];
-#ifdef ANSI_PROTOTYPES
- va_start(args, pattern);
-#else
- char *pattern;
- va_start(args);
- pattern = va_arg(args, char *);
-#endif
+ va_start (args, pattern);
- vsprintf(buf, pattern, args);
- va_end(args);
+ vsprintf (buf, pattern, args);
+ va_end (args);
- if (SERIAL_WRITE(st2000_desc, buf, strlen(buf)))
- fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+ if (SERIAL_WRITE (st2000_desc, buf, strlen (buf)))
+ fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
}
/* Read a character from the remote system, doing all the fancy timeout
stuff. */
static int
-readchar(timeout)
+readchar (timeout)
int timeout;
{
int c;
- c = SERIAL_READCHAR(st2000_desc, timeout);
+ c = SERIAL_READCHAR (st2000_desc, timeout);
#ifdef LOG_FILE
- putc(c & 0x7f, log_file);
+ putc (c & 0x7f, log_file);
#endif
if (c >= 0)
@@ -118,17 +103,17 @@ readchar(timeout)
if (timeout == 0)
return c; /* Polls shouldn't generate timeout errors */
- error("Timeout reading from remote system.");
+ error ("Timeout reading from remote system.");
}
- perror_with_name("remote-st2000");
+ perror_with_name ("remote-st2000");
}
/* Scan input from the remote system, until STRING is found. If DISCARD is
non-zero, then discard non-matching input, else print it out.
Let the user break out immediately. */
static void
-expect(string, discard)
+expect (string, discard)
char *string;
int discard;
{
@@ -138,7 +123,7 @@ expect(string, discard)
immediate_quit = 1;
while (1)
{
- c = readchar(timeout);
+ c = readchar (timeout);
if (c == *p++)
{
if (*p == '\0')
@@ -151,9 +136,9 @@ expect(string, discard)
{
if (!discard)
{
- fwrite(string, 1, (p - 1) - string, stdout);
- putchar((char)c);
- fflush(stdout);
+ fwrite (string, 1, (p - 1) - string, stdout);
+ putchar ((char) c);
+ fflush (stdout);
}
p = string;
}
@@ -175,13 +160,13 @@ expect(string, discard)
necessary to prevent getting into states from which we can't
recover. */
static void
-expect_prompt(discard)
+expect_prompt (discard)
int discard;
{
#if defined (LOG_FILE)
/* This is a convenient place to do this. The idea is to do it often
enough that we never lose much data if we terminate abnormally. */
- fflush(log_file);
+ fflush (log_file);
#endif
expect ("dbug> ", discard);
}
@@ -189,13 +174,13 @@ expect_prompt(discard)
/* Get a hex digit from the remote system & return its value.
If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
static int
-get_hex_digit(ignore_space)
+get_hex_digit (ignore_space)
int ignore_space;
{
int ch;
while (1)
{
- ch = readchar(timeout);
+ ch = readchar (timeout);
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
@@ -206,8 +191,8 @@ get_hex_digit(ignore_space)
;
else
{
- expect_prompt(1);
- error("Invalid hex digit from remote system.");
+ expect_prompt (1);
+ error ("Invalid hex digit from remote system.");
}
}
}
@@ -238,7 +223,7 @@ get_hex_regs (n, regno)
for (i = 0; i < n; i++)
{
int j;
-
+
val = 0;
for (j = 0; j < 8; j++)
val = (val << 4) + get_hex_digit (j == 0);
@@ -257,10 +242,10 @@ st2000_create_inferior (execfile, args, env)
int entry_pt;
if (args && *args)
- error("Can't pass arguments to remote STDEBUG process");
+ error ("Can't pass arguments to remote STDEBUG process");
if (execfile == 0 || exec_bfd == 0)
- error("No executable file specified");
+ error ("No executable file specified");
entry_pt = (int) bfd_get_start_address (exec_bfd);
@@ -281,7 +266,7 @@ st2000_create_inferior (execfile, args, env)
/* insert_step_breakpoint (); FIXME, do we need this? */
/* Let 'er rip... */
- proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
}
/* Open a connection to a remote debugger.
@@ -291,33 +276,33 @@ static int baudrate = 9600;
static char dev_name[100];
static void
-st2000_open(args, from_tty)
+st2000_open (args, from_tty)
char *args;
int from_tty;
{
int n;
char junk[100];
- target_preopen(from_tty);
-
- n = sscanf(args, " %s %d %s", dev_name, &baudrate, junk);
+ target_preopen (from_tty);
+
+ n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
if (n != 2)
- error("Bad arguments. Usage: target st2000 <device> <speed>\n\
+ error ("Bad arguments. Usage: target st2000 <device> <speed>\n\
or target st2000 <host> <port>\n");
- st2000_close(0);
+ st2000_close (0);
- st2000_desc = SERIAL_OPEN(dev_name);
+ st2000_desc = SERIAL_OPEN (dev_name);
if (!st2000_desc)
- perror_with_name(dev_name);
+ perror_with_name (dev_name);
- SERIAL_SETBAUDRATE(st2000_desc, baudrate);
+ SERIAL_SETBAUDRATE (st2000_desc, baudrate);
- SERIAL_RAW(st2000_desc);
+ SERIAL_RAW (st2000_desc);
- push_target(&st2000_ops);
+ push_target (&st2000_ops);
#if defined (LOG_FILE)
log_file = fopen (LOG_FILE, "w");
@@ -326,13 +311,13 @@ or target st2000 <host> <port>\n");
#endif
/* Hello? Are you there? */
- printf_stdebug("\003"); /* ^C wakes up dbug */
-
- expect_prompt(1);
+ printf_stdebug ("\003"); /* ^C wakes up dbug */
+
+ expect_prompt (1);
if (from_tty)
- printf("Remote %s connected to %s\n", target_shortname,
- dev_name);
+ printf ("Remote %s connected to %s\n", target_shortname,
+ dev_name);
}
/* Close out all files and local state before this target loses control. */
@@ -341,15 +326,16 @@ static void
st2000_close (quitting)
int quitting;
{
- SERIAL_CLOSE(st2000_desc);
+ SERIAL_CLOSE (st2000_desc);
#if defined (LOG_FILE)
- if (log_file) {
- if (ferror(log_file))
- fprintf(stderr, "Error writing log file.\n");
- if (fclose(log_file) != 0)
- fprintf(stderr, "Error closing log file.\n");
- }
+ if (log_file)
+ {
+ if (ferror (log_file))
+ fprintf (stderr, "Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ fprintf (stderr, "Error closing log file.\n");
+ }
#endif
}
@@ -360,11 +346,11 @@ static void
st2000_detach (from_tty)
int from_tty;
{
- pop_target(); /* calls st2000_close to do the real work */
+ pop_target (); /* calls st2000_close to do the real work */
if (from_tty)
printf ("Ending remote %s debugging\n", target_shortname);
}
-
+
/* Tell the remote machine to resume. */
static void
@@ -398,9 +384,9 @@ st2000_wait (status)
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
- timeout = 0; /* Don't time out -- user program is running. */
+ timeout = 0; /* Don't time out -- user program is running. */
- expect_prompt(0); /* Wait for prompt, outputting extraneous text */
+ expect_prompt (0); /* Wait for prompt, outputting extraneous text */
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = TARGET_SIGNAL_TRAP;
@@ -425,7 +411,7 @@ get_reg_name (regno)
b = buf;
for (p = REGISTER_NAME (regno); *p; p++)
- *b++ = toupper(*p);
+ *b++ = toupper (*p);
*b = '\000';
return buf;
@@ -442,7 +428,7 @@ st2000_fetch_registers ()
very often... I'll clean it up later. */
for (regno = 0; regno <= PC_REGNUM; regno++)
- st2000_fetch_register(regno);
+ st2000_fetch_register (regno);
}
/* Fetch register REGNO, or all registers if REGNO is -1.
@@ -473,7 +459,7 @@ st2000_store_registers ()
int regno;
for (regno = 0; regno <= PC_REGNUM; regno++)
- st2000_store_register(regno);
+ st2000_store_register (regno);
registers_changed ();
}
@@ -535,7 +521,7 @@ st2000_write_inferior_memory (memaddr, myaddr, len)
/* Read LEN bytes from inferior memory at MEMADDR. Put the result
at debugger address MYADDR. Returns length moved. */
static int
-st2000_read_inferior_memory(memaddr, myaddr, len)
+st2000_read_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
@@ -560,11 +546,12 @@ st2000_read_inferior_memory(memaddr, myaddr, len)
st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
doesn't need to work. Detect it and give up if there's an attempt
to do that. */
- if (((memaddr - 1) + len) < memaddr) {
- errno = EIO;
- return 0;
- }
-
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
startaddr = memaddr;
count = 0;
while (count < len)
@@ -595,7 +582,7 @@ st2000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
char *myaddr;
int len;
int write;
- struct target_ops *target; /* ignored */
+ struct target_ops *target; /* ignored */
{
if (write)
return st2000_write_inferior_memory (memaddr, myaddr, len);
@@ -608,7 +595,7 @@ st2000_kill (args, from_tty)
char *args;
int from_tty;
{
- return; /* Ignore attempts to kill target system */
+ return; /* Ignore attempts to kill target system */
}
/* Clean up when a program exits.
@@ -627,7 +614,8 @@ st2000_mourn_inferior ()
#define MAX_STDEBUG_BREAKPOINTS 16
-static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] = {0};
+static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] =
+{0};
static int
st2000_insert_breakpoint (addr, shadow)
@@ -646,12 +634,12 @@ st2000_insert_breakpoint (addr, shadow)
breakaddr[i] = addr;
st2000_read_inferior_memory (bp_addr, shadow, bp_size);
- printf_stdebug("BR %x H\r", addr);
- expect_prompt(1);
+ printf_stdebug ("BR %x H\r", addr);
+ expect_prompt (1);
return 0;
}
- fprintf(stderr, "Too many breakpoints (> 16) for STDBUG\n");
+ fprintf (stderr, "Too many breakpoints (> 16) for STDBUG\n");
return 1;
}
@@ -667,12 +655,12 @@ st2000_remove_breakpoint (addr, shadow)
{
breakaddr[i] = 0;
- printf_stdebug("CB %d\r", i);
- expect_prompt(1);
+ printf_stdebug ("CB %d\r", i);
+ expect_prompt (1);
return 0;
}
- fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ fprintf (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
return 1;
}
@@ -682,29 +670,29 @@ st2000_remove_breakpoint (addr, shadow)
static void
st2000_command (args, fromtty)
- char *args;
- int fromtty;
+ char *args;
+ int fromtty;
{
if (!st2000_desc)
- error("st2000 target not open.");
-
+ error ("st2000 target not open.");
+
if (!args)
- error("Missing command.");
-
- printf_stdebug("%s\r", args);
- expect_prompt(0);
+ error ("Missing command.");
+
+ printf_stdebug ("%s\r", args);
+ expect_prompt (0);
}
/* Connect the user directly to STDBUG. This command acts just like the
'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
-/*static struct ttystate ttystate;*/
+/*static struct ttystate ttystate; */
static void
-cleanup_tty()
+cleanup_tty ()
{
- printf("\r\n[Exiting connect mode]\r\n");
-/* SERIAL_RESTORE(0, &ttystate);*/
+ printf ("\r\n[Exiting connect mode]\r\n");
+/* SERIAL_RESTORE(0, &ttystate); */
}
#if 0
@@ -712,50 +700,50 @@ cleanup_tty()
static void
connect_command (args, fromtty)
- char *args;
- int fromtty;
+ char *args;
+ int fromtty;
{
fd_set readfds;
int numfds;
int c;
char cur_esc = 0;
- dont_repeat();
+ dont_repeat ();
if (st2000_desc < 0)
- error("st2000 target not open.");
-
+ error ("st2000 target not open.");
+
if (args)
- fprintf("This command takes no args. They have been ignored.\n");
-
- printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+ fprintf ("This command takes no args. They have been ignored.\n");
- serial_raw(0, &ttystate);
+ printf ("[Entering connect mode. Use ~. or ~^D to escape]\n");
- make_cleanup(cleanup_tty, 0);
+ serial_raw (0, &ttystate);
- FD_ZERO(&readfds);
+ make_cleanup (cleanup_tty, 0);
+
+ FD_ZERO (&readfds);
while (1)
{
do
{
- FD_SET(0, &readfds);
- FD_SET(st2000_desc, &readfds);
- numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
+ FD_SET (0, &readfds);
+ FD_SET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds);
+ numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
}
while (numfds == 0);
if (numfds < 0)
- perror_with_name("select");
+ perror_with_name ("select");
- if (FD_ISSET(0, &readfds))
+ if (FD_ISSET (0, &readfds))
{ /* tty input, send to stdebug */
- c = getchar();
+ c = getchar ();
if (c < 0)
- perror_with_name("connect");
+ perror_with_name ("connect");
- printf_stdebug("%c", c);
+ printf_stdebug ("%c", c);
switch (cur_esc)
{
case 0:
@@ -776,16 +764,16 @@ connect_command (args, fromtty)
}
}
- if (FD_ISSET(st2000_desc, &readfds))
+ if (FD_ISSET (DEPRECATED_SERIAL_FD (st2000_desc), &readfds))
{
while (1)
{
- c = readchar(0);
+ c = readchar (0);
if (c < 0)
break;
- putchar(c);
+ putchar (c);
}
- fflush(stdout);
+ fflush (stdout);
}
}
}
@@ -793,43 +781,43 @@ connect_command (args, fromtty)
/* Define the target subroutine names */
-struct target_ops st2000_ops ;
+struct target_ops st2000_ops;
-static void
-init_st2000_ops(void)
+static void
+init_st2000_ops (void)
{
- st2000_ops.to_shortname = "st2000";
- st2000_ops.to_longname = "Remote serial Tandem ST2000 target";
- st2000_ops.to_doc = "Use a remote computer running STDEBUG connected by a serial line;\n\
+ st2000_ops.to_shortname = "st2000";
+ st2000_ops.to_longname = "Remote serial Tandem ST2000 target";
+ st2000_ops.to_doc = "Use a remote computer running STDEBUG connected by a serial line;\n\
or a network connection.\n\
Arguments are the name of the device for the serial line,\n\
-the speed to connect at in bits per second." ;
- st2000_ops.to_open = st2000_open;
- st2000_ops.to_close = st2000_close;
- st2000_ops.to_attach = 0;
+the speed to connect at in bits per second.";
+ st2000_ops.to_open = st2000_open;
+ st2000_ops.to_close = st2000_close;
+ st2000_ops.to_attach = 0;
st2000_run_ops.to_post_attach = NULL;
st2000_ops.to_require_attach = NULL;
- st2000_ops.to_detach = st2000_detach;
+ st2000_ops.to_detach = st2000_detach;
st2000_ops.to_require_detach = NULL;
- st2000_ops.to_resume = st2000_resume;
- st2000_ops.to_wait = st2000_wait;
+ st2000_ops.to_resume = st2000_resume;
+ st2000_ops.to_wait = st2000_wait;
st2000_ops.to_post_wait = NULL;
- st2000_ops.to_fetch_registers = st2000_fetch_register;
- st2000_ops.to_store_registers = st2000_store_register;
- st2000_ops.to_prepare_to_store = st2000_prepare_to_store;
- st2000_ops.to_xfer_memory = st2000_xfer_inferior_memory;
- st2000_ops.to_files_info = st2000_files_info;
- st2000_ops.to_insert_breakpoint = st2000_insert_breakpoint;
- st2000_ops.to_remove_breakpoint = st2000_remove_breakpoint; /* Breakpoints */
- st2000_ops.to_terminal_init = 0;
- st2000_ops.to_terminal_inferior = 0;
- st2000_ops.to_terminal_ours_for_output = 0;
- st2000_ops.to_terminal_ours = 0;
- st2000_ops.to_terminal_info = 0; /* Terminal handling */
- st2000_ops.to_kill = st2000_kill;
- st2000_ops.to_load = 0; /* load */
- st2000_ops.to_lookup_symbol = 0; /* lookup_symbol */
- st2000_ops.to_create_inferior = st2000_create_inferior;
+ st2000_ops.to_fetch_registers = st2000_fetch_register;
+ st2000_ops.to_store_registers = st2000_store_register;
+ st2000_ops.to_prepare_to_store = st2000_prepare_to_store;
+ st2000_ops.to_xfer_memory = st2000_xfer_inferior_memory;
+ st2000_ops.to_files_info = st2000_files_info;
+ st2000_ops.to_insert_breakpoint = st2000_insert_breakpoint;
+ st2000_ops.to_remove_breakpoint = st2000_remove_breakpoint; /* Breakpoints */
+ st2000_ops.to_terminal_init = 0;
+ st2000_ops.to_terminal_inferior = 0;
+ st2000_ops.to_terminal_ours_for_output = 0;
+ st2000_ops.to_terminal_ours = 0;
+ st2000_ops.to_terminal_info = 0; /* Terminal handling */
+ st2000_ops.to_kill = st2000_kill;
+ st2000_ops.to_load = 0; /* load */
+ st2000_ops.to_lookup_symbol = 0; /* lookup_symbol */
+ st2000_ops.to_create_inferior = st2000_create_inferior;
st2000_ops.to_post_startup_inferior = NULL;
st2000_ops.to_acknowledge_created_inferior = NULL;
st2000_ops.to_clone_and_follow_inferior = NULL;
@@ -847,29 +835,29 @@ the speed to connect at in bits per second." ;
st2000_run_ops.to_has_execd = NULL;
st2000_run_ops.to_reported_exec_events_per_exec_call = NULL;
st2000_run_ops.to_has_exited = NULL;
- st2000_ops.to_mourn_inferior = st2000_mourn_inferior;
- st2000_ops.to_can_run = 0; /* can_run */
- st2000_ops.to_notice_signals = 0; /* notice_signals */
- st2000_ops.to_thread_alive = 0; /* thread alive */
- st2000_ops.to_stop = 0; /* to_stop */
+ st2000_ops.to_mourn_inferior = st2000_mourn_inferior;
+ st2000_ops.to_can_run = 0; /* can_run */
+ st2000_ops.to_notice_signals = 0; /* notice_signals */
+ st2000_ops.to_thread_alive = 0; /* thread alive */
+ st2000_ops.to_stop = 0; /* to_stop */
st2000_ops.to_pid_to_exec_file = NULL;
st2000_run_ops.to_core_file_to_sym_file = NULL;
- st2000_ops.to_stratum = process_stratum;
- st2000_ops.DONT_USE = 0; /* next */
- st2000_ops.to_has_all_memory = 1;
- st2000_ops.to_has_memory = 1;
- st2000_ops.to_has_stack = 1;
- st2000_ops.to_has_registers = 1;
- st2000_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
- st2000_ops.to_sections = 0;
- st2000_ops.to_sections_end = 0; /* Section pointers */
- st2000_ops.to_magic = OPS_MAGIC; /* Always the last thing */
-} ;
+ st2000_ops.to_stratum = process_stratum;
+ st2000_ops.DONT_USE = 0; /* next */
+ st2000_ops.to_has_all_memory = 1;
+ st2000_ops.to_has_memory = 1;
+ st2000_ops.to_has_stack = 1;
+ st2000_ops.to_has_registers = 1;
+ st2000_ops.to_has_execution = 1; /* all mem, mem, stack, regs, exec */
+ st2000_ops.to_sections = 0;
+ st2000_ops.to_sections_end = 0; /* Section pointers */
+ st2000_ops.to_magic = OPS_MAGIC; /* Always the last thing */
+};
void
_initialize_remote_st2000 ()
{
- init_st2000_ops() ;
+ init_st2000_ops ();
add_target (&st2000_ops);
add_com ("st2000 <command>", class_obscure, st2000_command,
"Send a command to the STDBUG monitor.");
diff --git a/contrib/gdb/gdb/srec.h b/contrib/gdb/gdb/srec.h
index 8253e03..ac18e9f 100644
--- a/contrib/gdb/gdb/srec.h
+++ b/contrib/gdb/gdb/srec.h
@@ -1,25 +1,26 @@
/* S-record download support for GDB, the GNU debugger.
Copyright 1995, 1996 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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. */
void load_srec PARAMS ((serial_t desc, const char *file, bfd_vma load_offset,
int maxrecsize, int flags, int hashmark,
- int (*waitack)(void)));
+ int (*waitack) (void)));
/* S-record capability flags */
@@ -33,4 +34,4 @@ void load_srec PARAMS ((serial_t desc, const char *file, bfd_vma load_offset,
| ((SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR) \
<< SREC_TERM_SHIFT))
-#define SREC_BINARY 0x00000040 /* Supports binary form of S-records */
+#define SREC_BINARY 0x00000040 /* Supports binary form of S-records */
diff --git a/contrib/gdb/gdb/standalone.c b/contrib/gdb/gdb/standalone.c
index 13fc476..ebb14d9 100644
--- a/contrib/gdb/gdb/standalone.c
+++ b/contrib/gdb/gdb/standalone.c
@@ -1,21 +1,22 @@
/* Interface to bare machine for GDB running as kernel debugger.
Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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>
#include <sys/ioctl.h>
@@ -33,19 +34,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
-#include "wait.h"
-
+#include "gdb_wait.h"
+
/* Random system calls, mostly no-ops to prevent link problems */
ioctl (desc, code, arg)
-{}
+{
+}
-int (* signal ()) ()
-{}
+int (*signal ()) ()
+{
+}
kill ()
-{}
+{
+}
getpid ()
{
@@ -53,10 +57,12 @@ getpid ()
}
sigsetmask ()
-{}
+{
+}
chdir ()
-{}
+{
+}
char *
getcwd (buf, len)
@@ -92,7 +98,7 @@ exit ()
char[] name of the file, ending with a null.
padding to multiple of 4 boundary.
char[] file contents. The length can be deduced from what was
- specified before. There is no terminating null here.
+ specified before. There is no terminating null here.
If the int at the front is zero, it means there are no more files.
@@ -141,14 +147,14 @@ open (filename, modes)
return -1;
}
- for (next = files_start; * (int *) next; next += * (int *) next)
+ for (next = files_start; *(int *) next; next += *(int *) next)
{
if (!STRCMP (next + 4, filename))
{
sourcebeg = next + 4 + strlen (next + 4) + 1;
sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
sourceptr = sourcebeg;
- sourcesize = next + * (int *) next - sourceptr;
+ sourcesize = next + *(int *) next - sourceptr;
sourceleft = sourcesize;
return sourcedesc;
}
@@ -324,10 +330,12 @@ fflush (ign)
/* Entries into core and inflow, needed only to make things link ok. */
exec_file_command ()
-{}
+{
+}
core_file_command ()
-{}
+{
+}
char *
get_exec_file (err)
@@ -350,19 +358,24 @@ kill_command ()
}
terminal_inferior ()
-{}
+{
+}
terminal_ours ()
-{}
+{
+}
terminal_init_inferior ()
-{}
+{
+}
write_inferior_register ()
-{}
+{
+}
read_inferior_register ()
-{}
+{
+}
read_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
@@ -417,16 +430,20 @@ vfork ()
and these definitions are so it will link without errors. */
ptrace ()
-{}
+{
+}
setpgrp ()
-{}
+{
+}
execle ()
-{}
+{
+}
_exit ()
-{}
+{
+}
/* Malloc calls these. */
@@ -564,7 +581,8 @@ wait (w)
#define HEAP_SIZE 400000
#endif
-char heap[HEAP_SIZE] = {0};
+char heap[HEAP_SIZE] =
+{0};
#ifndef STACK_SIZE
#define STACK_SIZE 100000
@@ -583,11 +601,12 @@ _initialize_standalone ()
/* Find the end of the data on files. */
- for (next = files_start; * (int *) next; next += * (int *) next) {}
+ for (next = files_start; *(int *) next; next += *(int *) next)
+ {
+ }
/* That is where free storage starts for sbrk to give out. */
next_free = next;
memory_limit = heap + sizeof heap;
}
-
diff --git a/contrib/gdb/gdb/stuff.c b/contrib/gdb/gdb/stuff.c
index eedbeab..babd29f 100644
--- a/contrib/gdb/gdb/stuff.c
+++ b/contrib/gdb/gdb/stuff.c
@@ -1,21 +1,22 @@
/* Program to stuff files into a specially prepared space in kdb.
Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
-This file is part of GDB.
+ 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 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.
+ 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. */
+ 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 13-Mar-86 by David Bridgham. */
@@ -38,11 +39,12 @@ main (argc, argv)
struct stat stat_buf;
int size, pad;
char buf[1024];
- static char zeros[4] = {0};
+ static char zeros[4] =
+ {0};
if (argc < 4)
- err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
- argv[0]);
+ err ("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+ argv[0]);
outfile = 0;
for (i = 1; i < argc; i++)
@@ -51,7 +53,7 @@ main (argc, argv)
outfile = argv[++i];
}
if (outfile == 0)
- err("Output file not specified\n");
+ err ("Output file not specified\n");
offset = get_offset (outfile, "_heap");
@@ -111,7 +113,7 @@ get_offset (file, sym_name)
err ("File %s not an a.out file\n", file);
/* read in symbol table */
- if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+ if ((symbol_table = (struct nlist *) malloc (file_hdr.a_syms)) == 0)
err ("Couldn't allocate space for symbol table\n");
if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
err ("lseek error: %s\n", strerror (errno));
@@ -122,7 +124,7 @@ get_offset (file, sym_name)
/* read in string table */
if (read (f, &size, 4) == -1)
err ("reading string table size: %s\n", strerror (errno));
- if ((strings = (char *)malloc (size)) == 0)
+ if ((strings = (char *) malloc (size)) == 0)
err ("Couldn't allocate memory for string table\n");
if (read (f, strings, size - 4) == -1)
err ("reading string table: %s\n", strerror (errno));
@@ -147,15 +149,17 @@ find_symbol (sym_name, symbol_table, length, strings)
/* Find symbol in question */
for (sym = symbol_table;
- sym != (struct nlist *)((char *)symbol_table + length);
+ sym != (struct nlist *) ((char *) symbol_table + length);
sym++)
- {
- if ((sym->n_type & N_TYPE) != N_DATA) continue;
- if (sym->n_un.n_strx == 0) continue;
- if (STREQ (sym_name, strings + sym->n_un.n_strx - 4))
- return sym->n_value;
- }
- err ("Data symbol %s not found in %s\n", sym_name, file);
+ {
+ if ((sym->n_type & N_TYPE) != N_DATA)
+ continue;
+ if (sym->n_un.n_strx == 0)
+ continue;
+ if (STREQ (sym_name, strings + sym->n_un.n_strx - 4))
+ return sym->n_value;
+ }
+ err ("Data symbol %s not found in %s\n", sym_name, file);
}
/* VARARGS */
OpenPOWER on IntegriCloud