import gdb-1999-12-21 snapshot

This commit is contained in:
Jason Molenda 1999-12-22 21:45:38 +00:00
parent d3a0947552
commit ed9a39ebf9
69 changed files with 6196 additions and 1946 deletions

View File

@ -1,3 +1,276 @@
1999-12-21 Stan Shebs <shebs@andros.cygnus.com>
* blockframe.c (generic_pop_current_frame): Cosmetic changes to
clarify.
1999-12-21 Jim Blandy <jimb@cygnus.com>
* Makefile.in (elf_bfd_h): Look for elf-bfd.h in BFD_SRC, not
BFD_DIR. Unlike bfd.h, it is not a generated file.
Fri Dec 17 18:24:58 1999 David Taylor <taylor@texas.cygnus.com>
* language.c (_initialize_language): move settings of language,
range, and type and corresponding function calls
set_language_command, set_type_command, and set_range_command
closer together to match the model of having the user set the
variable via the 'set {language | range | type}' commands.
This eliminates startup noise introduced by Jimmy Guo's change
of Dec 13th.
1999-12-17 Michael Snyder <msnyder@cleaver.cygnus.com>
* configure.in: test for <stdint.h>, which is not available
on earlier versions of Linux.
* config.in: define HAVE_STDINT_H if it's present.
* configure: autoconfiscate.
* lin-thread.c: if not HAVE_STDINT_H, stub out the entire module.
Fri Dec 17 20:45:21 1999 Andrew Cagney <cagney@b1.cygnus.com>
* target.c (find_target_beneath): Change ``='' in if to ``==''.
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
* defs.h (TIDGET): add default definition.
* lin-thread.c (check_for_thread_event): for now, just provide
an empty definition (to be filled in later).
1999-12-16 Fernando Nasser <fnasser@totem.to.cygnus.com>
* varobj.c (varobj_list): Improve the test and the text of the
assertion that guards against wrong tally of root varobjs.
(uninstall_variable): Fix for a bug in which the number of root
varobjs was not decremented if the first one in the list was deleted.
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
* linux-thread.c: Remove printf-debugging code.
* lin-thread.c: ditto.
* config/alpha/nm-linux.h: protect with NM_LINUX_H.
* testsuite/gdb.threads/linux-dp.exp: Make test for "New Thread"
message more forgiving. Ditto test for "info threads".
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
* lin-thread.c: new file. Implements multi-thread debugging on
Linux using the thread_db API first implemented on Solaris. This
frees GDB from any dependency on the internal implementation of
the thread library. Future versions of the thread library will
implement a libthread_db API for debuggers, which GDB will use.
* config/i386/linux.mh: add lin-thread.o to the link, and add
-ldl and -rdynamic since libthread_db is a dynamic library.
* config/alpha/alpha-linux.mh: ditto.
* configure.in: test for thread_db.h, proc_service.h
* configure: autoconf.
* config.in: conditionally define HAVE_THREAD_DB_H
and HAVE_PROC_SERVICE_H
* gdb_thread_db.h: new file, used when the system doesn't have it.
* gdb_proc_service.h: ditto.
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
* linux-thread.c: changes to accomodate the new lin-thread.c
module based on the thread_db API. These changes make parts of
linux-thread.c shareable with lin-thread.c.
(linuxthreads_wait_mask): replace with linuxthreads_block_mask.
(using_thread_db): new variable. Allows linux-thread module to
detect when lin-thread (thread_db API) module is in use.
(save_inferior_pid, restore_inferior_pid): make 32/64 bit safe.
(check_all_signal_numbers) make extern, shared with lin-thead.c.
(linuxthreads_new_objfile): use target_new_objfile_chain to share
this hook with the lin-thread module. Call the other module FIRST.
If using_thread_db is turned on by the other thread module, do not
set linuxthreads_debug and do not call update_stop_threads. Do call
check_all_signal_numbers, to be sure it gets set before target_wait.
(linux_child_wait): new function. Abstracts out the "child_wait"
functionality, so that it can be shared with the lin-thread module.
(linuxthreads_wait): call linux_child_wait, instead of doing the
waiting inline. If using_thread_db, do not call update_stop_threads
and do not turn on linuxthreads_debug.
(linuxthreads_mourn_inferior): abstract out the clearing of global
state, so that it can be shared with the lin-thread.c module.
(_initialize_linuxthreads): use linuxthreads_wait_mask to block
SIGCHLD exactly ONCE, and leave it blocked! Then linux_child_wait
will call sigsuspend when it wants to wait for this signal.
(thread_attach): abstract out ptrace attach to share with lin-thread.c
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
Make target_pid_to_str a target_ops vector.
* target.h (target_pid_to_str): redefine to use a target_ops vector.
(target_tid_to_str): default to using target_pid_to_str.
(target_pid_or_tid_to_str): ditto.
* target.c (update_current_target): inherit to_pid_to_str method.
(find_target_beneath): new function. Find target stratum below
the given one.
* config/nm-gnu.h: don't define target_pid_to_str.
* config/i386/tm-i386sol2.h: ditto.
* config/sparc/tm-sun4sol2.h: ditto.
* gnu-nat.c (init_gnu_ops): initialize to_pid_to_str vector.
* linux-thread.c (init_linuxthreads_ops): ditto.
* sol-thread.c (init_sol_thread_ops: ditto.
* procfs.c (init_procfs_ops): ditto.
* win32-nat.c (init_child_ops): ditto.
* config/i386/tm-cygwin.h: don't define target_pid_to_str.
* inftarg.c (child_pid_to_str): new function, used to initialize
to_pid_to_str vector. May be suppressed by defining CHILD_PID_TO_STR.
(init_child_ops): initialize to_pid_to_str using child_pid_to_str.
Derivative modules may substitute their own child_pid_to_str func
by defining CHILD_PID_TO_STR.
* lynx-nat.c (lynx_pid_to_str): rename to child_pid_to_str.
* config/nm-lynx.h: define CHILD_PID_TO_STR.
Don't define target_pid_to_str.
* hppah-nat.c (hppa_pid_to_str): rename to child_pid_to_str.
* infttrace.c (hppa_pid_or_tid_to_str): call child_pid_to str
instead of hppa_pid_to_str.
* config/pa/nm-hppah.h: define CHILD_PID_TO_STR.
Don't define target_pid_to_str.
1999-12-16 Michael Snyder <msnyder@cleaver.cygnus.com>
* i386-linux-nat.c: introduce PIDGET/TIDGET macros as on Solaris,
preparatory to using the thread_db debugging API for Linux.
(fill_gregset): guard against invalid input.
(fetch_regs): add a pid/thread_id argument, so we can fetch regs
from multiple processes/clones/threads. (store_regs): ditto.
(fetch_fpregs): ditto. (store_fpregs): ditto.
(fetch_xfpregs): ditto. (store_xfpregs): ditto.
(fetch_inferior_registers): use TIDGET to extract an appropriate
thread/clone/process id from inferior_pid, if there's one there,
and pass it to fetch_regs etc. (store_inferior_registers): ditto.
* infptrace.c: include every available version of wait.h.
introduce PIDGET/TIDGET macros for use with thread_db API on Linux.
(call_ptrace): rearrange lines that were split by an ifdef.
(fetch_register): use TIDGET to extract an appropriate process ID
from inferior_pid, in case we are debugging more than one process.
(store_register): ditto. This is for Linux.
(child_xfer_memory): use PIDGET to extract the main process id from
inferior_pid, in case we are debugging multiple processes that share
the same address space (as on Linux).
1999-12-16 Christopher Faylor <cgf@cygnus.com>
* win32-nat.c: Add a missing register to mappings array.
(child_fetch_inferior_registers): Use precalculated index into mappings
array as supply_registers argument.
(handle_output_debug_string): Avoid considering every debug string as a
cygwin signal.
(handle_exception): Trap first chance exceptions.
(child_create_inferior): Initialize Microsoft thread walking API.
(sgmb): New function. Used by Microsoft API for stack walking.
(child_frame_chain): New function. Uses Microsoft API for stack
walking.
(child_frame_chain_saved_pc): Ditto.
* config/i386/tm-cygwin.h: Define frame handling stuff.
1999-12-15 Stan Shebs <shebs@andros.cygnus.com>
ARM GNU/Linux support and general ARM target fixes/cleanup from
Scott Bambrough <scottb@netwinder.org>, plus obsoletion of the old
RISCix support.
* NEWS: Mention addition and obsoletion.
* configure.host: Recognize arm* instead of just arm.
(arm*-*-linux*): Recognize.
* configure.tgt: Ditto, plus assume arm*-*-* is embedded.
* config/arm/arm.mh, config/arm/arm.mt, config/arm/nm-arm.h,
config/arm/xm-arm.h: Mark as OBSOLETE.
* config/arm/embed.mt, config/arm/tm-embed.h: New files.
* config/arm/linux.mh, config/arm/linux.mt, config/arm/nm-linux.h,
config/arm/tm-linux.h, config/arm/xm-linux.h: Ditto.
* config/arm/tm-arm.h: Add more comments, eliminate PARAMS.
(STACK_END_ADDR): Remove.
(ARM_LE_BREAKPOINT, ARM_BE_BREAKPOINT, THUMB_LE_BREAKPOINT,
THUMB_BE_BREAKPOINT): Move to here from arm-tdep.c.
(NUM_REGS): Define as sum.
(NUM_FREGS, NUM_SREGS, NUM_GREGS): New definitions.
(FP_REGISTER_RAW_SIZE, FP_REGISTER_VIRTUAL_SIZE,
STATUS_REGISTER_SIZE): Define.
(REGISTER_BYTES, REGISTER_BYTE, REGISTER_RAW_SIZE,
REGISTER_VIRTUAL_SIZE): Rewrite to use symbolic values.
(REGISTER_CONVERTIBLE, REGISTER_CONVERT_TO_VIRTUAL,
REGISTER_CONVERT_TO_RAW, USE_STRUCT_CONVENTION,
EXTRACT_RETURN_VALUE): Rewrite to use new functions.
(IN_SIGTRAMP): Remove definition.
* arm-convert.s: Mark as OBSOLETE.
* arm-linux-nat.c: New file.
* Makefile.in: Add build rule for it.
* arm-tdep.c (struct frame_extra_info): New struct.
(arm_use_struct_convention): Rewrite.
(arm_push_arguments): Rewrite to handle more cases.
(arm_register_convertible, arm_register_convert_to_virtual,
arm_register_convert_to_raw, arm_extract_return_value): New
functions.
(LITTLE_BREAKPOINT, BIG_BREAKPOINT): Remove.
* arm-xdep.c: Mark as OBSOLETE.
1999-12-15 Elena Zannoni <ezannoni@kwikemart.cygnus.com>
* infcmd.c (run_stack_dummy): Temporarily lie about the target
ability to support asynchronous execution.
* remote.c (remote_can_async_p, remote_is_async_p): Return true
iff to_async_mask_value is true too.
(remote_async): Error out if called when to_async_mask_value is 0.
(init_remote_async_ops): Initialize to_async_mask_value to 1.
(remote_async_detach, remote_async_resume, remote_async_wait,
remote_async_kill): Change SERIAL_IS_ASYNC_P call to
target_is_async_p call.
(remote_async_resume): Change SERIAL_CAN_ASYNC_P call to
target_can_async_p call.
* target.c (update_current_target): Inherit to_async_mask_value.
(target_async_mask): New function. To temporarily turn the target
into a synchronous one for inferior function calls, and back to
asynchronous.
* target.h (to_async_mask_value): New entry in the target
vector.
(target_async_mask): Export.
(target_async_mask_value): Define.
Wed Dec 15 11:24:32 1999 Jeffrey A Law (law@cygnus.com)
* hp-psymtab-read.c (trans_lang): Use HP_LANGUAGE_FORTRAN instead
of HP_LANGUAGE_F77.
Wed Dec 15 13:37:55 1999 Andrew Cagney <cagney@b1.cygnus.com>
* gdb-events.h, gdb-events.c (set_gdb_event_hooks): Return the old
event hooks vector.
1999-08-13 Jim Kingdon <http://developer.redhat.com/>
* breakpoint.c (bpstat_stop_status): Revert 1998-09-08 change
to ->frame matching. The change did not match the ChangeLog
entry, looked fishy, and caused infinite stepping when running
"next" from main on sparc w/ RH Linux. Thanks to Jakub for the
report.
1999-12-14 Stan Shebs <shebs@andros.cygnus.com>
* arm-tdep.c (arm_get_next_pc): Add argument to shifted_reg_val
call.
1999-12-14 Mark Salter <msalter@cygnus.com>
* mips-tdep.c (mips_print_register): Fix printing of individual
registers when REGISTER_VIRTUAL_SIZE != REGISTER_RAW_SIZE.
Tue Dec 14 23:29:19 1999 Andrew Cagney <cagney@b1.cygnus.com>
* defs.h (mcalloc): Delcare.
* utils.c (xcalloc, mcalloc): New functions.
1999-12-13 Stan Shebs <shebs@andros.cygnus.com>
* config/arm/tm-arm.h: Reformat comments, in preparation for
real changes.
* arm-tdep.c: Similarly, plus change function definitions to
modern form.
1999-12-13 Michael Snyder <msnyder@cleaver.cygnus.com>
* breakpoint.h (enum bptype): add new BP type bp_thread_event.
@ -396,7 +669,7 @@ Thu Dec 2 17:14:53 1999 Andrew Cagney <cagney@b1.cygnus.com>
signal that we are ignoring, and GDB silently resumes the child,
resume ALL threads (not just the one that got the signal). All
threads are stopped, so all must be resumed.
(handle_inferior_pid): on detecting a thread context switch,
(handle_inferior_event): on detecting a thread context switch,
swap infrun_state ONLY if both the old thread and the new one
are in the thread list. Otherwise state information will be lost!
Problem may arise with flaky back-ends.

View File

@ -229,7 +229,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
VERSION = 19991213
VERSION = 19991221
DIST=gdb
LINT=/usr/5bin/lint
@ -414,7 +414,7 @@ LINTFILES = $(SFILES) $(YYFILES) @CONFIG_SRCS@ init.c
getopt_h = $(INCLUDE_DIR)/getopt.h
floatformat_h = $(INCLUDE_DIR)/floatformat.h
bfd_h = $(BFD_DIR)/bfd.h
elf_bfd_h = $(BFD_DIR)/elf-bfd.h
elf_bfd_h = $(BFD_SRC)/elf-bfd.h
wait_h = $(INCLUDE_DIR)/wait.h
dis-asm_h = $(INCLUDE_DIR)/dis-asm.h
remote-sim_h = $(INCLUDE_DIR)/remote-sim.h
@ -956,7 +956,7 @@ ALLDEPFILES = 29k-share/udi/udip2soc.c 29k-share/udi/udr.c \
29k-share/udi/udi2go32.c \
a29k-tdep.c a68v-nat.c alpha-nat.c alpha-tdep.c \
altos-xdep.c arm-convert.s \
arm-tdep.c arm-xdep.c coff-solib.c \
arm-linux-nat.c arm-tdep.c arm-xdep.c coff-solib.c \
convex-tdep.c convex-xdep.c \
core-sol2.c core-regset.c core-aout.c corelow.c \
dcache.c delta68-nat.c dpx2-nat.c dstread.c exec.c fork-child.c \
@ -1017,6 +1017,9 @@ alpha-tdep.o: alpha-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
annotate.o: annotate.c $(defs_h) annotate.h $(value_h) target.h $(gdbtypes_h)
arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
gdb_string.h
arm-tdep.o: arm-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h) \
$(gdbcore_h)

View File

@ -9,6 +9,10 @@ On SVR4 native platforms (such as Solaris), if you attach to a process
without first loading a symbol file, GDB will now attempt to locate and
load symbols from the running process's executable file.
* New native configurations
ARM GNU/Linux arm*-*-linux*
* New targets
Motorola MCore mcore-*-*
@ -21,6 +25,7 @@ TI TMS320C80 tic80-*-*
Altos 3068 m68*-altos-*
Convex c1-*-*, c2-*-*
Pyramid pyramid-*-*
ARM RISCix arm-*-* (as host)
Tahoe tahoe-*-*
* Remote targets can connect to a sub-program

View File

@ -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 */

547
gdb/arm-linux-nat.c Normal file
View File

@ -0,0 +1,547 @@
/* GNU/Linux on ARM native support.
Copyright 1999 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "gdb_string.h"
#include <sys/user.h>
#include <sys/ptrace.h>
#include <sys/utsname.h>
extern int arm_apcs_32;
#define typeNone 0x00
#define typeSingle 0x01
#define typeDouble 0x02
#define typeExtended 0x03
#define FPWORDS 28
#define CPSR_REGNUM 16
typedef union tagFPREG
{
unsigned int fSingle;
unsigned int fDouble[2];
unsigned int fExtended[3];
}
FPREG;
typedef struct tagFPA11
{
FPREG fpreg[8]; /* 8 floating point registers */
unsigned int fpsr; /* floating point status register */
unsigned int fpcr; /* floating point control register */
unsigned char fType[8]; /* type of floating point value held in
floating point registers. */
int initflag; /* NWFPE initialization flag. */
}
FPA11;
/* The following variables are used to determine the version of the
underlying Linux operating system. Examples:
Linux 2.0.35 Linux 2.2.12
os_version = 0x00020023 os_version = 0x0002020c
os_major = 2 os_major = 2
os_minor = 0 os_minor = 2
os_release = 35 os_release = 12
Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
These are initialized using get_linux_version() from
_initialize_arm_linux_nat(). */
static unsigned int os_version, os_major, os_minor, os_release;
static void
fetch_nw_fpe_single (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fSingle;
mem[1] = 0;
mem[2] = 0;
supply_register (F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nw_fpe_double (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fDouble[1];
mem[1] = fpa11->fpreg[fn].fDouble[0];
mem[2] = 0;
supply_register (F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nw_fpe_none (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
{
unsigned int mem[3] =
{0, 0, 0};
supply_register (F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nw_fpe_extended (unsigned int fn, FPA11 * fpa11, unsigned int *pmem)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
supply_register (F0_REGNUM + fn, (char *) &mem[0]);
}
static void
store_nw_fpe_single (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
fpa11->fpreg[fn].fSingle = mem[0];
fpa11->fType[fn] = typeSingle;
}
static void
store_nw_fpe_double (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
fpa11->fpreg[fn].fDouble[1] = mem[0];
fpa11->fpreg[fn].fDouble[0] = mem[1];
fpa11->fType[fn] = typeDouble;
}
void
store_nw_fpe_extended (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
fpa11->fType[fn] = typeDouble;
}
/* Get the whole floating point state of the process and store the
floating point stack into registers[]. */
static void
fetch_fpregs (void)
{
int ret, regno;
FPA11 fp;
/* Read the floating point state. */
ret = ptrace (PT_GETFPREGS, inferior_pid, 0, &fp);
if (ret < 0)
{
warning ("Unable to fetch the floating point state.");
return;
}
/* Fetch fpsr. */
supply_register (FPS_REGNUM, (char *) &fp.fpsr);
/* Fetch the floating point registers. */
for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
{
int fn = regno - F0_REGNUM;
unsigned int *p = (unsigned int *) &registers[REGISTER_BYTE (regno)];
switch (fp.fType[fn])
{
case typeSingle:
fetch_nw_fpe_single (fn, &fp, p);
break;
case typeDouble:
fetch_nw_fpe_double (fn, &fp, p);
break;
case typeExtended:
fetch_nw_fpe_extended (fn, &fp, p);
break;
default:
fetch_nw_fpe_none (fn, &fp, p);
}
}
}
/* Save the whole floating point state of the process using
the contents from registers[]. */
static void
store_fpregs (void)
{
int ret, regno;
unsigned int mem[3];
FPA11 fp;
/* Store fpsr. */
if (register_valid[FPS_REGNUM])
read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
/* Store the floating point registers. */
for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
{
if (register_valid[regno])
{
unsigned int fn = regno - F0_REGNUM;
switch (fp.fType[fn])
{
case typeSingle:
store_nw_fpe_single (fn, &fp);
break;
case typeDouble:
store_nw_fpe_double (fn, &fp);
break;
case typeExtended:
store_nw_fpe_extended (fn, &fp);
break;
}
}
}
ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, &fp);
if (ret < 0)
{
warning ("Unable to store floating point state.");
return;
}
}
/* Fetch all general registers of the process and store into
registers[]. */
static void
fetch_regs (void)
{
int ret, regno;
struct pt_regs regs;
ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, &regs);
if (ret < 0)
{
warning ("Unable to fetch general registers.");
return;
}
for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
supply_register (regno, (char *) &regs.uregs[regno]);
if (arm_apcs_32)
supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
else
supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
}
/* Store all general registers of the process from the values in
registers[]. */
static void
store_regs (void)
{
int ret, regno;
struct pt_regs regs;
ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, &regs);
if (ret < 0)
{
warning ("Unable to fetch general registers.");
return;
}
for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
{
if (register_valid[regno])
read_register_gen (regno, (char *) &regs.uregs[regno]);
}
ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, &regs);
if (ret < 0)
{
warning ("Unable to store general registers.");
return;
}
}
/* Fetch registers from the child process. Fetch all registers if
regno == -1, otherwise fetch all general registers or all floating
point registers depending upon the value of regno. */
void
fetch_inferior_registers (int regno)
{
if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
fetch_regs ();
if (((regno >= F0_REGNUM) && (regno <= FPS_REGNUM)) || (regno == -1))
fetch_fpregs ();
}
/* Store registers back into the inferior. Store all registers if
regno == -1, otherwise store all general registers or all floating
point registers depending upon the value of regno. */
void
store_inferior_registers (int regno)
{
if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
store_regs ();
if (((regno >= F0_REGNUM) && (regno <= FPS_REGNUM)) || (regno == -1))
store_fpregs ();
}
#ifdef GET_LONGJMP_TARGET
/* Figure out where the longjmp will land. We expect that we have
just entered longjmp and haven't yet altered r0, r1, so the
arguments are still in the registers. (A1_REGNUM) points at the
jmp_buf structure from which we extract the pc (JB_PC) that we will
land at. The pc is copied into ADDR. This routine returns true on
success. */
#define LONGJMP_TARGET_SIZE sizeof(int)
#define JB_ELEMENT_SIZE sizeof(int)
#define JB_SL 18
#define JB_FP 19
#define JB_SP 20
#define JB_PC 21
int
arm_get_longjmp_target (CORE_ADDR * pc)
{
CORE_ADDR jb_addr;
char buf[LONGJMP_TARGET_SIZE];
jb_addr = read_register (A1_REGNUM);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
LONGJMP_TARGET_SIZE))
return 0;
*pc = extract_address (buf, LONGJMP_TARGET_SIZE);
return 1;
}
#endif /* GET_LONGJMP_TARGET */
/*
Dynamic Linking on ARM Linux
----------------------------
Note: PLT = procedure linkage table
GOT = global offset table
As much as possible, ELF dynamic linking defers the resolution of
jump/call addresses until the last minute. The technique used is
inspired by the i386 ELF design, and is based on the following
constraints.
1) The calling technique should not force a change in the assembly
code produced for apps; it MAY cause changes in the way assembly
code is produced for position independent code (i.e. shared
libraries).
2) The technique must be such that all executable areas must not be
modified; and any modified areas must not be executed.
To do this, there are three steps involved in a typical jump:
1) in the code
2) through the PLT
3) using a pointer from the GOT
When the executable or library is first loaded, each GOT entry is
initialized to point to the code which implements dynamic name
resolution and code finding. This is normally a function in the
program interpreter (on ARM Linux this is usually ld-linux.so.2,
but it does not have to be). On the first invocation, the function
is located and the GOT entry is replaced with the real function
address. Subsequent calls go through steps 1, 2 and 3 and end up
calling the real code.
1) In the code:
b function_call
bl function_call
This is typical ARM code using the 26 bit relative branch or branch
and link instructions. The target of the instruction
(function_call is usually the address of the function to be called.
In position independent code, the target of the instruction is
actually an entry in the PLT when calling functions in a shared
library. Note that this call is identical to a normal function
call, only the target differs.
2) In the PLT:
The PLT is a synthetic area, created by the linker. It exists in
both executables and libraries. It is an array of stubs, one per
imported function call. It looks like this:
PLT[0]:
str lr, [sp, #-4]! @push the return address (lr)
ldr lr, [pc, #16] @load from 6 words ahead
add lr, pc, lr @form an address for GOT[0]
ldr pc, [lr, #8]! @jump to the contents of that addr
The return address (lr) is pushed on the stack and used for
calculations. The load on the second line loads the lr with
&GOT[3] - . - 20. The addition on the third leaves:
lr = (&GOT[3] - . - 20) + (. + 8)
lr = (&GOT[3] - 12)
lr = &GOT[0]
On the fourth line, the pc and lr are both updated, so that:
pc = GOT[2]
lr = &GOT[0] + 8
= &GOT[2]
NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
"tight", but allows us to keep all the PLT entries the same size.
PLT[n+1]:
ldr ip, [pc, #4] @load offset from gotoff
add ip, pc, ip @add the offset to the pc
ldr pc, [ip] @jump to that address
gotoff: .word GOT[n+3] - .
The load on the first line, gets an offset from the fourth word of
the PLT entry. The add on the second line makes ip = &GOT[n+3],
which contains either a pointer to PLT[0] (the fixup trampoline) or
a pointer to the actual code.
3) In the GOT:
The GOT contains helper pointers for both code (PLT) fixups and
data fixups. The first 3 entries of the GOT are special. The next
M entries (where M is the number of entries in the PLT) belong to
the PLT fixups. The next D (all remaining) entries belong to
various data fixups. The actual size of the GOT is 3 + M + D.
The GOT is also a synthetic area, created by the linker. It exists
in both executables and libraries. When the GOT is first
initialized , all the GOT entries relating to PLT fixups are
pointing to code back at PLT[0].
The special entries in the GOT are:
GOT[0] = linked list pointer used by the dynamic loader
GOT[1] = pointer to the reloc table for this module
GOT[2] = pointer to the fixup/resolver code
The first invocation of function call comes through and uses the
fixup/resolver code. On the entry to the fixup/resolver code:
ip = &GOT[n+3]
lr = &GOT[2]
stack[0] = return address (lr) of the function call
[r0, r1, r2, r3] are still the arguments to the function call
This is enough information for the fixup/resolver code to work
with. Before the fixup/resolver code returns, it actually calls
the requested function and repairs &GOT[n+3]. */
CORE_ADDR
arm_skip_solib_resolver (CORE_ADDR pc)
{
/* FIXME */
return 0;
}
int
arm_linux_register_u_addr (int blockend, int regnum)
{
return blockend + REGISTER_BYTE (regnum);
}
int
arm_linux_kernel_u_size (void)
{
return (sizeof (struct user));
}
/* 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_linux_extract_return_value (struct type *type,
char regbuf[REGISTER_BYTES],
char *valbuf)
{
/* ScottB: This needs to be looked at to handle the different
floating point emulators on ARM Linux. Right now the code
assumes that fetch inferior registers does the right thing for
GDB. I suspect this won't handle NWFPE registers correctly, nor
will the default ARM version (arm_extract_return_value()). */
int regnum = (TYPE_CODE_FLT == TYPE_CODE (type)) ? F0_REGNUM : A1_REGNUM;
memcpy (valbuf, &regbuf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
}
static unsigned int
get_linux_version (unsigned int *vmajor,
unsigned int *vminor,
unsigned int *vrelease)
{
struct utsname info;
char *pmajor, *pminor, *prelease, *tail;
if (-1 == uname (&info))
{
warning ("Unable to determine Linux version.");
return -1;
}
pmajor = strtok (info.release, ".");
pminor = strtok (NULL, ".");
prelease = strtok (NULL, ".");
*vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
*vminor = (unsigned int) strtoul (pminor, &tail, 0);
*vrelease = (unsigned int) strtoul (prelease, &tail, 0);
return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
}
void
_initialize_arm_linux_nat (void)
{
os_version = get_linux_version (&os_major, &os_minor, &os_release);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1229,19 +1229,18 @@ generic_save_dummy_frame_tos (sp)
dummy_frame_stack->top = sp;
}
/* Function: pop_frame
Restore the machine state from either the saved dummy stack or a
/* Restore the machine state from either the saved dummy stack or a
real stack frame. */
void
generic_pop_current_frame (pop)
void (*pop) (struct frame_info * frame);
generic_pop_current_frame (void (*popper) (struct frame_info * frame))
{
struct frame_info *frame = get_current_frame ();
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
else
pop (frame);
(*popper) (frame);
}
/* Function: pop_dummy_frame

View File

@ -2528,9 +2528,8 @@ bpstat_stop_status (pc, not_a_breakpoint)
real_breakpoint = 1;
}
if (b->frame && b->frame != (get_current_frame ())->frame &&
(b->type == bp_step_resume &&
(INNER_THAN (get_current_frame ()->frame, b->frame))))
if (b->frame &&
b->frame != (get_current_frame ())->frame)
bs->stop = 0;
else
{

View File

@ -285,6 +285,15 @@
/* Define if you have the <wait.h> header file. */
#undef HAVE_WAIT_H
/* Define if you have the <thread_db.h> header file. */
#undef HAVE_THREAD_DB_H
/* Define if you have the <proc_service.h> header file. */
#undef HAVE_PROC_SERVICE_H
/* Define if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H

View File

@ -3,7 +3,9 @@ XDEPFILES= ser-tcp.o
XM_FILE= xm-alphalinux.h
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o inftarg.o corelow.o core-regset.o alpha-nat.o \
fork-child.o solib.o linux-thread.o
fork-child.o solib.o linux-thread.o lin-thread.o
LOADLIBES = -ldl -rdynamic
MMALLOC =
MMALLOC_CFLAGS = -DNO_MMALLOC

View File

@ -18,6 +18,9 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef NM_LINUX_H
#define NM_LINUX_H
#include "nm-linux.h"
/* Figure out where the longjmp will land. We expect that we have just entered
@ -64,3 +67,4 @@ get_longjmp_target PARAMS ((CORE_ADDR *));
pointer to the first register. */
#define ALPHA_REGSET_BASE(regsetp) ((long *) (regsetp))
#endif /* NM_LINUX_H */

View File

@ -1,5 +1,6 @@
# Host: Acorn RISC machine running RISCiX (4.3bsd)
XDEPFILES= infptrace.o inftarg.o fork-child.o arm-xdep.o arm-convert.o
XM_FILE= xm-arm.h
NAT_FILE= nm-arm.h
# OBSOLETE # Host: Acorn RISC machine running RISCiX (4.3bsd)
# OBSOLETE XDEPFILES= infptrace.o inftarg.o fork-child.o arm-xdep.o arm-convert.o
# OBSOLETE
# OBSOLETE XM_FILE= xm-arm.h
# OBSOLETE
# OBSOLETE NAT_FILE= nm-arm.h

View File

@ -1,7 +1,7 @@
# Target: Acorn RISC machine (ARM) with simulator
TDEPFILES= arm-tdep.o remote-rdp.o remote-rdi.o
TDEPLIBS= rdi-share/libangsd.a
TM_FILE= tm-arm.h
SIM_OBS = remote-sim.o
SIM = ../sim/arm/libsim.a
# OBSOLETE # Target: Acorn RISC machine (ARM) with simulator
# OBSOLETE TDEPFILES= arm-tdep.o remote-rdp.o remote-rdi.oT
# OBSOLETE DEPLIBS= rdi-share/libangsd.a
# OBSOLETE TM_FILE= tm-arm.h
# OBSOLETE
# OBSOLETE SIM_OBS = remote-sim.o
# OBSOLETE SIM = ../sim/arm/libsim.a

7
gdb/config/arm/embed.mt Normal file
View File

@ -0,0 +1,7 @@
# Target: ARM embedded system
TDEPFILES= arm-tdep.o remote-rdp.o remote-rdi.o
TDEPLIBS= rdi-share/libangsd.a
TM_FILE= tm-embed.h
SIM_OBS = remote-sim.o
SIM = ../sim/arm/libsim.a

8
gdb/config/arm/linux.mh Normal file
View File

@ -0,0 +1,8 @@
# Host: ARM based machine running GNU/Linux
XM_FILE= xm-linux.h
XDEPFILES= ser-tcp.o
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
core-aout.o core-regset.o arm-linux-nat.o

5
gdb/config/arm/linux.mt Normal file
View File

@ -0,0 +1,5 @@
# Target: ARM based machine running GNU/Linux
TM_FILE= tm-linux.h
TDEPFILES= arm-tdep.o
GDBSERVER_DEPFILES= low-linux.o

View File

@ -1,28 +1,28 @@
/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR (0x01000000 - (UPAGES * NBPG))
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
#define FETCH_INFERIOR_REGISTERS
#define HOST_BYTE_ORDER LITTLE_ENDIAN
/* OBSOLETE /* Definitions to make GDB run on an ARM under RISCiX (4.3bsd). */
/* OBSOLETE Copyright (C) 1986, 1987, 1989 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 /* This is the amount to subtract from u.u_ar0 */
/* OBSOLETE to get the offset in the core file of the register values. *x/ */
/* OBSOLETE */
/* OBSOLETE #define KERNEL_U_ADDR (0x01000000 - (UPAGES * NBPG)) */
/* OBSOLETE */
/* OBSOLETE /* Override copies of {fetch,store}_inferior_registers in infptrace.c. *x/ */
/* OBSOLETE #define FETCH_INFERIOR_REGISTERS */
/* OBSOLETE #define HOST_BYTE_ORDER LITTLE_ENDIAN */

46
gdb/config/arm/nm-linux.h Normal file
View File

@ -0,0 +1,46 @@
/* Definitions to make GDB run on an ARM based machine under GNU/Linux.
Copyright 1999 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef NM_ARMLINUX_H
#define NM_ARMLINUX_H
/* Return sizeof user struct to callers in less machine dependent routines */
extern int kernel_u_size (void);
#define KERNEL_U_SIZE arm_linux_kernel_u_size()
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
#define FETCH_INFERIOR_REGISTERS
/* Tell gdb that we can attach and detach other processes. */
#define ATTACH_DETACH
extern int arm_register_u_addr (int, int);
#define REGISTER_U_ADDR(addr, blockend, regno) \
{ (addr) = arm_linux_register_u_addr((blockend), (regno)); }
/* We define this if link.h is available, because with ELF we use SVR4 style
shared libraries. */
#ifdef HAVE_LINK_H
#define SVR4_SHARED_LIBS
#include "solib.h" /* Support for shared libraries. */
#endif
#endif /* NM_ARMLINUX_H */

View File

@ -1,4 +1,4 @@
/* Definitions to make GDB target for an ARM
/* Definitions to target GDB to ARM targets.
Copyright 1986-1989, 1991, 1993-1999 Free Software Foundation, Inc.
This file is part of GDB.
@ -18,120 +18,168 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Forward decls for prototypes */
#ifndef TM_ARM_H
#define TM_ARM_H
/* Forward declarations for prototypes. */
struct type;
struct value;
#define TARGET_BYTE_ORDER_SELECTABLE
/* IEEE format floating point */
/* Target byte order on ARM defaults to selectable, and defaults to
little endian. */
#define TARGET_BYTE_ORDER_SELECTABLE_P 1
#define TARGET_BYTE_ORDER_DEFAULT LITTLE_ENDIAN
/* IEEE format floating point. */
#define IEEE_FLOAT
#define TARGET_DOUBLE_FORMAT (target_byte_order == BIG_ENDIAN \
? &floatformat_ieee_double_big \
: &floatformat_ieee_double_littlebyte_bigword)
/* FIXME: may need a floatformat_ieee_double_bigbyte_littleword format for
BIG_ENDIAN use. -fnf */
#define TARGET_DOUBLE_FORMAT (target_byte_order == BIG_ENDIAN \
? &floatformat_ieee_double_big \
: &floatformat_ieee_double_littlebyte_bigword)
/* When reading symbols, we need to zap the low bit of the address, which
may be set to 1 for Thumb functions. */
/* When reading symbols, we need to zap the low bit of the address,
which may be set to 1 for Thumb functions. */
#define SMASH_TEXT_ADDRESS(addr) ((addr) &= ~0x1)
/* Remove useless bits from addresses in a running program. */
CORE_ADDR arm_addr_bits_remove PARAMS ((CORE_ADDR));
CORE_ADDR arm_addr_bits_remove (CORE_ADDR);
#define ADDR_BITS_REMOVE(val) (arm_addr_bits_remove (val))
#define ADDR_BITS_REMOVE(val) (arm_addr_bits_remove (val))
/* Offset from address of function to start of its code.
Zero on most machines. */
/* Offset from address of function to start of its code. Zero on most
machines. */
#define FUNCTION_START_OFFSET 0
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
/* Advance PC across any function entry prologue instructions to reach
some "real" code. */
extern CORE_ADDR arm_skip_prologue PARAMS ((CORE_ADDR pc));
extern CORE_ADDR arm_skip_prologue (CORE_ADDR pc);
#define SKIP_PROLOGUE(pc) (arm_skip_prologue (pc))
#define SKIP_PROLOGUE(pc) (arm_skip_prologue (pc))
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
/* Immediately after a function call, return the saved pc. Can't
always go through the frames for this because on some machines the
new frame is not set up until the new function executes some
instructions. */
#define SAVED_PC_AFTER_CALL(frame) arm_saved_pc_after_call (frame)
#define SAVED_PC_AFTER_CALL(frame) arm_saved_pc_after_call (frame)
struct frame_info;
extern CORE_ADDR arm_saved_pc_after_call PARAMS ((struct frame_info *));
extern CORE_ADDR arm_saved_pc_after_call (struct frame_info *);
/* I don't know the real values for these. */
#define TARGET_UPAGES UPAGES
#define TARGET_NBPG NBPG
/* The following define instruction sequences that will cause ARM
cpu's to take an undefined instruction trap. These are used to
signal a breakpoint to GDB.
The newer ARMv4T cpu's are capable of operating in ARM or Thumb
modes. A different instruction is required for each mode. The ARM
cpu's can also be big or little endian. Thus four different
instructions are needed to support all cases.
Note: ARMv4 defines several new instructions that will take the
undefined instruction trap. ARM7TDMI is nominally ARMv4T, but does
not in fact add the new instructions. The new undefined
instructions in ARMv4 are all instructions that had no defined
behaviour in earlier chips. There is no guarantee that they will
raise an exception, but may be treated as NOP's. In practice, it
may only safe to rely on instructions matching:
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
C C C C 0 1 1 x x x x x x x x x x x x x x x x x x x x 1 x x x x
Even this may only true if the condition predicate is true. The
following use a condition predicate of ALWAYS so it is always TRUE.
There are other ways of forcing a breakpoint. ARM Linux, RisciX,
and I suspect NetBSD will all use a software interrupt rather than
an undefined instruction to force a trap. This can be handled by
redefining some or all of the following in a target dependent
fashion. */
/* Address of end of stack space. */
#define STACK_END_ADDR (0x01000000 - (TARGET_UPAGES * TARGET_NBPG))
#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7}
#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
#define THUMB_LE_BREAKPOINT {0xfe,0xdf}
#define THUMB_BE_BREAKPOINT {0xdf,0xfe}
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
/* !!!! if we're using RDP, then we're inserting breakpoints and storing
their handles instread of what was in memory. It is nice that
this is the same size as a handle - otherwise remote-rdp will
/* !!!! if we're using RDP, then we're inserting breakpoints and
storing their handles instread of what was in memory. It is nice
that this is the same size as a handle - otherwise remote-rdp will
have to change. */
/* BREAKPOINT_FROM_PC 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 the pc (if necessary) to
point to the actual memory location where the breakpoint should be
inserted. */
/* BREAKPOINT_FROM_PC 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 the pc (if
necessary) to point to the actual memory location where the
breakpoint should be inserted. */
extern breakpoint_from_pc_fn arm_breakpoint_from_pc;
#define BREAKPOINT_FROM_PC(pcptr, lenptr) arm_breakpoint_from_pc (pcptr, lenptr)
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
/* Amount PC must be decremented by after a breakpoint. This is often
the number of bytes in BREAKPOINT but not always. */
#define DECR_PC_AFTER_BREAK 0
/* code to execute to print interesting information about the
* floating point processor (if any)
* No need to define if there is nothing to do.
*/
/* Code to execute to print interesting information about the floating
point processor (if any) or emulator. No need to define if there
is nothing to do. */
extern void arm_float_info (void);
#define FLOAT_INFO { arm_float_info (); }
#define FLOAT_INFO { arm_float_info (); }
/* Say how long (ordinary) registers are. This is a piece of bogosity
used in push_word and a few other places; REGISTER_RAW_SIZE is the
real way to know how big a register is. */
#define REGISTER_SIZE 4
#define REGISTER_SIZE 4
/* Number of machine registers */
/* Say how long FP registers are. Used for documentation purposes and
code readability in this header. IEEE extended doubles are 80
bits. DWORD aligned they use 96 bits. */
#define FP_REGISTER_RAW_SIZE 12
/* Note: I make a fake copy of the pc in register 25 (calling it ps) so
that I can clear the status bits from pc (register 15) */
/* GCC doesn't support long doubles (extended IEEE values). The FP
register virtual size is therefore 64 bits. Used for documentation
purposes and code readability in this header. */
#define FP_REGISTER_VIRTUAL_SIZE 8
#define NUM_REGS 26
/* Status registers are the same size as general purpose registers.
Used for documentation purposes and code readability in this
header. */
#define STATUS_REGISTER_SIZE REGISTER_SIZE
/* Number of machine registers. The only define actually required
is NUM_REGS. The other definitions are used for documentation
purposes and code readability. */
/* For 26 bit ARM code, a fake copy of the PC is placed in register 25 (PS)
(and called PS for processor status) so the status bits can be cleared
from the PC (register 15). For 32 bit ARM code, a copy of CPSR is placed
in PS. */
#define NUM_FREGS 8 /* Number of floating point registers. */
#define NUM_SREGS 2 /* Number of status registers. */
#define NUM_GREGS 16 /* Number of general purpose registers. */
#define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SREGS)
/* An array of names of registers. */
extern char **arm_register_names;
#define REGISTER_NAME(i) arm_register_names[i]
/* Register numbers of various important registers.
Note that some of these values are "real" register numbers,
and correspond to the general registers of the machine,
and some are "phony" register numbers which are too large
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
/* Register numbers of various important registers. Note that some of
these values are "real" register numbers, and correspond to the
general registers of the machine, and some are "phony" register
numbers which are too large to be actual register numbers as far as
the user is concerned but do serve to get the desired values when
passed to read_register. */
#define A1_REGNUM 0 /* first integer-like argument */
#define A4_REGNUM 3 /* last integer-like argument */
@ -180,88 +228,97 @@ extern char **arm_register_names;
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (16*4 + 12*8 + 4 + 4)
#define REGISTER_BYTES ((NUM_GREGS * REGISTER_SIZE) + \
(NUM_FREGS * FP_REGISTER_RAW_SIZE) + \
(NUM_SREGS * STATUS_REGISTER_SIZE))
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) (((N) < F0_REGNUM) ? (N)*4 : \
(((N) < PS_REGNUM) ? 16*4 + ((N) - 16)*12 : \
16*4 + 8*12 + ((N) - FPS_REGNUM) * 4))
#define REGISTER_BYTE(N) \
((N) < F0_REGNUM \
? (N) * REGISTER_SIZE \
: ((N) < PS_REGNUM \
? (NUM_GREGS * REGISTER_SIZE + \
((N) - F0_REGNUM) * FP_REGISTER_RAW_SIZE) \
: (NUM_GREGS * REGISTER_SIZE + \
NUM_FREGS * FP_REGISTER_RAW_SIZE + \
((N) - FPS_REGNUM) * STATUS_REGISTER_SIZE)))
/* Number of bytes of storage in the actual machine representation
for register N. On the vax, all regs are 4 bytes. */
/* Number of bytes of storage in the actual machine representation for
register N. All registers are 4 bytes, except fp0 - fp7, which are
12 bytes in length. */
#define REGISTER_RAW_SIZE(N) \
((N) < F0_REGNUM ? REGISTER_SIZE : \
(N) < FPS_REGNUM ? FP_REGISTER_RAW_SIZE : STATUS_REGISTER_SIZE)
#define REGISTER_RAW_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 12)
/* Number of bytes of storage in the program's representation
for register N. On the vax, all regs are 4 bytes. */
#define REGISTER_VIRTUAL_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 8)
/* Number of bytes of storage in a program's representation
for register N. */
#define REGISTER_VIRTUAL_SIZE(N) \
((N) < F0_REGNUM ? REGISTER_SIZE : \
(N) < FPS_REGNUM ? FP_REGISTER_VIRTUAL_SIZE : STATUS_REGISTER_SIZE)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 12
#define MAX_REGISTER_RAW_SIZE FP_REGISTER_RAW_SIZE
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE FP_REGISTER_VIRTUAL_SIZE
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion from raw format to
virtual format. */
extern int arm_register_convertible (unsigned int);
#define REGISTER_CONVERTIBLE(REGNUM) (arm_register_convertible (REGNUM))
/* Nonzero if register N requires conversion
from raw format to virtual format. */
#define REGISTER_CONVERTIBLE(N) ((unsigned)(N) - F0_REGNUM < 8)
/* Convert data from raw format for register REGNUM in buffer FROM
to virtual format with type TYPE in buffer TO. */
void convert_from_extended (void *ptr, /*double*/void *dbl);
/* Convert data from raw format for register REGNUM in buffer FROM to
virtual format with type TYPE in buffer TO. */
extern void arm_register_convert_to_virtual (unsigned int regnum,
struct type *type,
void *from, void *to);
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
{ \
double val; \
convert_from_extended ((FROM), & val); \
store_floating ((TO), TYPE_LENGTH (TYPE), val); \
}
arm_register_convert_to_virtual (REGNUM, TYPE, FROM, TO)
/* Convert data from virtual format with type TYPE in buffer FROM
to raw format for register REGNUM in buffer TO. */
/* Convert data from virtual format with type TYPE in buffer FROM to
raw format for register REGNUM in buffer TO. */
extern void convert_to_extended (void *ptr, /*double*/void *dbl);
extern void arm_register_convert_to_raw (unsigned int regnum,
struct type *type,
void *from, void *to);
#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
arm_register_convert_to_raw (REGNUM, TYPE, FROM, TO)
#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
{ \
double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
convert_to_extended (&val, (TO)); \
}
/* Return the GDB type object for the "standard" data type
of data in register N. */
/* Return the GDB type object for the "standard" data type of data in
register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((unsigned)(N) - F0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
(((unsigned)(N) - F0_REGNUM) < NUM_FREGS \
? builtin_type_double : builtin_type_int)
/* The system C compiler uses a similar structure return convention to gcc */
extern use_struct_convention_fn arm_use_struct_convention;
#define USE_STRUCT_CONVENTION(gcc_p, type) arm_use_struct_convention (gcc_p, type)
#define USE_STRUCT_CONVENTION(gcc_p, type) \
arm_use_struct_convention (gcc_p, type)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
{ write_register (0, (ADDR)); }
write_register (A1_REGNUM, (ADDR))
/* 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. */
/* 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. */
extern void arm_extract_return_value (struct type *, char[], char *);
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
convert_from_extended (REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
else \
memcpy (VALBUF, REGBUF, TYPE_LENGTH (TYPE))
arm_extract_return_value ((TYPE), (REGBUF), (VALBUF))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
/* Write into appropriate registers a function return value of type
TYPE, given in virtual format. */
extern void convert_to_extended (void *dbl, void *ptr);
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) { \
char _buf[MAX_REGISTER_RAW_SIZE]; \
@ -275,7 +332,7 @@ extern use_struct_convention_fn arm_use_struct_convention;
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(extract_address ((PTR) (REGBUF), REGISTER_RAW_SIZE(0)))
(extract_address ((PTR)(REGBUF), REGISTER_RAW_SIZE(0)))
/* Specify that for the native compiler variables for a particular
lexical context are listed after the beginning LBRAC instead of
@ -283,11 +340,11 @@ extern use_struct_convention_fn arm_use_struct_convention;
#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
/* 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) */
/* 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) */
#define EXTRA_FRAME_INFO \
struct frame_saved_regs fsr; \
@ -295,29 +352,29 @@ extern use_struct_convention_fn arm_use_struct_convention;
int frameoffset; \
int framereg;
extern void arm_init_extra_frame_info PARAMS ((int fromleaf,
struct frame_info *fi));
extern void arm_init_extra_frame_info (int fromleaf, struct frame_info * fi);
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
arm_init_extra_frame_info (fromleaf, fi)
arm_init_extra_frame_info ((fromleaf), (fi))
/* Return the frame address. On ARM, it is R11; on Thumb it is R7. */
CORE_ADDR arm_target_read_fp PARAMS ((void));
CORE_ADDR arm_target_read_fp (void);
#define TARGET_READ_FP() arm_target_read_fp ()
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* Describe the pointer in each stack frame to the previous stack
frame (its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
/* FRAME_CHAIN takes a frame's nominal address and produces the
frame's chain-pointer.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller. */
#define FRAME_CHAIN(thisframe) (CORE_ADDR) arm_frame_chain (thisframe)
extern CORE_ADDR arm_frame_chain PARAMS ((struct frame_info *));
#define FRAME_CHAIN(thisframe) arm_frame_chain (thisframe)
extern CORE_ADDR arm_frame_chain (struct frame_info *);
extern int arm_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
#define FRAME_CHAIN_VALID(chain, thisframe) arm_frame_chain_valid (chain, thisframe)
extern int arm_frame_chain_valid (CORE_ADDR, struct frame_info *);
#define FRAME_CHAIN_VALID(chain, thisframe) \
arm_frame_chain_valid (chain, thisframe)
/* Define other aspects of the stack frame. */
@ -325,14 +382,14 @@ extern int arm_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0.
Sometimes we have functions that do a little setup (like saving the vN
registers with the stmdb instruction, but DO NOT set up a frame.
Sometimes we have functions that do a little setup (like saving the
vN registers with the stmdb instruction, but DO NOT set up a frame.
The symbol table will report this as a prologue. However, it is
important not to try to parse these partial frames as frames, or we
important not to try to parse these partial frames as frames, or we
will get really confused.
So I will demand 3 instructions between the start & end of the prologue
before I call it a real prologue, i.e. at least
So I will demand 3 instructions between the start & end of the
prologue before I call it a real prologue, i.e. at least
mov ip, sp,
stmdb sp!, {}
sub sp, ip, #4. */
@ -340,11 +397,11 @@ extern int arm_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
extern int arm_frameless_function_invocation (struct frame_info *fi);
#define FRAMELESS_FUNCTION_INVOCATION(FI) \
(arm_frameless_function_invocation (FI))
/* Saved Pc. */
#define FRAME_SAVED_PC(FRAME) arm_frame_saved_pc (FRAME)
extern CORE_ADDR arm_frame_saved_pc PARAMS ((struct frame_info *));
extern CORE_ADDR arm_frame_saved_pc (struct frame_info *);
#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
@ -355,15 +412,15 @@ extern CORE_ADDR arm_frame_saved_pc PARAMS ((struct frame_info *));
#define FRAME_NUM_ARGS(fi) (-1)
/* Return number of bytes at start of arglist that are not really args. */
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
/* Put here the code to store, into a struct frame_saved_regs, the
addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
ways in the stack frame. sp is even more special: the address we
return for it IS the sp for the next frame. */
struct frame_saved_regs;
struct frame_info;
@ -371,24 +428,24 @@ void arm_frame_find_saved_regs (struct frame_info * fi,
struct frame_saved_regs * fsr);
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
arm_frame_find_saved_regs (frame_info, &(frame_saved_regs));
arm_frame_find_saved_regs (frame_info, &(frame_saved_regs));
/* Things needed for making the inferior call functions. */
#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
(arm_push_arguments ((nargs), (args), (sp), (struct_return), (struct_addr)))
extern CORE_ADDR arm_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
sp = arm_push_arguments ((nargs), (args), (sp), (struct_return), (struct_addr))
extern CORE_ADDR arm_push_arguments (int, struct value **, CORE_ADDR, int,
CORE_ADDR);
/* Push an empty stack frame, to record the current PC, etc. */
void arm_push_dummy_frame PARAMS ((void));
void arm_push_dummy_frame (void);
#define PUSH_DUMMY_FRAME arm_push_dummy_frame ()
/* Discard from the stack the innermost frame, restoring all registers. */
void arm_pop_frame PARAMS ((void));
void arm_pop_frame (void);
#define POP_FRAME arm_pop_frame ()
@ -400,69 +457,59 @@ void arm_pop_frame PARAMS ((void));
Note this is 12 bytes. */
#define CALL_DUMMY {0xe1a0e00f, 0xe1a0f004, 0xE7FFDEFE}
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
#define CALL_DUMMY {0xe1a0e00f, 0xe1a0f004, 0xe7ffdefe}
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
#define CALL_DUMMY_BREAKPOINT_OFFSET arm_call_dummy_breakpoint_offset()
extern int arm_call_dummy_breakpoint_offset PARAMS ((void));
extern int arm_call_dummy_breakpoint_offset (void);
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
/* Insert the specified number of args and function address into a
call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
arm_fix_call_dummy (dummyname, pc, fun, nargs, args, type, gcc_p)
arm_fix_call_dummy ((dummyname), (pc), (fun), (nargs), (args), (type), (gcc_p))
void arm_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
int nargs, struct value ** args,
struct type * type, int gcc_p));
void arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
int nargs, struct value ** args,
struct type * type, int gcc_p);
CORE_ADDR arm_get_next_pc PARAMS ((CORE_ADDR));
CORE_ADDR arm_get_next_pc (CORE_ADDR pc);
/* Functions for dealing with Thumb call thunks. */
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) arm_in_call_stub (pc, name)
#define SKIP_TRAMPOLINE_CODE(pc) arm_skip_stub (pc)
extern int arm_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
extern CORE_ADDR arm_skip_stub PARAMS ((CORE_ADDR pc));
/* Function to determine whether MEMADDR is in a Thumb function. */
extern int arm_pc_is_thumb PARAMS ((bfd_vma memaddr));
/* Function to determine whether MEMADDR is in a call dummy called from
a Thumb function. */
extern int arm_pc_is_thumb_dummy PARAMS ((bfd_vma memaddr));
/* Macros for setting and testing a bit in a minimal symbol that
marks it as Thumb function. The MSB of the minimal symbol's
"info" field is used for this purpose. This field is already
being used to store the symbol size, so the assumption is
that the symbol size cannot exceed 2^31.
/* Macros for setting and testing a bit in a minimal symbol that marks
it as Thumb function. The MSB of the minimal symbol's "info" field
is used for this purpose. This field is already being used to store
the symbol size, so the assumption is that the symbol size cannot
exceed 2^31.
COFF_MAKE_MSYMBOL_SPECIAL
ELF_MAKE_MSYMBOL_SPECIAL tests whether the COFF or ELF symbol corresponds
to a thumb function, and sets a "special" bit in a
minimal symbol to indicate that it does
MSYMBOL_SET_SPECIAL actually sets the "special" bit
MSYMBOL_IS_SPECIAL tests the "special" bit in a minimal symbol
MSYMBOL_SIZE returns the size of the minimal symbol, i.e.
the "info" field with the "special" bit masked out
*/
ELF_MAKE_MSYMBOL_SPECIAL
These macros test whether the COFF or ELF symbol corresponds to a
thumb function, and set a "special" bit in a minimal symbol to
indicate that it does.
MSYMBOL_SET_SPECIAL Actually sets the "special" bit.
MSYMBOL_IS_SPECIAL Tests the "special" bit in a minimal symbol.
MSYMBOL_SIZE Returns the size of the minimal symbol,
i.e. the "info" field with the "special" bit
masked out
*/
extern int coff_sym_is_thumb (int val);
#define MSYMBOL_SET_SPECIAL(msym) \
MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000)
MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) | 0x80000000)
#define MSYMBOL_IS_SPECIAL(msym) \
(((long) MSYMBOL_INFO (msym) & 0x80000000) != 0)
#define MSYMBOL_SIZE(msym) \
((long) MSYMBOL_INFO (msym) & 0x7fffffff)
/* Thumb symbol are of type STT_LOPROC, (synonymous with STT_ARM_TFUNC) */
/* Thumb symbols are of type STT_LOPROC, (synonymous with STT_ARM_TFUNC) */
#define ELF_MAKE_MSYMBOL_SPECIAL(sym,msym) \
{ if(ELF_ST_TYPE(((elf_symbol_type *)(sym))->internal_elf_sym.st_info) == STT_LOPROC) \
MSYMBOL_SET_SPECIAL(msym); }
{ if(ELF_ST_TYPE(((elf_symbol_type *)(sym))->internal_elf_sym.st_info) == STT_LOPROC) \
MSYMBOL_SET_SPECIAL(msym); }
#define COFF_MAKE_MSYMBOL_SPECIAL(val,msym) \
{ if(coff_sym_is_thumb(val)) MSYMBOL_SET_SPECIAL(msym); }
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) 0
#endif /* TM_ARM_H */

66
gdb/config/arm/tm-embed.h Normal file
View File

@ -0,0 +1,66 @@
/* Definitions to target GDB to ARM embedded systems.
Copyright 1986-1989, 1991, 1993-1999 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef TM_ARMEMBED_H
#define TM_ARMEMBED_H
/* Include the common ARM definitions. */
#include "arm/tm-arm.h"
/* I don't know the real values for these. */
#define TARGET_UPAGES UPAGES
#define TARGET_NBPG NBPG
/* Address of end of stack space. */
#define STACK_END_ADDR (0x01000000 - (TARGET_UPAGES * TARGET_NBPG))
/* The first 0x20 bytes are the trap vectors. */
#define LOWEST_PC 0x20
/* Override defaults. */
#undef THUMB_LE_BREAKPOINT
#define THUMB_LE_BREAKPOINT {0xbe,0xbe}
#undef THUMB_BE_BREAKPOINT
#define THUMB_BE_BREAKPOINT {0xbe,0xbe}
/* Specify that for the native compiler variables for a particular
lexical context are listed after the beginning LBRAC instead of
before in the executables list of symbols. */
#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
/* Functions for dealing with Thumb call thunks. */
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) arm_in_call_stub (pc, name)
#define SKIP_TRAMPOLINE_CODE(pc) arm_skip_stub (pc)
extern int arm_in_call_stub PARAMS ((CORE_ADDR pc, char *name));
extern CORE_ADDR arm_skip_stub PARAMS ((CORE_ADDR pc));
/* Function to determine whether MEMADDR is in a Thumb function. */
extern int arm_pc_is_thumb PARAMS ((bfd_vma memaddr));
/* Function to determine whether MEMADDR is in a call dummy called from
a Thumb function. */
extern int arm_pc_is_thumb_dummy PARAMS ((bfd_vma memaddr));
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) 0
#endif /* TM_ARMEMBED_H */

122
gdb/config/arm/tm-linux.h Normal file
View File

@ -0,0 +1,122 @@
/* Target definitions for GNU/Linux on ARM, for GDB.
Copyright 1999 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef TM_ARMLINUX_H
#define TM_ARMLINUX_H
/* Include the common ARM target definitions. */
#include "arm/tm-arm.h"
#include "tm-linux.h"
/* Target byte order on ARM Linux is not selectable. */
#undef TARGET_BYTE_ORDER_SELECTABLE_P
#define TARGET_BYTE_ORDER_SELECTABLE_P 0
/* Under ARM Linux the traditional way of performing a breakpoint is to
execute a particular software interrupt, rather than use a particular
undefined instruction to provoke a trap. Upon exection of the software
interrupt the kernel stops the inferior with a SIGTRAP, and wakes the
debugger. Since ARM Linux is little endian, and doesn't support Thumb
at the moment we redefined ARM_LE_BREAKPOINT to use the correct software
interrupt. */
#undef ARM_LE_BREAKPOINT
#define ARM_LE_BREAKPOINT {0x01,0x00,0x9f,0xef}
/* This sequence of words used in the CALL_DUMMY are the following
instructions:
mov lr, pc
mov pc, r4
swi bkpt_swi
Note this is 12 bytes. */
#undef CALL_DUMMY
#define CALL_DUMMY {0xe1a0e00f, 0xe1a0f004, 0xef9f001}
/* 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. */
extern void arm_linux_extract_return_value (struct type *, char[], char *);
#undef EXTRACT_RETURN_VALUE
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
arm_linux_extract_return_value ((TYPE), (REGBUF), (VALBUF))
/* The first page is not writeable in ARM Linux. */
#define LOWEST_PC 0x8000
/* Define NO_SINGLE_STEP if ptrace(PT_STEP,...) fails to function correctly
on ARM Linux. This is the case on 2.0.x kernels, 2.1.x kernels and some
2.2.x kernels. This will include the implementation of single_step()
in armlinux-tdep.c. See armlinux-ss.c for more details. */
/* #define NO_SINGLE_STEP 1 */
/* Offset to saved PC in sigcontext structure, from <asm/sigcontext.h> */
#define SIGCONTEXT_PC_OFFSET (sizeof(unsigned long) * 18)
/* Figure out where the longjmp will land. The code expects that longjmp
has just been entered and the code had not altered the registers, so
the arguments are are still in r0-r1. r0 points at the jmp_buf structure
from which the target pc (JB_PC) is extracted. This pc value is copied
into ADDR. This routine returns true on success */
extern int arm_get_longjmp_target (CORE_ADDR *);
#define GET_LONGJMP_TARGET(addr) arm_get_longjmp_target (addr)
/* On ARM Linux, each call to a library routine goes through a small piece
of trampoline code in the ".plt" section. The wait_for_inferior()
routine uses this macro to detect when we have stepped into one of
these fragments. We do not use lookup_solib_trampoline_symbol_by_pc,
because we cannot always find the shared library trampoline symbols. */
extern int in_plt_section (CORE_ADDR, char *);
#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) in_plt_section((pc), (name))
/* On ARM Linux, a call to a library routine does not have to go through
any trampoline code. */
#define IN_SOLIB_RETURN_TRAMPOLINE(pc, name) 0
/* If PC is in a shared library trampoline code, return the PC
where the function itself actually starts. If not, return 0. */
extern CORE_ADDR find_solib_trampoline_target (CORE_ADDR pc);
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
/* When we call a function in a shared library, and the PLT sends us
into the dynamic linker to find the function's real address, we
need to skip over the dynamic linker call. This function decides
when to skip, and where to skip to. See the comments for
SKIP_SOLIB_RESOLVER at the top of infrun.c. */
extern CORE_ADDR arm_skip_solib_resolver (CORE_ADDR pc);
#define SKIP_SOLIB_RESOLVER arm_skip_solib_resolver
/* When we call a function in a shared library, and the PLT sends us
into the dynamic linker to find the function's real address, we
need to skip over the dynamic linker call. This function decides
when to skip, and where to skip to. See the comments for
SKIP_SOLIB_RESOLVER at the top of infrun.c. */
#if 0
#undef IN_SOLIB_DYNSYM_RESOLVE_CODE
extern CORE_ADDR arm_in_solib_dynsym_resolve_code (CORE_ADDR pc, char *name);
#define IN_SOLIB_DYNSYM_RESOLVE_CODE arm_in_solib_dynsym_resolve_code
/* ScottB: Current definition is
extern CORE_ADDR in_svr4_dynsym_resolve_code (CORE_ADDR pc, char *name);
#define IN_SOLIB_DYNSYM_RESOLVE_CODE in_svr4_dynsym_resolve_code */
#endif
#endif /* TM_ARMLINUX_H */

View File

@ -1,77 +1,77 @@
/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define HOST_BYTE_ORDER LITTLE_ENDIAN
#if 0
/* Interface definitions for kernel debugger KDB. */
/* Map machine fault codes into signal numbers.
First subtract 0, divide by 4, then index in a table.
Faults for which the entry in this table is 0
are not handled by KDB; the program's own trap handler
gets to handle then. */
#define FAULT_CODE_ORIGIN 0
#define FAULT_CODE_UNITS 4
#define FAULT_TABLE \
{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0}
/* Start running with a stack stretching from BEG to END.
BEG and END should be symbols meaningful to the assembler.
This is used only for kdb. */
#define INIT_STACK(beg, end) \
{ asm (".globl end"); \
asm ("movl $ end, sp"); \
asm ("clrl fp"); }
/* Push the frame pointer register on the stack. */
#define PUSH_FRAME_PTR \
asm ("pushl fp");
/* Copy the top-of-stack to the frame pointer register. */
#define POP_FRAME_PTR \
asm ("movl (sp), fp");
/* After KDB is entered by a fault, push all registers
that GDB thinks about (all NUM_REGS of them),
so that they appear in order of ascending GDB register number.
The fault code will be on the stack beyond the last register. */
#define PUSH_REGISTERS \
{ asm ("pushl 8(sp)"); \
asm ("pushl 8(sp)"); \
asm ("pushal 0x14(sp)"); \
asm ("pushr $037777"); }
/* Assuming the registers (including processor status) have been
pushed on the stack in order of ascending GDB register number,
restore them and return to the address in the saved PC register. */
#define POP_REGISTERS \
{ asm ("popr $037777"); \
asm ("subl2 $8,(sp)"); \
asm ("movl (sp),sp"); \
asm ("rei"); }
#endif /* 0 */
/* OBSOLETE /* Definitions to make GDB run on an ARM under RISCiX (4.3bsd). */
/* OBSOLETE Copyright (C) 1986, 1987, 1989 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 #define HOST_BYTE_ORDER LITTLE_ENDIAN */
/* OBSOLETE */
/* OBSOLETE */
/* OBSOLETE #if 0 */
/* OBSOLETE /* Interface definitions for kernel debugger KDB. *x/ */
/* OBSOLETE */
/* OBSOLETE /* Map machine fault codes into signal numbers. */
/* OBSOLETE First subtract 0, divide by 4, then index in a table. */
/* OBSOLETE Faults for which the entry in this table is 0 */
/* OBSOLETE are not handled by KDB; the program's own trap handler */
/* OBSOLETE gets to handle then. *x/ */
/* OBSOLETE */
/* OBSOLETE #define FAULT_CODE_ORIGIN 0 */
/* OBSOLETE #define FAULT_CODE_UNITS 4 */
/* OBSOLETE #define FAULT_TABLE \ */
/* OBSOLETE { 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \ */
/* OBSOLETE 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \ */
/* OBSOLETE 0, 0, 0, 0, 0, 0, 0, 0} */
/* OBSOLETE */
/* OBSOLETE /* Start running with a stack stretching from BEG to END. */
/* OBSOLETE BEG and END should be symbols meaningful to the assembler. */
/* OBSOLETE This is used only for kdb. *x/ */
/* OBSOLETE */
/* OBSOLETE #define INIT_STACK(beg, end) \ */
/* OBSOLETE { asm (".globl end"); \ */
/* OBSOLETE asm ("movl $ end, sp"); \ */
/* OBSOLETE asm ("clrl fp"); } */
/* OBSOLETE */
/* OBSOLETE /* Push the frame pointer register on the stack. *x/ */
/* OBSOLETE #define PUSH_FRAME_PTR \ */
/* OBSOLETE asm ("pushl fp"); */
/* OBSOLETE */
/* OBSOLETE /* Copy the top-of-stack to the frame pointer register. *x/ */
/* OBSOLETE #define POP_FRAME_PTR \ */
/* OBSOLETE asm ("movl (sp), fp"); */
/* OBSOLETE */
/* OBSOLETE /* After KDB is entered by a fault, push all registers */
/* OBSOLETE that GDB thinks about (all NUM_REGS of them), */
/* OBSOLETE so that they appear in order of ascending GDB register number. */
/* OBSOLETE The fault code will be on the stack beyond the last register. *x/ */
/* OBSOLETE */
/* OBSOLETE #define PUSH_REGISTERS \ */
/* OBSOLETE { asm ("pushl 8(sp)"); \ */
/* OBSOLETE asm ("pushl 8(sp)"); \ */
/* OBSOLETE asm ("pushal 0x14(sp)"); \ */
/* OBSOLETE asm ("pushr $037777"); } */
/* OBSOLETE */
/* OBSOLETE /* Assuming the registers (including processor status) have been */
/* OBSOLETE pushed on the stack in order of ascending GDB register number, */
/* OBSOLETE restore them and return to the address in the saved PC register. *x/ */
/* OBSOLETE */
/* OBSOLETE #define POP_REGISTERS \ */
/* OBSOLETE { asm ("popr $037777"); \ */
/* OBSOLETE asm ("subl2 $8,(sp)"); \ */
/* OBSOLETE asm ("movl (sp),sp"); \ */
/* OBSOLETE asm ("rei"); } */
/* OBSOLETE #endif /* 0 *x/ */

37
gdb/config/arm/xm-linux.h Normal file
View File

@ -0,0 +1,37 @@
/* Host definitions for ARM GNU/Linux, for GDB, the GNU debugger.
Copyright 1999 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef XM_ARMLINUX_H
#define XM_ARMLINUX_H
#define HOST_BYTE_ORDER LITTLE_ENDIAN
#define HAVE_TERMIOS
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#define KERNEL_U_ADDR 0x0
#define NEED_POSIX_SETPGID
/* Need R_OK etc, but USG isn't defined. */
#include <unistd.h>
#endif /* XM_ARMLINUX_H */

View File

@ -5,4 +5,6 @@ XDEPFILES= ser-tcp.o
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
core-aout.o i386v-nat.o i386-linux-nat.o linux-thread.o
core-aout.o i386v-nat.o i386-linux-nat.o linux-thread.o lin-thread.o
LOADLIBES = -ldl -rdynamic

View File

@ -29,4 +29,20 @@
extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR pc, char *name));
extern char *cygwin_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) cygwin_pid_to_str (PID)
struct frame_info;
void child_init_frame(int x, struct frame_info *);
CORE_ADDR child_frame_saved_pc(struct frame_info *);
CORE_ADDR child_frame_chain(struct frame_info *);
#undef FRAME_CHAIN_VALID_ALTERNATE
#define FRAME_CHAIN_VALID_ALTERNATE 1
#undef INIT_EXTRA_FRAME_INFO
#define INIT_EXTRA_FRAME_INFO(x, f) child_init_frame(x, f)
#undef FRAME_CHAIN
#define FRAME_CHAIN child_frame_chain
#undef FRAME_SAVED_PC
#define FRAME_SAVED_PC child_frame_saved_pc

View File

@ -53,12 +53,10 @@ extern char *sunpro_static_transform_name PARAMS ((char *));
#ifdef HAVE_THREAD_DB_LIB
extern char *solaris_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) solaris_pid_to_str (PID)
#else
extern char *procfs_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) procfs_pid_to_str (PID)
#endif

View File

@ -422,7 +422,9 @@ extern void mips_push_dummy_frame PARAMS ((void));
#define POP_FRAME mips_pop_frame()
extern void mips_pop_frame PARAMS ((void));
#if !GDB_MULTI_ARCH
#define CALL_DUMMY { 0 }
#endif
#define CALL_DUMMY_START_OFFSET (0)

View File

@ -26,8 +26,6 @@
#include <mach.h>
#include <mach/exception.h>
#undef target_pid_to_str
#define target_pid_to_str(pid) gnu_target_pid_to_str(pid)
extern char *gnu_target_pid_to_str (int pid);
/* Before storing, we need to read all the registers. */

View File

@ -37,14 +37,25 @@
struct objfile;
/* Hook to look at new objfiles (shared libraries) */
extern void
linuxthreads_new_objfile PARAMS ((struct objfile *objfile));
#define target_new_objfile(OBJFILE) linuxthreads_new_objfile (OBJFILE)
/* Method to print a human-readable thread description */
extern char *
linuxthreads_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) linuxthreads_pid_to_str (PID)
extern int
linuxthreads_prepare_to_proceed PARAMS ((int step));
#define PREPARE_TO_PROCEED(select_it) linuxthreads_prepare_to_proceed (1)
/* Defined to make stepping-over-breakpoints be thread-atomic. */
#define USE_THREAD_STEP_NEEDED 1
/* Macros to extract process id and thread id from a composite pid/tid.
Allocate lower 19 bits for process id, next 12 bits for thread id, and
one bit for a flag to indicate a user thread vs. a kernel thread. */
#define PIDGET(PID) (((PID) & 0xffff))
#define TIDGET(PID) (((PID) & 0x7fffffff) >> 16)
#define MERGEPID(PID, TID) (((PID) & 0xffff) | ((TID) << 16))

View File

@ -75,10 +75,9 @@ extern int child_wait PARAMS ((int pid, struct target_waitstatus * status));
/* Lynx needs a special definition of this so that we can
print out the pid and thread number seperatly. */
#undef target_pid_to_str
#define target_pid_to_str(PID) lynx_pid_to_str (PID)
/* override child_pid_to_str in inftarg.c */
#define CHILD_PID_TO_STR
extern char *lynx_pid_to_str PARAMS ((int pid));
#endif /* NM_LYNX_H */

View File

@ -90,6 +90,7 @@ extern int hppa_prepare_to_proceed PARAMS ((void));
#define CHILD_HAS_SYSCALL_EVENT
#define CHILD_POST_ATTACH
#define CHILD_THREAD_ALIVE
#define CHILD_PID_TO_STR
#define REQUIRE_ATTACH(pid) hppa_require_attach(pid)
extern int hppa_require_attach PARAMS ((int));
@ -226,9 +227,8 @@ extern void hppa_disable_page_protection_events PARAMS ((int));
* than processes. So we need a new way to print
* the string. Code is in hppah-nat.c.
*/
#define target_pid_to_str( pid ) \
hppa_pid_to_str( pid )
extern char *hppa_pid_to_str PARAMS ((pid_t));
extern char *child_pid_to_str PARAMS ((pid_t));
#define target_tid_to_str( pid ) \
hppa_tid_to_str( pid )
@ -277,13 +277,6 @@ extern void hppa_ensure_vforking_parent_remains_stopped PARAMS ((int));
hppa_resume_execd_vforking_child_to_get_parent_vfork ()
extern int hppa_resume_execd_vforking_child_to_get_parent_vfork PARAMS ((void));
#ifdef HAVE_HPUX_THREAD_SUPPORT
extern char *hpux_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) hpux_pid_to_str (PID)
#endif /* HAVE_HPUX_THREAD_SUPPORT */
#define HPUXHPPA
#define MAY_SWITCH_FROM_INFERIOR_PID (1)

View File

@ -85,11 +85,9 @@ extern char *sunpro_static_transform_name PARAMS ((char *));
#ifdef HAVE_THREAD_DB_LIB
extern char *solaris_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) solaris_pid_to_str (PID)
#else
extern char *procfs_pid_to_str PARAMS ((int pid));
#define target_pid_to_str(PID) procfs_pid_to_str (PID)
#endif

575
gdb/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
case "${host_cpu}" in
alpha*) gdb_host_cpu=alpha ;;
arm*) gdb_host_cpu=arm ;;
# OBSOLETE c[12]) gdb_host_cpu=convex ;;
hppa*) gdb_host_cpu=pa ;;
i[3456]86*) gdb_host_cpu=i386 ;;
@ -35,7 +36,8 @@ alpha*-*-osf2*) gdb_host=alpha-osf2 ;;
alpha*-*-osf[3456789]*) gdb_host=alpha-osf3 ;;
alpha*-*-linux*) gdb_host=alpha-linux ;;
arm-*-*) gdb_host=arm ;;
arm*-*-linux*) gdb_host=linux ;;
arm*-*-*) gdb_host=arm ;;
# OBSOLETE c[12]-*-*) gdb_host=convex ;;

View File

@ -79,9 +79,9 @@ AC_TYPE_SIGNAL
AC_HEADER_STDC
AC_CHECK_HEADERS(ctype.h curses.h endian.h link.h \
AC_CHECK_HEADERS(ctype.h curses.h endian.h link.h thread_db.h proc_service.h \
memory.h objlist.h ptrace.h sgtty.h stddef.h stdlib.h \
string.h sys/procfs.h sys/ptrace.h sys/reg.h \
string.h sys/procfs.h sys/ptrace.h sys/reg.h stdint.h \
term.h termio.h termios.h unistd.h wait.h sys/wait.h \
wchar.h wctype.h asm/debugreg.h sys/debugreg.h sys/select.h \
time.h sys/ioctl.h)

View File

@ -13,6 +13,7 @@
case "${target_cpu}" in
alpha*) gdb_target_cpu=alpha ;;
arm*) gdb_target_cpu=arm ;;
# OBSOLETE c[12]) gdb_target_cpu=convex ;;
hppa*) gdb_target_cpu=pa ;;
i[3456]86*) gdb_target_cpu=i386 ;;
@ -50,8 +51,9 @@ alpha*-*-linux*) gdb_target=alpha-linux ;;
arc-*-*) gdb_target=arc ;;
arm-*-* | thumb-*-* | strongarm-*-*)
gdb_target=arm
arm*-*-linux*) gdb_target=linux ;;
arm*-*-* | thumb*-*-* | strongarm*-*-*)
gdb_target=embed
configdirs="$configdirs rdi-share"
;;
# OBSOLETE c1-*-*) gdb_target=convex ;;

View File

@ -329,6 +329,7 @@ extern int myread (int, char *, int);
extern int query (char *, ...) ATTR_FORMAT (printf, 1, 2);
#if !defined (USE_MMALLOC)
extern PTR mcalloc (void *, size_t, size_t);
extern PTR mmalloc (PTR, size_t);
extern PTR mrealloc (PTR, PTR, size_t);
extern void mfree (PTR, PTR);
@ -1283,7 +1284,8 @@ extern int use_windows;
the actual pid. */
#ifndef PIDGET
#define PIDGET(pid) (pid)
#define PIDGET(PID) (PID)
#define TIDGET(PID) 0
#endif
/* If under Cygwin, provide backwards compatibility with older

View File

@ -84,13 +84,15 @@ breakpoint_modify_event (int b)
#endif
#if WITH_GDB_EVENTS
void
struct gdb_events *
set_gdb_event_hooks (struct gdb_events *vector)
{
struct gdb_events *old_events = current_event_hooks;
if (vector == NULL)
current_event_hooks = &queue_event_hooks;
else
current_event_hooks = vector;
return old_events;
}
#endif

View File

@ -83,7 +83,7 @@ extern void breakpoint_modify_event (int b);
#endif
/* Install custom gdb-events hooks. */
extern void set_gdb_event_hooks (struct gdb_events *vector);
extern struct gdb_events *set_gdb_event_hooks (struct gdb_events *vector);
/* Deliver any pending events. */
extern void gdb_events_deliver (struct gdb_events *vector);

View File

@ -257,7 +257,7 @@ echo "#endif"
cat <<EOF
/* Install custom gdb-events hooks. */
extern void set_gdb_event_hooks (struct gdb_events *vector);
extern struct gdb_events *set_gdb_event_hooks (struct gdb_events *vector);
/* Deliver any pending events. */
extern void gdb_events_deliver (struct gdb_events *vector);
@ -361,13 +361,15 @@ echo "#endif"
echo ""
cat <<EOF
#if WITH_GDB_EVENTS
void
struct gdb_events *
set_gdb_event_hooks (struct gdb_events *vector)
{
struct gdb_events *old_events = current_event_hooks;
if (vector == NULL)
current_event_hooks = &queue_event_hooks;
else
current_event_hooks = vector;
return old_events;
EOF
function_list | while eval read $read
do

24
gdb/gdb_proc_service.h Normal file
View File

@ -0,0 +1,24 @@
typedef enum {
PS_OK, /* generic "call succeeded" */
PS_ERR, /* generic. */
PS_BADPID, /* bad process handle */
PS_BADLID, /* bad lwp identifier */
PS_BADADDR, /* bad address */
PS_NOSYM, /* p_lookup() could not find given symbol */
PS_NOFREGS
/*
* FPU register set not available for given
* lwp
*/
} ps_err_e;
typedef unsigned int lwpid_t;
typedef unsigned long paddr_t;
typedef unsigned long psaddr_t;
typedef gregset_t prgregset_t; /* BOGUS BOGUS BOGUS */
typedef fpregset_t prfpregset_t; /* BOGUS BOGUS BOGUS */
struct ps_prochandle; /* user defined. */

427
gdb/gdb_thread_db.h Normal file
View File

@ -0,0 +1,427 @@
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _THREAD_DB_H
#define _THREAD_DB_H 1
/* This is the debugger interface for the LinuxThreads library. It is
modelled closely after the interface with same names in Solaris with
the goal to share the same code in the debugger. */
#include <pthread.h>
#include <stdint.h>
#include <sys/types.h>
/*#include <sys/ucontext.h>*/
/* Error codes of the library. */
typedef enum
{
TD_OK, /* No error. */
TD_ERR, /* No further specified error. */
TD_NOTHR, /* No matching thread found. */
TD_NOSV, /* No matching synchronization handle found. */
TD_NOLWP, /* No matching light-weighted process found. */
TD_BADPH, /* Invalid process handle. */
TD_BADTH, /* Invalid thread handle. */
TD_BADSH, /* Invalid synchronization handle. */
TD_BADTA, /* Invalid thread agent. */
TD_BADKEY, /* Invalid key. */
TD_NOMSG, /* No event available. */
TD_NOFPREGS, /* No floating-point register content available. */
TD_NOLIBTHREAD, /* Application not linked with thread library. */
TD_NOEVENT, /* Requested event is not supported. */
TD_NOCAPAB, /* Capability not available. */
TD_DBERR, /* Internal debug library error. */
TD_NOAPLIC, /* Operation is not applicable. */
TD_NOTSD, /* No thread-specific data available. */
TD_MALLOC, /* Out of memory. */
TD_PARTIALREG,/* Not entire register set was read or written. */
TD_NOXREGS /* X register set not available for given thread. */
} td_err_e;
/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to
select threads regardless of state in td_ta_thr_iter(). */
typedef enum
{
TD_THR_ANY_STATE,
TD_THR_UNKNOWN,
TD_THR_STOPPED,
TD_THR_RUN,
TD_THR_ACTIVE,
TD_THR_ZOMBIE,
TD_THR_SLEEP,
TD_THR_STOPPED_ASLEEP
} td_thr_state_e;
/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used
to select threads regardless of type in td_ta_thr_iter(). */
typedef enum
{
TD_THR_ANY_TYPE,
TD_THR_USER,
TD_THR_SYSTEM
} td_thr_type_e;
/* Types of the debugging library. */
/* Addresses. */
/*typedef void *psaddr_t;*/
/* Handle for a process. This type is opaque. */
typedef struct td_thragent td_thragent_t;
/* The actual thread handle type. This is also opaque. */
typedef struct td_thrhandle
{
td_thragent_t *th_ta_p;
psaddr_t th_unique;
} td_thrhandle_t;
/* Flags for `td_ta_thr_iter'. */
#define TD_THR_ANY_USER_FLAGS 0xffffffff
#define TD_THR_LOWEST_PRIORITY -20
#define TD_SIGNO_MASK NULL
#define TD_EVENTSIZE 2
#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */
#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */
#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */
/* Bitmask of enabled events. */
typedef struct td_thr_events
{
uint32_t event_bits[TD_EVENTSIZE];
} td_thr_events_t;
/* Event set manipulation macros. */
#define __td_eventmask(n) \
(UINT32_C (1) << (((n) - 1) & BT_UIMASK))
#define __td_eventword(n) \
((UINT32_C ((n) - 1)) >> BT_UISHIFT)
#define td_event_emptyset(setp) \
do { \
int __i; \
for (__i = TD_EVENTSIZE; __i > 0; --__i) \
(setp)->event_bits[__i - 1] = 0; \
} while (0)
#define td_event_fillset(setp) \
do { \
int __i; \
for (__i = TD_EVENTSIZE; __i > 0; --__i) \
(setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \
} while (0)
#define td_event_addset(setp, n) \
(((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n))
#define td_event_delset(setp, n) \
(((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n))
#define td_eventismember(setp, n) \
(__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)]))
#if TD_EVENTSIZE == 2
# define td_eventisempty(setp) \
(!((setp)->event_bits[0]) && !((setp)->event_bits[1]))
#else
# error "td_eventisempty must be changed to match TD_EVENTSIZE"
#endif
/* Events reportable by the thread implementation. */
typedef enum
{
TD_ALL_EVENTS, /* Pseudo-event number. */
TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */
TD_READY, /* Is executable now. */
TD_SLEEP, /* Blocked in a synchronization obj. */
TD_SWITCHTO, /* Now assigned to a process. */
TD_SWITCHFROM, /* Not anymore assigned to a process. */
TD_LOCK_TRY, /* Trying to get an unavailable lock. */
TD_CATCHSIG, /* Signal posted to the thread. */
TD_IDLE, /* Process getting idle. */
TD_CREATE, /* New thread created. */
TD_DEATH, /* Thread terminated. */
TD_PREEMPT, /* Preempted. */
TD_PRI_INHERIT, /* Inherited elevated priority. */
TD_REAP, /* Reaped. */
TD_CONCURRENCY, /* Number of processes changing. */
TD_TIMEOUT, /* Conditional variable wait timed out. */
TD_MIN_EVENT_NUM = TD_READY,
TD_MAX_EVENT_NUM = TD_TIMEOUT,
TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */
} td_event_e;
/* Values representing the different ways events are reported. */
typedef enum
{
NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */
NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically
inserted. */
NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */
} td_notify_e;
/* Description how event type is reported. */
typedef struct td_notify
{
td_notify_e type; /* Way the event is reported. */
union
{
psaddr_t bptaddr; /* Address of breakpoint. */
int syscallno; /* Number of system call used. */
} u;
} td_notify_t;
/* Structure used to report event. */
typedef struct td_event_msg
{
td_event_e event; /* Event type being reported. */
const td_thrhandle_t *th_p; /* Thread reporting the event. */
union
{
# if 0
td_synchandle_t *sh; /* Handle of synchronization object. */
#endif
uintptr_t data; /* Event specific data. */
} msg;
} td_event_msg_t;
/* Gathered statistics about the process. */
typedef struct td_ta_stats
{
int nthreads; /* Total number of threads in use. */
int r_concurrency; /* Concurrency level requested by user. */
int nrunnable_num; /* Average runnable threads, numerator. */
int nrunnable_den; /* Average runnable threads, denominator. */
int a_concurrency_num; /* Achieved concurrency level, numerator. */
int a_concurrency_den; /* Achieved concurrency level, denominator. */
int nlwps_num; /* Average number of processes in use,
numerator. */
int nlwps_den; /* Average number of processes in use,
denominator. */
int nidle_num; /* Average number of idling processes,
numerator. */
int nidle_den; /* Average number of idling processes,
denominator. */
} td_ta_stats_t;
/* Since Sun's library is based on Solaris threads we have to define a few
types to map them to POSIX threads. */
typedef pthread_t thread_t;
typedef pthread_key_t thread_key_t;
/* Linux has different names for the register set types. */
/*typedef gregset_t prgregset_t;*/
/*typedef fpregset_t prfpregset_t;*/
/* Callback for iteration over threads. */
typedef int td_thr_iter_f __P ((const td_thrhandle_t *, void *));
/* Callback for iteration over thread local data. */
typedef int td_key_iter_f __P ((thread_key_t, void (*) (void *), void *));
/* Forward declaration. This has to be defined by the user. */
struct ps_prochandle;
/* We don't have any differences between processes and threads, therefore
have only one PID type. */
/*typedef pid_t lwpid_t;*/
/* Information about the thread. */
typedef struct td_thrinfo
{
td_thragent_t *ti_ta_p; /* Process handle. */
unsigned int ti_user_flags; /* Unused. */
thread_t ti_tid; /* Thread ID returned by
pthread_create(). */
char *ti_tls; /* Pointer to thread-local data. */
psaddr_t ti_startfunc; /* Start function passed to
pthread_create(). */
psaddr_t ti_stkbase; /* Base of thread's stack. */
long int ti_stksize; /* Size of thread's stack. */
psaddr_t ti_ro_area; /* Unused. */
int ti_ro_size; /* Unused. */
td_thr_state_e ti_state; /* Thread state. */
unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */
td_thr_type_e ti_type; /* Type of the thread (system vs
user thread). */
intptr_t ti_pc; /* Unused. */
intptr_t ti_sp; /* Unused. */
short int ti_flags; /* Unused. */
int ti_pri; /* Thread priority. */
lwpid_t ti_lid; /* Unused. */
sigset_t ti_sigmask; /* Signal mask. */
unsigned char ti_traceme; /* Nonzero if event reporting
enabled. */
unsigned char ti_preemptflag; /* Unused. */
unsigned char ti_pirecflag; /* Unused. */
sigset_t ti_pending; /* Set of pending signals. */
td_thr_events_t ti_events; /* Set of enabled events. */
} td_thrinfo_t;
/* Prototypes for exported library functions. */
/* Initialize the thread debug support library. */
extern td_err_e td_init (void);
/* Historical relict. Should not be used anymore. */
extern td_err_e td_log (void);
/* Generate new thread debug library handle for process PS. */
extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta);
/* Free resources allocated for TA. */
extern td_err_e td_ta_delete (td_thragent_t *__ta);
/* Get number of currently running threads in process associated with TA. */
extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np);
/* Return process handle passed in `td_ta_new' for process associated with
TA. */
extern td_err_e td_ta_get_ph (const td_thragent_t *__ta,
struct ps_prochandle **__ph);
/* Map thread library handle PT to thread debug library handle for process
associated with TA and store result in *TH. */
extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt,
td_thrhandle_t *__th);
/* Map process ID LWPID to thread debug library handle for process
associated with TA and store result in *TH. */
extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid,
td_thrhandle_t *__th);
/* Call for each thread in a process associated with TA the callback function
CALLBACK. */
extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta,
td_thr_iter_f *__callback, void *__cbdata_p,
td_thr_state_e __state, int __ti_pri,
sigset_t *__ti_sigmask_p,
unsigned int __ti_user_flags);
/* Call for each defined thread local data entry the callback function KI. */
extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
void *__p);
/* Get event address for EVENT. */
extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
td_event_e __event, td_notify_t *__ptr);
/* Set suggested concurrency level for process associated with TA. */
extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
/* Enable collecting statistics for process associated with TA. */
extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable);
/* Reset statistics. */
extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta);
/* Retrieve statistics from process associated with TA. */
extern td_err_e td_ta_get_stats (const td_thragent_t *__ta,
td_ta_stats_t *__statsp);
/* Validate that TH is a thread handle. */
extern td_err_e td_thr_validate (const td_thrhandle_t *__th);
/* Return information about thread TH. */
extern td_err_e td_thr_get_info (const td_thrhandle_t *__th,
td_thrinfo_t *__infop);
/* Retrieve floating-point register contents of process running thread TH. */
extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th,
prfpregset_t *__regset);
/* Retrieve general register contents of process running thread TH. */
extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th,
prgregset_t __gregs);
/* Retrieve extended register contents of process running thread TH. */
extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs);
/* Get size of extended register set of process running thread TH. */
extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep);
/* Set floating-point register contents of process running thread TH. */
extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th,
const prfpregset_t *__fpregs);
/* Set general register contents of process running thread TH. */
extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th,
prgregset_t __gregs);
/* Set extended register contents of process running thread TH. */
extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th,
const void *__addr);
/* Enable reporting for EVENT for thread TH. */
extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event);
/* Enable EVENT for thread TH. */
extern td_err_e td_thr_set_event (const td_thrhandle_t *__th,
td_thr_events_t *__event);
/* Disable EVENT for thread TH. */
extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th,
td_thr_events_t *__event);
/* Get event message for thread TH. */
extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th,
td_event_msg_t *__msg);
/* Set priority of thread TH. */
extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio);
/* Set pending signals for thread TH. */
extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th,
unsigned char __n, const sigset_t *__ss);
/* Set signal mask for thread TH. */
extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th,
const sigset_t *__ss);
/* Return thread local data associated with key TK in thread TH. */
extern td_err_e td_thr_tsd (const td_thrhandle_t *__th,
const thread_key_t __tk, void **__data);
/* Suspend execution of thread TH. */
extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th);
/* Resume execution of thread TH. */
extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th);
#endif /* thread_db.h */

View File

@ -2415,6 +2415,35 @@ gnu_xfer_memory (memaddr, myaddr, len, write, target)
}
}
/* Return printable description of proc. */
static char *
proc_string (struct proc *proc)
{
static char tid_str[80];
if (proc_is_task (proc))
sprintf (tid_str, "process %d", proc->inf->pid);
else
sprintf (tid_str, "thread %d.%d",
proc->inf->pid, pid_to_thread_id (proc->tid));
return tid_str;
}
static char *
gnu_pid_to_str (int tid)
{
struct inf *inf = current_inferior;
struct proc *thread = inf_tid_to_thread (inf, tid);
if (thread)
return proc_string (thread);
else
{
static char tid_str[80];
sprintf (tid_str, "bogus thread id %d", tid);
return tid_str;
}
}
extern void gnu_store_registers (int regno);
extern void gnu_fetch_registers (int regno);
@ -2473,6 +2502,7 @@ init_gnu_ops (void)
gnu_ops.to_can_run = gnu_can_run; /* to_can_run */
gnu_ops.to_notice_signals = 0; /* to_notice_signals */
gnu_ops.to_thread_alive = gnu_thread_alive; /* to_thread_alive */
gnu_ops.to_pid_to_str = gnu_pid_to_str; /* to_pid_to_str */
gnu_ops.to_stop = gnu_stop; /* to_stop */
gnu_ops.to_pid_to_exec_file = gnu_pid_to_exec_file; /* to_pid_to_exec_file */
gnu_ops.to_core_file_to_sym_file = NULL;
@ -2488,35 +2518,6 @@ init_gnu_ops (void)
gnu_ops.to_magic = OPS_MAGIC; /* to_magic */
} /* init_gnu_ops */
/* Return printable description of proc. */
char *
proc_string (struct proc *proc)
{
static char tid_str[80];
if (proc_is_task (proc))
sprintf (tid_str, "process %d", proc->inf->pid);
else
sprintf (tid_str, "thread %d.%d",
proc->inf->pid, pid_to_thread_id (proc->tid));
return tid_str;
}
char *
gnu_target_pid_to_str (int tid)
{
struct inf *inf = current_inferior;
struct proc *thread = inf_tid_to_thread (inf, tid);
if (thread)
return proc_string (thread);
else
{
static char tid_str[80];
sprintf (tid_str, "bogus thread id %d", tid);
return tid_str;
}
}
/* User task commands. */
struct cmd_list_element *set_task_cmd_list = 0;

View File

@ -99,7 +99,7 @@ trans_lang (in_lang)
else if (in_lang == HP_LANGUAGE_CPLUSPLUS)
return language_cplus;
else if (in_lang == HP_LANGUAGE_F77)
else if (in_lang == HP_LANGUAGE_FORTRAN)
return language_fortran;
else

View File

@ -438,7 +438,7 @@ child_post_follow_vfork (parent_pid, followed_parent, child_pid, followed_child)
/* Format a process id, given PID. Be sure to terminate
this with a null--it's going to be printed via a "%s". */
char *
hppa_pid_to_str (pid)
child_pid_to_str (pid)
pid_t pid;
{
/* Static because address returned */
@ -658,7 +658,7 @@ hppa_pid_or_tid_to_str (id)
pid_t id;
{
/* In the ptrace world, there are only processes. */
return hppa_pid_to_str (id);
return child_pid_to_str (id);
}
/* This function has no meaning in a non-threaded world. Thus, we

View File

@ -34,6 +34,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <sys/reg.h>
#endif
/*
* Some systems (Linux) may have threads implemented as pseudo-processes,
* in which case we may be tracing more than one process at a time.
* In that case, inferior_pid will contain the main process ID and the
* individual thread (process) id mashed together. These macros are
* used to separate them out. The definitions may be overridden in tm.h
*/
#if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
#define PIDGET(PID) PID
#define TIDGET(PID) 0
#endif
/* This is a duplicate of the table in i386-xdep.c. */
static int regmap[] =
@ -141,12 +154,12 @@ fill_gregset (gregset_t *gregsetp,
/* Read the general registers from the process, and store them
in registers[]. */
static void
fetch_regs ()
fetch_regs (int tid)
{
int ret, regno;
gregset_t buf;
ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf);
ret = ptrace (PTRACE_GETREGS, tid, 0, (int) &buf);
if (ret < 0)
{
warning ("Couldn't get registers");
@ -160,12 +173,12 @@ fetch_regs ()
/* Set the inferior's general registers to the values in registers[]
--- but only those registers marked as valid. */
static void
store_regs ()
store_regs (int tid)
{
int ret, regno;
gregset_t buf;
ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf);
ret = ptrace (PTRACE_GETREGS, tid, 0, (int) &buf);
if (ret < 0)
{
warning ("Couldn't get registers");
@ -174,7 +187,7 @@ store_regs ()
convert_to_gregset (&buf, registers, register_valid);
ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, (int)buf);
ret = ptrace (PTRACE_SETREGS, tid, 0, (int)buf);
if (ret < 0)
{
warning ("Couldn't write registers");
@ -285,12 +298,12 @@ fill_fpregset (fpregset_t *fpregsetp,
/* Get the whole floating point state of the process and store the
floating point stack into registers[]. */
static void
fetch_fpregs ()
fetch_fpregs (int tid)
{
int ret, regno;
fpregset_t buf;
ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf);
ret = ptrace (PTRACE_GETFPREGS, tid, 0, (int) &buf);
if (ret < 0)
{
warning ("Couldn't get floating point status");
@ -306,12 +319,12 @@ fetch_fpregs ()
/* Set the inferior's floating-point registers to the values in
registers[] --- but only those registers marked valid. */
static void
store_fpregs ()
store_fpregs (int tid)
{
int ret;
fpregset_t buf;
ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf);
ret = ptrace (PTRACE_GETFPREGS, tid, 0, (int) &buf);
if (ret < 0)
{
warning ("Couldn't get floating point status");
@ -320,7 +333,7 @@ store_fpregs ()
convert_to_fpregset (&buf, registers, register_valid);
ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, (int) &buf);
ret = ptrace (PTRACE_SETFPREGS, tid, 0, (int) &buf);
if (ret < 0)
{
warning ("Couldn't write floating point status");
@ -427,7 +440,7 @@ convert_to_xfpregset (struct user_xfpregs_struct *xfpregs,
/* Make a PTRACE_GETXFPREGS request, and supply all the register
values that yields to GDB. */
static int
fetch_xfpregs ()
fetch_xfpregs (int tid)
{
int ret;
struct user_xfpregs_struct xfpregs;
@ -435,7 +448,7 @@ fetch_xfpregs ()
if (! have_ptrace_getxfpregs)
return 0;
ret = ptrace (PTRACE_GETXFPREGS, inferior_pid, 0, &xfpregs);
ret = ptrace (PTRACE_GETXFPREGS, tid, 0, &xfpregs);
if (ret == -1)
{
if (errno == EIO)
@ -456,7 +469,7 @@ fetch_xfpregs ()
/* Send all the valid register values in GDB's register file covered
by the PTRACE_SETXFPREGS request to the inferior. */
static int
store_xfpregs ()
store_xfpregs (int tid)
{
int ret;
struct user_xfpregs_struct xfpregs;
@ -464,7 +477,7 @@ store_xfpregs ()
if (! have_ptrace_getxfpregs)
return 0;
ret = ptrace (PTRACE_GETXFPREGS, inferior_pid, 0, &xfpregs);
ret = ptrace (PTRACE_GETXFPREGS, tid, 0, &xfpregs);
if (ret == -1)
{
if (errno == EIO)
@ -479,7 +492,7 @@ store_xfpregs ()
convert_to_xfpregset (&xfpregs, registers, register_valid);
if (ptrace (PTRACE_SETXFPREGS, inferior_pid, 0, &xfpregs) < 0)
if (ptrace (PTRACE_SETXFPREGS, tid, 0, &xfpregs) < 0)
{
warning ("Couldn't write floating-point and SSE registers.");
return 0;
@ -511,8 +524,8 @@ dummy_sse_values ()
/* Stub versions of the above routines, for systems that don't have
PTRACE_GETXFPREGS. */
static int store_xfpregs () { return 0; }
static int fetch_xfpregs () { return 0; }
static int store_xfpregs (int tid) { return 0; }
static int fetch_xfpregs (int tid) { return 0; }
static void dummy_sse_values () {}
#endif
@ -528,27 +541,33 @@ static void dummy_sse_values () {}
void
fetch_inferior_registers (int regno)
{
/* linux lwp id's are process id's */
int tid;
if ((tid = TIDGET (inferior_pid)) == 0)
tid = inferior_pid; /* not a threaded program */
/* Use the xfpregs requests whenever possible, since they transfer
more registers in one system call, and we'll cache the results.
But remember that fetch_xfpregs can fail, and return zero. */
if (regno == -1)
{
fetch_regs ();
if (fetch_xfpregs ())
fetch_regs (tid);
if (fetch_xfpregs (tid))
return;
fetch_fpregs ();
fetch_fpregs (tid);
return;
}
if (GETREGS_SUPPLIES (regno))
{
fetch_regs ();
fetch_regs (tid);
return;
}
if (GETXFPREGS_SUPPLIES (regno))
{
if (fetch_xfpregs ())
if (fetch_xfpregs (tid))
return;
/* Either our processor or our kernel doesn't support the SSE
@ -557,7 +576,7 @@ fetch_inferior_registers (int regno)
more graceful to handle differences in the register set using
gdbarch. Until then, this will at least make things work
plausibly. */
fetch_fpregs ();
fetch_fpregs (tid);
dummy_sse_values ();
return;
}
@ -577,32 +596,38 @@ void
store_inferior_registers (regno)
int regno;
{
/* linux lwp id's are process id's */
int tid;
if ((tid = TIDGET (inferior_pid)) == 0)
tid = inferior_pid; /* not a threaded program */
/* Use the xfpregs requests whenever possible, since they transfer
more registers in one system call. But remember that
fetch_xfpregs can fail, and return zero. */
store_xfpregs can fail, and return zero. */
if (regno == -1)
{
store_regs ();
if (store_xfpregs ())
store_regs (tid);
if (store_xfpregs (tid))
return;
store_fpregs ();
store_fpregs (tid);
return;
}
if (GETREGS_SUPPLIES (regno))
{
store_regs ();
store_regs (tid);
return;
}
if (GETXFPREGS_SUPPLIES (regno))
{
if (store_xfpregs ())
if (store_xfpregs (tid))
return;
/* Either our processor or our kernel doesn't support the SSE
registers, so just write the FP registers in the traditional way. */
store_fpregs ();
store_fpregs (tid);
return;
}

View File

@ -845,6 +845,7 @@ run_stack_dummy (addr, buffer)
char *buffer;
{
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
int saved_async = 0;
/* Now proceed, having reached the desired place. */
clear_proceed_status ();
@ -891,7 +892,15 @@ run_stack_dummy (addr, buffer)
disable_watchpoints_before_interactive_call_start ();
proceed_to_finish = 1; /* We want stop_registers, please... */
if (target_can_async_p ())
saved_async = target_async_mask (0);
proceed (addr, TARGET_SIGNAL_0, 0);
if (saved_async)
target_async_mask (saved_async);
enable_watchpoints_after_interactive_call_stop ();
discard_cleanups (old_cleanups);

View File

@ -24,10 +24,18 @@
#include "inferior.h"
#include "target.h"
#include "gdb_string.h"
#ifdef HAVE_WAIT_H
#include <wait.h>
#else
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include "wait.h" /* NOTE: This is ../include/wait.h */
#endif
/* "wait.h" fills in the gaps left by <wait.h> */
#include "wait.h" /* NOTE: This is ../include/wait.h */
#include "command.h"
#ifdef USG
@ -109,6 +117,22 @@ static void fetch_register PARAMS ((int));
static void store_register PARAMS ((int));
#endif
/*
* Some systems (Linux) may have threads implemented as pseudo-processes,
* in which case we may be tracing more than one process at a time.
* In that case, inferior_pid will contain the main process ID and the
* individual thread (process) id mashed together. These macros are
* used to separate them out. The definitions may be overridden in tm.h
*
* NOTE: default definitions here are for systems with no threads.
* Useful definitions MUST be provided in tm.h
*/
#if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
#define PIDGET(PID) PID
#define TIDGET(PID) 0
#endif
void _initialize_kernel_u_addr PARAMS ((void));
void _initialize_infptrace PARAMS ((void));
@ -135,14 +159,13 @@ call_ptrace (request, pid, addr, data)
if (request == PT_SETTRC)
{
errno = 0;
pt_status = ptrace (PT_SETTRC, pid, addr, data
#if defined (FIVE_ARG_PTRACE)
#if !defined (FIVE_ARG_PTRACE)
pt_status = ptrace (PT_SETTRC, pid, addr, data);
#else
/* Deal with HPUX 8.0 braindamage. We never use the
calls which require the fifth argument. */
,0
pt_status = ptrace (PT_SETTRC, pid, addr, data, 0);
#endif
);
if (errno)
perror_with_name ("ptrace");
#if 0
@ -173,13 +196,14 @@ call_ptrace (request, pid, addr, data)
saved_errno = errno;
errno = 0;
#endif
pt_status = ptrace (request, pid, addr, data
#if defined (FIVE_ARG_PTRACE)
#if !defined (FIVE_ARG_PTRACE)
pt_status = ptrace (request, pid, addr, data);
#else
/* Deal with HPUX 8.0 braindamage. We never use the
calls which require the fifth argument. */
,0
pt_status = ptrace (request, pid, addr, data, 0);
#endif
);
#if 0
if (errno)
printf (" [errno = %d]", errno);
@ -275,7 +299,9 @@ child_resume (pid, step, signal)
target_signal_to_host (signal));
if (errno)
perror_with_name ("ptrace");
{
perror_with_name ("ptrace");
}
}
#endif /* CHILD_RESUME */
@ -368,6 +394,7 @@ fetch_register (regno)
register int i;
unsigned int offset; /* Offset of registers within the u area. */
char buf[MAX_REGISTER_RAW_SIZE];
int tid;
if (CANNOT_FETCH_REGISTER (regno))
{
@ -376,18 +403,23 @@ fetch_register (regno)
return;
}
/* Overload thread id onto process id */
if ((tid = TIDGET (inferior_pid)) == 0)
tid = inferior_pid; /* no thread id, just use process id */
offset = U_REGS_OFFSET;
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
*(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
*(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
(PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (PTRACE_XFER_TYPE);
if (errno != 0)
{
sprintf (mess, "reading register %s (#%d)", REGISTER_NAME (regno), regno);
sprintf (mess, "reading register %s (#%d)",
REGISTER_NAME (regno), regno);
perror_with_name (mess);
}
}
@ -432,24 +464,30 @@ store_register (regno)
char mess[128]; /* For messages */
register int i;
unsigned int offset; /* Offset of registers within the u area. */
int tid;
if (CANNOT_STORE_REGISTER (regno))
{
return;
}
/* Overload thread id onto process id */
if ((tid = TIDGET (inferior_pid)) == 0)
tid = inferior_pid; /* no thread id, just use process id */
offset = U_REGS_OFFSET;
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
*(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
regaddr += sizeof (PTRACE_XFER_TYPE);
if (errno != 0)
{
sprintf (mess, "writing register %s (#%d)", REGISTER_NAME (regno), regno);
sprintf (mess, "writing register %s (#%d)",
REGISTER_NAME (regno), regno);
perror_with_name (mess);
}
}
@ -520,14 +558,14 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
{
/* Need part of initial word -- fetch it. */
buffer[0] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr,
0);
buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_pid),
(PTRACE_ARG3_TYPE) addr, 0);
}
if (count > 1) /* FIXME, avoid if even boundary */
{
buffer[count - 1]
= ptrace (PT_READ_I, inferior_pid,
buffer[count - 1]
= ptrace (PT_READ_I, PIDGET (inferior_pid),
((PTRACE_ARG3_TYPE)
(addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
0);
@ -544,15 +582,15 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PT_WRITE_D, inferior_pid, (PTRACE_ARG3_TYPE) addr,
buffer[i]);
ptrace (PT_WRITE_D, PIDGET (inferior_pid),
(PTRACE_ARG3_TYPE) addr, buffer[i]);
if (errno)
{
/* Using the appropriate one (I or D) is necessary for
Gould NP1, at least. */
errno = 0;
ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) addr,
buffer[i]);
ptrace (PT_WRITE_I, PIDGET (inferior_pid),
(PTRACE_ARG3_TYPE) addr, buffer[i]);
}
if (errno)
return 0;
@ -567,7 +605,7 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
buffer[i] = ptrace (PT_READ_I, inferior_pid,
buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_pid),
(PTRACE_ARG3_TYPE) addr, 0);
if (errno)
return 0;

View File

@ -814,6 +814,14 @@ child_core_file_to_sym_file (core)
}
#if !defined(CHILD_PID_TO_STR)
char *
child_pid_to_str (pid)
int pid;
{
return normal_pid_to_str (pid);
}
#endif
static void
init_child_ops ()
@ -865,6 +873,7 @@ init_child_ops ()
child_ops.to_mourn_inferior = child_mourn_inferior;
child_ops.to_can_run = child_can_run;
child_ops.to_thread_alive = child_thread_alive;
child_ops.to_pid_to_str = child_pid_to_str;
child_ops.to_stop = child_stop;
child_ops.to_enable_exception_callback = child_enable_exception_callback;
child_ops.to_get_current_exception_event = child_get_current_exception_event;

View File

@ -5773,7 +5773,7 @@ hppa_pid_or_tid_to_str (id)
/* Does this appear to be a process? If so, print it that way. */
if (is_process_id (id))
return hppa_pid_to_str (id);
return child_pid_to_str (id);
/* Else, print both the GDB thread number and the system thread id. */
sprintf (buf, "thread %d (", pid_to_thread_id (id));

View File

@ -1578,12 +1578,11 @@ _initialize_language ()
add_language (&auto_language_defn);
language = savestring ("auto", strlen ("auto"));
range = savestring ("auto", strlen ("auto"));
type = savestring ("auto", strlen ("auto"));
/* Have the above take effect */
set_language_command (language, 0);
type = savestring ("auto", strlen ("auto"));
set_type_command (NULL, 0);
range = savestring ("auto", strlen ("auto"));
set_range_command (NULL, 0);
}

2140
gdb/lin-thread.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -115,7 +115,7 @@ static int *linuxthreads_wait_status; /* wait array of status */
static int linuxthreads_wait_last; /* index of last valid elt in
linuxthreads_wait_{pid,status} */
static sigset_t linuxthreads_wait_mask; /* sigset with SIGCHLD */
static sigset_t linuxthreads_block_mask; /* sigset without SIGCHLD */
static int linuxthreads_step_pid; /* current stepped pid */
static int linuxthreads_step_signo; /* current stepped target signal */
@ -170,6 +170,13 @@ struct linuxthreads_signal linuxthreads_sig_debug = {
"__pthread_sig_debug", 0, 0, 0, 0, 0
};
/* Set by thread_db module when it takes over the thread_stratum.
In that case we must:
a) refrain from turning on the debug signal, and
b) refrain from calling add_thread. */
int using_thread_db = 0;
/* A table of breakpoint locations, one per PID. */
static struct linuxthreads_breakpoint {
CORE_ADDR pc; /* PC of breakpoint */
@ -292,23 +299,37 @@ linuxthreads_find_trap (pid, stop)
{
/* Make sure that we'll find what we're looking for. */
if (!found_trap)
kill (pid, SIGTRAP);
{
kill (pid, SIGTRAP);
}
if (!found_stop)
kill (pid, SIGSTOP);
{
kill (pid, SIGSTOP);
}
}
/* Catch all status until SIGTRAP and optionally SIGSTOP show up. */
for (;;)
{
/* resume the child every time... */
child_resume (pid, 1, TARGET_SIGNAL_0);
/* loop as long as errno == EINTR:
waitpid syscall may be aborted due to GDB receiving a signal.
FIXME: EINTR handling should no longer be necessary here, since
we now block SIGCHLD except in an explicit sigsuspend call. */
for (;;)
{
rpid = waitpid (pid, &status, __WCLONE);
if (rpid > 0)
break;
{
break;
}
if (errno == EINTR)
continue;
{
continue;
}
/* There are a few reasons the wait call above may have
failed. If the thread manager dies, its children get
@ -320,9 +341,11 @@ linuxthreads_find_trap (pid, stop)
2.0.36. */
rpid = waitpid (pid, &status, 0);
if (rpid > 0)
break;
{
break;
}
if (errno != EINTR)
perror_with_name ("waitpid");
perror_with_name ("find_trap/waitpid");
}
if (!WIFSTOPPED(status)) /* Thread has died */
@ -347,7 +370,9 @@ linuxthreads_find_trap (pid, stop)
/* Resend any other signals we noticed to the thread, to be received
when we continue it. */
while (--last >= 0)
kill (pid, WSTOPSIG(wstatus[last]));
{
kill (pid, WSTOPSIG(wstatus[last]));
}
return 1;
}
@ -357,15 +382,22 @@ static void
restore_inferior_pid (arg)
void *arg;
{
int pid = (int) arg;
inferior_pid = pid;
#if TARGET_PTR_BIT > TARGET_INT_BIT
inferior_pid = (int) ((long) arg);
#else
inferior_pid = (int) arg;
#endif
}
/* Register a cleanup to restore the value of inferior_pid. */
static struct cleanup *
save_inferior_pid ()
{
#if TARGET_PTR_BIT > TARGET_INT_BIT
return make_cleanup (restore_inferior_pid, (void *) ((long) inferior_pid));
#else
return make_cleanup (restore_inferior_pid, (void *) inferior_pid);
#endif
}
static void
@ -476,8 +508,7 @@ check_signal_number (sig)
sig->print = signal_print_update (target_signal_from_host (num), 0);
}
static void
void
check_all_signal_numbers ()
{
/* If this isn't a LinuxThreads program, quit early. */
@ -497,6 +528,7 @@ check_all_signal_numbers ()
sact.sa_handler = sigchld_handler;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
if (linuxthreads_sig_debug.signal > 0)
sigaction(linuxthreads_sig_cancel.signal, &sact, NULL);
else
@ -576,7 +608,6 @@ iterate_active_threads (func, all)
(*func)(pid);
}
}
}
/* Insert a thread breakpoint at linuxthreads_breakpoint_addr.
@ -640,9 +671,13 @@ kill_thread (pid)
int pid;
{
if (in_thread_list (pid))
ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
{
ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
}
else
kill (pid, SIGKILL);
{
kill (pid, SIGKILL);
}
}
/* Resume a thread */
@ -655,9 +690,13 @@ resume_thread (pid)
&& linuxthreads_thread_alive (pid))
{
if (pid == linuxthreads_step_pid)
child_resume (pid, 1, linuxthreads_step_signo);
{
child_resume (pid, 1, linuxthreads_step_signo);
}
else
child_resume (pid, 0, TARGET_SIGNAL_0);
{
child_resume (pid, 0, TARGET_SIGNAL_0);
}
}
}
@ -677,6 +716,15 @@ detach_thread (pid)
}
}
/* Attach a thread */
void
attach_thread (pid)
int pid;
{
if (ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0) != 0)
perror_with_name ("attach_thread");
}
/* Stop a thread */
static void
stop_thread (pid)
@ -685,17 +733,21 @@ stop_thread (pid)
if (pid != inferior_pid)
{
if (in_thread_list (pid))
kill (pid, SIGSTOP);
{
kill (pid, SIGSTOP);
}
else if (ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0) == 0)
{
if (!linuxthreads_attach_pending)
printf_unfiltered ("[New %s]\n", target_pid_to_str (pid));
printf_filtered ("[New %s]\n", target_pid_to_str (pid));
add_thread (pid);
if (linuxthreads_sig_debug.signal)
/* After a new thread in glibc 2.1 signals gdb its existence,
it suspends itself and wait for linuxthreads_sig_restart,
now we can wake up it. */
kill (pid, linuxthreads_sig_restart.signal);
{
/* After a new thread in glibc 2.1 signals gdb its existence,
it suspends itself and wait for linuxthreads_sig_restart,
now we can wake it up. */
kill (pid, linuxthreads_sig_restart.signal);
}
}
else
perror_with_name ("ptrace in stop_thread");
@ -712,14 +764,22 @@ wait_thread (pid)
if (pid != inferior_pid && in_thread_list (pid))
{
/* loop as long as errno == EINTR:
waitpid syscall may be aborted if GDB receives a signal.
FIXME: EINTR handling should no longer be necessary here, since
we now block SIGCHLD except during an explicit sigsuspend call. */
for (;;)
{
/* Get first pid status. */
rpid = waitpid(pid, &status, __WCLONE);
if (rpid > 0)
break;
{
break;
}
if (errno == EINTR)
continue;
{
continue;
}
/* There are two reasons this might have failed:
@ -739,9 +799,11 @@ wait_thread (pid)
didn't work. */
rpid = waitpid(pid, &status, 0);
if (rpid > 0)
break;
{
break;
}
if (errno != EINTR && linuxthreads_thread_alive (pid))
perror_with_name ("waitpid");
perror_with_name ("wait_thread/waitpid");
/* the thread is dead. */
return;
@ -810,16 +872,17 @@ update_stop_threads (test_pid)
if (!in_thread_list (test_pid))
{
if (!linuxthreads_attach_pending)
printf_unfiltered ("[New %s]\n",
target_pid_to_str (test_pid));
printf_filtered ("[New %s]\n",
target_pid_to_str (test_pid));
add_thread (test_pid);
if (linuxthreads_sig_debug.signal
&& inferior_pid == test_pid)
/* After a new thread in glibc 2.1 signals gdb its
existence, it suspends itself and wait for
linuxthreads_sig_restart, now we can wake up
it. */
kill (test_pid, linuxthreads_sig_restart.signal);
{
/* After a new thread in glibc 2.1 signals gdb its
existence, it suspends itself and wait for
linuxthreads_sig_restart, now we can wake it up. */
kill (test_pid, linuxthreads_sig_restart.signal);
}
}
}
iterate_active_threads (stop_thread, 0);
@ -851,6 +914,13 @@ linuxthreads_new_objfile (objfile)
{
struct minimal_symbol *ms;
/* Call predecessor on chain, if any.
Calling the new module first allows it to dominate,
if it finds its compatible libraries. */
if (target_new_objfile_chain)
target_new_objfile_chain (objfile);
if (!objfile)
{
/* We're starting an entirely new executable, so we can no
@ -989,19 +1059,21 @@ any thread other than the main thread.");
linuxthreads_breakpoint_zombie = (struct linuxthreads_breakpoint *)
xmalloc (sizeof (struct linuxthreads_breakpoint) * (linuxthreads_max + 1));
if (inferior_pid && !linuxthreads_attach_pending)
if (inferior_pid &&
!linuxthreads_attach_pending &&
!using_thread_db) /* suppressed by thread_db module */
{
int on = 1;
target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
linuxthreads_attach_pending = 1;
update_stop_threads (inferior_pid);
linuxthreads_attach_pending = 0;
}
check_all_signal_numbers ();
quit:
/* Call predecessor on chain, if any. */
if (target_new_objfile_chain)
target_new_objfile_chain (objfile);
}
/* If we have switched threads from a one that stopped at breakpoint,
@ -1147,7 +1219,9 @@ linuxthreads_resume (pid, step, signo)
enum target_signal signo;
{
if (!linuxthreads_max || stop_soon_quietly || linuxthreads_manager_pid == 0)
child_ops.to_resume (pid, step, signo);
{
child_ops.to_resume (pid, step, signo);
}
else
{
int rpid;
@ -1208,11 +1282,69 @@ linuxthreads_resume (pid, step, signo)
}
/* Resume initial thread. */
/* [unles it has a wait event pending] */
if (!linuxthreads_pending_status (rpid))
child_ops.to_resume (rpid, step, signo);
{
child_ops.to_resume (rpid, step, signo);
}
}
}
/* Abstract out the child_wait functionality. */
int
linux_child_wait (pid, rpid, status)
int pid;
int *rpid;
int *status;
{
int save_errno;
/* Note: inftarg has these inside the loop. */
set_sigint_trap (); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
errno = save_errno = 0;
for (;;)
{
errno = 0;
*rpid = waitpid (pid, status, __WCLONE | WNOHANG);
save_errno = errno;
if (*rpid > 0)
{
/* Got an event -- break out */
break;
}
if (errno == EINTR) /* interrupted by signal, try again */
{
continue;
}
errno = 0;
*rpid = waitpid (pid, status, WNOHANG);
if (*rpid > 0)
{
/* Got an event -- break out */
break;
}
if (errno == EINTR)
{
continue;
}
if (errno != 0 && save_errno != 0)
{
break;
}
sigsuspend(&linuxthreads_block_mask);
}
clear_sigio_trap ();
clear_sigint_trap ();
return errno ? errno : save_errno;
}
/* Wait for any threads to stop. We may have to convert PID from a thread id
to a LWP id, and vice versa on the way out. */
@ -1280,44 +1412,8 @@ linuxthreads_wait (pid, ourstatus)
if (rpid == 0)
{
int save_errno;
sigset_t omask;
set_sigint_trap(); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
sigprocmask(SIG_BLOCK, &linuxthreads_wait_mask, &omask);
for (;;)
{
rpid = waitpid (pid, &status, __WCLONE | WNOHANG);
if (rpid > 0)
break;
if (rpid == 0)
save_errno = 0;
else if (errno != EINTR)
save_errno = errno;
else
continue;
rpid = waitpid (pid, &status, WNOHANG);
if (rpid > 0)
break;
if (rpid < 0)
{
if (errno == EINTR)
continue;
else if (save_errno != 0)
break;
}
sigsuspend(&omask);
}
sigprocmask(SIG_SETMASK, &omask, NULL);
save_errno = errno;
clear_sigio_trap ();
clear_sigint_trap();
save_errno = linux_child_wait (pid, &rpid, &status);
if (rpid == -1)
{
@ -1338,15 +1434,19 @@ linuxthreads_wait (pid, ourstatus)
}
}
/* Signals arrive in any order. So get all signals until SIGTRAP
and resend previous ones to be held after. */
/* We have now gotten a new event from waitpid above. */
/* Signals arrive in any order. So get all signals until
SIGTRAP and resend previous ones to be held after. */
if (linuxthreads_max
&& !linuxthreads_breakpoints_inserted
&& WIFSTOPPED(status))
if (WSTOPSIG(status) == SIGTRAP)
{
while (--last >= 0)
kill (rpid, WSTOPSIG(wstatus[last]));
{
kill (rpid, WSTOPSIG(wstatus[last]));
}
/* insert negative zombie breakpoint */
for (i = 0; i <= linuxthreads_breakpoint_last; i++)
@ -1368,7 +1468,9 @@ linuxthreads_wait (pid, ourstatus)
if (wstatus[i] == status)
break;
if (i >= last)
wstatus[last++] = status;
{
wstatus[last++] = status;
}
}
child_resume (rpid, 1, TARGET_SIGNAL_0);
continue;
@ -1387,9 +1489,13 @@ linuxthreads_wait (pid, ourstatus)
if (!linuxthreads_pending_status (rpid))
{
if (linuxthreads_step_pid == rpid)
child_resume (rpid, 1, linuxthreads_step_signo);
{
child_resume (rpid, 1, linuxthreads_step_signo);
}
else
child_resume (rpid, 0, TARGET_SIGNAL_0);
{
child_resume (rpid, 0, TARGET_SIGNAL_0);
}
}
continue;
}
@ -1433,9 +1539,13 @@ linuxthreads_wait (pid, ourstatus)
write_pc_pid (linuxthreads_breakpoint_zombie[i].pc
- DECR_PC_AFTER_BREAK, rpid);
if (linuxthreads_step_pid == rpid)
child_resume (rpid, 1, linuxthreads_step_signo);
{
child_resume (rpid, 1, linuxthreads_step_signo);
}
else
child_resume (rpid, 0, TARGET_SIGNAL_0);
{
child_resume (rpid, 0, TARGET_SIGNAL_0);
}
continue;
}
}
@ -1453,8 +1563,12 @@ linuxthreads_wait (pid, ourstatus)
if (linuxthreads_attach_pending && !stop_soon_quietly)
{
int on = 1;
target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
update_stop_threads (rpid);
if (!using_thread_db)
{
target_write_memory (linuxthreads_debug,
(char *) &on, sizeof (on));
update_stop_threads (rpid);
}
linuxthreads_attach_pending = 0;
}
@ -1496,6 +1610,19 @@ Use the \"file\" or \"exec-file\" command.");
child_ops.to_create_inferior (exec_file, allargs, env);
}
void
linuxthreads_discard_global_state ()
{
linuxthreads_inferior_pid = 0;
linuxthreads_breakpoint_pid = 0;
linuxthreads_step_pid = 0;
linuxthreads_step_signo = TARGET_SIGNAL_0;
linuxthreads_manager_pid = 0;
linuxthreads_initial_pid = 0;
linuxthreads_attach_pending = 0;
linuxthreads_max = 0;
}
/* Clean up after the inferior dies. */
static void
@ -1506,13 +1633,7 @@ linuxthreads_mourn_inferior ()
int off = 0;
target_write_memory (linuxthreads_debug, (char *)&off, sizeof (off));
linuxthreads_inferior_pid = 0;
linuxthreads_breakpoint_pid = 0;
linuxthreads_step_pid = 0;
linuxthreads_step_signo = TARGET_SIGNAL_0;
linuxthreads_manager_pid = 0;
linuxthreads_initial_pid = 0;
linuxthreads_attach_pending = 0;
linuxthreads_discard_global_state ();
init_thread_list(); /* Destroy thread info */
}
@ -1566,12 +1687,18 @@ linuxthreads_kill ()
/* Wait for all threads. */
do
rpid = waitpid (-1, &status, __WCLONE | WNOHANG);
{
rpid = waitpid (-1, &status, __WCLONE | WNOHANG);
}
while (rpid > 0 || errno == EINTR);
/* FIXME: should no longer need to handle EINTR here. */
do
rpid = waitpid (-1, &status, WNOHANG);
{
rpid = waitpid (-1, &status, WNOHANG);
}
while (rpid > 0 || errno == EINTR);
/* FIXME: should no longer need to handle EINTR here. */
linuxthreads_mourn_inferior ();
}
@ -1617,6 +1744,7 @@ linuxthreads_can_run ()
{
return child_suppress_run;
}
static void
init_linuxthreads_ops ()
@ -1636,6 +1764,7 @@ init_linuxthreads_ops ()
linuxthreads_ops.to_create_inferior = linuxthreads_create_inferior;
linuxthreads_ops.to_mourn_inferior = linuxthreads_mourn_inferior;
linuxthreads_ops.to_thread_alive = linuxthreads_thread_alive;
linuxthreads_ops.to_pid_to_str = linuxthreads_pid_to_str;
linuxthreads_ops.to_magic = OPS_MAGIC;
}
@ -1643,6 +1772,7 @@ void
_initialize_linuxthreads ()
{
struct sigaction sact;
sigset_t linuxthreads_wait_mask; /* sigset with SIGCHLD */
init_linuxthreads_ops ();
add_target (&linuxthreads_ops);
@ -1664,4 +1794,10 @@ _initialize_linuxthreads ()
/* initialize SIGCHLD mask */
sigemptyset (&linuxthreads_wait_mask);
sigaddset (&linuxthreads_wait_mask, SIGCHLD);
/* Use SIG_BLOCK to block receipt of SIGCHLD.
The block_mask will allow us to wait for this signal explicitly. */
sigprocmask(SIG_BLOCK,
&linuxthreads_wait_mask,
&linuxthreads_block_mask);
}

View File

@ -774,7 +774,7 @@ child_resume (pid, step, signal)
buffer. */
char *
lynx_pid_to_str (pid)
child_pid_to_str (pid)
int pid;
{
static char buf[40];

View File

@ -2430,8 +2430,18 @@ mips_print_register (regnum, all)
gdb_stdout, 0, 1, 0, Val_pretty_default);
/* Else print as integer in hex. */
else
print_scalar_formatted (raw_buffer, REGISTER_VIRTUAL_TYPE (regnum),
'x', 0, gdb_stdout);
{
int offset;
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
else
offset = 0;
print_scalar_formatted (raw_buffer + offset,
REGISTER_VIRTUAL_TYPE (regnum),
'x', 0, gdb_stdout);
}
}
/* Replacement for generic do_registers_info.
@ -3783,6 +3793,7 @@ mips_gdbarch_init (info, arches)
switch (info.bfd_arch_info->mach)
{
case bfd_mach_mips4100:
case bfd_mach_mips4111:
tdep->mips_fpu_type = MIPS_FPU_NONE;
break;
default:

View File

@ -5899,6 +5899,9 @@ init_procfs_ops ()
procfs_ops.to_can_run = procfs_can_run;
procfs_ops.to_notice_signals = procfs_notice_signals;
procfs_ops.to_thread_alive = procfs_thread_alive;
#ifdef TIDGET
procfs_ops.to_pid_to_str = procfs_pid_to_str;
#endif
procfs_ops.to_stop = procfs_stop;
procfs_ops.to_stratum = process_stratum;
procfs_ops.to_has_all_memory = 1;

View File

@ -2137,7 +2137,7 @@ remote_async_detach (args, from_tty)
remote_send (buf, PBUFSIZ);
/* Unregister the file descriptor from the event loop. */
if (SERIAL_IS_ASYNC_P (remote_desc))
if (target_is_async_p ())
SERIAL_ASYNC (remote_desc, NULL, 0);
pop_target ();
@ -2254,14 +2254,14 @@ remote_async_resume (pid, step, siggnal)
/* FIXME: ezannoni 1999-09-28: We may need to move this out of here
into infcmd.c in order to allow inferior function calls to work
NOT asynchronously. */
if (event_loop_p && SERIAL_CAN_ASYNC_P (remote_desc))
if (event_loop_p && target_can_async_p ())
target_async (inferior_event_handler, 0);
/* Tell the world that the target is now executing. */
/* FIXME: cagney/1999-09-23: Is it the targets responsibility to set
this? Instead, should the client of target just assume (for
async targets) that the target is going to start executing? Is
this information already found in the continuation block? */
if (SERIAL_IS_ASYNC_P (remote_desc))
if (target_is_async_p ())
target_executing = 1;
putpkt (buf);
}
@ -2710,14 +2710,14 @@ remote_async_wait (pid, status)
{
unsigned char *p;
if (!SERIAL_IS_ASYNC_P (remote_desc))
if (!target_is_async_p ())
ofunc = signal (SIGINT, remote_interrupt);
/* FIXME: cagney/1999-09-27: If we're in async mode we should
_never_ wait for ever -> test on target_is_async_p().
However, before we do that we need to ensure that the caller
knows how to take the target into/out of async mode. */
getpkt (buf, PBUFSIZ, wait_forever_enabled_p);
if (!SERIAL_IS_ASYNC_P (remote_desc))
if (!target_is_async_p ())
signal (SIGINT, ofunc);
/* This is a hook for when we need to do something (perhaps the
@ -4009,7 +4009,7 @@ static void
remote_async_kill ()
{
/* Unregister the file descriptor from the event loop. */
if (SERIAL_IS_ASYNC_P (remote_desc))
if (target_is_async_p ())
SERIAL_ASYNC (remote_desc, NULL, 0);
/* For some mysterious reason, wait_for_inferior calls kill instead of
@ -5297,14 +5297,14 @@ static int
remote_can_async_p (void)
{
/* We're async whenever the serial device is. */
return SERIAL_CAN_ASYNC_P (remote_desc);
return (current_target.to_async_mask_value) && SERIAL_CAN_ASYNC_P (remote_desc);
}
static int
remote_is_async_p (void)
{
/* We're async whenever the serial device is. */
return SERIAL_IS_ASYNC_P (remote_desc);
return (current_target.to_async_mask_value) && SERIAL_IS_ASYNC_P (remote_desc);
}
/* Pass the SERIAL event on and up to the client. One day this code
@ -5326,6 +5326,9 @@ remote_async_serial_handler (serial_t scb, void *context)
static void
remote_async (void (*callback) (enum inferior_event_type event_type, void *context), void *context)
{
if (current_target.to_async_mask_value == 0)
internal_error ("Calling remote_async when async is masked");
if (callback != NULL)
{
SERIAL_ASYNC (remote_desc, remote_async_serial_handler, NULL);
@ -5382,6 +5385,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
remote_async_ops.to_can_async_p = remote_can_async_p;
remote_async_ops.to_is_async_p = remote_is_async_p;
remote_async_ops.to_async = remote_async;
remote_async_ops.to_async_mask_value = 1;
remote_async_ops.to_magic = OPS_MAGIC;
}

View File

@ -1609,6 +1609,7 @@ init_sol_thread_ops ()
sol_thread_ops.to_can_run = sol_thread_can_run;
sol_thread_ops.to_notice_signals = sol_thread_notice_signals;
sol_thread_ops.to_thread_alive = sol_thread_alive;
sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
sol_thread_ops.to_find_new_threads = sol_find_new_threads;
sol_thread_ops.to_stop = sol_thread_stop;
sol_thread_ops.to_stratum = process_stratum;
@ -1659,6 +1660,7 @@ init_sol_core_ops ()
sol_core_ops.to_has_registers = 1;
sol_core_ops.to_has_execution = 0;
sol_core_ops.to_has_thread_control = tc_none;
sol_core_ops.to_pid_to_str = solaris_pid_to_str;
sol_core_ops.to_sections = 0;
sol_core_ops.to_sections_end = 0;
sol_core_ops.to_magic = OPS_MAGIC;

View File

@ -78,7 +78,7 @@ static void
target_command PARAMS ((char *, int));
static struct target_ops *
find_default_run_target PARAMS ((char *));
find_default_run_target PARAMS ((char *));
static void
update_current_target PARAMS ((void));
@ -536,6 +536,7 @@ update_current_target ()
INHERIT (to_notice_signals, t);
INHERIT (to_thread_alive, t);
INHERIT (to_find_new_threads, t);
INHERIT (to_pid_to_str, t);
INHERIT (to_stop, t);
INHERIT (to_query, t);
INHERIT (to_rcmd, t);
@ -556,6 +557,7 @@ update_current_target ()
INHERIT (to_can_async_p, t);
INHERIT (to_is_async_p, t);
INHERIT (to_async, t);
INHERIT (to_async_mask_value, t);
INHERIT (to_magic, t);
#undef INHERIT
@ -1046,6 +1048,14 @@ target_link (modname, t_reloc)
*t_reloc = (CORE_ADDR) -1;
}
int
target_async_mask (int mask)
{
int saved_async_masked_status = target_async_mask_value;
target_async_mask_value = mask;
return saved_async_masked_status;
}
/* Look through the list of possible targets for a target that can
execute a run or attach command without any other data. This is
used to locate the default process stratum.
@ -1226,6 +1236,9 @@ find_run_target ()
return (count == 1 ? runable : NULL);
}
/* Find a single core_stratum target in the list of targets and return it.
If for some reason there is more than one, return NULL. */
struct target_ops *
find_core_target ()
{
@ -1247,6 +1260,27 @@ find_core_target ()
return (count == 1 ? runable : NULL);
}
/*
* Find the next target down the stack from the specified target.
*/
struct target_ops *
find_target_beneath (t)
struct target_ops *t;
{
struct target_stack_item *cur;
for (cur = target_stack; cur; cur = cur->next)
if (cur->target_ops == t)
break;
if (cur == NULL || cur->next == NULL)
return NULL;
else
return cur->next->target_ops;
}
/* The inferior process has died. Long live the inferior! */
@ -2053,6 +2087,7 @@ init_dummy_target ()
dummy_target.to_require_detach = find_default_require_detach;
dummy_target.to_create_inferior = find_default_create_inferior;
dummy_target.to_clone_and_follow_inferior = find_default_clone_and_follow_inferior;
dummy_target.to_pid_to_str = normal_pid_to_str;
dummy_target.to_stratum = dummy_stratum;
dummy_target.to_magic = OPS_MAGIC;
}

View File

@ -414,6 +414,7 @@ struct target_ops
void (*to_notice_signals) PARAMS ((int pid));
int (*to_thread_alive) PARAMS ((int pid));
void (*to_find_new_threads) PARAMS ((void));
char *(*to_pid_to_str) PARAMS ((int));
void (*to_stop) PARAMS ((void));
int (*to_query) PARAMS ((int /*char */ , char *, char *, int *));
void (*to_rcmd) (char *command, struct gdb_file *output);
@ -438,6 +439,7 @@ struct target_ops
int (*to_can_async_p) (void);
int (*to_is_async_p) (void);
void (*to_async) (void (*cb) (enum inferior_event_type, void *context), void *context);
int to_async_mask_value;
int to_magic;
/* Need sub-structure for target machine related rather than comm related? */
};
@ -597,7 +599,8 @@ target_detach PARAMS ((char *, int));
#define target_prepare_to_store() \
(*current_target.to_prepare_to_store) ()
extern int target_read_string PARAMS ((CORE_ADDR, char **, int, int *));
extern int
target_read_string PARAMS ((CORE_ADDR, char **, int, int *));
extern int
target_read_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
@ -621,15 +624,17 @@ child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
of bytes actually transfered is not defined) and ERR is set to a
non-zero error indication. */
extern int target_read_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
extern int
target_read_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
extern int target_write_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
extern int
target_write_memory_partial (CORE_ADDR addr, char *buf, int len, int *err);
extern char *
child_pid_to_exec_file PARAMS ((int));
child_pid_to_exec_file PARAMS ((int));
extern char *
child_core_file_to_sym_file PARAMS ((char *));
child_core_file_to_sym_file PARAMS ((char *));
#if defined(CHILD_POST_ATTACH)
extern void
@ -1060,24 +1065,41 @@ extern void target_load (char *arg, int from_tty);
/* Put the target in async mode with the specified callback function. */
#define target_async(CALLBACK,CONTEXT) (current_target.to_async((CALLBACK), (CONTEXT)))
/* This is to be used ONLY within run_stack_dummy(). It
provides a workaround, to have inferior function calls done in
sychronous mode, even though the target is asynchronous. After
target_async_mask(0) is called, calls to target_can_async_p() will
return FALSE , so that target_resume() will not try to start the
target asynchronously. After the inferior stops, we IMMEDIATELY
restore the previous nature of the target, by calling
target_async_mask(1). After that, target_can_async_p() will return
TRUE. ANY OTHER USE OF THIS FEATURE IS DEPRECATED.
FIXME ezannoni 1999-12-13: we won't need this once we move
the turning async on and off to the single execution commands,
from where it is done currently, in remote_resume().*/
#define target_async_mask_value \
(current_target.to_async_mask_value)
extern int target_async_mask (int mask);
extern void target_link PARAMS ((char *, CORE_ADDR *));
/* Converts a process id to a string. Usually, the string just contains
`process xyz', but on some systems it may contain
`process xyz thread abc'. */
#ifndef target_pid_to_str
#define target_pid_to_str(PID) \
normal_pid_to_str (PID)
extern char *normal_pid_to_str PARAMS ((int pid));
#endif
#undef target_pid_to_str
#define target_pid_to_str(PID) current_target.to_pid_to_str (PID)
#ifndef target_tid_to_str
#define target_tid_to_str(PID) \
normal_pid_to_str (PID)
target_pid_to_str (PID)
extern char *normal_pid_to_str PARAMS ((int pid));
#endif
/*
* New Objfile Event Hook:
*
@ -1105,7 +1127,7 @@ extern void (*target_new_objfile_hook) PARAMS ((struct objfile *));
#ifndef target_pid_or_tid_to_str
#define target_pid_or_tid_to_str(ID) \
normal_pid_to_str (ID)
target_pid_to_str (ID)
#endif
/* Attempts to find the pathname of the executable file
@ -1321,24 +1343,28 @@ noprocess PARAMS ((void));
extern void
find_default_attach PARAMS ((char *, int));
void
extern void
find_default_require_attach PARAMS ((char *, int));
void
extern void
find_default_require_detach PARAMS ((int, char *, int));
extern void
find_default_create_inferior PARAMS ((char *, char *, char **));
void
extern void
find_default_clone_and_follow_inferior PARAMS ((int, int *));
extern struct target_ops *find_run_target PARAMS ((void));
extern struct target_ops *
find_run_target PARAMS ((void));
extern struct target_ops *
find_core_target PARAMS ((void));
find_core_target PARAMS ((void));
int
extern struct target_ops *
find_target_beneath PARAMS ((struct target_ops *));
extern int
target_resize_to_sections PARAMS ((struct target_ops *target, int num_added));
/* Stuff that should be shared among the various remote targets. */

View File

@ -1,9 +1,12 @@
1999-12-13n Fernando Nasser <fnasser@totem.to.cygnus.com>
1999-12-16 Stan Shebs <shebs@andros.cygnus.com>
* gdb.base/default.exp: Match arm* etc instead of arm in "info
float" test.
1999-12-13 Fernando Nasser <fnasser@totem.to.cygnus.com>
* gdb.base/watchpoint.exp: Add missing "(timeout)" to test message.
1999-12-13n Fernando Nasser <fnasser@totem.to.cygnus.com>
* gdb.base/break.exp: Add missing anchor to reg exp on "finish from
outermost frame disallowed".

View File

@ -298,11 +298,11 @@ gdb_test "info frame" "No stack.|No selected frame." "info frame"
#test info files
gdb_test "info files" "" "info files"
#test info float
if [istarget "arm-*-*"] then {
if [istarget "arm*-*-*"] then {
gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
} elseif [istarget "thumb-*-*"] then {
} elseif [istarget "thumb*-*-*"] then {
gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
} elseif [istarget "strongarm-*-*"] then {
} elseif [istarget "strongarm*-*-*"] then {
gdb_test "info float" "Software FPU type.*mask:.*flags:.*" "info float"
} elseif [istarget "i\[3456\]86-*-*"] then {
gdb_test "info float" "R7:.*Status Word:.*Opcode:.*" "info float"

View File

@ -68,7 +68,7 @@ for {set i 0} {$i < 5} {incr i} {
gdb_continue_to_breakpoint "about to create philosopher: $i"
send_gdb "next\n"
gdb_expect {
-re "\\\[New Thread .*\\\].*$gdb_prompt $" {
-re "\\\[New .*\\\].*$gdb_prompt $" {
pass "create philosopher: $i"
}
-re "Program received signal.*(Unknown signal|SIGUSR).*$gdb_prompt $" {
@ -90,7 +90,7 @@ for {set i 0} {$i < 5} {incr i} {
# Run until there are some threads.
gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: info threads 2"]
gdb_continue_to_breakpoint "main thread's sleep"
gdb_test "info threads" "7 Thread .*6 Thread .*5 Thread .*4 Thread .*3 Thread .*2 Thread .* \\(initial thread\\) main \\(argc=1, argv=.*\\) at .*linux-dp.c:.*1 Thread .* \\(manager thread\\).*" "info threads 2"
gdb_test "info threads" "7 Thread .*6 Thread .*5 Thread .*4 Thread .*3 Thread .*2 Thread .*1 Thread .*" "info threads 2"
# Try setting a thread-specific breakpoint.
gdb_breakpoint "print_philosopher thread 5"

View File

@ -931,6 +931,12 @@ request_quit (signo)
#if !defined (USE_MMALLOC)
void *
mcalloc (void *md, size_t number, size_t size)
{
return calloc (number, size);
}
PTR
mmalloc (md, size)
PTR md;
@ -1092,6 +1098,17 @@ xmalloc (size)
return (xmmalloc ((PTR) NULL, size));
}
/* Like calloc but get error if no storage available */
PTR
xcalloc (size_t number, size_t size)
{
void *mem = mcalloc (NULL, number, size);
if (mem == NULL)
nomem (number * size);
return mem;
}
/* Like mrealloc but get error if no storage available. */
PTR

View File

@ -165,8 +165,11 @@ static const int mappings[] =
context_offset (FloatSave.ErrorOffset),
context_offset (FloatSave.DataSelector),
context_offset (FloatSave.DataOffset),
context_offset (FloatSave.ErrorSelector)
};
#undef context_offset
/* This vector maps the target's idea of an exception (extracted
from the DEBUG_EVENT structure) to GDB's idea. */
@ -297,7 +300,7 @@ do_child_fetch_inferior_registers (int r)
supply_register (r, (char *) &l);
}
else if (r >= 0)
supply_register (r, ((char *) &current_thread->context) + mappings[r]);
supply_register (r, context_offset);
else
{
for (r = 0; r < NUM_REGS; r++)
@ -529,11 +532,12 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
|| !s || !*s)
return gotasig;
if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1))
if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
{
if (strncmp (s, "cYg", 3))
if (strncmp (s, "cYg", 3) != 0)
warning (s);
}
else
{
char *p;
int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
@ -592,9 +596,11 @@ handle_exception (struct target_waitstatus *ourstatus)
default:
/* This may be a structured exception handling exception. In
that case, we want to let the program try to handle it, and
only break if we see the exception a second time. */
only break if we see the exception a second time.
if (current_event.u.Exception.dwFirstChance)
return 0;
*/
printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
current_event.u.Exception.ExceptionRecord.ExceptionCode,
@ -1017,6 +1023,9 @@ child_create_inferior (exec_file, allargs, env)
get_child_debug_event (inferior_pid, &dummy, &event_code, &ret);
while (event_code != EXCEPTION_DEBUG_EVENT);
SymSetOptions (SYMOPT_DEFERRED_LOADS);
SymInitialize (current_process_handle, NULL, TRUE);
proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
}
@ -1170,6 +1179,7 @@ init_child_ops (void)
child_ops.to_can_run = child_can_run;
child_ops.to_notice_signals = 0;
child_ops.to_thread_alive = win32_child_thread_alive;
child_ops.to_pid_to_str = cygwin_pid_to_str;
child_ops.to_stop = child_stop;
child_ops.to_stratum = process_stratum;
child_ops.DONT_USE = 0;
@ -1255,40 +1265,60 @@ cygwin_pid_to_str (int pid)
sprintf (buf, "thread %d.0x%x", current_event.dwProcessId, pid);
return buf;
}
#ifdef NOTYET
CORE_ADDR
win32_read_fp ()
static LPVOID __stdcall
sfta(HANDLE h, DWORD d)
{
STACKFRAME *sf = current_thread->sf;
memset (&sf, 0, sizeof(sf));
sf->AddrPC.Offset = current_thread->context.Eip;
sf->AddrPC.Mode = AddrModeFlat;
sf->AddrStack.Offset = current_thread->context.Esp;
sf->AddrStack.Mode = AddrModeFlat;
sf->AddrFrame.Offset = current_thread->context.Ebp;
if (!StackWalk (IMAGE_FILE_MACHINE_I386, current_process_handle,
current->thread->h, sf, NULL, NULL,
SymFunctionTableAccess, SymGetModuleBase, NULL))
return NULL;
return (CORE_ADDR) sf.AddrFrame.Offset;
return NULL;
}
static DWORD __stdcall
sgmb(HANDLE h, DWORD d)
{
#if 0
return 4;
#else
return SymGetModuleBase (h, d) ?: 4;
#endif
}
CORE_ADDR
child_frame_chain(struct frame_info *thisframe)
child_frame_chain(struct frame_info *f)
{
STACKFRAME *sf = current->thread->sf;
#if 0
sf.AddrPC.Offset = thisframe->pc;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = thisframe->;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = cx->Ebp;
#endif
STACKFRAME *sf = (STACKFRAME *) f->extra_info;
if (!StackWalk (IMAGE_FILE_MACHINE_I386, current_process_handle,
current->thread->h, &sf, NULL, NULL,
SymFunctionTableAccess, SymGetModuleBase, NULL))
return NULL;
return (CORE_ADDR) sf->AddrFrame.Offset;
current_thread->h, sf, NULL, NULL, SymFunctionTableAccess, sgmb, NULL) ||
!sf->AddrReturn.Offset)
return 0;
return sf->AddrFrame.Offset;
}
CORE_ADDR
child_frame_saved_pc(struct frame_info *f)
{
STACKFRAME *sf = (STACKFRAME *) f->extra_info;
return sf->AddrReturn.Offset;
}
void
child_init_frame(int leaf, struct frame_info *f)
{
STACKFRAME *sf;
if (f->next && f->next->extra_info)
f->extra_info = f->next->extra_info;
else if (f->prev && f->prev->extra_info)
f->extra_info = f->prev->extra_info;
else
{
sf = (STACKFRAME *) frame_obstack_alloc (sizeof (*sf));
f->extra_info = (struct frame_extra_info *) sf;
memset (sf, 0, sizeof(*sf));
sf->AddrPC.Offset = f->pc;
sf->AddrPC.Mode = AddrModeFlat;
sf->AddrStack.Offset = current_thread->context.Esp;
sf->AddrStack.Mode = AddrModeFlat;
sf->AddrFrame.Offset = f->frame;
sf->AddrFrame.Mode = AddrModeFlat;
}
}
#endif

View File

@ -1,3 +1,8 @@
1999-12-17 Dave Brolley <brolley@cygnus.com>
* sim-profile.h: (set_profile_option_mask): Add prototype.
* sim-profile.c (set_profile_option_mask): No longer static.
Wed Dec 8 21:47:13 1999 Andrew Cagney <cagney@b1.cygnus.com>
* sim-arange.c: Include <string.h>

View File

@ -108,7 +108,7 @@ static const OPTION profile_options[] = {
/* Set/reset the profile options indicated in MASK. */
static SIM_RC
SIM_RC
set_profile_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg)
{
int profile_nr;

View File

@ -65,6 +65,10 @@ enum {
| (1 << PROFILE_MODEL_IDX) \
| (1 << PROFILE_CORE_IDX))
/* Utility to set profile options. */
SIM_RC set_profile_option_mask (SIM_DESC sd_, const char *name_, int mask_,
const char *arg_);
/* Utility to parse a --profile-<foo> option. */
/* ??? On the one hand all calls could be confined to sim-profile.c, but
on the other hand keeping a module's profiling option with the module's