diff options
author | Jason Molenda <jsm@bugshack.cygnus.com> | 1999-12-22 21:45:00 +0000 |
---|---|---|
committer | Jason Molenda <jsm@bugshack.cygnus.com> | 1999-12-22 21:45:00 +0000 |
commit | 2800c5dc333169fb3e1d2bed6f96912ec8cf982c (patch) | |
tree | ea29215395ff424fd4060ad305c1b84ae3f3f90c | |
parent | 25f56f63638eebc41a9b95296eebb40563ea0db5 (diff) | |
download | gdb-2800c5dc333169fb3e1d2bed6f96912ec8cf982c.tar.gz |
import gdb-1999-12-21 snapshotgdb-1999-12-21
69 files changed, 6205 insertions, 1955 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index efe4adb2f3a..878e2d1951a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -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. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9fbb5e0b722..98683bb28d3 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -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) @@ -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 diff --git a/gdb/arm-convert.s b/gdb/arm-convert.s index 416132b77c7..8124052bb10 100644 --- a/gdb/arm-convert.s +++ b/gdb/arm-convert.s @@ -1,16 +1,16 @@ - .text - .global _convert_from_extended - -_convert_from_extended: - - ldfe f0,[a1] - stfd f0,[a2] - movs pc,lr - - .global _convert_to_extended - -_convert_to_extended: - - ldfd f0,[a1] - stfe f0,[a2] - movs pc,lr +/* OBSOLETE .text */ +/* OBSOLETE .global _convert_from_extended */ +/* OBSOLETE */ +/* OBSOLETE _convert_from_extended: */ +/* OBSOLETE */ +/* OBSOLETE ldfe f0,[a1] */ +/* OBSOLETE stfd f0,[a2] */ +/* OBSOLETE movs pc,lr */ +/* OBSOLETE */ +/* OBSOLETE .global _convert_to_extended */ +/* OBSOLETE */ +/* OBSOLETE _convert_to_extended: */ +/* OBSOLETE */ +/* OBSOLETE ldfd f0,[a1] */ +/* OBSOLETE stfe f0,[a2] */ +/* OBSOLETE movs pc,lr */ diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c new file mode 100644 index 00000000000..f7380503043 --- /dev/null +++ b/gdb/arm-linux-nat.c @@ -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 *) ®isters[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, ®s); + if (ret < 0) + { + warning ("Unable to fetch general registers."); + return; + } + + for (regno = A1_REGNUM; regno < PC_REGNUM; regno++) + supply_register (regno, (char *) ®s.uregs[regno]); + + if (arm_apcs_32) + supply_register (PS_REGNUM, (char *) ®s.uregs[CPSR_REGNUM]); + else + supply_register (PS_REGNUM, (char *) ®s.uregs[PC_REGNUM]); + + regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]); + supply_register (PC_REGNUM, (char *) ®s.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, ®s); + 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 *) ®s.uregs[regno]); + } + + ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, ®s); + + 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, ®buf[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); +} diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 99139ac115b..71a000ab365 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -1,5 +1,5 @@ -/* Target-dependent code for the Acorn Risc Machine (ARM). - Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995-1999 +/* Common target dependent code for GDB on ARM systems. + Copyright 1988, 1989, 1991, 1992, 1993, 1995-1999 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,8 @@ #include "gdb_string.h" #include "coff/internal.h" /* Internal format of COFF symbols in BFD */ +extern void _initialize_arm_tdep (void); + /* The following macros are actually wrong. Neither arm nor thumb can or should set the lsb on addr. @@ -42,67 +44,162 @@ #define MAKE_THUMB_ADDR(addr) ((addr) | 1) #define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1) -/* Macros to round N up or down to the next A boundary; A must be - a power of two. */ -#define ROUND_DOWN(n,a) ((n) & ~((a) - 1)) -#define ROUND_UP(n,a) (((n) + (a) - 1) & ~((a) - 1)) - +/* Default register names as specified by APCS. */ static char *apcs_register_names[] = -{ "a1", "a2", "a3", "a4", /* 0 1 2 3 */ - "v1", "v2", "v3", "v4", /* 4 5 6 7 */ - "v5", "v6", "sl", "fp", /* 8 9 10 11 */ - "ip", "sp", "lr", "pc", /* 12 13 14 15 */ - "f0", "f1", "f2", "f3", /* 16 17 18 19 */ - "f4", "f5", "f6", "f7", /* 20 21 22 23 */ - "fps","ps" } /* 24 25 */; - -/* These names are the ones which gcc emits, and - I find them less confusing. Toggle between them - using the `othernames' command. */ +{"a1", "a2", "a3", "a4", /* 0 1 2 3 */ + "v1", "v2", "v3", "v4", /* 4 5 6 7 */ + "v5", "v6", "sl", "fp", /* 8 9 10 11 */ + "ip", "sp", "lr", "pc", /* 12 13 14 15 */ + "f0", "f1", "f2", "f3", /* 16 17 18 19 */ + "f4", "f5", "f6", "f7", /* 20 21 22 23 */ + "fps", "ps"} /* 24 25 */ ; + +/* Alternate set of registers names used by GCC. */ static char *additional_register_names[] = -{ "r0", "r1", "r2", "r3", /* 0 1 2 3 */ - "r4", "r5", "r6", "r7", /* 4 5 6 7 */ - "r8", "r9", "r10", "r11", /* 8 9 10 11 */ - "r12", "r13", "r14", "pc", /* 12 13 14 15 */ - "f0", "f1", "f2", "f3", /* 16 17 18 19 */ - "f4", "f5", "f6", "f7", /* 20 21 22 23 */ - "fps","ps" } /* 24 25 */; - -/* By default use the APCS registers names */ - +{"r0", "r1", "r2", "r3", /* 0 1 2 3 */ + "r4", "r5", "r6", "r7", /* 4 5 6 7 */ + "r8", "r9", "r10", "r11", /* 8 9 10 11 */ + "r12", "r13", "r14", "pc", /* 12 13 14 15 */ + "f0", "f1", "f2", "f3", /* 16 17 18 19 */ + "f4", "f5", "f6", "f7", /* 20 21 22 23 */ + "fps", "ps"} /* 24 25 */ ; + +/* This is the variable that is set with "set disassembly-flavor". + By default use the APCS registers names. */ char **arm_register_names = apcs_register_names; -/* This is the variable the is set with "set disassembly-flavor", - and its legitimate values. */ + +/* Valid register name flavours. */ static char apcs_flavor[] = "apcs"; static char r_prefix_flavor[] = "r-prefix"; -static char *valid_flavors[] = { +static char *valid_flavors[] = +{ apcs_flavor, r_prefix_flavor, NULL }; + +/* Disassembly flavor to use. */ static char *disassembly_flavor = apcs_flavor; -/* This is used to keep the bfd arch_info in sync with the disassembly flavor. */ -static void set_disassembly_flavor_sfunc PARAMS ((char *, int, \ - struct cmd_list_element *)); -static void set_disassembly_flavor (); +/* This is used to keep the bfd arch_info in sync with the disassembly + flavor. */ +static void set_disassembly_flavor_sfunc(char *, int, + struct cmd_list_element *); +static void set_disassembly_flavor (void); + +static void convert_from_extended (void *ptr, void *dbl); + +/* Define other aspects of the stack frame. We keep the offsets of + all saved registers, 'cause we need 'em a lot! We also keep the + current size of the stack frame, and the offset of the frame + pointer from the stack pointer (for frameless functions, and when + we're still in the prologue of a function with a frame) */ + +struct frame_extra_info + { + struct frame_saved_regs fsr; + int framesize; + int frameoffset; + int framereg; + }; + +/* Will a function return an aggregate type in memory or in a + register? Return 0 if an aggregate type can be returned in a + register, 1 if it must be returned in memory. */ -/* Should call_function allocate stack space for a struct return? */ -/* The system C compiler uses a similar structure return convention to gcc */ int -arm_use_struct_convention (gcc_p, type) - int gcc_p; - struct type *type; +arm_use_struct_convention (int gcc_p, struct type *type) { - return (TYPE_LENGTH (type) > 4); + int nRc; + register enum type_code code; + + /* In the ARM ABI, "integer" like aggregate types are returned in + registers. For an aggregate type to be integer like, its size + must be less than or equal to REGISTER_SIZE and the offset of + each addressable subfield must be zero. Note that bit fields are + not addressable, and all addressable subfields of unions always + start at offset zero. + + This function is based on the behaviour of GCC 2.95.1. + See: gcc/arm.c: arm_return_in_memory() for details. + + Note: All versions of GCC before GCC 2.95.2 do not set up the + parameters correctly for a function returning the following + structure: struct { float f;}; This should be returned in memory, + not a register. Richard Earnshaw sent me a patch, but I do not + know of any way to detect if a function like the above has been + compiled with the correct calling convention. */ + + /* All aggregate types that won't fit in a register must be returned + in memory. */ + if (TYPE_LENGTH (type) > REGISTER_SIZE) + { + return 1; + } + + /* The only aggregate types that can be returned in a register are + structs and unions. Arrays must be returned in memory. */ + code = TYPE_CODE (type); + if ((TYPE_CODE_STRUCT != code) && (TYPE_CODE_UNION != code)) + { + return 1; + } + + /* Assume all other aggregate types can be returned in a register. + Run a check for structures, unions and arrays. */ + nRc = 0; + + if ((TYPE_CODE_STRUCT == code) || (TYPE_CODE_UNION == code)) + { + int i; + /* Need to check if this struct/union is "integer" like. For + this to be true, its size must be less than or equal to + REGISTER_SIZE and the offset of each addressable subfield + must be zero. Note that bit fields are not addressable, and + unions always start at offset zero. If any of the subfields + is a floating point type, the struct/union cannot be an + integer type. */ + + /* For each field in the object, check: + 1) Is it FP? --> yes, nRc = 1; + 2) Is it addressable (bitpos != 0) and + not packed (bitsize == 0)? + --> yes, nRc = 1 + */ + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + enum type_code field_type_code; + field_type_code = TYPE_CODE (TYPE_FIELD_TYPE (type, i)); + + /* Is it a floating point type field? */ + if (field_type_code == TYPE_CODE_FLT) + { + nRc = 1; + break; + } + + /* If bitpos != 0, then we have to care about it. */ + if (TYPE_FIELD_BITPOS (type, i) != 0) + { + /* Bitfields are not addressable. If the field bitsize is + zero, then the field is not packed. Hence it cannot be + a bitfield or any other packed type. */ + if (TYPE_FIELD_BITSIZE (type, i) == 0) + { + nRc = 1; + break; + } + } + } + } + + return nRc; } int -arm_frame_chain_valid (chain, thisframe) - CORE_ADDR chain; - struct frame_info *thisframe; +arm_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) { -#define LOWEST_PC 0x20 /* the first 0x20 bytes are the trap vectors. */ return (chain != 0 && (FRAME_SAVED_PC (thisframe) >= LOWEST_PC)); } @@ -110,48 +207,49 @@ arm_frame_chain_valid (chain, thisframe) int arm_apcs_32 = 1; -/* Flag set by arm_fix_call_dummy that tells whether the target function - is a Thumb function. This flag is checked by arm_push_arguments. - FIXME: Change the PUSH_ARGUMENTS macro (and its use in valops.c) to - pass the function address as an additional parameter. */ +/* Flag set by arm_fix_call_dummy that tells whether the target + function is a Thumb function. This flag is checked by + arm_push_arguments. FIXME: Change the PUSH_ARGUMENTS macro (and + its use in valops.c) to pass the function address as an additional + parameter. */ static int target_is_thumb; -/* Flag set by arm_fix_call_dummy that tells whether the calling function - is a Thumb function. This flag is checked by arm_pc_is_thumb - and arm_call_dummy_breakpoint_offset. */ +/* Flag set by arm_fix_call_dummy that tells whether the calling + function is a Thumb function. This flag is checked by + arm_pc_is_thumb and arm_call_dummy_breakpoint_offset. */ static int caller_is_thumb; -/* Tell if the program counter value in MEMADDR is in a Thumb function. */ +/* Determine if the program counter specified in MEMADDR is in a Thumb + function. */ int -arm_pc_is_thumb (memaddr) - bfd_vma memaddr; +arm_pc_is_thumb (bfd_vma memaddr) { struct minimal_symbol *sym; - CORE_ADDR sp; - /* If bit 0 of the address is set, assume this is a Thumb address. */ + /* If bit 0 of the address is set, assume this is a Thumb address. */ if (IS_THUMB_ADDR (memaddr)) return 1; - /* Thumb function have a "special" bit set in minimal symbols */ + /* Thumb functions have a "special" bit set in minimal symbols. */ sym = lookup_minimal_symbol_by_pc (memaddr); if (sym) { return (MSYMBOL_IS_SPECIAL (sym)); } else - return 0; + { + return 0; + } } -/* Tell if the program counter value in MEMADDR is in a call dummy that - is being called from a Thumb function. */ +/* Determine if the program counter specified in MEMADDR is in a call + dummy being called from a Thumb function. */ int -arm_pc_is_thumb_dummy (memaddr) - bfd_vma memaddr; +arm_pc_is_thumb_dummy (bfd_vma memaddr) { CORE_ADDR sp = read_sp (); @@ -162,8 +260,7 @@ arm_pc_is_thumb_dummy (memaddr) } CORE_ADDR -arm_addr_bits_remove (val) - CORE_ADDR val; +arm_addr_bits_remove (CORE_ADDR val) { if (arm_pc_is_thumb (val)) return (val & (arm_apcs_32 ? 0xfffffffe : 0x03fffffe)); @@ -172,26 +269,24 @@ arm_addr_bits_remove (val) } CORE_ADDR -arm_saved_pc_after_call (frame) - struct frame_info *frame; +arm_saved_pc_after_call (struct frame_info *frame) { return ADDR_BITS_REMOVE (read_register (LR_REGNUM)); } int -arm_frameless_function_invocation (fi) - struct frame_info *fi; +arm_frameless_function_invocation (struct frame_info *fi) { CORE_ADDR func_start, after_prologue; int frameless; - + func_start = (get_pc_function_start ((fi)->pc) + FUNCTION_START_OFFSET); after_prologue = SKIP_PROLOGUE (func_start); - + /* There are some frameless functions whose first two instructions - follow the standard APCS form, in which case after_prologue - will be func_start + 8. */ - + follow the standard APCS form, in which case after_prologue will + be func_start + 8. */ + frameless = (after_prologue < func_start + 12); return frameless; } @@ -202,11 +297,10 @@ arm_frameless_function_invocation (fi) add r7, sp, #12 Sometimes the latter instruction may be replaced by: mov r7, sp - */ + */ static CORE_ADDR -thumb_skip_prologue (pc) - CORE_ADDR pc; +thumb_skip_prologue (CORE_ADDR pc) { CORE_ADDR current_pc; @@ -214,32 +308,31 @@ thumb_skip_prologue (pc) { unsigned short insn = read_memory_unsigned_integer (current_pc, 2); - if ((insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */ - && (insn & 0xff00) != 0xb000 /* add sp, #simm */ - && (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */ - && insn != 0x466f /* mov r7, sp */ - && (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */ + if ((insn & 0xfe00) != 0xb400 /* push {..., r7, lr} */ + && (insn & 0xff00) != 0xb000 /* add sp, #simm */ + && (insn & 0xff00) != 0xaf00 /* add r7, sp, #imm */ + && insn != 0x466f /* mov r7, sp */ + && (insn & 0xffc0) != 0x4640) /* mov r0-r7, r8-r15 */ break; } return current_pc; } -/* APCS (ARM procedure call standard) defines the following prologue: +/* The APCS (ARM Procedure Call Standard) defines the following + prologue: mov ip, sp [stmfd sp!, {a1,a2,a3,a4}] stmfd sp!, {...,fp,ip,lr,pc} - [stfe f7, [sp, #-12]!] - [stfe f6, [sp, #-12]!] - [stfe f5, [sp, #-12]!] - [stfe f4, [sp, #-12]!] - sub fp, ip, #nn // nn == 20 or 4 depending on second ins - */ + [stfe f7, [sp, #-12]!] + [stfe f6, [sp, #-12]!] + [stfe f5, [sp, #-12]!] + [stfe f4, [sp, #-12]!] + sub fp, ip, #nn @@ nn == 20 or 4 depending on second insn */ CORE_ADDR -arm_skip_prologue (pc) - CORE_ADDR pc; +arm_skip_prologue (CORE_ADDR pc) { unsigned long inst; CORE_ADDR skip_pc; @@ -247,7 +340,7 @@ arm_skip_prologue (pc) struct symtab_and_line sal; /* See what the symbol table says. */ - + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) { sal = find_pc_line (func_addr, 0); @@ -281,11 +374,12 @@ arm_skip_prologue (pc) inst = read_memory_integer (skip_pc, 4); /* Any insns after this point may float into the code, if it makes - for better instruction scheduling, so we skip them only if - we find them, but still consdier the function to be frame-ful */ + for better instruction scheduling, so we skip them only if we + find them, but still consdier the function to be frame-ful. */ - /* We may have either one sfmfd instruction here, or several stfe insns, - depending on the version of floating point code we support. */ + /* We may have either one sfmfd instruction here, or several stfe + insns, depending on the version of floating point code we + support. */ if ((inst & 0xffbf0fff) == 0xec2d0200) /* sfmfd fn, <cnt>, [sp]! */ { skip_pc += 4; @@ -328,12 +422,8 @@ arm_skip_prologue (pc) 12 bytes. The frame register is R7. */ /* *INDENT-ON* */ - - - static void -thumb_scan_prologue (fi) - struct frame_info *fi; +thumb_scan_prologue (struct frame_info *fi) { CORE_ADDR prologue_start; CORE_ADDR prologue_end; @@ -417,9 +507,8 @@ thumb_scan_prologue (fi) } } -/* Function: check_prologue_cache - Check if prologue for this frame's PC has already been scanned. - If it has, copy the relevant information about that prologue and +/* Check if prologue for this frame's PC has already been scanned. If + it has, copy the relevant information about that prologue and return non-zero. Otherwise do not copy anything and return zero. The information saved in the cache includes: @@ -428,18 +517,16 @@ thumb_scan_prologue (fi) * the offsets of saved regs (relative to the old SP); and * the offset from the stack pointer to the frame pointer - The cache contains only one entry, since this is adequate - for the typical sequence of prologue scan requests we get. - When performing a backtrace, GDB will usually ask to scan - the same function twice in a row (once to get the frame chain, - and once to fill in the extra frame information). - */ + The cache contains only one entry, since this is adequate for the + typical sequence of prologue scan requests we get. When performing + a backtrace, GDB will usually ask to scan the same function twice + in a row (once to get the frame chain, and once to fill in the + extra frame information). */ static struct frame_info prologue_cache; static int -check_prologue_cache (fi) - struct frame_info *fi; +check_prologue_cache (struct frame_info *fi) { int i; @@ -457,13 +544,10 @@ check_prologue_cache (fi) } -/* Function: save_prologue_cache - Copy the prologue information from fi to the prologue cache. - */ +/* Copy the prologue information from fi to the prologue cache. */ static void -save_prologue_cache (fi) - struct frame_info *fi; +save_prologue_cache (struct frame_info *fi) { int i; @@ -477,8 +561,7 @@ save_prologue_cache (fi) } -/* Function: arm_scan_prologue - This function decodes an ARM function prologue to determine: +/* This function decodes an ARM function prologue to determine: 1) the size of the stack frame 2) which registers are saved on it 3) the offsets of saved regs @@ -487,20 +570,20 @@ save_prologue_cache (fi) There are two basic forms for the ARM prologue. The fixed argument function call will look like: - - mov ip, sp - stmfd sp!, {fp, ip, lr, pc} - sub fp, ip, #4 - [sub sp, sp, #4] + + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + [sub sp, sp, #4] Which would create this stack frame (offsets relative to FP): - IP -> 4 (caller's stack) - FP -> 0 PC (points to address of stmfd instruction + 8 in callee) - -4 LR (return address in caller) - -8 IP (copy of caller's SP) - -12 FP (caller's FP) - SP -> -28 Local variables - + IP -> 4 (caller's stack) + FP -> 0 PC (points to address of stmfd instruction + 8 in callee) + -4 LR (return address in caller) + -8 IP (copy of caller's SP) + -12 FP (caller's FP) + SP -> -28 Local variables + The frame size would thus be 32 bytes, and the frame offset would be 28 bytes. The stmfd call can also save any of the vN registers it plans to use, which increases the frame size accordingly. @@ -508,25 +591,25 @@ save_prologue_cache (fi) Note: The stored PC is 8 off of the STMFD instruction that stored it because the ARM Store instructions always store PC + 8 when you read the PC register. - + A variable argument function call will look like: - mov ip, sp - stmfd sp!, {a1, a2, a3, a4} - stmfd sp!, {fp, ip, lr, pc} - sub fp, ip, #20 - + mov ip, sp + stmfd sp!, {a1, a2, a3, a4} + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #20 + Which would create this stack frame (offsets relative to FP): - IP -> 20 (caller's stack) - 16 A4 - 12 A3 - 8 A2 - 4 A1 - FP -> 0 PC (points to address of stmfd instruction + 8 in callee) - -4 LR (return address in caller) - -8 IP (copy of caller's SP) - -12 FP (caller's FP) - SP -> -28 Local variables + IP -> 20 (caller's stack) + 16 A4 + 12 A3 + 8 A2 + 4 A1 + FP -> 0 PC (points to address of stmfd instruction + 8 in callee) + -4 LR (return address in caller) + -8 IP (copy of caller's SP) + -12 FP (caller's FP) + SP -> -28 Local variables The frame size would thus be 48 bytes, and the frame offset would be 28 bytes. @@ -542,12 +625,11 @@ save_prologue_cache (fi) instruction at the end of the prologue. I have never seen GCC produce this, and the ARM docs don't mention it. We still test for it below in case it happens... - -*/ + + */ static void -arm_scan_prologue (fi) - struct frame_info *fi; +arm_scan_prologue (struct frame_info *fi) { int regno, sp_offset, fp_offset; CORE_ADDR prologue_start, prologue_end, current_pc; @@ -586,17 +668,17 @@ arm_scan_prologue (fi) { /* Get address of the stmfd in the prologue of the callee; the saved PC is the address of the stmfd + 8. */ - prologue_start = ADDR_BITS_REMOVE(read_memory_integer (fi->frame, 4)) + prologue_start = ADDR_BITS_REMOVE (read_memory_integer (fi->frame, 4)) - 8; - prologue_end = prologue_start + 64; /* This is all the insn's - that could be in the prologue, - plus room for 5 insn's inserted - by the scheduler. */ + prologue_end = prologue_start + 64; /* This is all the insn's + that could be in the prologue, + plus room for 5 insn's inserted + by the scheduler. */ } /* Now search the prologue looking for instructions that set up the frame pointer, adjust the stack pointer, and save registers. - + Be careful, however, and if it doesn't look like a prologue, don't try to scan it. If, for instance, a frameless function begins with stmfd sp!, then we will tell ourselves there is @@ -609,21 +691,21 @@ arm_scan_prologue (fi) sp_offset = fp_offset = 0; - if (read_memory_unsigned_integer (prologue_start, 4) - == 0xe1a0c00d) /* mov ip, sp */ + if (read_memory_unsigned_integer (prologue_start, 4) + == 0xe1a0c00d) /* mov ip, sp */ { - for (current_pc = prologue_start +4; current_pc < prologue_end; + for (current_pc = prologue_start + 4; current_pc < prologue_end; current_pc += 4) { unsigned int insn = read_memory_unsigned_integer (current_pc, 4); - + if ((insn & 0xffff0000) == 0xe92d0000) /* stmfd sp!, {..., fp, ip, lr, pc} or stmfd sp!, {a1, a2, a3, a4} */ { int mask = insn & 0xffff; - + /* Calculate offsets of saved registers. */ for (regno = PC_REGNUM; regno >= 0; regno--) if (mask & (1 << regno)) @@ -632,47 +714,47 @@ arm_scan_prologue (fi) fi->fsr.regs[regno] = sp_offset; } } - else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */ + else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */ { - unsigned imm = insn & 0xff; /* immediate value */ - unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ - imm = (imm >> rot) | (imm << (32-rot)); + unsigned imm = insn & 0xff; /* immediate value */ + unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ + imm = (imm >> rot) | (imm << (32 - rot)); fp_offset = -imm; fi->framereg = FP_REGNUM; } - else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */ + else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */ { - unsigned imm = insn & 0xff; /* immediate value */ - unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ - imm = (imm >> rot) | (imm << (32-rot)); + unsigned imm = insn & 0xff; /* immediate value */ + unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ + imm = (imm >> rot) | (imm << (32 - rot)); sp_offset -= imm; } - else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */ + else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */ { sp_offset -= 12; regno = F0_REGNUM + ((insn >> 12) & 0x07); fi->fsr.regs[regno] = sp_offset; } - else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */ + else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */ { - int n_saved_fp_regs, i; + int n_saved_fp_regs; unsigned int fp_start_reg, fp_bound_reg; - - if ((insn & 0x800) == 0x800) /* N0 is set */ - { - if ((insn & 0x40000) == 0x40000) /* N1 is set */ + + if ((insn & 0x800) == 0x800) /* N0 is set */ + { + if ((insn & 0x40000) == 0x40000) /* N1 is set */ n_saved_fp_regs = 3; else n_saved_fp_regs = 1; } else - { - if ((insn & 0x40000) == 0x40000) /* N1 is set */ + { + if ((insn & 0x40000) == 0x40000) /* N1 is set */ n_saved_fp_regs = 2; else n_saved_fp_regs = 4; } - + fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7); fp_bound_reg = fp_start_reg + n_saved_fp_regs; for (; fp_start_reg < fp_bound_reg; fp_start_reg++) @@ -682,8 +764,9 @@ arm_scan_prologue (fi) } } else - continue; /* The optimizer might shove anything into the - prologue, so we just skip what we don't recognize. */ + /* The optimizer might shove anything into the prologue, + so we just skip what we don't recognize. */ + continue; } } @@ -692,22 +775,19 @@ arm_scan_prologue (fi) [new FP] - [new SP]. */ fi->framesize = -sp_offset; fi->frameoffset = fp_offset - sp_offset; - + save_prologue_cache (fi); } - -/* Function: find_callers_reg - Find REGNUM on the stack. Otherwise, it's in an active register. One thing - we might want to do here is to check REGNUM against the clobber mask, and - somehow flag it as invalid if it isn't saved on the stack somewhere. This - would provide a graceful failure mode when trying to get the value of - caller-saves registers for an inner frame. */ +/* Find REGNUM on the stack. Otherwise, it's in an active register. + One thing we might want to do here is to check REGNUM against the + clobber mask, and somehow flag it as invalid if it isn't saved on + the stack somewhere. This would provide a graceful failure mode + when trying to get the value of caller-saves registers for an inner + frame. */ static CORE_ADDR -arm_find_callers_reg (fi, regnum) - struct frame_info *fi; - int regnum; +arm_find_callers_reg (struct frame_info *fi, int regnum) { for (; fi; fi = fi->next) @@ -739,12 +819,8 @@ arm_find_callers_reg (fi, regnum) */ /* *INDENT-ON* */ - - - CORE_ADDR -arm_frame_chain (fi) - struct frame_info *fi; +arm_frame_chain (struct frame_info *fi) { #if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */ CORE_ADDR fn_start, callers_pc, fp; @@ -796,20 +872,17 @@ arm_frame_chain (fi) return fi->frame + fi->framesize; } -/* Function: init_extra_frame_info - This function actually figures out the frame address for a given pc and - sp. This is tricky because we sometimes don't use an explicit - frame pointer, and the previous stack pointer isn't necessarily recorded - on the stack. The only reliable way to get this info is to - examine the prologue. - FROMLEAF is a little confusing, it means this is the next frame up - the chain AFTER a frameless function. If this is true, then the - frame value for this frame is still in the fp register. */ +/* This function actually figures out the frame address for a given pc + and sp. This is tricky because we sometimes don't use an explicit + frame pointer, and the previous stack pointer isn't necessarily + recorded on the stack. The only reliable way to get this info is + to examine the prologue. FROMLEAF is a little confusing, it means + this is the next frame up the chain AFTER a frameless function. If + this is true, then the frame value for this frame is still in the + fp register. */ void -arm_init_extra_frame_info (fromleaf, fi) - int fromleaf; - struct frame_info * fi; +arm_init_extra_frame_info (int fromleaf, struct frame_info *fi) { int reg; @@ -836,23 +909,21 @@ arm_init_extra_frame_info (fromleaf, fi) if (!fi->next) /* this is the innermost frame? */ fi->frame = read_register (fi->framereg); - else - /* not the innermost frame */ - /* If we have an FP, the callee saved it. */ - if (fi->framereg == FP_REGNUM || fi->framereg == THUMB_FP_REGNUM) - { - if (fi->next->fsr.regs[fi->framereg] != 0) - fi->frame = - read_memory_integer (fi->next->fsr.regs[fi->framereg], 4); - else if (fromleaf) - /* If we were called by a frameless fn. then our frame - is still in the frame pointer register on the - board... */ - fi->frame = read_fp (); - } + else if (fi->framereg == FP_REGNUM || fi->framereg == THUMB_FP_REGNUM) + { + /* not the innermost frame */ + /* If we have an FP, the callee saved it. */ + if (fi->next->fsr.regs[fi->framereg] != 0) + fi->frame = + read_memory_integer (fi->next->fsr.regs[fi->framereg], 4); + else if (fromleaf) + /* If we were called by a frameless fn. then our frame is + still in the frame pointer register on the board... */ + fi->frame = read_fp (); + } - /* Calculate actual addresses of saved registers using offsets determined - by arm_scan_prologue. */ + /* Calculate actual addresses of saved registers using offsets + determined by arm_scan_prologue. */ for (reg = 0; reg < NUM_REGS; reg++) if (fi->fsr.regs[reg] != 0) fi->fsr.regs[reg] += fi->frame + fi->framesize - fi->frameoffset; @@ -860,18 +931,16 @@ arm_init_extra_frame_info (fromleaf, fi) } -/* Function: frame_saved_pc - Find the caller of this frame. We do this by seeing if LR_REGNUM is saved - in the stack anywhere, otherwise we get it from the registers. +/* Find the caller of this frame. We do this by seeing if LR_REGNUM + is saved in the stack anywhere, otherwise we get it from the + registers. The old definition of this function was a macro: #define FRAME_SAVED_PC(FRAME) \ - ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4)) - */ + ADDR_BITS_REMOVE (read_memory_integer ((FRAME)->frame - 4, 4)) */ CORE_ADDR -arm_frame_saved_pc (fi) - struct frame_info *fi; +arm_frame_saved_pc (struct frame_info *fi) { #if 0 /* FIXME: enable this code if we convert to new call dummy scheme. */ if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) @@ -884,12 +953,11 @@ arm_frame_saved_pc (fi) } } - /* Return the frame address. On ARM, it is R11; on Thumb it is R7. Examine the Program Status Register to decide which state we're in. */ CORE_ADDR -arm_target_read_fp () +arm_target_read_fp (void) { if (read_register (PS_REGNUM) & 0x20) /* Bit 5 is Thumb state bit */ return read_register (THUMB_FP_REGNUM); /* R7 if Thumb */ @@ -897,19 +965,17 @@ arm_target_read_fp () return read_register (FP_REGNUM); /* R11 if ARM */ } +/* Calculate the frame offsets of the saved registers (ARM version). */ -/* Calculate the frame offsets of the saved registers (ARM version). */ void -arm_frame_find_saved_regs (fi, regaddr) - struct frame_info *fi; - struct frame_saved_regs *regaddr; +arm_frame_find_saved_regs (struct frame_info *fi, + struct frame_saved_regs *regaddr) { memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs)); } - void -arm_push_dummy_frame () +arm_push_dummy_frame (void) { CORE_ADDR old_sp = read_register (SP_REGNUM); CORE_ADDR sp = old_sp; @@ -923,8 +989,8 @@ arm_push_dummy_frame () /* stmdb sp!, {r0-r10, fp, ip, lr, pc} */ prologue_start = sp = push_word (sp, 0xe92ddfff); - /* push a pointer to the dummy prologue + 12, because when - stm instruction stores the PC, it stores the address of the stm + /* Push a pointer to the dummy prologue + 12, because when stm + instruction stores the PC, it stores the address of the stm instruction itself plus 12. */ fp = sp = push_word (sp, prologue_start + 12); sp = push_word (sp, read_register (PC_REGNUM)); /* FIXME: was PS_REGNUM */ @@ -940,8 +1006,8 @@ arm_push_dummy_frame () } /* Fix up the call dummy, based on whether the processor is currently - in Thumb or ARM mode, and whether the target function is Thumb - or ARM. There are three different situations requiring three + in Thumb or ARM mode, and whether the target function is Thumb or + ARM. There are three different situations requiring three different dummies: * ARM calling ARM: uses the call dummy in tm-arm.h, which has already @@ -951,19 +1017,12 @@ arm_push_dummy_frame () * Thumb calling anything: uses the Thumb dummy defined below, which works for calling both ARM and Thumb functions. - All three call dummies expect to receive the target function address - in R4, with the low bit set if it's a Thumb function. - */ + All three call dummies expect to receive the target function + address in R4, with the low bit set if it's a Thumb function. */ void -arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) - char *dummy; - CORE_ADDR pc; - CORE_ADDR fun; - int nargs; - value_ptr *args; - struct type *type; - int gcc_p; +arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, + value_ptr *args, struct type *type, int gcc_p) { static short thumb_dummy[4] = { @@ -976,9 +1035,10 @@ arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) /* Set flag indicating whether the current PC is in a Thumb function. */ caller_is_thumb = arm_pc_is_thumb (read_pc ()); - /* If the target function is Thumb, set the low bit of the function address. - And if the CPU is currently in ARM mode, patch the second instruction - of call dummy to use a BX instruction to switch to Thumb mode. */ + /* If the target function is Thumb, set the low bit of the function + address. And if the CPU is currently in ARM mode, patch the + second instruction of call dummy to use a BX instruction to + switch to Thumb mode. */ target_is_thumb = arm_pc_is_thumb (fun); if (target_is_thumb) { @@ -1003,21 +1063,20 @@ arm_fix_call_dummy (dummy, pc, fun, nargs, args, type, gcc_p) } } - /* Put the target address in r4; the call dummy will copy this to the PC. */ + /* Put the target address in r4; the call dummy will copy this to + the PC. */ write_register (4, fun); } - /* Return the offset in the call dummy of the instruction that needs - to have a breakpoint placed on it. This is the offset of the 'swi 24' - instruction, which is no longer actually used, but simply acts + to have a breakpoint placed on it. This is the offset of the 'swi + 24' instruction, which is no longer actually used, but simply acts as a place-holder now. - This implements the CALL_DUMMY_BREAK_OFFSET macro. - */ + This implements the CALL_DUMMY_BREAK_OFFSET macro. */ int -arm_call_dummy_breakpoint_offset () +arm_call_dummy_breakpoint_offset (void) { if (caller_is_thumb) return 4; @@ -1025,126 +1084,135 @@ arm_call_dummy_breakpoint_offset () return 8; } +/* Note: ScottB + + This function does not support passing parameters using the FPA + variant of the APCS. It passes any floating point arguments in the + general registers and/or on the stack. */ CORE_ADDR -arm_push_arguments (nargs, args, sp, struct_return, struct_addr) - int nargs; - value_ptr *args; - CORE_ADDR sp; - int struct_return; - CORE_ADDR struct_addr; +arm_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp, + int struct_return, CORE_ADDR struct_addr) { - int argreg; - int float_argreg; - int argnum; - int stack_offset; - struct stack_arg + char *fp; + int argnum, argreg, nstack_size; + + /* Walk through the list of args and determine how large a temporary + stack is required. Need to take care here as structs may be + passed on the stack, and we have to to push them. */ + nstack_size = -4 * REGISTER_SIZE; /* Some arguments go into A1-A4. */ + if (struct_return) /* The struct address goes in A1. */ + nstack_size += REGISTER_SIZE; + + /* Walk through the arguments and add their size to nstack_size. */ + for (argnum = 0; argnum < nargs; argnum++) { - char *val; int len; - int offset; - }; - struct stack_arg *stack_args = - (struct stack_arg *) alloca (nargs * sizeof (struct stack_arg)); - int nstack_args = 0; + struct type *arg_type; + + arg_type = check_typedef (VALUE_TYPE (args[argnum])); + len = TYPE_LENGTH (arg_type); + /* ANSI C code passes float arguments as integers, K&R code + passes float arguments as doubles. Correct for this here. */ + if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len) + nstack_size += FP_REGISTER_VIRTUAL_SIZE; + else + nstack_size += len; + } - /* Initialize the integer and float register pointers. */ + /* Allocate room on the stack, and initialize our stack frame + pointer. */ + fp = NULL; + if (nstack_size > 0) + { + sp -= nstack_size; + fp = (char *) sp; + } + + /* Initialize the integer argument register pointer. */ argreg = A1_REGNUM; - float_argreg = F0_REGNUM; - /* the struct_return pointer occupies the first parameter-passing reg */ + /* The struct_return pointer occupies the first parameter passing + register. */ if (struct_return) write_register (argreg++, struct_addr); - /* The offset onto the stack at which we will start copying parameters - (after the registers are used up) begins at 16 in the old ABI. - This leaves room for the "home" area for register parameters. */ - stack_offset = REGISTER_SIZE * 4; - - /* Process args from left to right. Store as many as allowed in - registers, save the rest to be pushed on the stack */ + /* Process arguments from left to right. Store as many as allowed + in the parameter passing registers (A1-A4), and save the rest on + the temporary stack. */ for (argnum = 0; argnum < nargs; argnum++) { + int len; char *val; - value_ptr arg = args[argnum]; - struct type *arg_type = check_typedef (VALUE_TYPE (arg)); - struct type *target_type = TYPE_TARGET_TYPE (arg_type); - int len = TYPE_LENGTH (arg_type); - enum type_code typecode = TYPE_CODE (arg_type); + double dbl_arg; CORE_ADDR regval; - int newarg; - - val = (char *) VALUE_CONTENTS (arg); - - /* If the argument is a pointer to a function, and it's a Thumb + enum type_code typecode; + struct type *arg_type, *target_type; + + arg_type = check_typedef (VALUE_TYPE (args[argnum])); + target_type = TYPE_TARGET_TYPE (arg_type); + len = TYPE_LENGTH (arg_type); + typecode = TYPE_CODE (arg_type); + val = (char *) VALUE_CONTENTS (args[argnum]); + + /* ANSI C code passes float arguments as integers, K&R code + passes float arguments as doubles. The .stabs record for + for ANSI prototype floating point arguments records the + type as FP_INTEGER, while a K&R style (no prototype) + .stabs records the type as FP_FLOAT. In this latter case + the compiler converts the float arguments to double before + calling the function. */ + if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len) + { + float f = *(float *) val; + dbl_arg = f; + val = (char *) &dbl_arg; + len = sizeof (double); + } +#if 0 + /* If the argument is a pointer to a function, and it is a Thumb function, set the low bit of the pointer. */ - if (typecode == TYPE_CODE_PTR - && target_type != NULL - && TYPE_CODE (target_type) == TYPE_CODE_FUNC) + if (TYPE_CODE_PTR == typecode + && NULL != target_type + && TYPE_CODE_FUNC == TYPE_CODE (target_type)) { - regval = extract_address (val, len); + CORE_ADDR regval = extract_address (val, len); if (arm_pc_is_thumb (regval)) store_address (val, len, MAKE_THUMB_ADDR (regval)); } - -#define MAPCS_FLOAT 0 /* --mapcs-float not implemented by the compiler yet */ -#if MAPCS_FLOAT - /* Up to four floating point arguments can be passed in floating - point registers on ARM (not on Thumb). */ - if (typecode == TYPE_CODE_FLT - && float_argreg <= ARM_LAST_FP_ARG_REGNUM - && !target_is_thumb) - { - /* This is a floating point value that fits entirely - in a single register. */ - regval = extract_address (val, len); - write_register (float_argreg++, regval); - } - else #endif + /* Copy the argument to general registers or the stack in + register-sized pieces. Large arguments are split between + registers and stack. */ + while (len > 0) { - /* Copy the argument to general registers or the stack in - register-sized pieces. Large arguments are split between - registers and stack. */ - while (len > 0) + int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE; + + if (argreg <= ARM_LAST_ARG_REGNUM) { - if (argreg <= ARM_LAST_ARG_REGNUM) - { - int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE; - regval = extract_address (val, partial_len); - - /* It's a simple argument being passed in a general - register. */ - write_register (argreg, regval); - argreg++; - len -= partial_len; - val += partial_len; - } - else - { - /* keep for later pushing */ - stack_args[nstack_args].val = val; - stack_args[nstack_args++].len = len; - break; - } + /* It's an argument being passed in a general register. */ + regval = extract_address (val, partial_len); + write_register (argreg++, regval); } + else + { + /* Push the arguments onto the stack. */ + write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE); + fp += REGISTER_SIZE; + } + + len -= partial_len; + val += partial_len; } } - /* now do the real stack pushing, process args right to left */ - while (nstack_args--) - { - sp -= stack_args[nstack_args].len; - write_memory (sp, stack_args[nstack_args].val, - stack_args[nstack_args].len); - } /* Return adjusted stack pointer. */ return sp; } void -arm_pop_frame () +arm_pop_frame (void) { struct frame_info *frame = get_current_frame (); int regnum; @@ -1163,8 +1231,7 @@ arm_pop_frame () } static void -print_fpu_flags (flags) - int flags; +print_fpu_flags (int flags) { if (flags & (1 << 0)) fputs ("IVO ", stdout); @@ -1180,14 +1247,14 @@ print_fpu_flags (flags) } void -arm_float_info () +arm_float_info (void) { register unsigned long status = read_register (FPS_REGNUM); int type; type = (status >> 24) & 127; printf ("%s FPU type %d\n", - (status & (1<<31)) ? "Hardware" : "Software", + (status & (1 << 31)) ? "Hardware" : "Software", type); fputs ("mask: ", stdout); print_fpu_flags (status >> 16); @@ -1200,16 +1267,14 @@ arm_float_info () command, and does that. */ static void -set_disassembly_flavor_sfunc (args, from_tty, c) - char *args; - int from_tty; - struct cmd_list_element *c; +set_disassembly_flavor_sfunc (char *args, int from_tty, + struct cmd_list_element *c) { set_disassembly_flavor (); } static void -set_disassembly_flavor () +set_disassembly_flavor (void) { if (disassembly_flavor == apcs_flavor) { @@ -1221,17 +1286,17 @@ set_disassembly_flavor () { if (arm_toggle_regnames () == 1) arm_toggle_regnames (); - arm_register_names = additional_register_names; - } + arm_register_names = additional_register_names; + } } -/* arm_othernames implements the "othernames" command. This is kind of - hacky, and I prefer the set-show disassembly-flavor which is also used - for the x86 gdb. I will keep this around, however, in case anyone is - actually using it. */ +/* arm_othernames implements the "othernames" command. This is kind + of hacky, and I prefer the set-show disassembly-flavor which is + also used for the x86 gdb. I will keep this around, however, in + case anyone is actually using it. */ static void -arm_othernames () +arm_othernames (char *names, int n) { if (disassembly_flavor == r_prefix_flavor) { @@ -1245,29 +1310,80 @@ arm_othernames () } } -/* FIXME: Fill in with the 'right thing', see asm - template in arm-convert.s */ +#if 0 +/* FIXME: The generated assembler works but sucks. Instead of using + r0, r1 it pushes them on the stack, then loads them into r3, r4 and + uses those registers. I must be missing something. ScottB */ void -convert_from_extended (ptr, dbl) - void *ptr; - void *dbl; +convert_from_extended (void *ptr, void *dbl) +{ + __asm__ (" + ldfe f0,[%0] + stfd f0,[%1] " +: /* no output */ +: "r" (ptr), "r" (dbl)); +} + +void +convert_to_extended (void *dbl, void *ptr) +{ + __asm__ (" + ldfd f0,[%0] + stfe f0,[%1] " +: /* no output */ +: "r" (dbl), "r" (ptr)); +} +#else +static void +convert_from_extended (void *ptr, void *dbl) { *(double *) dbl = *(double *) ptr; } void -convert_to_extended (dbl, ptr) - void *ptr; - void *dbl; +convert_to_extended (void *dbl, void *ptr) { *(double *) ptr = *(double *) dbl; } +#endif + +/* Nonzero if register N requires conversion from raw format to + virtual format. */ + +int +arm_register_convertible (unsigned int regnum) +{ + return ((regnum - F0_REGNUM) < 8); +} + +/* Convert data from raw format for register REGNUM in buffer FROM to + virtual format with type TYPE in buffer TO. */ + +void +arm_register_convert_to_virtual (unsigned int regnum, struct type *type, + void *from, void *to) +{ + double val; + + convert_from_extended (from, &val); + store_floating (to, TYPE_LENGTH (type), val); +} + +/* Convert data from virtual format with type TYPE in buffer FROM to + raw format for register REGNUM in buffer TO. */ + +void +arm_register_convert_to_raw (unsigned int regnum, struct type *type, + void *from, void *to) +{ + double val = extract_floating (from, TYPE_LENGTH (type)); + + convert_to_extended (&val, to); +} static int -condition_true (cond, status_reg) - unsigned long cond; - unsigned long status_reg; +condition_true (unsigned long cond, unsigned long status_reg) { if (cond == INST_AL || cond == INST_NV) return 1; @@ -1300,10 +1416,10 @@ condition_true (cond, status_reg) return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)); case INST_GT: return (((status_reg & FLAG_Z) == 0) && - (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0))); + (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0))); case INST_LE: return (((status_reg & FLAG_Z) != 0) || - (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0))); + (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0))); } return 1; } @@ -1318,11 +1434,8 @@ condition_true (cond, status_reg) #define ARM_PC_32 1 static unsigned long -shifted_reg_val (inst, carry, pc_val, status_reg) - unsigned long inst; - int carry; - unsigned long pc_val; - unsigned long status_reg; +shifted_reg_val (unsigned long inst, int carry, unsigned long pc_val, + unsigned long status_reg) { unsigned long res, shift; int rm = bits (inst, 0, 3); @@ -1370,12 +1483,10 @@ shifted_reg_val (inst, carry, pc_val, status_reg) return res & 0xffffffff; } - /* Return number of 1-bits in VAL. */ static int -bitcount (val) - unsigned long val; +bitcount (unsigned long val) { int nbits; for (nbits = 0; val != 0; nbits++) @@ -1383,10 +1494,8 @@ bitcount (val) return nbits; } - static CORE_ADDR -thumb_get_next_pc (pc) - CORE_ADDR pc; +thumb_get_next_pc (CORE_ADDR pc) { unsigned long pc_val = ((unsigned long) pc) + 4; /* PC after prefetch */ unsigned short inst1 = read_memory_integer (pc, 2); @@ -1427,10 +1536,8 @@ thumb_get_next_pc (pc) return nextpc; } - CORE_ADDR -arm_get_next_pc (pc) - CORE_ADDR pc; +arm_get_next_pc (CORE_ADDR pc) { unsigned long pc_val; unsigned long this_instr; @@ -1570,7 +1677,7 @@ arm_get_next_pc (pc) int c = (status & FLAG_C) ? 1 : 0; unsigned long offset = (bit (this_instr, 25) - ? shifted_reg_val (this_instr, c, pc_val) + ? shifted_reg_val (this_instr, c, pc_val, status) : bits (this_instr, 0, 11)); if (bit (this_instr, 23)) @@ -1655,9 +1762,7 @@ arm_get_next_pc (pc) #include "libcoff.h" static int -gdb_print_insn_arm (memaddr, info) - bfd_vma memaddr; - disassemble_info *info; +gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info) { if (arm_pc_is_thumb (memaddr)) { @@ -1695,28 +1800,16 @@ gdb_print_insn_arm (memaddr, info) return print_insn_little_arm (memaddr, info); } -/* Sequence of bytes for breakpoint instruction. */ -#define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7} /* Recognized illegal opcodes */ -#define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE} -#define THUMB_LE_BREAKPOINT {0xbe,0xbe} -#define THUMB_BE_BREAKPOINT {0xbe,0xbe} - -/* The following has been superseded by BREAKPOINT_FOR_PC, but - is defined merely to keep mem-break.c happy. */ -#define LITTLE_BREAKPOINT ARM_LE_BREAKPOINT -#define BIG_BREAKPOINT ARM_BE_BREAKPOINT - -/* This function implements the BREAKPOINT_FROM_PC macro. It uses the program - counter value to determine whether a 16- or 32-bit breakpoint should be - used. It returns a pointer to a string of bytes that encode a breakpoint - instruction, stores the length of the string to *lenptr, and adjusts pc - (if necessary) to point to the actual memory location where the +/* This function implements the BREAKPOINT_FROM_PC macro. It uses the + program counter value to determine whether a 16-bit or 32-bit + breakpoint should be used. It returns a pointer to a string of + bytes that encode a breakpoint instruction, stores the length of + the string to *lenptr, and adjusts the program counter (if + necessary) to point to the actual memory location where the breakpoint should be inserted. */ unsigned char * -arm_breakpoint_from_pc (pcptr, lenptr) - CORE_ADDR *pcptr; - int *lenptr; +arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) { if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr)) { @@ -1751,33 +1844,44 @@ arm_breakpoint_from_pc (pcptr, lenptr) } } } -/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline). - This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */ + +/* Extract from an array REGBUF containing the (raw) register state a + function return value of type TYPE, and copy that, in virtual + format, into VALBUF. */ + +void +arm_extract_return_value (struct type *type, + char regbuf[REGISTER_BYTES], + char *valbuf) +{ + if (TYPE_CODE_FLT == TYPE_CODE (type)) + convert_from_extended (®buf[REGISTER_BYTE (F0_REGNUM)], valbuf); + else + memcpy (valbuf, ®buf[REGISTER_BYTE (A1_REGNUM)], TYPE_LENGTH (type)); +} + +/* Return non-zero if the PC is inside a thumb call thunk. */ int -arm_in_call_stub (pc, name) - CORE_ADDR pc; - char *name; +arm_in_call_stub (CORE_ADDR pc, char *name) { CORE_ADDR start_addr; - /* Find the starting address of the function containing the PC. If the - caller didn't give us a name, look it up at the same time. */ + /* Find the starting address of the function containing the PC. If + the caller didn't give us a name, look it up at the same time. */ if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0) return 0; return strncmp (name, "_call_via_r", 11) == 0; } - -/* If PC is in a Thumb call or return stub, return the address of the target - PC, which is in a register. The thunk functions are called _called_via_xx, - where x is the register name. The possible names are r0-r9, sl, fp, ip, - sp, and lr. */ +/* If PC is in a Thumb call or return stub, return the address of the + target PC, which is in a register. The thunk functions are called + _called_via_xx, where x is the register name. The possible names + are r0-r9, sl, fp, ip, sp, and lr. */ CORE_ADDR -arm_skip_stub (pc) - CORE_ADDR pc; +arm_skip_stub (CORE_ADDR pc) { char *name; CORE_ADDR start_addr; @@ -1789,8 +1893,8 @@ arm_skip_stub (pc) /* Call thunks always start with "_call_via_". */ if (strncmp (name, "_call_via_", 10) == 0) { - /* Use the name suffix to determine which register contains - the target PC. */ + /* Use the name suffix to determine which register contains the + target PC. */ static char *table[15] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr" @@ -1801,48 +1905,50 @@ arm_skip_stub (pc) if (strcmp (&name[10], table[regno]) == 0) return read_register (regno); } + return 0; /* not a stub */ } - void -_initialize_arm_tdep () +_initialize_arm_tdep (void) { struct cmd_list_element *new_cmd; tm_print_insn = gdb_print_insn_arm; - + /* Sync the opcode insn printer with our register viewer: */ if (arm_toggle_regnames () != 1) arm_toggle_regnames (); /* Add the deprecated "othernames" command */ - + add_com ("othernames", class_obscure, arm_othernames, "Switch to the other set of register names."); /* Add the disassembly-flavor command */ - + new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class, - valid_flavors, - (char *) &disassembly_flavor, - "Set the disassembly flavor, \ + valid_flavors, + (char *) &disassembly_flavor, + "Set the disassembly flavor, \ the valid values are \"apcs\" and \"r-prefix\", \ and the default value is \"apcs\".", - &setlist); + &setlist); new_cmd->function.sfunc = set_disassembly_flavor_sfunc; - add_show_from_set(new_cmd, &showlist); - + add_show_from_set (new_cmd, &showlist); + /* ??? Maybe this should be a boolean. */ add_show_from_set (add_set_cmd ("apcs32", no_class, - var_zinteger, (char *)&arm_apcs_32, + var_zinteger, (char *) &arm_apcs_32, "Set usage of ARM 32-bit mode.\n", &setlist), - & showlist); + &showlist); } -/* Test whether the coff symbol specific value corresponds to a Thumb function */ +/* Test whether the coff symbol specific value corresponds to a Thumb + function. */ + int coff_sym_is_thumb (int val) { diff --git a/gdb/arm-xdep.c b/gdb/arm-xdep.c index 3c253c58809..64ca9003665 100644 --- a/gdb/arm-xdep.c +++ b/gdb/arm-xdep.c @@ -1,575 +1,575 @@ -/* Acorn Risc Machine host machine support. - Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include "defs.h" -#include "frame.h" -#include "inferior.h" -#include "opcode/arm.h" - -#include <sys/param.h> -#include <sys/dir.h> -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/ptrace.h> -#include <machine/reg.h> - -#define N_TXTADDR(hdr) 0x8000 -#define N_DATADDR(hdr) (hdr.a_text + 0x8000) - -#include "gdbcore.h" - -#include <sys/user.h> /* After a.out.h */ -#include <sys/file.h> -#include "gdb_stat.h" - -#include <errno.h> - -void -fetch_inferior_registers (regno) - int regno; /* Original value discarded */ -{ - register unsigned int regaddr; - char buf[MAX_REGISTER_RAW_SIZE]; - register int i; - - struct user u; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; - offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - - KERNEL_U_ADDR; - - registers_fetched (); - - for (regno = 0; regno < 16; regno++) - { - regaddr = offset + regno * 4; - *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, - (PTRACE_ARG3_TYPE) regaddr, 0); - if (regno == PC_REGNUM) - *(int *) &buf[0] = GET_PC_PART (*(int *) &buf[0]); - supply_register (regno, buf); - } - *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, - (PTRACE_ARG3_TYPE) (offset + PC * 4), 0); - supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */ - - /* read the floating point registers */ - offset = (char *) &u.u_fp_regs - (char *) &u; - *(int *) buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0); - supply_register (FPS_REGNUM, buf); - for (regno = 16; regno < 24; regno++) - { - regaddr = offset + 4 + 12 * (regno - 16); - for (i = 0; i < 12; i += sizeof (int)) - *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, - (PTRACE_ARG3_TYPE) (regaddr + i), 0); - supply_register (regno, buf); - } -} - -/* Store our register values back into the inferior. - If REGNO is -1, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ - -void -store_inferior_registers (regno) - int regno; -{ - register unsigned int regaddr; - char buf[80]; - - struct user u; - unsigned long value; - unsigned int offset = (char *) &u.u_ar0 - (char *) &u; - offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - - KERNEL_U_ADDR; - - if (regno >= 0) - { - if (regno >= 16) - return; - regaddr = offset + 4 * regno; - errno = 0; - value = read_register (regno); - if (regno == PC_REGNUM) - value = SET_PC_PART (read_register (PS_REGNUM), value); - ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); - if (errno != 0) - { - sprintf (buf, "writing register number %d", regno); - perror_with_name (buf); - } - } - else - for (regno = 0; regno < 15; regno++) - { - regaddr = offset + regno * 4; - errno = 0; - value = read_register (regno); - if (regno == PC_REGNUM) - value = SET_PC_PART (read_register (PS_REGNUM), value); - ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); - if (errno != 0) - { - sprintf (buf, "writing all regs, number %d", regno); - perror_with_name (buf); - } - } -} - -/* Work with core dump and executable files, for GDB. - This code would be in corefile.c if it weren't machine-dependent. */ - -/* Structure to describe the chain of shared libraries used - by the execfile. - e.g. prog shares Xt which shares X11 which shares c. */ - -struct shared_library -{ - struct exec_header header; - char name[SHLIBLEN]; - CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */ - long data_offset; /* offset of data section in file */ - int chan; /* file descriptor for the file */ - struct shared_library *shares; /* library this one shares */ -}; -static struct shared_library *shlib = 0; - -/* Hook for `exec_file_command' command to call. */ - -extern void (*exec_file_display_hook) (); - -static CORE_ADDR unshared_text_start; - -/* extended header from exec file (for shared library info) */ - -static struct exec_header exec_header; - -void -core_file_command (filename, from_tty) - char *filename; - int from_tty; -{ - int val; - - /* Discard all vestiges of any previous core file - and mark data and stack spaces as empty. */ - - if (corefile) - free (corefile); - corefile = 0; - - if (corechan >= 0) - close (corechan); - corechan = -1; - - data_start = 0; - data_end = 0; - stack_start = STACK_END_ADDR; - stack_end = STACK_END_ADDR; - - /* Now, if a new core file was specified, open it and digest it. */ - - if (filename) - { - filename = tilde_expand (filename); - make_cleanup (free, filename); - - if (have_inferior_p ()) - error ("To look at a core file, you must kill the program with \"kill\"."); - corechan = open (filename, O_RDONLY, 0); - if (corechan < 0) - perror_with_name (filename); - /* 4.2-style (and perhaps also sysV-style) core dump file. */ - { - struct user u; - - unsigned int reg_offset, fp_reg_offset; - - val = myread (corechan, &u, sizeof u); - if (val < 0) - perror_with_name ("Not a core file: reading upage"); - if (val != sizeof u) - error ("Not a core file: could only read %d bytes", val); - - /* We are depending on exec_file_command having been called - previously to set exec_data_start. Since the executable - and the core file share the same text segment, the address - of the data segment will be the same in both. */ - data_start = exec_data_start; - - data_end = data_start + NBPG * u.u_dsize; - stack_start = stack_end - NBPG * u.u_ssize; - data_offset = NBPG * UPAGES; - stack_offset = NBPG * (UPAGES + u.u_dsize); - - /* Some machines put an absolute address in here and some put - the offset in the upage of the regs. */ - reg_offset = (int) u.u_ar0; - if (reg_offset > NBPG * UPAGES) - reg_offset -= KERNEL_U_ADDR; - fp_reg_offset = (char *) &u.u_fp_regs - (char *) &u; - - /* I don't know where to find this info. - So, for now, mark it as not available. */ - N_SET_MAGIC (core_aouthdr, 0); - - /* Read the register values out of the core file and store - them where `read_register' will find them. */ - - { - register int regno; - - for (regno = 0; regno < NUM_REGS; regno++) - { - char buf[MAX_REGISTER_RAW_SIZE]; - - if (regno < 16) - val = lseek (corechan, reg_offset + 4 * regno, 0); - else if (regno < 24) - val = lseek (corechan, fp_reg_offset + 4 + 12 * (regno - 24), 0); - else if (regno == 24) - val = lseek (corechan, fp_reg_offset, 0); - else if (regno == 25) - val = lseek (corechan, reg_offset + 4 * PC, 0); - if (val < 0 - || (val = myread (corechan, buf, sizeof buf)) < 0) - { - char *buffer = (char *) alloca (strlen (REGISTER_NAME (regno)) - + 30); - strcpy (buffer, "Reading register "); - strcat (buffer, REGISTER_NAME (regno)); - - perror_with_name (buffer); - } - - if (regno == PC_REGNUM) - *(int *) buf = GET_PC_PART (*(int *) buf); - supply_register (regno, buf); - } - } - } - if (filename[0] == '/') - corefile = savestring (filename, strlen (filename)); - else - { - corefile = concat (current_directory, "/", filename, NULL); - } - - flush_cached_frames (); - select_frame (get_current_frame (), 0); - validate_files (); - } - else if (from_tty) - printf ("No core file now.\n"); -} - -#if 0 -/* Work with core dump and executable files, for GDB. - This code would be in corefile.c if it weren't machine-dependent. */ - -/* Structure to describe the chain of shared libraries used - by the execfile. - e.g. prog shares Xt which shares X11 which shares c. */ - -struct shared_library -{ - struct exec_header header; - char name[SHLIBLEN]; - CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */ - long data_offset; /* offset of data section in file */ - int chan; /* file descriptor for the file */ - struct shared_library *shares; /* library this one shares */ -}; -static struct shared_library *shlib = 0; - -/* Hook for `exec_file_command' command to call. */ - -extern void (*exec_file_display_hook) (); - -static CORE_ADDR unshared_text_start; - -/* extended header from exec file (for shared library info) */ - -static struct exec_header exec_header; - -void -exec_file_command (filename, from_tty) - char *filename; - int from_tty; -{ - int val; - - /* Eliminate all traces of old exec file. - Mark text segment as empty. */ - - if (execfile) - free (execfile); - execfile = 0; - data_start = 0; - data_end -= exec_data_start; - text_start = 0; - unshared_text_start = 0; - text_end = 0; - exec_data_start = 0; - exec_data_end = 0; - if (execchan >= 0) - close (execchan); - execchan = -1; - if (shlib) - { - close_shared_library (shlib); - shlib = 0; - } - - /* Now open and digest the file the user requested, if any. */ - - if (filename) - { - filename = tilde_expand (filename); - make_cleanup (free, filename); - - execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, - &execfile); - if (execchan < 0) - perror_with_name (filename); - - { - struct stat st_exec; - -#ifdef HEADER_SEEK_FD - HEADER_SEEK_FD (execchan); -#endif - - val = myread (execchan, &exec_header, sizeof exec_header); - exec_aouthdr = exec_header.a_exec; - - if (val < 0) - perror_with_name (filename); - - text_start = 0x8000; - - /* Look for shared library if needed */ - if (exec_header.a_exec.a_magic & MF_USES_SL) - shlib = open_shared_library (exec_header.a_shlibname, text_start); - - text_offset = N_TXTOFF (exec_aouthdr); - exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; - - if (shlib) - { - unshared_text_start = shared_text_end (shlib) & ~0x7fff; - stack_start = shlib->header.a_exec.a_sldatabase; - stack_end = STACK_END_ADDR; - } - else - unshared_text_start = 0x8000; - text_end = unshared_text_start + exec_aouthdr.a_text; - - exec_data_start = unshared_text_start + exec_aouthdr.a_text; - exec_data_end = exec_data_start + exec_aouthdr.a_data; - - data_start = exec_data_start; - data_end += exec_data_start; - - fstat (execchan, &st_exec); - exec_mtime = st_exec.st_mtime; - } - - validate_files (); - } - else if (from_tty) - printf ("No executable file now.\n"); - - /* Tell display code (if any) about the changed file name. */ - if (exec_file_display_hook) - (*exec_file_display_hook) (filename); -} -#endif - -#if 0 -/* Read from the program's memory (except for inferior processes). - This function is misnamed, since it only reads, never writes; and - since it will use the core file and/or executable file as necessary. - - It should be extended to write as well as read, FIXME, for patching files. - - Return 0 if address could be read, EIO if addresss out of bounds. */ - -int -xfer_core_file (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - register int i; - register int val; - int xferchan; - char **xferfile; - int fileptr; - int returnval = 0; - - while (len > 0) - { - xferfile = 0; - xferchan = 0; - - /* Determine which file the next bunch of addresses reside in, - and where in the file. Set the file's read/write pointer - to point at the proper place for the desired address - and set xferfile and xferchan for the correct file. - - If desired address is nonexistent, leave them zero. - - i is set to the number of bytes that can be handled - along with the next address. - - We put the most likely tests first for efficiency. */ - - /* Note that if there is no core file - data_start and data_end are equal. */ - if (memaddr >= data_start && memaddr < data_end) - { - i = min (len, data_end - memaddr); - fileptr = memaddr - data_start + data_offset; - xferfile = &corefile; - xferchan = corechan; - } - /* Note that if there is no core file - stack_start and stack_end define the shared library data. */ - else if (memaddr >= stack_start && memaddr < stack_end) - { - if (corechan < 0) - { - struct shared_library *lib; - for (lib = shlib; lib; lib = lib->shares) - if (memaddr >= lib->header.a_exec.a_sldatabase && - memaddr < lib->header.a_exec.a_sldatabase + - lib->header.a_exec.a_data) - break; - if (lib) - { - i = min (len, lib->header.a_exec.a_sldatabase + - lib->header.a_exec.a_data - memaddr); - fileptr = lib->data_offset + memaddr - - lib->header.a_exec.a_sldatabase; - xferfile = execfile; - xferchan = lib->chan; - } - } - else - { - i = min (len, stack_end - memaddr); - fileptr = memaddr - stack_start + stack_offset; - xferfile = &corefile; - xferchan = corechan; - } - } - else if (corechan < 0 - && memaddr >= exec_data_start && memaddr < exec_data_end) - { - i = min (len, exec_data_end - memaddr); - fileptr = memaddr - exec_data_start + exec_data_offset; - xferfile = &execfile; - xferchan = execchan; - } - else if (memaddr >= text_start && memaddr < text_end) - { - struct shared_library *lib; - for (lib = shlib; lib; lib = lib->shares) - if (memaddr >= lib->text_start && - memaddr < lib->text_start + lib->header.a_exec.a_text) - break; - if (lib) - { - i = min (len, lib->header.a_exec.a_text + - lib->text_start - memaddr); - fileptr = memaddr - lib->text_start + text_offset; - xferfile = &execfile; - xferchan = lib->chan; - } - else - { - i = min (len, text_end - memaddr); - fileptr = memaddr - unshared_text_start + text_offset; - xferfile = &execfile; - xferchan = execchan; - } - } - else if (memaddr < text_start) - { - i = min (len, text_start - memaddr); - } - else if (memaddr >= text_end - && memaddr < (corechan >= 0 ? data_start : exec_data_start)) - { - i = min (len, data_start - memaddr); - } - else if (corechan >= 0 - && memaddr >= data_end && memaddr < stack_start) - { - i = min (len, stack_start - memaddr); - } - else if (corechan < 0 && memaddr >= exec_data_end) - { - i = min (len, -memaddr); - } - else if (memaddr >= stack_end && stack_end != 0) - { - i = min (len, -memaddr); - } - else - { - /* Address did not classify into one of the known ranges. - This shouldn't happen; we catch the endpoints. */ - internal_error ("Bad case logic in xfer_core_file."); - } - - /* Now we know which file to use. - Set up its pointer and transfer the data. */ - if (xferfile) - { - if (*xferfile == 0) - if (xferfile == &execfile) - error ("No program file to examine."); - else - error ("No core dump file or running program to examine."); - val = lseek (xferchan, fileptr, 0); - if (val < 0) - perror_with_name (*xferfile); - val = myread (xferchan, myaddr, i); - if (val < 0) - perror_with_name (*xferfile); - } - /* If this address is for nonexistent memory, - read zeros if reading, or do nothing if writing. - Actually, we never right. */ - else - { - memset (myaddr, '\0', i); - returnval = EIO; - } - - memaddr += i; - myaddr += i; - len -= i; - } - return returnval; -} -#endif +/* OBSOLETE /* Acorn Risc Machine host machine support. */ +/* OBSOLETE Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. */ +/* OBSOLETE */ +/* OBSOLETE This file is part of GDB. */ +/* OBSOLETE */ +/* OBSOLETE This program is free software; you can redistribute it and/or modify */ +/* OBSOLETE it under the terms of the GNU General Public License as published by */ +/* OBSOLETE the Free Software Foundation; either version 2 of the License, or */ +/* OBSOLETE (at your option) any later version. */ +/* OBSOLETE */ +/* OBSOLETE This program is distributed in the hope that it will be useful, */ +/* OBSOLETE but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* OBSOLETE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* OBSOLETE GNU General Public License for more details. */ +/* OBSOLETE */ +/* OBSOLETE You should have received a copy of the GNU General Public License */ +/* OBSOLETE along with this program; if not, write to the Free Software */ +/* OBSOLETE Foundation, Inc., 59 Temple Place - Suite 330, */ +/* OBSOLETE Boston, MA 02111-1307, USA. *x/ */ +/* OBSOLETE */ +/* OBSOLETE #include "defs.h" */ +/* OBSOLETE #include "frame.h" */ +/* OBSOLETE #include "inferior.h" */ +/* OBSOLETE #include "opcode/arm.h" */ +/* OBSOLETE */ +/* OBSOLETE #include <sys/param.h> */ +/* OBSOLETE #include <sys/dir.h> */ +/* OBSOLETE #include <signal.h> */ +/* OBSOLETE #include <sys/ioctl.h> */ +/* OBSOLETE #include <sys/ptrace.h> */ +/* OBSOLETE #include <machine/reg.h> */ +/* OBSOLETE */ +/* OBSOLETE #define N_TXTADDR(hdr) 0x8000 */ +/* OBSOLETE #define N_DATADDR(hdr) (hdr.a_text + 0x8000) */ +/* OBSOLETE */ +/* OBSOLETE #include "gdbcore.h" */ +/* OBSOLETE */ +/* OBSOLETE #include <sys/user.h> /* After a.out.h *x/ */ +/* OBSOLETE #include <sys/file.h> */ +/* OBSOLETE #include "gdb_stat.h" */ +/* OBSOLETE */ +/* OBSOLETE #include <errno.h> */ +/* OBSOLETE */ +/* OBSOLETE void */ +/* OBSOLETE fetch_inferior_registers (regno) */ +/* OBSOLETE int regno; /* Original value discarded *x/ */ +/* OBSOLETE { */ +/* OBSOLETE register unsigned int regaddr; */ +/* OBSOLETE char buf[MAX_REGISTER_RAW_SIZE]; */ +/* OBSOLETE register int i; */ +/* OBSOLETE */ +/* OBSOLETE struct user u; */ +/* OBSOLETE unsigned int offset = (char *) &u.u_ar0 - (char *) &u; */ +/* OBSOLETE offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) */ +/* OBSOLETE - KERNEL_U_ADDR; */ +/* OBSOLETE */ +/* OBSOLETE registers_fetched (); */ +/* OBSOLETE */ +/* OBSOLETE for (regno = 0; regno < 16; regno++) */ +/* OBSOLETE { */ +/* OBSOLETE regaddr = offset + regno * 4; */ +/* OBSOLETE *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, */ +/* OBSOLETE (PTRACE_ARG3_TYPE) regaddr, 0); */ +/* OBSOLETE if (regno == PC_REGNUM) */ +/* OBSOLETE *(int *) &buf[0] = GET_PC_PART (*(int *) &buf[0]); */ +/* OBSOLETE supply_register (regno, buf); */ +/* OBSOLETE } */ +/* OBSOLETE *(int *) &buf[0] = ptrace (PT_READ_U, inferior_pid, */ +/* OBSOLETE (PTRACE_ARG3_TYPE) (offset + PC * 4), 0); */ +/* OBSOLETE supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc *x/ */ +/* OBSOLETE */ +/* OBSOLETE /* read the floating point registers *x/ */ +/* OBSOLETE offset = (char *) &u.u_fp_regs - (char *) &u; */ +/* OBSOLETE *(int *) buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0); */ +/* OBSOLETE supply_register (FPS_REGNUM, buf); */ +/* OBSOLETE for (regno = 16; regno < 24; regno++) */ +/* OBSOLETE { */ +/* OBSOLETE regaddr = offset + 4 + 12 * (regno - 16); */ +/* OBSOLETE for (i = 0; i < 12; i += sizeof (int)) */ +/* OBSOLETE *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, */ +/* OBSOLETE (PTRACE_ARG3_TYPE) (regaddr + i), 0); */ +/* OBSOLETE supply_register (regno, buf); */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE /* Store our register values back into the inferior. */ +/* OBSOLETE If REGNO is -1, do this for all registers. */ +/* OBSOLETE Otherwise, REGNO specifies which register (so we can save time). *x/ */ +/* OBSOLETE */ +/* OBSOLETE void */ +/* OBSOLETE store_inferior_registers (regno) */ +/* OBSOLETE int regno; */ +/* OBSOLETE { */ +/* OBSOLETE register unsigned int regaddr; */ +/* OBSOLETE char buf[80]; */ +/* OBSOLETE */ +/* OBSOLETE struct user u; */ +/* OBSOLETE unsigned long value; */ +/* OBSOLETE unsigned int offset = (char *) &u.u_ar0 - (char *) &u; */ +/* OBSOLETE offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) */ +/* OBSOLETE - KERNEL_U_ADDR; */ +/* OBSOLETE */ +/* OBSOLETE if (regno >= 0) */ +/* OBSOLETE { */ +/* OBSOLETE if (regno >= 16) */ +/* OBSOLETE return; */ +/* OBSOLETE regaddr = offset + 4 * regno; */ +/* OBSOLETE errno = 0; */ +/* OBSOLETE value = read_register (regno); */ +/* OBSOLETE if (regno == PC_REGNUM) */ +/* OBSOLETE value = SET_PC_PART (read_register (PS_REGNUM), value); */ +/* OBSOLETE ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); */ +/* OBSOLETE if (errno != 0) */ +/* OBSOLETE { */ +/* OBSOLETE sprintf (buf, "writing register number %d", regno); */ +/* OBSOLETE perror_with_name (buf); */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE else */ +/* OBSOLETE for (regno = 0; regno < 15; regno++) */ +/* OBSOLETE { */ +/* OBSOLETE regaddr = offset + regno * 4; */ +/* OBSOLETE errno = 0; */ +/* OBSOLETE value = read_register (regno); */ +/* OBSOLETE if (regno == PC_REGNUM) */ +/* OBSOLETE value = SET_PC_PART (read_register (PS_REGNUM), value); */ +/* OBSOLETE ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value); */ +/* OBSOLETE if (errno != 0) */ +/* OBSOLETE { */ +/* OBSOLETE sprintf (buf, "writing all regs, number %d", regno); */ +/* OBSOLETE perror_with_name (buf); */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE /* Work with core dump and executable files, for GDB. */ +/* OBSOLETE This code would be in corefile.c if it weren't machine-dependent. *x/ */ +/* OBSOLETE */ +/* OBSOLETE /* Structure to describe the chain of shared libraries used */ +/* OBSOLETE by the execfile. */ +/* OBSOLETE e.g. prog shares Xt which shares X11 which shares c. *x/ */ +/* OBSOLETE */ +/* OBSOLETE struct shared_library */ +/* OBSOLETE { */ +/* OBSOLETE struct exec_header header; */ +/* OBSOLETE char name[SHLIBLEN]; */ +/* OBSOLETE CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file *x/ */ +/* OBSOLETE long data_offset; /* offset of data section in file *x/ */ +/* OBSOLETE int chan; /* file descriptor for the file *x/ */ +/* OBSOLETE struct shared_library *shares; /* library this one shares *x/ */ +/* OBSOLETE }; */ +/* OBSOLETE static struct shared_library *shlib = 0; */ +/* OBSOLETE */ +/* OBSOLETE /* Hook for `exec_file_command' command to call. *x/ */ +/* OBSOLETE */ +/* OBSOLETE extern void (*exec_file_display_hook) (); */ +/* OBSOLETE */ +/* OBSOLETE static CORE_ADDR unshared_text_start; */ +/* OBSOLETE */ +/* OBSOLETE /* extended header from exec file (for shared library info) *x/ */ +/* OBSOLETE */ +/* OBSOLETE static struct exec_header exec_header; */ +/* OBSOLETE */ +/* OBSOLETE void */ +/* OBSOLETE core_file_command (filename, from_tty) */ +/* OBSOLETE char *filename; */ +/* OBSOLETE int from_tty; */ +/* OBSOLETE { */ +/* OBSOLETE int val; */ +/* OBSOLETE */ +/* OBSOLETE /* Discard all vestiges of any previous core file */ +/* OBSOLETE and mark data and stack spaces as empty. *x/ */ +/* OBSOLETE */ +/* OBSOLETE if (corefile) */ +/* OBSOLETE free (corefile); */ +/* OBSOLETE corefile = 0; */ +/* OBSOLETE */ +/* OBSOLETE if (corechan >= 0) */ +/* OBSOLETE close (corechan); */ +/* OBSOLETE corechan = -1; */ +/* OBSOLETE */ +/* OBSOLETE data_start = 0; */ +/* OBSOLETE data_end = 0; */ +/* OBSOLETE stack_start = STACK_END_ADDR; */ +/* OBSOLETE stack_end = STACK_END_ADDR; */ +/* OBSOLETE */ +/* OBSOLETE /* Now, if a new core file was specified, open it and digest it. *x/ */ +/* OBSOLETE */ +/* OBSOLETE if (filename) */ +/* OBSOLETE { */ +/* OBSOLETE filename = tilde_expand (filename); */ +/* OBSOLETE make_cleanup (free, filename); */ +/* OBSOLETE */ +/* OBSOLETE if (have_inferior_p ()) */ +/* OBSOLETE error ("To look at a core file, you must kill the program with \"kill\"."); */ +/* OBSOLETE corechan = open (filename, O_RDONLY, 0); */ +/* OBSOLETE if (corechan < 0) */ +/* OBSOLETE perror_with_name (filename); */ +/* OBSOLETE /* 4.2-style (and perhaps also sysV-style) core dump file. *x/ */ +/* OBSOLETE { */ +/* OBSOLETE struct user u; */ +/* OBSOLETE */ +/* OBSOLETE unsigned int reg_offset, fp_reg_offset; */ +/* OBSOLETE */ +/* OBSOLETE val = myread (corechan, &u, sizeof u); */ +/* OBSOLETE if (val < 0) */ +/* OBSOLETE perror_with_name ("Not a core file: reading upage"); */ +/* OBSOLETE if (val != sizeof u) */ +/* OBSOLETE error ("Not a core file: could only read %d bytes", val); */ +/* OBSOLETE */ +/* OBSOLETE /* We are depending on exec_file_command having been called */ +/* OBSOLETE previously to set exec_data_start. Since the executable */ +/* OBSOLETE and the core file share the same text segment, the address */ +/* OBSOLETE of the data segment will be the same in both. *x/ */ +/* OBSOLETE data_start = exec_data_start; */ +/* OBSOLETE */ +/* OBSOLETE data_end = data_start + NBPG * u.u_dsize; */ +/* OBSOLETE stack_start = stack_end - NBPG * u.u_ssize; */ +/* OBSOLETE data_offset = NBPG * UPAGES; */ +/* OBSOLETE stack_offset = NBPG * (UPAGES + u.u_dsize); */ +/* OBSOLETE */ +/* OBSOLETE /* Some machines put an absolute address in here and some put */ +/* OBSOLETE the offset in the upage of the regs. *x/ */ +/* OBSOLETE reg_offset = (int) u.u_ar0; */ +/* OBSOLETE if (reg_offset > NBPG * UPAGES) */ +/* OBSOLETE reg_offset -= KERNEL_U_ADDR; */ +/* OBSOLETE fp_reg_offset = (char *) &u.u_fp_regs - (char *) &u; */ +/* OBSOLETE */ +/* OBSOLETE /* I don't know where to find this info. */ +/* OBSOLETE So, for now, mark it as not available. *x/ */ +/* OBSOLETE N_SET_MAGIC (core_aouthdr, 0); */ +/* OBSOLETE */ +/* OBSOLETE /* Read the register values out of the core file and store */ +/* OBSOLETE them where `read_register' will find them. *x/ */ +/* OBSOLETE */ +/* OBSOLETE { */ +/* OBSOLETE register int regno; */ +/* OBSOLETE */ +/* OBSOLETE for (regno = 0; regno < NUM_REGS; regno++) */ +/* OBSOLETE { */ +/* OBSOLETE char buf[MAX_REGISTER_RAW_SIZE]; */ +/* OBSOLETE */ +/* OBSOLETE if (regno < 16) */ +/* OBSOLETE val = lseek (corechan, reg_offset + 4 * regno, 0); */ +/* OBSOLETE else if (regno < 24) */ +/* OBSOLETE val = lseek (corechan, fp_reg_offset + 4 + 12 * (regno - 24), 0); */ +/* OBSOLETE else if (regno == 24) */ +/* OBSOLETE val = lseek (corechan, fp_reg_offset, 0); */ +/* OBSOLETE else if (regno == 25) */ +/* OBSOLETE val = lseek (corechan, reg_offset + 4 * PC, 0); */ +/* OBSOLETE if (val < 0 */ +/* OBSOLETE || (val = myread (corechan, buf, sizeof buf)) < 0) */ +/* OBSOLETE { */ +/* OBSOLETE char *buffer = (char *) alloca (strlen (REGISTER_NAME (regno)) */ +/* OBSOLETE + 30); */ +/* OBSOLETE strcpy (buffer, "Reading register "); */ +/* OBSOLETE strcat (buffer, REGISTER_NAME (regno)); */ +/* OBSOLETE */ +/* OBSOLETE perror_with_name (buffer); */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE if (regno == PC_REGNUM) */ +/* OBSOLETE *(int *) buf = GET_PC_PART (*(int *) buf); */ +/* OBSOLETE supply_register (regno, buf); */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE if (filename[0] == '/') */ +/* OBSOLETE corefile = savestring (filename, strlen (filename)); */ +/* OBSOLETE else */ +/* OBSOLETE { */ +/* OBSOLETE corefile = concat (current_directory, "/", filename, NULL); */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE flush_cached_frames (); */ +/* OBSOLETE select_frame (get_current_frame (), 0); */ +/* OBSOLETE validate_files (); */ +/* OBSOLETE } */ +/* OBSOLETE else if (from_tty) */ +/* OBSOLETE printf ("No core file now.\n"); */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE #if 0 */ +/* OBSOLETE /* Work with core dump and executable files, for GDB. */ +/* OBSOLETE This code would be in corefile.c if it weren't machine-dependent. *x/ */ +/* OBSOLETE */ +/* OBSOLETE /* Structure to describe the chain of shared libraries used */ +/* OBSOLETE by the execfile. */ +/* OBSOLETE e.g. prog shares Xt which shares X11 which shares c. *x/ */ +/* OBSOLETE */ +/* OBSOLETE struct shared_library */ +/* OBSOLETE { */ +/* OBSOLETE struct exec_header header; */ +/* OBSOLETE char name[SHLIBLEN]; */ +/* OBSOLETE CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file *x/ */ +/* OBSOLETE long data_offset; /* offset of data section in file *x/ */ +/* OBSOLETE int chan; /* file descriptor for the file *x/ */ +/* OBSOLETE struct shared_library *shares; /* library this one shares *x/ */ +/* OBSOLETE }; */ +/* OBSOLETE static struct shared_library *shlib = 0; */ +/* OBSOLETE */ +/* OBSOLETE /* Hook for `exec_file_command' command to call. *x/ */ +/* OBSOLETE */ +/* OBSOLETE extern void (*exec_file_display_hook) (); */ +/* OBSOLETE */ +/* OBSOLETE static CORE_ADDR unshared_text_start; */ +/* OBSOLETE */ +/* OBSOLETE /* extended header from exec file (for shared library info) *x/ */ +/* OBSOLETE */ +/* OBSOLETE static struct exec_header exec_header; */ +/* OBSOLETE */ +/* OBSOLETE void */ +/* OBSOLETE exec_file_command (filename, from_tty) */ +/* OBSOLETE char *filename; */ +/* OBSOLETE int from_tty; */ +/* OBSOLETE { */ +/* OBSOLETE int val; */ +/* OBSOLETE */ +/* OBSOLETE /* Eliminate all traces of old exec file. */ +/* OBSOLETE Mark text segment as empty. *x/ */ +/* OBSOLETE */ +/* OBSOLETE if (execfile) */ +/* OBSOLETE free (execfile); */ +/* OBSOLETE execfile = 0; */ +/* OBSOLETE data_start = 0; */ +/* OBSOLETE data_end -= exec_data_start; */ +/* OBSOLETE text_start = 0; */ +/* OBSOLETE unshared_text_start = 0; */ +/* OBSOLETE text_end = 0; */ +/* OBSOLETE exec_data_start = 0; */ +/* OBSOLETE exec_data_end = 0; */ +/* OBSOLETE if (execchan >= 0) */ +/* OBSOLETE close (execchan); */ +/* OBSOLETE execchan = -1; */ +/* OBSOLETE if (shlib) */ +/* OBSOLETE { */ +/* OBSOLETE close_shared_library (shlib); */ +/* OBSOLETE shlib = 0; */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE /* Now open and digest the file the user requested, if any. *x/ */ +/* OBSOLETE */ +/* OBSOLETE if (filename) */ +/* OBSOLETE { */ +/* OBSOLETE filename = tilde_expand (filename); */ +/* OBSOLETE make_cleanup (free, filename); */ +/* OBSOLETE */ +/* OBSOLETE execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, */ +/* OBSOLETE &execfile); */ +/* OBSOLETE if (execchan < 0) */ +/* OBSOLETE perror_with_name (filename); */ +/* OBSOLETE */ +/* OBSOLETE { */ +/* OBSOLETE struct stat st_exec; */ +/* OBSOLETE */ +/* OBSOLETE #ifdef HEADER_SEEK_FD */ +/* OBSOLETE HEADER_SEEK_FD (execchan); */ +/* OBSOLETE #endif */ +/* OBSOLETE */ +/* OBSOLETE val = myread (execchan, &exec_header, sizeof exec_header); */ +/* OBSOLETE exec_aouthdr = exec_header.a_exec; */ +/* OBSOLETE */ +/* OBSOLETE if (val < 0) */ +/* OBSOLETE perror_with_name (filename); */ +/* OBSOLETE */ +/* OBSOLETE text_start = 0x8000; */ +/* OBSOLETE */ +/* OBSOLETE /* Look for shared library if needed *x/ */ +/* OBSOLETE if (exec_header.a_exec.a_magic & MF_USES_SL) */ +/* OBSOLETE shlib = open_shared_library (exec_header.a_shlibname, text_start); */ +/* OBSOLETE */ +/* OBSOLETE text_offset = N_TXTOFF (exec_aouthdr); */ +/* OBSOLETE exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text; */ +/* OBSOLETE */ +/* OBSOLETE if (shlib) */ +/* OBSOLETE { */ +/* OBSOLETE unshared_text_start = shared_text_end (shlib) & ~0x7fff; */ +/* OBSOLETE stack_start = shlib->header.a_exec.a_sldatabase; */ +/* OBSOLETE stack_end = STACK_END_ADDR; */ +/* OBSOLETE } */ +/* OBSOLETE else */ +/* OBSOLETE unshared_text_start = 0x8000; */ +/* OBSOLETE text_end = unshared_text_start + exec_aouthdr.a_text; */ +/* OBSOLETE */ +/* OBSOLETE exec_data_start = unshared_text_start + exec_aouthdr.a_text; */ +/* OBSOLETE exec_data_end = exec_data_start + exec_aouthdr.a_data; */ +/* OBSOLETE */ +/* OBSOLETE data_start = exec_data_start; */ +/* OBSOLETE data_end += exec_data_start; */ +/* OBSOLETE */ +/* OBSOLETE fstat (execchan, &st_exec); */ +/* OBSOLETE exec_mtime = st_exec.st_mtime; */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE validate_files (); */ +/* OBSOLETE } */ +/* OBSOLETE else if (from_tty) */ +/* OBSOLETE printf ("No executable file now.\n"); */ +/* OBSOLETE */ +/* OBSOLETE /* Tell display code (if any) about the changed file name. *x/ */ +/* OBSOLETE if (exec_file_display_hook) */ +/* OBSOLETE (*exec_file_display_hook) (filename); */ +/* OBSOLETE } */ +/* OBSOLETE #endif */ +/* OBSOLETE */ +/* OBSOLETE #if 0 */ +/* OBSOLETE /* Read from the program's memory (except for inferior processes). */ +/* OBSOLETE This function is misnamed, since it only reads, never writes; and */ +/* OBSOLETE since it will use the core file and/or executable file as necessary. */ +/* OBSOLETE */ +/* OBSOLETE It should be extended to write as well as read, FIXME, for patching files. */ +/* OBSOLETE */ +/* OBSOLETE Return 0 if address could be read, EIO if addresss out of bounds. *x/ */ +/* OBSOLETE */ +/* OBSOLETE int */ +/* OBSOLETE xfer_core_file (memaddr, myaddr, len) */ +/* OBSOLETE CORE_ADDR memaddr; */ +/* OBSOLETE char *myaddr; */ +/* OBSOLETE int len; */ +/* OBSOLETE { */ +/* OBSOLETE register int i; */ +/* OBSOLETE register int val; */ +/* OBSOLETE int xferchan; */ +/* OBSOLETE char **xferfile; */ +/* OBSOLETE int fileptr; */ +/* OBSOLETE int returnval = 0; */ +/* OBSOLETE */ +/* OBSOLETE while (len > 0) */ +/* OBSOLETE { */ +/* OBSOLETE xferfile = 0; */ +/* OBSOLETE xferchan = 0; */ +/* OBSOLETE */ +/* OBSOLETE /* Determine which file the next bunch of addresses reside in, */ +/* OBSOLETE and where in the file. Set the file's read/write pointer */ +/* OBSOLETE to point at the proper place for the desired address */ +/* OBSOLETE and set xferfile and xferchan for the correct file. */ +/* OBSOLETE */ +/* OBSOLETE If desired address is nonexistent, leave them zero. */ +/* OBSOLETE */ +/* OBSOLETE i is set to the number of bytes that can be handled */ +/* OBSOLETE along with the next address. */ +/* OBSOLETE */ +/* OBSOLETE We put the most likely tests first for efficiency. *x/ */ +/* OBSOLETE */ +/* OBSOLETE /* Note that if there is no core file */ +/* OBSOLETE data_start and data_end are equal. *x/ */ +/* OBSOLETE if (memaddr >= data_start && memaddr < data_end) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, data_end - memaddr); */ +/* OBSOLETE fileptr = memaddr - data_start + data_offset; */ +/* OBSOLETE xferfile = &corefile; */ +/* OBSOLETE xferchan = corechan; */ +/* OBSOLETE } */ +/* OBSOLETE /* Note that if there is no core file */ +/* OBSOLETE stack_start and stack_end define the shared library data. *x/ */ +/* OBSOLETE else if (memaddr >= stack_start && memaddr < stack_end) */ +/* OBSOLETE { */ +/* OBSOLETE if (corechan < 0) */ +/* OBSOLETE { */ +/* OBSOLETE struct shared_library *lib; */ +/* OBSOLETE for (lib = shlib; lib; lib = lib->shares) */ +/* OBSOLETE if (memaddr >= lib->header.a_exec.a_sldatabase && */ +/* OBSOLETE memaddr < lib->header.a_exec.a_sldatabase + */ +/* OBSOLETE lib->header.a_exec.a_data) */ +/* OBSOLETE break; */ +/* OBSOLETE if (lib) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, lib->header.a_exec.a_sldatabase + */ +/* OBSOLETE lib->header.a_exec.a_data - memaddr); */ +/* OBSOLETE fileptr = lib->data_offset + memaddr - */ +/* OBSOLETE lib->header.a_exec.a_sldatabase; */ +/* OBSOLETE xferfile = execfile; */ +/* OBSOLETE xferchan = lib->chan; */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE else */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, stack_end - memaddr); */ +/* OBSOLETE fileptr = memaddr - stack_start + stack_offset; */ +/* OBSOLETE xferfile = &corefile; */ +/* OBSOLETE xferchan = corechan; */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE else if (corechan < 0 */ +/* OBSOLETE && memaddr >= exec_data_start && memaddr < exec_data_end) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, exec_data_end - memaddr); */ +/* OBSOLETE fileptr = memaddr - exec_data_start + exec_data_offset; */ +/* OBSOLETE xferfile = &execfile; */ +/* OBSOLETE xferchan = execchan; */ +/* OBSOLETE } */ +/* OBSOLETE else if (memaddr >= text_start && memaddr < text_end) */ +/* OBSOLETE { */ +/* OBSOLETE struct shared_library *lib; */ +/* OBSOLETE for (lib = shlib; lib; lib = lib->shares) */ +/* OBSOLETE if (memaddr >= lib->text_start && */ +/* OBSOLETE memaddr < lib->text_start + lib->header.a_exec.a_text) */ +/* OBSOLETE break; */ +/* OBSOLETE if (lib) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, lib->header.a_exec.a_text + */ +/* OBSOLETE lib->text_start - memaddr); */ +/* OBSOLETE fileptr = memaddr - lib->text_start + text_offset; */ +/* OBSOLETE xferfile = &execfile; */ +/* OBSOLETE xferchan = lib->chan; */ +/* OBSOLETE } */ +/* OBSOLETE else */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, text_end - memaddr); */ +/* OBSOLETE fileptr = memaddr - unshared_text_start + text_offset; */ +/* OBSOLETE xferfile = &execfile; */ +/* OBSOLETE xferchan = execchan; */ +/* OBSOLETE } */ +/* OBSOLETE } */ +/* OBSOLETE else if (memaddr < text_start) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, text_start - memaddr); */ +/* OBSOLETE } */ +/* OBSOLETE else if (memaddr >= text_end */ +/* OBSOLETE && memaddr < (corechan >= 0 ? data_start : exec_data_start)) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, data_start - memaddr); */ +/* OBSOLETE } */ +/* OBSOLETE else if (corechan >= 0 */ +/* OBSOLETE && memaddr >= data_end && memaddr < stack_start) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, stack_start - memaddr); */ +/* OBSOLETE } */ +/* OBSOLETE else if (corechan < 0 && memaddr >= exec_data_end) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, -memaddr); */ +/* OBSOLETE } */ +/* OBSOLETE else if (memaddr >= stack_end && stack_end != 0) */ +/* OBSOLETE { */ +/* OBSOLETE i = min (len, -memaddr); */ +/* OBSOLETE } */ +/* OBSOLETE else */ +/* OBSOLETE { */ +/* OBSOLETE /* Address did not classify into one of the known ranges. */ +/* OBSOLETE This shouldn't happen; we catch the endpoints. *x/ */ +/* OBSOLETE internal_error ("Bad case logic in xfer_core_file."); */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE /* Now we know which file to use. */ +/* OBSOLETE Set up its pointer and transfer the data. *x/ */ +/* OBSOLETE if (xferfile) */ +/* OBSOLETE { */ +/* OBSOLETE if (*xferfile == 0) */ +/* OBSOLETE if (xferfile == &execfile) */ +/* OBSOLETE error ("No program file to examine."); */ +/* OBSOLETE else */ +/* OBSOLETE error ("No core dump file or running program to examine."); */ +/* OBSOLETE val = lseek (xferchan, fileptr, 0); */ +/* OBSOLETE if (val < 0) */ +/* OBSOLETE perror_with_name (*xferfile); */ +/* OBSOLETE val = myread (xferchan, myaddr, i); */ +/* OBSOLETE if (val < 0) */ +/* OBSOLETE perror_with_name (*xferfile); */ +/* OBSOLETE } */ +/* OBSOLETE /* If this address is for nonexistent memory, */ +/* OBSOLETE read zeros if reading, or do nothing if writing. */ +/* OBSOLETE Actually, we never right. *x/ */ +/* OBSOLETE else */ +/* OBSOLETE { */ +/* OBSOLETE memset (myaddr, '\0', i); */ +/* OBSOLETE returnval = EIO; */ +/* OBSOLETE } */ +/* OBSOLETE */ +/* OBSOLETE memaddr += i; */ +/* OBSOLETE myaddr += i; */ +/* OBSOLETE len -= i; */ +/* OBSOLETE } */ +/* OBSOLETE return returnval; */ +/* OBSOLETE } */ +/* OBSOLETE #endif */ diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 6ce753ef02e..d00f5c23fc6 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -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 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 1ffda2b1f97..e1f97c7309b 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -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 { diff --git a/gdb/config.in b/gdb/config.in index fb29b6843fd..669a84a4e59 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -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 diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh index 05e0cb697de..3cbc3eeed36 100644 --- a/gdb/config/alpha/alpha-linux.mh +++ b/gdb/config/alpha/alpha-linux.mh @@ -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 diff --git a/gdb/config/alpha/nm-linux.h b/gdb/config/alpha/nm-linux.h index 49b4fc38f4e..979b8174d33 100644 --- a/gdb/config/alpha/nm-linux.h +++ b/gdb/config/alpha/nm-linux.h @@ -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 */ diff --git a/gdb/config/arm/arm.mh b/gdb/config/arm/arm.mh index 4fcf0de6951..60381f0a69a 100644 --- a/gdb/config/arm/arm.mh +++ b/gdb/config/arm/arm.mh @@ -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 diff --git a/gdb/config/arm/arm.mt b/gdb/config/arm/arm.mt index f6f16a31564..ef34aa5e2de 100644 --- a/gdb/config/arm/arm.mt +++ b/gdb/config/arm/arm.mt @@ -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 diff --git a/gdb/config/arm/embed.mt b/gdb/config/arm/embed.mt new file mode 100644 index 00000000000..c854d17a71a --- /dev/null +++ b/gdb/config/arm/embed.mt @@ -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 diff --git a/gdb/config/arm/linux.mh b/gdb/config/arm/linux.mh new file mode 100644 index 00000000000..3c6dccc82d2 --- /dev/null +++ b/gdb/config/arm/linux.mh @@ -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 diff --git a/gdb/config/arm/linux.mt b/gdb/config/arm/linux.mt new file mode 100644 index 00000000000..b85ae48bf6d --- /dev/null +++ b/gdb/config/arm/linux.mt @@ -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 diff --git a/gdb/config/arm/nm-arm.h b/gdb/config/arm/nm-arm.h index 45ef76c3288..06ba83700d9 100644 --- a/gdb/config/arm/nm-arm.h +++ b/gdb/config/arm/nm-arm.h @@ -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 */ diff --git a/gdb/config/arm/nm-linux.h b/gdb/config/arm/nm-linux.h new file mode 100644 index 00000000000..125d72f67ff --- /dev/null +++ b/gdb/config/arm/nm-linux.h @@ -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 */ diff --git a/gdb/config/arm/tm-arm.h b/gdb/config/arm/tm-arm.h index d33477def20..fb7f7b9c93f 100644 --- a/gdb/config/arm/tm-arm.h +++ b/gdb/config/arm/tm-arm.h @@ -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 *)); - -/* 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)) +extern CORE_ADDR arm_saved_pc_after_call (struct frame_info *); + +/* 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. */ + +#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 - -/* Number of machine registers */ - -/* 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) */ - -#define NUM_REGS 26 +#define REGISTER_SIZE 4 + +/* 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 + +/* 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 + +/* 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)) - -/* Number of bytes of storage in the actual machine representation - for register N. On the vax, all regs are 4 bytes. */ - -#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) +#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. 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) + +/* 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. */ -#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. */ +/* 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)) -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) - -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)); + arm_fix_call_dummy ((dummyname), (pc), (fun), (nargs), (args), (type), (gcc_p)) -CORE_ADDR arm_get_next_pc PARAMS ((CORE_ADDR)); +void arm_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, + int nargs, struct value ** args, + struct type * type, int 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)); +CORE_ADDR arm_get_next_pc (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 */ diff --git a/gdb/config/arm/tm-embed.h b/gdb/config/arm/tm-embed.h new file mode 100644 index 00000000000..f42b4f2ead8 --- /dev/null +++ b/gdb/config/arm/tm-embed.h @@ -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 */ diff --git a/gdb/config/arm/tm-linux.h b/gdb/config/arm/tm-linux.h new file mode 100644 index 00000000000..27cc0d1573b --- /dev/null +++ b/gdb/config/arm/tm-linux.h @@ -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 */ diff --git a/gdb/config/arm/xm-arm.h b/gdb/config/arm/xm-arm.h index d73095a3eee..c3b618512e2 100644 --- a/gdb/config/arm/xm-arm.h +++ b/gdb/config/arm/xm-arm.h @@ -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/ */ diff --git a/gdb/config/arm/xm-linux.h b/gdb/config/arm/xm-linux.h new file mode 100644 index 00000000000..ef724b5d9bb --- /dev/null +++ b/gdb/config/arm/xm-linux.h @@ -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 */ diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh index 8464934ef95..febed9a2958 100644 --- a/gdb/config/i386/linux.mh +++ b/gdb/config/i386/linux.mh @@ -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 diff --git a/gdb/config/i386/tm-cygwin.h b/gdb/config/i386/tm-cygwin.h index 2faa4bf2003..aade1682a4d 100644 --- a/gdb/config/i386/tm-cygwin.h +++ b/gdb/config/i386/tm-cygwin.h @@ -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 diff --git a/gdb/config/i386/tm-i386sol2.h b/gdb/config/i386/tm-i386sol2.h index 6fcfceff55d..f35912fe6cc 100644 --- a/gdb/config/i386/tm-i386sol2.h +++ b/gdb/config/i386/tm-i386sol2.h @@ -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 diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h index 6e7e72c5762..ea9d04c9eea 100644 --- a/gdb/config/mips/tm-mips.h +++ b/gdb/config/mips/tm-mips.h @@ -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) diff --git a/gdb/config/nm-gnu.h b/gdb/config/nm-gnu.h index acd75212d60..b6e016fb55e 100644 --- a/gdb/config/nm-gnu.h +++ b/gdb/config/nm-gnu.h @@ -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. */ diff --git a/gdb/config/nm-linux.h b/gdb/config/nm-linux.h index 980530681e3..9b225827c54 100644 --- a/gdb/config/nm-linux.h +++ b/gdb/config/nm-linux.h @@ -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)) + diff --git a/gdb/config/nm-lynx.h b/gdb/config/nm-lynx.h index e97b886971a..88974b180b3 100644 --- a/gdb/config/nm-lynx.h +++ b/gdb/config/nm-lynx.h @@ -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 */ diff --git a/gdb/config/pa/nm-hppah.h b/gdb/config/pa/nm-hppah.h index 7b277d12246..c7466ca40de 100644 --- a/gdb/config/pa/nm-hppah.h +++ b/gdb/config/pa/nm-hppah.h @@ -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) diff --git a/gdb/config/sparc/tm-sun4sol2.h b/gdb/config/sparc/tm-sun4sol2.h index 74c2d4ec21b..07b5896fc6e 100644 --- a/gdb/config/sparc/tm-sun4sol2.h +++ b/gdb/config/sparc/tm-sun4sol2.h @@ -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 diff --git a/gdb/configure b/gdb/configure index 2016ab62156..259525d0737 100755 --- a/gdb/configure +++ b/gdb/configure @@ -78,7 +78,6 @@ program_suffix=NONE program_transform_name=s,x,x, silent= site= -sitefile= srcdir= target=NONE verbose= @@ -193,7 +192,6 @@ Configuration: --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages - --site-file=FILE use FILE as the site file --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX @@ -364,11 +362,6 @@ EOF -site=* | --site=* | --sit=*) site="$ac_optarg" ;; - -site-file | --site-file | --site-fil | --site-fi | --site-f) - ac_prev=sitefile ;; - -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*) - sitefile="$ac_optarg" ;; - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) @@ -534,16 +527,12 @@ fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. -if test -z "$sitefile"; then - if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi -else - CONFIG_SITE="$sitefile" fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then @@ -587,7 +576,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:591: checking for $ac_word" >&5 +echo "configure:580: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -617,7 +606,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:621: checking for $ac_word" >&5 +echo "configure:610: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -668,7 +657,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:672: checking for $ac_word" >&5 +echo "configure:661: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -700,7 +689,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:704: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:693: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -711,12 +700,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 715 "configure" +#line 704 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -742,12 +731,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:746: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:735: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:751: checking whether we are using GNU C" >&5 +echo "configure:740: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -756,7 +745,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:760: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -775,7 +764,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:779: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:768: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -807,7 +796,7 @@ else fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:811: checking how to run the C preprocessor" >&5 +echo "configure:800: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -822,13 +811,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 826 "configure" +#line 815 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:832: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:821: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -839,13 +828,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 843 "configure" +#line 832 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:838: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -856,13 +845,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 860 "configure" +#line 849 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:866: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -887,9 +876,9 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for AIX""... $ac_c" 1>&6 -echo "configure:891: checking for AIX" >&5 +echo "configure:880: checking for AIX" >&5 cat > conftest.$ac_ext <<EOF -#line 893 "configure" +#line 882 "configure" #include "confdefs.h" #ifdef _AIX yes @@ -911,7 +900,7 @@ rm -f conftest* echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 -echo "configure:915: checking for POSIXized ISC" >&5 +echo "configure:904: checking for POSIXized ISC" >&5 if test -d /etc/conf/kconfig.d && grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 then @@ -935,7 +924,7 @@ fi echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6 -echo "configure:939: checking for ${CC-cc} option to accept ANSI C" >&5 +echo "configure:928: checking for ${CC-cc} option to accept ANSI C" >&5 if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -951,7 +940,7 @@ for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__ do CC="$ac_save_CC $ac_arg" cat > conftest.$ac_ext <<EOF -#line 955 "configure" +#line 944 "configure" #include "confdefs.h" #include <stdarg.h> #include <stdio.h> @@ -988,7 +977,7 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } EOF -if { (eval echo configure:992: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:981: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_prog_cc_stdc="$ac_arg"; break else @@ -1059,7 +1048,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:1063: checking host system type" >&5 +echo "configure:1052: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -1080,7 +1069,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:1084: checking target system type" >&5 +echo "configure:1073: checking target system type" >&5 target_alias=$target case "$target_alias" in @@ -1098,7 +1087,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:1102: checking build system type" >&5 +echo "configure:1091: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -1123,7 +1112,7 @@ test "$host_alias" != "$target_alias" && ALL_LINGUAS= echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:1127: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:1116: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1152,7 +1141,7 @@ fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1156: checking for $ac_word" >&5 +echo "configure:1145: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1180,12 +1169,12 @@ else fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1184: checking for ANSI C header files" >&5 +echo "configure:1173: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1189 "configure" +#line 1178 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -1193,7 +1182,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1197: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1186: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1210,7 +1199,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 1214 "configure" +#line 1203 "configure" #include "confdefs.h" #include <string.h> EOF @@ -1228,7 +1217,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 1232 "configure" +#line 1221 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -1249,7 +1238,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 1253 "configure" +#line 1242 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1260,7 +1249,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:1264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -1284,12 +1273,12 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:1288: checking for working const" >&5 +echo "configure:1277: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1293 "configure" +#line 1282 "configure" #include "confdefs.h" int main() { @@ -1338,7 +1327,7 @@ ccp = (char const *const *) p; ; return 0; } EOF -if { (eval echo configure:1342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1331: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -1359,21 +1348,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:1363: checking for inline" >&5 +echo "configure:1352: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <<EOF -#line 1370 "configure" +#line 1359 "configure" #include "confdefs.h" int main() { } $ac_kw foo() { ; return 0; } EOF -if { (eval echo configure:1377: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1366: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -1399,12 +1388,12 @@ EOF esac echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:1403: checking for off_t" >&5 +echo "configure:1392: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1408 "configure" +#line 1397 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -1432,12 +1421,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1436: checking for size_t" >&5 +echo "configure:1425: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1441 "configure" +#line 1430 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -1467,19 +1456,19 @@ fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:1471: checking for working alloca.h" >&5 +echo "configure:1460: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1476 "configure" +#line 1465 "configure" #include "confdefs.h" #include <alloca.h> int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:1483: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -1500,12 +1489,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:1504: checking for alloca" >&5 +echo "configure:1493: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1509 "configure" +#line 1498 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -1533,7 +1522,7 @@ int main() { char *p = (char *) alloca(1); ; return 0; } EOF -if { (eval echo configure:1537: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -1565,12 +1554,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:1569: checking whether alloca needs Cray hooks" >&5 +echo "configure:1558: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1574 "configure" +#line 1563 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -1595,12 +1584,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1599: checking for $ac_func" >&5 +echo "configure:1588: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1604 "configure" +#line 1593 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1623,7 +1612,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1650,7 +1639,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:1654: checking stack direction for C alloca" >&5 +echo "configure:1643: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1658,7 +1647,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 1662 "configure" +#line 1651 "configure" #include "confdefs.h" find_stack_direction () { @@ -1677,7 +1666,7 @@ main () exit (find_stack_direction() < 0); } EOF -if { (eval echo configure:1681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1670: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -1702,17 +1691,17 @@ for ac_hdr in unistd.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1706: checking for $ac_hdr" >&5 +echo "configure:1695: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1711 "configure" +#line 1700 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1716: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1741,12 +1730,12 @@ done for ac_func in getpagesize do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1745: checking for $ac_func" >&5 +echo "configure:1734: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1750 "configure" +#line 1739 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -1769,7 +1758,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:1773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1762: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1794,7 +1783,7 @@ fi done echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:1798: checking for working mmap" >&5 +echo "configure:1787: checking for working mmap" >&5 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1802,7 +1791,7 @@ else ac_cv_func_mmap_fixed_mapped=no else cat > conftest.$ac_ext <<EOF -#line 1806 "configure" +#line 1795 "configure" #include "confdefs.h" /* Thanks to Mike Haertel and Jim Avera for this test. @@ -1942,7 +1931,7 @@ main() } EOF -if { (eval echo configure:1946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1935: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_mmap_fixed_mapped=yes else @@ -1970,17 +1959,17 @@ unistd.h values.h sys/param.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1974: checking for $ac_hdr" >&5 +echo "configure:1963: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1979 "configure" +#line 1968 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1984: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2010,12 +1999,12 @@ done __argz_count __argz_stringify __argz_next do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2014: checking for $ac_func" >&5 +echo "configure:2003: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2019 "configure" +#line 2008 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2038,7 +2027,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2042: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2067,12 +2056,12 @@ done for ac_func in stpcpy do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2071: checking for $ac_func" >&5 +echo "configure:2060: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2076 "configure" +#line 2065 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2095,7 +2084,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2099: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2129,19 +2118,19 @@ EOF if test $ac_cv_header_locale_h = yes; then echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 -echo "configure:2133: checking for LC_MESSAGES" >&5 +echo "configure:2122: checking for LC_MESSAGES" >&5 if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2138 "configure" +#line 2127 "configure" #include "confdefs.h" #include <locale.h> int main() { return LC_MESSAGES ; return 0; } EOF -if { (eval echo configure:2145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2134: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* am_cv_val_LC_MESSAGES=yes else @@ -2162,7 +2151,7 @@ EOF fi fi echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 -echo "configure:2166: checking whether NLS is requested" >&5 +echo "configure:2155: checking whether NLS is requested" >&5 # Check whether --enable-nls or --disable-nls was given. if test "${enable_nls+set}" = set; then enableval="$enable_nls" @@ -2182,7 +2171,7 @@ fi EOF echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 -echo "configure:2186: checking whether included gettext is requested" >&5 +echo "configure:2175: checking whether included gettext is requested" >&5 # Check whether --with-included-gettext or --without-included-gettext was given. if test "${with_included_gettext+set}" = set; then withval="$with_included_gettext" @@ -2201,17 +2190,17 @@ fi ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 -echo "configure:2205: checking for libintl.h" >&5 +echo "configure:2194: checking for libintl.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2210 "configure" +#line 2199 "configure" #include "confdefs.h" #include <libintl.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2215: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2204: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2228,19 +2217,19 @@ fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 -echo "configure:2232: checking for gettext in libc" >&5 +echo "configure:2221: checking for gettext in libc" >&5 if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2237 "configure" +#line 2226 "configure" #include "confdefs.h" #include <libintl.h> int main() { return (int) gettext ("") ; return 0; } EOF -if { (eval echo configure:2244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* gt_cv_func_gettext_libc=yes else @@ -2256,7 +2245,7 @@ echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 if test "$gt_cv_func_gettext_libc" != "yes"; then echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 -echo "configure:2260: checking for bindtextdomain in -lintl" >&5 +echo "configure:2249: checking for bindtextdomain in -lintl" >&5 ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2264,7 +2253,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <<EOF -#line 2268 "configure" +#line 2257 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -2275,7 +2264,7 @@ int main() { bindtextdomain() ; return 0; } EOF -if { (eval echo configure:2279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2268: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2291,19 +2280,19 @@ fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 -echo "configure:2295: checking for gettext in libintl" >&5 +echo "configure:2284: checking for gettext in libintl" >&5 if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2300 "configure" +#line 2289 "configure" #include "confdefs.h" int main() { return (int) gettext ("") ; return 0; } EOF -if { (eval echo configure:2307: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* gt_cv_func_gettext_libintl=yes else @@ -2331,7 +2320,7 @@ EOF # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2335: checking for $ac_word" >&5 +echo "configure:2324: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2365,12 +2354,12 @@ fi for ac_func in dcgettext do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2369: checking for $ac_func" >&5 +echo "configure:2358: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2374 "configure" +#line 2363 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -2393,7 +2382,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:2397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2420,7 +2409,7 @@ done # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2424: checking for $ac_word" >&5 +echo "configure:2413: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2456,7 +2445,7 @@ fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2460: checking for $ac_word" >&5 +echo "configure:2449: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2488,7 +2477,7 @@ else fi cat > conftest.$ac_ext <<EOF -#line 2492 "configure" +#line 2481 "configure" #include "confdefs.h" int main() { @@ -2496,7 +2485,7 @@ extern int _nl_msg_cat_cntr; return _nl_msg_cat_cntr ; return 0; } EOF -if { (eval echo configure:2500: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* CATOBJEXT=.gmo DATADIRNAME=share @@ -2528,7 +2517,7 @@ fi # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2532: checking for $ac_word" >&5 +echo "configure:2521: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2562,7 +2551,7 @@ fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2566: checking for $ac_word" >&5 +echo "configure:2555: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2598,7 +2587,7 @@ fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2602: checking for $ac_word" >&5 +echo "configure:2591: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2688,7 +2677,7 @@ fi LINGUAS= else echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 -echo "configure:2692: checking for catalogs to be installed" >&5 +echo "configure:2681: checking for catalogs to be installed" >&5 NEW_LINGUAS= for lang in ${LINGUAS=$ALL_LINGUAS}; do case "$ALL_LINGUAS" in @@ -2716,17 +2705,17 @@ echo "configure:2692: checking for catalogs to be installed" >&5 if test "$CATOBJEXT" = ".cat"; then ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 -echo "configure:2720: checking for linux/version.h" >&5 +echo "configure:2709: checking for linux/version.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 2725 "configure" +#line 2714 "configure" #include "confdefs.h" #include <linux/version.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2730: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2719: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -2817,12 +2806,12 @@ fi . ${srcdir}/configure.tgt -for ac_prog in mawk gawk nawk awk +for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2826: checking for $ac_word" >&5 +echo "configure:2815: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2863,7 +2852,7 @@ done # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2867: checking for a BSD compatible install" >&5 +echo "configure:2856: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2924,7 +2913,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2928: checking for $ac_word" >&5 +echo "configure:2917: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2956,7 +2945,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2960: checking for $ac_word" >&5 +echo "configure:2949: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2988,7 +2977,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2992: checking for $ac_word" >&5 +echo "configure:2981: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3025,7 +3014,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:3029: checking for $ac_word" >&5 +echo "configure:3018: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3077,12 +3066,12 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:3081: checking return type of signal handlers" >&5 +echo "configure:3070: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3086 "configure" +#line 3075 "configure" #include "confdefs.h" #include <sys/types.h> #include <signal.h> @@ -3099,7 +3088,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:3103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3092: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -3119,12 +3108,12 @@ EOF echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:3123: checking for ANSI C header files" >&5 +echo "configure:3112: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3128 "configure" +#line 3117 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -3132,7 +3121,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3136: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3125: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3149,7 +3138,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 3153 "configure" +#line 3142 "configure" #include "confdefs.h" #include <string.h> EOF @@ -3167,7 +3156,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 3171 "configure" +#line 3160 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -3188,7 +3177,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 3192 "configure" +#line 3181 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -3199,7 +3188,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:3203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3192: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -3223,26 +3212,26 @@ EOF fi -for ac_hdr in ctype.h curses.h endian.h link.h \ +for ac_hdr in 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 do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3236: checking for $ac_hdr" >&5 +echo "configure:3225: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3241 "configure" +#line 3230 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3246: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -3269,12 +3258,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:3273: checking whether stat file-mode macros are broken" >&5 +echo "configure:3262: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3278 "configure" +#line 3267 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/stat.h> @@ -3326,12 +3315,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:3330: checking for working const" >&5 +echo "configure:3319: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3335 "configure" +#line 3324 "configure" #include "confdefs.h" int main() { @@ -3380,7 +3369,7 @@ ccp = (char const *const *) p; ; return 0; } EOF -if { (eval echo configure:3384: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -3404,12 +3393,12 @@ fi for ac_func in setpgid sbrk sigaction isascii bzero bcopy btowc poll sigprocmask do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3408: checking for $ac_func" >&5 +echo "configure:3397: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3413 "configure" +#line 3402 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -3432,7 +3421,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:3436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3459,19 +3448,19 @@ done # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:3463: checking for working alloca.h" >&5 +echo "configure:3452: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3468 "configure" +#line 3457 "configure" #include "confdefs.h" #include <alloca.h> int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:3475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3464: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -3492,12 +3481,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:3496: checking for alloca" >&5 +echo "configure:3485: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3501 "configure" +#line 3490 "configure" #include "confdefs.h" #ifdef __GNUC__ @@ -3525,7 +3514,7 @@ int main() { char *p = (char *) alloca(1); ; return 0; } EOF -if { (eval echo configure:3529: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3518: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -3557,12 +3546,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:3561: checking whether alloca needs Cray hooks" >&5 +echo "configure:3550: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3566 "configure" +#line 3555 "configure" #include "confdefs.h" #if defined(CRAY) && ! defined(CRAY2) webecray @@ -3587,12 +3576,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3591: checking for $ac_func" >&5 +echo "configure:3580: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3596 "configure" +#line 3585 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -3615,7 +3604,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:3619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3642,7 +3631,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:3646: checking stack direction for C alloca" >&5 +echo "configure:3635: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3650,7 +3639,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <<EOF -#line 3654 "configure" +#line 3643 "configure" #include "confdefs.h" find_stack_direction () { @@ -3669,7 +3658,7 @@ main () exit (find_stack_direction() < 0); } EOF -if { (eval echo configure:3673: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -3692,19 +3681,19 @@ fi echo $ac_n "checking for PTRACE_GETXFPREGS""... $ac_c" 1>&6 -echo "configure:3696: checking for PTRACE_GETXFPREGS" >&5 +echo "configure:3685: checking for PTRACE_GETXFPREGS" >&5 if eval "test \"`echo '$''{'gdb_cv_have_ptrace_getxfpregs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3701 "configure" +#line 3690 "configure" #include "confdefs.h" #include <sys/ptrace.h> int main() { PTRACE_GETXFPREGS; ; return 0; } EOF -if { (eval echo configure:3708: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3697: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gdb_cv_have_ptrace_getxfpregs=yes else @@ -3725,7 +3714,7 @@ EOF fi echo $ac_n "checking for socketpair in -lsocket""... $ac_c" 1>&6 -echo "configure:3729: checking for socketpair in -lsocket" >&5 +echo "configure:3718: checking for socketpair in -lsocket" >&5 ac_lib_var=`echo socket'_'socketpair | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3733,7 +3722,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <<EOF -#line 3737 "configure" +#line 3726 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3744,7 +3733,7 @@ int main() { socketpair() ; return 0; } EOF -if { (eval echo configure:3748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3737: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3774,12 +3763,12 @@ fi for ac_func in socketpair do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3778: checking for $ac_func" >&5 +echo "configure:3767: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3783 "configure" +#line 3772 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -3802,7 +3791,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:3806: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3829,12 +3818,12 @@ done echo $ac_n "checking whether malloc must be declared""... $ac_c" 1>&6 -echo "configure:3833: checking whether malloc must be declared" >&5 +echo "configure:3822: checking whether malloc must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_malloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3838 "configure" +#line 3827 "configure" #include "confdefs.h" #include <stdio.h> @@ -3855,7 +3844,7 @@ int main() { char *(*pfn) = (char *(*)) malloc ; return 0; } EOF -if { (eval echo configure:3859: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3848: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_malloc=no else @@ -3876,12 +3865,12 @@ EOF fi echo $ac_n "checking whether realloc must be declared""... $ac_c" 1>&6 -echo "configure:3880: checking whether realloc must be declared" >&5 +echo "configure:3869: checking whether realloc must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_realloc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3885 "configure" +#line 3874 "configure" #include "confdefs.h" #include <stdio.h> @@ -3902,7 +3891,7 @@ int main() { char *(*pfn) = (char *(*)) realloc ; return 0; } EOF -if { (eval echo configure:3906: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3895: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_realloc=no else @@ -3923,12 +3912,12 @@ EOF fi echo $ac_n "checking whether free must be declared""... $ac_c" 1>&6 -echo "configure:3927: checking whether free must be declared" >&5 +echo "configure:3916: checking whether free must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_free'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3932 "configure" +#line 3921 "configure" #include "confdefs.h" #include <stdio.h> @@ -3949,7 +3938,7 @@ int main() { char *(*pfn) = (char *(*)) free ; return 0; } EOF -if { (eval echo configure:3953: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_free=no else @@ -3970,12 +3959,12 @@ EOF fi echo $ac_n "checking whether strerror must be declared""... $ac_c" 1>&6 -echo "configure:3974: checking whether strerror must be declared" >&5 +echo "configure:3963: checking whether strerror must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_strerror'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3979 "configure" +#line 3968 "configure" #include "confdefs.h" #include <stdio.h> @@ -3996,7 +3985,7 @@ int main() { char *(*pfn) = (char *(*)) strerror ; return 0; } EOF -if { (eval echo configure:4000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3989: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_strerror=no else @@ -4017,12 +4006,12 @@ EOF fi echo $ac_n "checking whether strdup must be declared""... $ac_c" 1>&6 -echo "configure:4021: checking whether strdup must be declared" >&5 +echo "configure:4010: checking whether strdup must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_strdup'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4026 "configure" +#line 4015 "configure" #include "confdefs.h" #include <stdio.h> @@ -4043,7 +4032,7 @@ int main() { char *(*pfn) = (char *(*)) strdup ; return 0; } EOF -if { (eval echo configure:4047: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4036: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_strdup=no else @@ -4064,12 +4053,12 @@ EOF fi echo $ac_n "checking whether strstr must be declared""... $ac_c" 1>&6 -echo "configure:4068: checking whether strstr must be declared" >&5 +echo "configure:4057: checking whether strstr must be declared" >&5 if eval "test \"`echo '$''{'bfd_cv_decl_needed_strstr'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4073 "configure" +#line 4062 "configure" #include "confdefs.h" #include <stdio.h> @@ -4090,7 +4079,7 @@ int main() { char *(*pfn) = (char *(*)) strstr ; return 0; } EOF -if { (eval echo configure:4094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4083: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_decl_needed_strstr=no else @@ -4117,9 +4106,9 @@ fi # could be expunged. --jsm 1999-03-22 echo $ac_n "checking for HPUX save_state structure""... $ac_c" 1>&6 -echo "configure:4121: checking for HPUX save_state structure" >&5 +echo "configure:4110: checking for HPUX save_state structure" >&5 cat > conftest.$ac_ext <<EOF -#line 4123 "configure" +#line 4112 "configure" #include "confdefs.h" #include <machine/save_state.h> EOF @@ -4134,7 +4123,7 @@ fi rm -f conftest* cat > conftest.$ac_ext <<EOF -#line 4138 "configure" +#line 4127 "configure" #include "confdefs.h" #include <machine/save_state.h> EOF @@ -4186,7 +4175,7 @@ EOF gdb_cv_hostos_is_solaris=yes ;; esac echo $ac_n "checking for directory proc entries""... $ac_c" 1>&6 -echo "configure:4190: checking for directory proc entries" >&5 +echo "configure:4179: checking for directory proc entries" >&5 # The [gdb_host != sun4sol2] hack is because Solaris does provide the # multiple procfs files as of Solaris 2.6, but GDB can't use it right now. if test "$ac_cv_header_sys_procfs_h" = yes -a \ @@ -4208,19 +4197,19 @@ fi if test "$ac_cv_header_sys_procfs_h" = yes; then echo $ac_n "checking for pstatus_t in sys/procfs.h""... $ac_c" 1>&6 -echo "configure:4212: checking for pstatus_t in sys/procfs.h" >&5 +echo "configure:4201: checking for pstatus_t in sys/procfs.h" >&5 if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_pstatus_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4217 "configure" +#line 4206 "configure" #include "confdefs.h" #include <sys/procfs.h> int main() { pstatus_t avar ; return 0; } EOF -if { (eval echo configure:4224: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4213: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_have_sys_procfs_type_pstatus_t=yes else @@ -4242,19 +4231,19 @@ EOF echo "$ac_t""$bfd_cv_have_sys_procfs_type_pstatus_t" 1>&6 echo $ac_n "checking for prrun_t in sys/procfs.h""... $ac_c" 1>&6 -echo "configure:4246: checking for prrun_t in sys/procfs.h" >&5 +echo "configure:4235: checking for prrun_t in sys/procfs.h" >&5 if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_prrun_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4251 "configure" +#line 4240 "configure" #include "confdefs.h" #include <sys/procfs.h> int main() { prrun_t avar ; return 0; } EOF -if { (eval echo configure:4258: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4247: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_have_sys_procfs_type_prrun_t=yes else @@ -4276,19 +4265,19 @@ EOF echo "$ac_t""$bfd_cv_have_sys_procfs_type_prrun_t" 1>&6 echo $ac_n "checking for gregset_t in sys/procfs.h""... $ac_c" 1>&6 -echo "configure:4280: checking for gregset_t in sys/procfs.h" >&5 +echo "configure:4269: checking for gregset_t in sys/procfs.h" >&5 if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_gregset_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4285 "configure" +#line 4274 "configure" #include "confdefs.h" #include <sys/procfs.h> int main() { gregset_t avar ; return 0; } EOF -if { (eval echo configure:4292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_have_sys_procfs_type_gregset_t=yes else @@ -4310,19 +4299,19 @@ EOF echo "$ac_t""$bfd_cv_have_sys_procfs_type_gregset_t" 1>&6 echo $ac_n "checking for fpregset_t in sys/procfs.h""... $ac_c" 1>&6 -echo "configure:4314: checking for fpregset_t in sys/procfs.h" >&5 +echo "configure:4303: checking for fpregset_t in sys/procfs.h" >&5 if eval "test \"`echo '$''{'bfd_cv_have_sys_procfs_type_fpregset_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4319 "configure" +#line 4308 "configure" #include "confdefs.h" #include <sys/procfs.h> int main() { fpregset_t avar ; return 0; } EOF -if { (eval echo configure:4326: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4315: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* bfd_cv_have_sys_procfs_type_fpregset_t=yes else @@ -4346,12 +4335,12 @@ EOF echo $ac_n "checking for PIOCSET ioctl entry in sys/procfs.h""... $ac_c" 1>&6 -echo "configure:4350: checking for PIOCSET ioctl entry in sys/procfs.h" >&5 +echo "configure:4339: checking for PIOCSET ioctl entry in sys/procfs.h" >&5 if eval "test \"`echo '$''{'gdb_cv_have_procfs_piocset'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4355 "configure" +#line 4344 "configure" #include "confdefs.h" #include <unistd.h> #include <sys/types.h> @@ -4364,7 +4353,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:4368: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4357: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gdb_cv_have_procfs_piocset=yes else @@ -4386,7 +4375,7 @@ EOF fi echo $ac_n "checking for main in -lm""... $ac_c" 1>&6 -echo "configure:4390: checking for main in -lm" >&5 +echo "configure:4379: checking for main in -lm" >&5 ac_lib_var=`echo m'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4394,14 +4383,14 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <<EOF -#line 4398 "configure" +#line 4387 "configure" #include "confdefs.h" int main() { main() ; return 0; } EOF -if { (eval echo configure:4405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4430,7 +4419,7 @@ fi echo $ac_n "checking for wctype in -lc""... $ac_c" 1>&6 -echo "configure:4434: checking for wctype in -lc" >&5 +echo "configure:4423: checking for wctype in -lc" >&5 ac_lib_var=`echo c'_'wctype | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4438,7 +4427,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lc $LIBS" cat > conftest.$ac_ext <<EOF -#line 4442 "configure" +#line 4431 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -4449,7 +4438,7 @@ int main() { wctype() ; return 0; } EOF -if { (eval echo configure:4453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4442: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4468,7 +4457,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for wctype in -lw""... $ac_c" 1>&6 -echo "configure:4472: checking for wctype in -lw" >&5 +echo "configure:4461: checking for wctype in -lw" >&5 ac_lib_var=`echo w'_'wctype | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4476,7 +4465,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lw $LIBS" cat > conftest.$ac_ext <<EOF -#line 4480 "configure" +#line 4469 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -4487,7 +4476,7 @@ int main() { wctype() ; return 0; } EOF -if { (eval echo configure:4491: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4480: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4519,12 +4508,12 @@ fi echo $ac_n "checking for long long support in compiler""... $ac_c" 1>&6 -echo "configure:4523: checking for long long support in compiler" >&5 +echo "configure:4512: checking for long long support in compiler" >&5 if eval "test \"`echo '$''{'gdb_cv_c_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4528 "configure" +#line 4517 "configure" #include "confdefs.h" int main() { @@ -4534,7 +4523,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:4538: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4527: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gdb_cv_c_long_long=yes else @@ -4556,7 +4545,7 @@ fi echo $ac_n "checking for long long support in printf""... $ac_c" 1>&6 -echo "configure:4560: checking for long long support in printf" >&5 +echo "configure:4549: checking for long long support in printf" >&5 if eval "test \"`echo '$''{'gdb_cv_printf_has_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4564,7 +4553,7 @@ else gdb_cv_printf_has_long_long=no else cat > conftest.$ac_ext <<EOF -#line 4568 "configure" +#line 4557 "configure" #include "confdefs.h" int main () { @@ -4578,7 +4567,7 @@ int main () { return (strcmp ("0x0123456789abcdef", buf)); } EOF -if { (eval echo configure:4582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then gdb_cv_printf_has_long_long=yes else @@ -4602,19 +4591,19 @@ echo "$ac_t""$gdb_cv_printf_has_long_long" 1>&6 echo $ac_n "checking for long double support in compiler""... $ac_c" 1>&6 -echo "configure:4606: checking for long double support in compiler" >&5 +echo "configure:4595: checking for long double support in compiler" >&5 if eval "test \"`echo '$''{'ac_cv_c_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4611 "configure" +#line 4600 "configure" #include "confdefs.h" int main() { long double foo; ; return 0; } EOF -if { (eval echo configure:4618: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4607: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_long_double=yes else @@ -4636,7 +4625,7 @@ fi echo $ac_n "checking for long double support in printf""... $ac_c" 1>&6 -echo "configure:4640: checking for long double support in printf" >&5 +echo "configure:4629: checking for long double support in printf" >&5 if eval "test \"`echo '$''{'gdb_cv_printf_has_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4644,7 +4633,7 @@ else gdb_cv_printf_has_long_double=no else cat > conftest.$ac_ext <<EOF -#line 4648 "configure" +#line 4637 "configure" #include "confdefs.h" int main () { @@ -4654,7 +4643,7 @@ int main () { return (strncmp ("3.14159", buf, 7)); } EOF -if { (eval echo configure:4658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4647: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then gdb_cv_printf_has_long_double=yes else @@ -4678,7 +4667,7 @@ echo "$ac_t""$gdb_cv_printf_has_long_double" 1>&6 echo $ac_n "checking for long double support in scanf""... $ac_c" 1>&6 -echo "configure:4682: checking for long double support in scanf" >&5 +echo "configure:4671: checking for long double support in scanf" >&5 if eval "test \"`echo '$''{'gdb_cv_scanf_has_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4686,7 +4675,7 @@ else gdb_cv_scanf_has_long_double=no else cat > conftest.$ac_ext <<EOF -#line 4690 "configure" +#line 4679 "configure" #include "confdefs.h" int main () { @@ -4696,7 +4685,7 @@ int main () { return !(f > 3.14159 && f < 3.14160); } EOF -if { (eval echo configure:4700: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then gdb_cv_scanf_has_long_double=yes else @@ -4722,17 +4711,17 @@ for ac_hdr in unistd.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4726: checking for $ac_hdr" >&5 +echo "configure:4715: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4731 "configure" +#line 4720 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4736: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4725: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4761,12 +4750,12 @@ done for ac_func in getpagesize do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4765: checking for $ac_func" >&5 +echo "configure:4754: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 4770 "configure" +#line 4759 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -4789,7 +4778,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:4793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4814,7 +4803,7 @@ fi done echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:4818: checking for working mmap" >&5 +echo "configure:4807: checking for working mmap" >&5 if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4822,7 +4811,7 @@ else ac_cv_func_mmap_fixed_mapped=no else cat > conftest.$ac_ext <<EOF -#line 4826 "configure" +#line 4815 "configure" #include "confdefs.h" /* Thanks to Mike Haertel and Jim Avera for this test. @@ -4962,7 +4951,7 @@ main() } EOF -if { (eval echo configure:4966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_mmap_fixed_mapped=yes else @@ -4991,7 +4980,7 @@ if test ${build} = ${host} -a ${host} = ${target} ; then case ${host_os} in hpux*) echo $ac_n "checking for HPUX/OSF thread support""... $ac_c" 1>&6 -echo "configure:4995: checking for HPUX/OSF thread support" >&5 +echo "configure:4984: checking for HPUX/OSF thread support" >&5 if test -f /usr/include/dce/cma_config.h ; then if test "$GCC" = "yes" ; then echo "$ac_t""yes" 1>&6 @@ -5010,7 +4999,7 @@ EOF ;; solaris*) echo $ac_n "checking for Solaris thread debugging library""... $ac_c" 1>&6 -echo "configure:5014: checking for Solaris thread debugging library" >&5 +echo "configure:5003: checking for Solaris thread debugging library" >&5 if test -f /usr/lib/libthread_db.so.1 ; then echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -5020,7 +5009,7 @@ EOF CONFIG_OBS="${CONFIG_OBS} sol-thread.o" CONFIG_SRCS="${CONFIG_SRCS} sol-thread.c" echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:5024: checking for dlopen in -ldl" >&5 +echo "configure:5013: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5028,7 +5017,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <<EOF -#line 5032 "configure" +#line 5021 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5039,7 +5028,7 @@ int main() { dlopen() ; return 0; } EOF -if { (eval echo configure:5043: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5071,17 +5060,17 @@ fi # all symbols visible in the dynamic symbol table. hold_ldflags=$LDFLAGS echo $ac_n "checking for the ld -export-dynamic flag""... $ac_c" 1>&6 -echo "configure:5075: checking for the ld -export-dynamic flag" >&5 +echo "configure:5064: checking for the ld -export-dynamic flag" >&5 LDFLAGS="${LDFLAGS} -Wl,-export-dynamic" cat > conftest.$ac_ext <<EOF -#line 5078 "configure" +#line 5067 "configure" #include "confdefs.h" int main() { int i; ; return 0; } EOF -if { (eval echo configure:5085: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* found=yes else @@ -5100,13 +5089,13 @@ rm -f conftest* # Sun randomly tweaked the prototypes in <proc_service.h> # at one point. echo $ac_n "checking if <proc_service.h> is old""... $ac_c" 1>&6 -echo "configure:5104: checking if <proc_service.h> is old" >&5 +echo "configure:5093: checking if <proc_service.h> is old" >&5 if eval "test \"`echo '$''{'gdb_cv_proc_service_is_old'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5110 "configure" +#line 5099 "configure" #include "confdefs.h" #include <proc_service.h> @@ -5117,7 +5106,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:5121: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5110: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* gdb_cv_proc_service_is_old=no else @@ -5263,12 +5252,12 @@ fi # In the Cygwin environment, we need some additional flags. echo $ac_n "checking for cygwin""... $ac_c" 1>&6 -echo "configure:5390: checking for cygwin" >&5 +echo "configure:5379: checking for cygwin" >&5 if eval "test \"`echo '$''{'gdb_cv_os_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5395 "configure" +#line 5384 "configure" #include "confdefs.h" #if defined (__CYGWIN__) || defined (__CYGWIN32__) @@ -5302,7 +5291,7 @@ if test x$gdb_cv_os_cygwin = xyes; then else TERM_LIB= echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 -echo "configure:5429: checking for tgetent in -lncurses" >&5 +echo "configure:5418: checking for tgetent in -lncurses" >&5 ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5310,7 +5299,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <<EOF -#line 5437 "configure" +#line 5426 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5321,7 +5310,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5437: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5340,7 +5329,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lHcurses""... $ac_c" 1>&6 -echo "configure:5467: checking for tgetent in -lHcurses" >&5 +echo "configure:5456: checking for tgetent in -lHcurses" >&5 ac_lib_var=`echo Hcurses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5348,7 +5337,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lHcurses $LIBS" cat > conftest.$ac_ext <<EOF -#line 5475 "configure" +#line 5464 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5359,7 +5348,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5378,7 +5367,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -ltermlib""... $ac_c" 1>&6 -echo "configure:5505: checking for tgetent in -ltermlib" >&5 +echo "configure:5494: checking for tgetent in -ltermlib" >&5 ac_lib_var=`echo termlib'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5386,7 +5375,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ltermlib $LIBS" cat > conftest.$ac_ext <<EOF -#line 5513 "configure" +#line 5502 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5397,7 +5386,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5416,7 +5405,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 -echo "configure:5543: checking for tgetent in -ltermcap" >&5 +echo "configure:5532: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5424,7 +5413,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ltermcap $LIBS" cat > conftest.$ac_ext <<EOF -#line 5551 "configure" +#line 5540 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5435,7 +5424,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5454,7 +5443,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 -echo "configure:5581: checking for tgetent in -lcurses" >&5 +echo "configure:5570: checking for tgetent in -lcurses" >&5 ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5462,7 +5451,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lcurses $LIBS" cat > conftest.$ac_ext <<EOF -#line 5589 "configure" +#line 5578 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5473,7 +5462,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5492,7 +5481,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -lterminfo""... $ac_c" 1>&6 -echo "configure:5619: checking for tgetent in -lterminfo" >&5 +echo "configure:5608: checking for tgetent in -lterminfo" >&5 ac_lib_var=`echo terminfo'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5500,7 +5489,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lterminfo $LIBS" cat > conftest.$ac_ext <<EOF -#line 5627 "configure" +#line 5616 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -5511,7 +5500,7 @@ int main() { tgetent() ; return 0; } EOF -if { (eval echo configure:5638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5563,7 +5552,7 @@ fi # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 -echo "configure:6774: checking for X" >&5 +echo "configure:6763: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -5625,12 +5614,12 @@ if test "$ac_x_includes" = NO; then # First, try using that file with no special directory specified. cat > conftest.$ac_ext <<EOF -#line 6836 "configure" +#line 6825 "configure" #include "confdefs.h" #include <$x_direct_test_include> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6830: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5699,14 +5688,14 @@ if test "$ac_x_libraries" = NO; then ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <<EOF -#line 6910 "configure" +#line 6899 "configure" #include "confdefs.h" int main() { ${x_direct_test_function}() ; return 0; } EOF -if { (eval echo configure:6917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. @@ -5986,12 +5975,12 @@ fi echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 -echo "configure:7268: checking for Cygwin environment" >&5 +echo "configure:7257: checking for Cygwin environment" >&5 if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 7273 "configure" +#line 7262 "configure" #include "confdefs.h" int main() { @@ -6002,7 +5991,7 @@ int main() { return __CYGWIN__; ; return 0; } EOF -if { (eval echo configure:7284: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7273: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else @@ -6019,19 +6008,19 @@ echo "$ac_t""$ac_cv_cygwin" 1>&6 CYGWIN= test "$ac_cv_cygwin" = yes && CYGWIN=yes echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 -echo "configure:7301: checking for mingw32 environment" >&5 +echo "configure:7290: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 7306 "configure" +#line 7295 "configure" #include "confdefs.h" int main() { return __MINGW32__; ; return 0; } EOF -if { (eval echo configure:7313: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7302: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else @@ -6050,7 +6039,7 @@ test "$ac_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:7332: checking for executable suffix" >&5 +echo "configure:7321: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6060,10 +6049,10 @@ else rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= - if { (eval echo configure:7342: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + if { (eval echo configure:7331: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in - *.c | *.o | *.obj | *.ilk | *.pdb) ;; + *.c | *.o | *.obj) ;; *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; esac done diff --git a/gdb/configure.host b/gdb/configure.host index b1160018cb1..30fce818efc 100644 --- a/gdb/configure.host +++ b/gdb/configure.host @@ -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 ;; diff --git a/gdb/configure.in b/gdb/configure.in index 3dae4a3070c..0377402b5ca 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -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) diff --git a/gdb/configure.tgt b/gdb/configure.tgt index a80a5b6a372..e25b363b544 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -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 ;; diff --git a/gdb/defs.h b/gdb/defs.h index 7825680953f..27c24c891f8 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -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 diff --git a/gdb/gdb-events.c b/gdb/gdb-events.c index a8c41925de7..3a4f497d128 100644 --- a/gdb/gdb-events.c +++ b/gdb/gdb-events.c @@ -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 diff --git a/gdb/gdb-events.h b/gdb/gdb-events.h index 3985ffed85c..c98af7a4f63 100644 --- a/gdb/gdb-events.h +++ b/gdb/gdb-events.h @@ -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); diff --git a/gdb/gdb-events.sh b/gdb/gdb-events.sh index 620322d932c..6b9dc810aad 100755 --- a/gdb/gdb-events.sh +++ b/gdb/gdb-events.sh @@ -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 diff --git a/gdb/gdb_proc_service.h b/gdb/gdb_proc_service.h new file mode 100644 index 00000000000..dfbf9647d0e --- /dev/null +++ b/gdb/gdb_proc_service.h @@ -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. */ diff --git a/gdb/gdb_thread_db.h b/gdb/gdb_thread_db.h new file mode 100644 index 00000000000..5bb196344b1 --- /dev/null +++ b/gdb/gdb_thread_db.h @@ -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 */ diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c index 24c0a009617..de5631b7987 100644 --- a/gdb/gnu-nat.c +++ b/gdb/gnu-nat.c @@ -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; diff --git a/gdb/hp-psymtab-read.c b/gdb/hp-psymtab-read.c index 7d533050e6f..d3d0ff2eeff 100644 --- a/gdb/hp-psymtab-read.c +++ b/gdb/hp-psymtab-read.c @@ -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 diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c index 643232c9116..abc55fcd933 100644 --- a/gdb/hppah-nat.c +++ b/gdb/hppah-nat.c @@ -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 diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index cec0f8ebb11..2b350f07b2c 100644 --- a/gdb/i386-linux-nat.c +++ b/gdb/i386-linux-nat.c @@ -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; } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 726c80d63f4..489e3b1e122 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -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); diff --git a/gdb/infptrace.c b/gdb/infptrace.c index 8984b0c6829..d8463e67246 100644 --- a/gdb/infptrace.c +++ b/gdb/infptrace.c @@ -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; diff --git a/gdb/inftarg.c b/gdb/inftarg.c index fb31ffb143f..01c5b474c46 100644 --- a/gdb/inftarg.c +++ b/gdb/inftarg.c @@ -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; diff --git a/gdb/infttrace.c b/gdb/infttrace.c index 626d8135660..cf4b12ca82f 100644 --- a/gdb/infttrace.c +++ b/gdb/infttrace.c @@ -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)); diff --git a/gdb/language.c b/gdb/language.c index be248ea990d..05f710f4f67 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -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); } diff --git a/gdb/lin-thread.c b/gdb/lin-thread.c new file mode 100644 index 00000000000..2f255c0e54a --- /dev/null +++ b/gdb/lin-thread.c @@ -0,0 +1,2140 @@ +/* Multi-threaded debugging support for the thread_db interface, + used on operating systems such as Solaris and 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. */ + +/* This module implements a thread_stratum target that sits on top of + a normal process_stratum target (such as procfs or ptrace). The + process_stratum target must install this thread_stratum target when + it detects the presence of the thread_db shared library. + + This module will then use the thread_db API to add thread-awareness + to the functionality provided by the process_stratum target (or in + some cases, to add user-level thread awareness on top of the + kernel-level thread awareness that is already provided by the + process_stratum target). + + Solaris threads (for instance) are a multi-level thread implementation; + the kernel provides a Light Weight Process (LWP) which the procfs + process_stratum module is aware of. This module must then mediate + the relationship between kernel LWP threads and user (eg. posix) + threads. + + Linux threads are likely to be different -- but the thread_db + library API should make the difference largely transparent to GDB. + + */ + +/* The thread_db API provides a number of functions that give the caller + access to the inner workings of the child process's thread library. + We will be using the following (others may be added): + + td_thr_validate Confirm valid "live" thread + td_thr_get_info Get info about a thread + td_thr_getgregs Get thread's general registers + td_thr_getfpregs Get thread's floating point registers + td_thr_setgregs Set thread's general registers + td_thr_setfpregs Set thread's floating point registers + td_ta_map_id2thr Get thread handle from thread id + td_ta_map_lwp2thr Get thread handle from LWP id + td_ta_thr_iter Iterate over all threads (with callback) + + In return, the debugger has to provide certain services to the + thread_db library. Some of these aren't actually required to do + anything in practice. For instance, the thread_db expects to be + able to stop the child process and start it again: but in our + context, the child process will always be stopped already when we + invoke the thread_db library, so the functions that we provide for + the library to stop and start the child process are no-ops. + + Here is the list of functions which we export to the thread_db + library, divided into no-op functions vs. functions that actually + have to do something: + + No-op functions: + + ps_pstop Stop the child process + ps_pcontinue Continue the child process + ps_lstop Stop a specific LWP (kernel thread) + ps_lcontinue Continue an LWP + ps_lgetxregsize Get size of LWP's xregs (sparc) + ps_lgetxregs Get LWP's xregs (sparc) + ps_lsetxregs Set LWP's xregs (sparc) + + Functions that have to do useful work: + + ps_pglobal_lookup Get the address of a global symbol + ps_pdread Read memory, data segment + ps_ptread Read memory, text segment + ps_pdwrite Write memory, data segment + ps_ptwrite Write memory, text segment + ps_lgetregs Get LWP's general registers + ps_lgetfpregs Get LWP's floating point registers + ps_lsetregs Set LWP's general registers + ps_lsetfpregs Set LWP's floating point registers + ps_lgetLDT Get LWP's Local Descriptor Table (x86) + + Thus, if we ask the thread_db library to give us the general registers + for user thread X, thread_db may figure out that user thread X is + actually mapped onto kernel thread Y. Thread_db does not know how + to obtain the registers for kernel thread Y, but GDB does, so thread_db + turns the request right back to us via the ps_lgetregs callback. */ + +#include "defs.h" +#include "gdbthread.h" +#include "target.h" +#include "inferior.h" +#include "gdbcmd.h" + +#ifdef HAVE_WAIT_H +#include <wait.h> +#else +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#endif + +/* "wait.h" fills in the gaps left by <wait.h> */ +#include "wait.h" + +#include <time.h> + +#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T) +#include <sys/procfs.h> +#endif + +#if defined (HAVE_PROC_SERVICE_H) +#include <proc_service.h> /* defines incoming API (ps_* callbacks) */ +#else +#include "gdb_proc_service.h" +#endif + +#if defined HAVE_STDINT_H /* Pre-5.2 systems don't have this header */ +#if defined (HAVE_THREAD_DB_H) +#include <thread_db.h> /* defines outgoing API (td_thr_* calls) */ +#else +#include "gdb_thread_db.h" +#endif + +#include <dlfcn.h> /* dynamic library interface */ + +#ifndef TIDGET +#define TIDGET(PID) (((PID) & 0x7fffffff) >> 16) +#define PIDGET(PID) (((PID) & 0xffff)) +#define MERGEPID(PID, TID) (((PID) & 0xffff) | ((TID) << 16)) +#endif + +/* Macros for superimposing PID and TID into inferior_pid. */ +#define THREAD_FLAG 0x80000000 +#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0) +#define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0) +#define GET_LWP(PID) TIDGET (PID) +#define GET_THREAD(PID) TIDGET (PID) +#define BUILD_LWP(TID, PID) MERGEPID (PID, TID) +#define BUILD_THREAD(TID, PID) (MERGEPID (PID, TID) | THREAD_FLAG) + +/* + * target_beneath is a pointer to the target_ops underlying this one. + */ + +static struct target_ops *target_beneath; + + +/* + * target vector defined in this module: + */ + +static struct target_ops thread_db_ops; + +/* + * Typedefs required to resolve differences between the thread_db + * and proc_service API defined on different versions of Solaris: + */ + +#if defined(PROC_SERVICE_IS_OLD) +typedef const struct ps_prochandle *gdb_ps_prochandle_t; +typedef char *gdb_ps_read_buf_t; +typedef char *gdb_ps_write_buf_t; +typedef int gdb_ps_size_t; +#else +typedef struct ps_prochandle *gdb_ps_prochandle_t; +typedef void *gdb_ps_read_buf_t; +typedef const void *gdb_ps_write_buf_t; +typedef size_t gdb_ps_size_t; +#endif + +/* + * proc_service callback functions, called by thread_db. + */ + +ps_err_e +ps_pstop (gdb_ps_prochandle_t ph) /* Process stop */ +{ + return PS_OK; +} + +ps_err_e +ps_pcontinue (gdb_ps_prochandle_t ph) /* Process continue */ +{ + return PS_OK; +} + +ps_err_e +ps_lstop (gdb_ps_prochandle_t ph, /* LWP stop */ + lwpid_t lwpid) +{ + return PS_OK; +} + +ps_err_e +ps_lcontinue (gdb_ps_prochandle_t ph, /* LWP continue */ + lwpid_t lwpid) +{ + return PS_OK; +} + +ps_err_e +ps_lgetxregsize (gdb_ps_prochandle_t ph, /* Get XREG size */ + lwpid_t lwpid, + int *xregsize) +{ + return PS_OK; +} + +ps_err_e +ps_lgetxregs (gdb_ps_prochandle_t ph, /* Get XREGS */ + lwpid_t lwpid, + caddr_t xregset) +{ + return PS_OK; +} + +ps_err_e +ps_lsetxregs (gdb_ps_prochandle_t ph, /* Set XREGS */ + lwpid_t lwpid, + caddr_t xregset) +{ + return PS_OK; +} + +void +ps_plog (const char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + vfprintf_filtered (gdb_stderr, fmt, args); +} + +/* Look up a symbol in GDB's global symbol table. + Return the symbol's address. + FIXME: it would be more correct to look up the symbol in the context + of the LD_OBJECT_NAME provided. However we're probably fairly safe + as long as there aren't name conflicts with other libraries. */ + +ps_err_e +ps_pglobal_lookup (gdb_ps_prochandle_t ph, + const char *ld_object_name, /* the library name */ + const char *ld_symbol_name, /* the symbol name */ + paddr_t *ld_symbol_addr) /* return the symbol addr */ +{ + struct minimal_symbol *ms; + + ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL); + + if (!ms) + return PS_NOSYM; + + *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms); + + return PS_OK; +} + +/* Worker function for all memory reads and writes: */ +static ps_err_e rw_common (const struct ps_prochandle *ph, + paddr_t addr, + char *buf, + int size, + int write_p); + +/* target_xfer_memory direction consts */ +enum {PS_READ = 0, PS_WRITE = 1}; + +ps_err_e +ps_pdread (gdb_ps_prochandle_t ph, /* read from data segment */ + paddr_t addr, + gdb_ps_read_buf_t buf, + gdb_ps_size_t size) +{ + return rw_common (ph, addr, buf, size, PS_READ); +} + +ps_err_e +ps_pdwrite (gdb_ps_prochandle_t ph, /* write to data segment */ + paddr_t addr, + gdb_ps_write_buf_t buf, + gdb_ps_size_t size) +{ + return rw_common (ph, addr, (char *) buf, size, PS_WRITE); +} + +ps_err_e +ps_ptread (gdb_ps_prochandle_t ph, /* read from text segment */ + paddr_t addr, + gdb_ps_read_buf_t buf, + gdb_ps_size_t size) +{ + return rw_common (ph, addr, buf, size, PS_READ); +} + +ps_err_e +ps_ptwrite (gdb_ps_prochandle_t ph, /* write to text segment */ + paddr_t addr, + gdb_ps_write_buf_t buf, + gdb_ps_size_t size) +{ + return rw_common (ph, addr, (char *) buf, size, PS_WRITE); +} + +static struct cleanup *save_inferior_pid (void); +static void restore_inferior_pid (void *saved_pid); +static char *thr_err_string (td_err_e); +static char *thr_state_string (td_thr_state_e); + +struct ps_prochandle { + int pid; +}; + +struct ps_prochandle main_prochandle; +td_thragent_t * main_threadagent; + +/* + * Common proc_service routine for reading and writing memory. + */ + +/* FIXME: once we've munged the inferior_pid, why can't we + simply call target_read/write_memory and return? */ + + +static ps_err_e +rw_common (const struct ps_prochandle *ph, + paddr_t addr, + char *buf, + int size, + int write_p) +{ + struct cleanup *old_chain = save_inferior_pid (); + int to_do = size; + int done = 0; + + inferior_pid = main_prochandle.pid; + + while (to_do > 0) + { + done = current_target.to_xfer_memory (addr, buf, size, write_p, + ¤t_target); + if (done <= 0) + { + if (write_p == PS_READ) + print_sys_errmsg ("rw_common (): read", errno); + else + print_sys_errmsg ("rw_common (): write", errno); + + return PS_ERR; + } + to_do -= done; + buf += done; + } + do_cleanups (old_chain); + return PS_OK; +} + +/* Cleanup functions used by the register callbacks + (which have to manipulate the global inferior_pid). */ + +ps_err_e +ps_lgetregs (gdb_ps_prochandle_t ph, /* Get LWP general regs */ + lwpid_t lwpid, + prgregset_t gregset) +{ + struct cleanup *old_chain = save_inferior_pid (); + + inferior_pid = BUILD_LWP (lwpid, main_prochandle.pid); + current_target.to_fetch_registers (-1); + + fill_gregset (gregset, -1); + do_cleanups (old_chain); + + return PS_OK; +} + +ps_err_e +ps_lsetregs (gdb_ps_prochandle_t ph, /* Set LWP general regs */ + lwpid_t lwpid, + const prgregset_t gregset) +{ + struct cleanup *old_chain = save_inferior_pid (); + + inferior_pid = BUILD_LWP (lwpid, main_prochandle.pid); + supply_gregset (gregset); + current_target.to_store_registers (-1); + do_cleanups (old_chain); + return PS_OK; +} + +ps_err_e +ps_lgetfpregs (gdb_ps_prochandle_t ph, /* Get LWP float regs */ + lwpid_t lwpid, + prfpregset_t *fpregset) +{ + struct cleanup *old_chain = save_inferior_pid (); + + inferior_pid = BUILD_LWP (lwpid, main_prochandle.pid); + current_target.to_fetch_registers (-1); + fill_fpregset (fpregset, -1); + do_cleanups (old_chain); + return PS_OK; +} + +ps_err_e +ps_lsetfpregs (gdb_ps_prochandle_t ph, /* Set LWP float regs */ + lwpid_t lwpid, + const prfpregset_t *fpregset) +{ + struct cleanup *old_chain = save_inferior_pid (); + + inferior_pid = BUILD_LWP (lwpid, main_prochandle.pid); + supply_fpregset (fpregset); + current_target.to_store_registers (-1); + do_cleanups (old_chain); + return PS_OK; +} + +/* + * ps_getpid + * + * return the main pid for the child process + * (special for Linux -- not used on Solaris) + */ + +pid_t +ps_getpid (gdb_ps_prochandle_t ph) +{ + return ph->pid; +} + +#ifdef TM_I386SOL2_H + +/* Reads the local descriptor table of a LWP. */ + +ps_err_e +ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid, + struct ssd *pldt) +{ + /* NOTE: only used on Solaris, therefore OK to refer to procfs.c */ + extern struct ssd *procfs_find_LDT_entry (int); + struct ssd *ret; + + ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, + PIDGET (main_prochandle.pid))); + if (ret) + { + memcpy (pldt, ret, sizeof (struct ssd)); + return PS_OK; + } + else /* LDT not found. */ + return PS_ERR; +} +#endif /* TM_I386SOL2_H */ + +/* + * Pointers to thread_db functions: + * + * These are a dynamic library mechanism. + * The dlfcn.h interface will be used to initialize these + * so that they point to the appropriate functions in the + * thread_db dynamic library. This is done dynamically + * so that GDB can still run on systems that lack thread_db. + */ + +static td_err_e (*p_td_init) (void); + +static td_err_e (*p_td_ta_new) (const struct ps_prochandle *ph_p, + td_thragent_t **ta_pp); + +static td_err_e (*p_td_ta_delete) (td_thragent_t *ta_p); + +static td_err_e (*p_td_ta_get_nthreads) (const td_thragent_t *ta_p, + int *nthread_p); + + +static td_err_e (*p_td_ta_thr_iter) (const td_thragent_t *ta_p, + td_thr_iter_f *cb, + void *cbdata_p, + td_thr_state_e state, + int ti_pri, + sigset_t *ti_sigmask_p, + unsigned ti_user_flags); + +static td_err_e (*p_td_ta_event_addr) (const td_thragent_t *ta_p, + u_long event, + td_notify_t *notify_p); + +static td_err_e (*p_td_ta_event_getmsg) (const td_thragent_t *ta_p, + td_event_msg_t *msg); + +static td_err_e (*p_td_ta_set_event) (const td_thragent_t *ta_p, + td_thr_events_t *events); + +static td_err_e (*p_td_thr_validate) (const td_thrhandle_t *th_p); + +static td_err_e (*p_td_thr_event_enable) (const td_thrhandle_t *th_p, + int on_off); + +static td_err_e (*p_td_thr_get_info) (const td_thrhandle_t *th_p, + td_thrinfo_t *ti_p); + +static td_err_e (*p_td_thr_getgregs) (const td_thrhandle_t *th_p, + prgregset_t regset); + +static td_err_e (*p_td_thr_setgregs) (const td_thrhandle_t *th_p, + const prgregset_t regset); + +static td_err_e (*p_td_thr_getfpregs) (const td_thrhandle_t *th_p, + prfpregset_t *fpregset); + +static td_err_e (*p_td_thr_setfpregs) (const td_thrhandle_t *th_p, + const prfpregset_t *fpregset); + +static td_err_e (*p_td_ta_map_id2thr) (const td_thragent_t *ta_p, + thread_t tid, + td_thrhandle_t *th_p); + +static td_err_e (*p_td_ta_map_lwp2thr) (const td_thragent_t *ta_p, + lwpid_t lwpid, + td_thrhandle_t *th_p); + +/* + * API and target vector initialization function: thread_db_initialize. + * + * NOTE: this function is deliberately NOT named with the GDB convention + * of module initializer function names that begin with "_initialize". + * This module is NOT intended to be auto-initialized at GDB startup. + * Rather, it will only be initialized when a multi-threaded child + * process is detected. + * + */ + +/* + * Initializer for thread_db library interface. + * This function does the dynamic library stuff (dlopen, dlsym), + * and then calls the thread_db library's one-time initializer + * function (td_init). If everything succeeds, this function + * returns true; otherwise it returns false, and this module + * cannot be used. + */ + +static int +init_thread_db_library () +{ + void *dlhandle; + td_err_e ret; + + /* Open a handle to the "thread_db" dynamic library. */ + if ((dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW)) == NULL) + return 0; /* fail */ + + /* Initialize pointers to the dynamic library functions we will use. + * Note that we are not calling the functions here -- we are only + * establishing pointers to them. + */ + + /* td_init: initialize thread_db library. */ + if ((p_td_init = dlsym (dlhandle, "td_init")) == NULL) + return 0; /* fail */ + /* td_ta_new: register a target process with thread_db. */ + if ((p_td_ta_new = dlsym (dlhandle, "td_ta_new")) == NULL) + return 0; /* fail */ + /* td_ta_delete: un-register a target process with thread_db. */ + if ((p_td_ta_delete = dlsym (dlhandle, "td_ta_delete")) == NULL) + return 0; /* fail */ + + /* td_ta_map_id2thr: get thread handle from thread id. */ + if ((p_td_ta_map_id2thr = dlsym (dlhandle, "td_ta_map_id2thr")) == NULL) + return 0; /* fail */ + /* td_ta_map_lwp2thr: get thread handle from lwp id. */ + if ((p_td_ta_map_lwp2thr = dlsym (dlhandle, "td_ta_map_lwp2thr")) == NULL) + return 0; /* fail */ + /* td_ta_get_nthreads: get number of threads in target process. */ + if ((p_td_ta_get_nthreads = dlsym (dlhandle, "td_ta_get_nthreads")) == NULL) + return 0; /* fail */ + /* td_ta_thr_iter: iterate over all thread handles. */ + if ((p_td_ta_thr_iter = dlsym (dlhandle, "td_ta_thr_iter")) == NULL) + return 0; /* fail */ + + /* td_thr_validate: make sure a thread handle is real and alive. */ + if ((p_td_thr_validate = dlsym (dlhandle, "td_thr_validate")) == NULL) + return 0; /* fail */ + /* td_thr_get_info: get a bunch of info about a thread. */ + if ((p_td_thr_get_info = dlsym (dlhandle, "td_thr_get_info")) == NULL) + return 0; /* fail */ + /* td_thr_getgregs: get general registers for thread. */ + if ((p_td_thr_getgregs = dlsym (dlhandle, "td_thr_getgregs")) == NULL) + return 0; /* fail */ + /* td_thr_setgregs: set general registers for thread. */ + if ((p_td_thr_setgregs = dlsym (dlhandle, "td_thr_setgregs")) == NULL) + return 0; /* fail */ + /* td_thr_getfpregs: get floating point registers for thread. */ + if ((p_td_thr_getfpregs = dlsym (dlhandle, "td_thr_getfpregs")) == NULL) + return 0; /* fail */ + /* td_thr_setfpregs: set floating point registers for thread. */ + if ((p_td_thr_setfpregs = dlsym (dlhandle, "td_thr_setfpregs")) == NULL) + return 0; /* fail */ + + ret = p_td_init (); + if (ret != TD_OK) + { + warning ("init_thread_db: td_init: %s", thr_err_string (ret)); + return 0; + } + + /* Optional functions: + We can still debug even if the following functions are not found. */ + + /* td_ta_event_addr: get the breakpoint address for specified event. */ + p_td_ta_event_addr = dlsym (dlhandle, "td_ta_event_addr"); + + /* td_ta_event_getmsg: get the next event message for the process. */ + p_td_ta_event_getmsg = dlsym (dlhandle, "td_ta_event_getmsg"); + + /* td_ta_set_event: request notification of an event. */ + p_td_ta_set_event = dlsym (dlhandle, "td_ta_set_event"); + + /* td_thr_event_enable: enable event reporting in a thread. */ + p_td_thr_event_enable = dlsym (dlhandle, "td_thr_event_enable"); + + return 1; /* success */ +} + +/* + * Local utility functions: + */ + + +/* + + LOCAL FUNCTION + + save_inferior_pid - Save inferior_pid on the cleanup list + restore_inferior_pid - Restore inferior_pid from the cleanup list + + SYNOPSIS + + struct cleanup *save_inferior_pid (void); + void restore_inferior_pid (void *saved_pid); + + DESCRIPTION + + These two functions act in unison to restore inferior_pid in + case of an error. + + NOTES + + inferior_pid is a global variable that needs to be changed by many + of these routines before calling functions in procfs.c. In order + to guarantee that inferior_pid gets restored (in case of errors), + you need to call save_inferior_pid before changing it. At the end + of the function, you should invoke do_cleanups to restore it. + + */ + +static struct cleanup * +save_inferior_pid (void) +{ +#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 +restore_inferior_pid (void *saved_pid) +{ +#if TARGET_PTR_BIT > TARGET_INT_BIT + inferior_pid = (int) ((long) saved_pid); +#else + inferior_pid = (int) saved_pid; +#endif +} + +/* + + LOCAL FUNCTION + + thr_err_string - Convert a thread_db error code to a string + + SYNOPSIS + + char * thr_err_string (errcode) + + DESCRIPTION + + Return a string description of the thread_db errcode. If errcode + is unknown, then return an <unknown> message. + + */ + +static char * +thr_err_string (errcode) + td_err_e errcode; +{ + static char buf[50]; + + switch (errcode) { + case TD_OK: return "generic 'call succeeded'"; + case TD_ERR: return "generic error"; + case TD_NOTHR: return "no thread to satisfy query"; + case TD_NOSV: return "no sync handle to satisfy query"; + case TD_NOLWP: return "no lwp to satisfy query"; + case TD_BADPH: return "invalid process handle"; + case TD_BADTH: return "invalid thread handle"; + case TD_BADSH: return "invalid synchronization handle"; + case TD_BADTA: return "invalid thread agent"; + case TD_BADKEY: return "invalid key"; + case TD_NOMSG: return "no event message for getmsg"; + case TD_NOFPREGS: return "FPU register set not available"; + case TD_NOLIBTHREAD: return "application not linked with libthread"; + case TD_NOEVENT: return "requested event is not supported"; + case TD_NOCAPAB: return "capability not available"; + case TD_DBERR: return "debugger service failed"; + case TD_NOAPLIC: return "operation not applicable to"; + case TD_NOTSD: return "no thread-specific data for this thread"; + case TD_MALLOC: return "malloc failed"; + case TD_PARTIALREG: return "only part of register set was written/read"; + case TD_NOXREGS: return "X register set not available for this thread"; + default: + sprintf (buf, "unknown thread_db error '%d'", errcode); + return buf; + } +} + +/* + + LOCAL FUNCTION + + thr_state_string - Convert a thread_db state code to a string + + SYNOPSIS + + char *thr_state_string (statecode) + + DESCRIPTION + + Return the thread_db state string associated with statecode. + If statecode is unknown, then return an <unknown> message. + + */ + +static char * +thr_state_string (statecode) + td_thr_state_e statecode; +{ + static char buf[50]; + + switch (statecode) { + case TD_THR_STOPPED: return "stopped by debugger"; + case TD_THR_RUN: return "runnable"; + case TD_THR_ACTIVE: return "active"; + case TD_THR_ZOMBIE: return "zombie"; + case TD_THR_SLEEP: return "sleeping"; + case TD_THR_STOPPED_ASLEEP: return "stopped by debugger AND blocked"; + default: + sprintf (buf, "unknown thread_db state %d", statecode); + return buf; + } +} + +/* + * Local thread/event list. + * This data structure will be used to hold a list of threads and + * pending/deliverable events. + */ + +typedef struct THREADINFO { + thread_t tid; /* thread ID */ + pid_t lid; /* process/lwp ID */ + td_thr_state_e state; /* thread state (a la thread_db) */ + td_thr_type_e type; /* thread type (a la thread_db) */ + int pending; /* true if holding a pending event */ + int status; /* wait status of any interesting event */ +} threadinfo; + +threadinfo * threadlist; +int threadlist_max = 0; /* current size of table */ +int threadlist_top = 0; /* number of threads now in table */ +#define THREADLIST_ALLOC 100 /* chunk size by which to expand table */ + +static threadinfo * +insert_thread (tid, lid, state, type) + int tid; + int lid; + td_thr_state_e state; + td_thr_type_e type; +{ + if (threadlist_top >= threadlist_max) + { + threadlist_max += THREADLIST_ALLOC; + threadlist = realloc (threadlist, + threadlist_max * sizeof (threadinfo)); + if (threadlist == NULL) + return NULL; + } + threadlist[threadlist_top].tid = tid; + threadlist[threadlist_top].lid = lid; + threadlist[threadlist_top].state = state; + threadlist[threadlist_top].type = type; + threadlist[threadlist_top].pending = 0; + threadlist[threadlist_top].status = 0; + + return &threadlist[threadlist_top++]; +} + +static void +empty_threadlist () +{ + threadlist_top = 0; +} + +static threadinfo * +next_pending_event () +{ + int i; + + for (i = 0; i < threadlist_top; i++) + if (threadlist[i].pending) + return &threadlist[i]; + + return NULL; +} + +static void +threadlist_iter (func, data, state, type) + int (*func) (); + void *data; + td_thr_state_e state; + td_thr_type_e type; +{ + int i; + + for (i = 0; i < threadlist_top; i++) + if ((state == TD_THR_ANY_STATE || state == threadlist[i].state) && + (type == TD_THR_ANY_TYPE || type == threadlist[i].type)) + if ((*func) (&threadlist[i], data) != 0) + break; + + return; +} + +/* + * Global state + * + * Here we keep state information all collected in one place. + */ + +/* This flag is set when we activate, so that we don't do it twice. + Defined in linux-thread.c and used for inter-target syncronization. */ +extern int using_thread_db; + +/* The process id for which we've stopped. + * This is only set when we actually stop all threads. + * Otherwise it's zero. + */ +static int event_pid; + +/* + * The process id for a new thread to which we've just attached. + * This process needs special handling at resume time. + */ +static int attach_pid; + + +/* + * thread_db event handling: + * + * The mechanism for event notification via the thread_db API. + * These events are implemented as breakpoints. The thread_db + * library gives us an address where we can set a breakpoint. + * When the breakpoint is hit, it represents an event of interest + * such as: + * Thread creation + * Thread death + * Thread reap + */ + +/* Location of the thread creation event breakpoint. The code at this + location in the child process will be called by the pthread library + whenever a new thread is created. By setting a special breakpoint + at this location, GDB can detect when a new thread is created. We + obtain this location via the td_ta_event_addr call. */ + +static CORE_ADDR thread_creation_bkpt_address; + +/* Location of the thread death event breakpoint. The code at this + location in the child process will be called by the pthread library + whenever a thread is destroyed. By setting a special breakpoint at + this location, GDB can detect when a new thread is created. We + obtain this location via the td_ta_event_addr call. */ + +static CORE_ADDR thread_death_bkpt_address; + +/* This function handles the global parts of enabling thread events. + The thread-specific enabling is handled per-thread elsewhere. */ + +static void +enable_thread_event_reporting (ta) + td_thragent_t *ta; +{ + td_thr_events_t events; + td_notify_t notify; + CORE_ADDR addr; + + if (p_td_ta_set_event == NULL || + p_td_ta_event_addr == NULL || + p_td_ta_event_getmsg == NULL || + p_td_thr_event_enable == NULL) + return; /* can't do thread event reporting without these funcs */ + + /* set process wide mask saying which events we are interested in */ + td_event_emptyset (&events); + td_event_addset (&events, TD_CREATE); + td_event_addset (&events, TD_DEATH); + + if (p_td_ta_set_event (ta, &events) != TD_OK) + { + warning ("unable to set global thread event mask"); + return; + } + + /* Delete previous thread event breakpoints, if any. */ + remove_thread_event_breakpoints (); + + /* create breakpoints -- thread creation and death */ + /* thread creation */ + /* get breakpoint location */ + if (p_td_ta_event_addr (ta, TD_CREATE, ¬ify) != TD_OK) + { + warning ("unable to get location for thread creation breakpoint"); + return; + } + + /* Set up the breakpoint. */ + create_thread_event_breakpoint (notify.u.bptaddr); + + /* Save it's location. */ + thread_creation_bkpt_address = notify.u.bptaddr; + + /* thread death */ + /* get breakpoint location */ + if (p_td_ta_event_addr (ta, TD_DEATH, ¬ify) != TD_OK) + { + warning ("unable to get location for thread death breakpoint"); + return; + } + /* Set up the breakpoint. */ + create_thread_event_breakpoint (notify.u.bptaddr); + + /* Save it's location. */ + thread_death_bkpt_address = notify.u.bptaddr; +} + +/* This function handles the global parts of disabling thread events. + The thread-specific enabling is handled per-thread elsewhere. */ + +static void +disable_thread_event_reporting (ta) + td_thragent_t *ta; +{ + td_thr_events_t events; + + /* set process wide mask saying we aren't interested in any events */ + td_event_emptyset (&events); + p_td_ta_set_event (main_threadagent, &events); + + /* Delete thread event breakpoints, if any. */ + remove_thread_event_breakpoints (); + thread_creation_bkpt_address = 0; + thread_death_bkpt_address = 0; +} + +/* check_for_thread_event + + if it's a thread event we recognize (currently + we only recognize creation and destruction + events), return 1; else return 0. */ + + +static int +check_for_thread_event (struct target_waitstatus *tws, int event_pid) +{ + /* FIXME: to be more efficient, we should keep a static + list of threads, and update it only here (with td_ta_thr_iter). */ +} + +static void +thread_db_push_target (void) +{ + /* Called ONLY from thread_db_new_objfile after td_ta_new call succeeds. */ + + /* Push this target vector */ + push_target (&thread_db_ops); + /* Find the underlying process-layer target for calling later. */ + target_beneath = find_target_beneath (&thread_db_ops); + using_thread_db = 1; + /* Turn on thread_db event-reporting API. */ + enable_thread_event_reporting (main_threadagent); +} + +static void +thread_db_unpush_target (void) +{ + /* Must be called whenever we remove ourself from the target stack! */ + + using_thread_db = 0; + target_beneath = NULL; + + /* delete local list of threads */ + empty_threadlist (); + /* Turn off the thread_db API. */ + p_td_ta_delete (main_threadagent); + /* Unpush this target vector */ + unpush_target (&thread_db_ops); + /* Reset linuxthreads module. */ + linuxthreads_discard_global_state (); +} + +/* + * New objfile hook function: + * Called for each new objfile (image, shared lib) in the target process. + * + * The purpose of this function is to detect that the target process + * is linked with the (appropriate) thread library. So every time a + * new target shared library is detected, we will call td_ta_new. + * If it succeeds, we know we have a multi-threaded target process + * that we can debug using the thread_db API. + */ + +/* + * new_objfile function: + * + * connected to target_new_objfile_hook, this function gets called + * every time a new binary image is loaded. + * + * At each call, we attempt to open the thread_db connection to the + * child process. If it succeeds, we know we have a libthread process + * and we can debug it with this target vector. Therefore we push + * ourself onto the target stack. + */ + +static void (*target_new_objfile_chain) (struct objfile *objfile); +static int stop_or_attach_thread_callback (const td_thrhandle_t *th, + void *data); +static int wait_thread_callback (const td_thrhandle_t *th, + void *data); + +static void +thread_db_new_objfile (struct objfile *objfile) +{ + td_err_e ret; + + if (using_thread_db) /* libthread already detected, and */ + goto quit; /* thread target vector activated. */ + + if (objfile == NULL) + goto quit; /* un-interesting object file */ + + /* Initialize our "main prochandle" with the main inferior pid. */ + main_prochandle.pid = PIDGET (inferior_pid); + + /* Now attempt to open a thread_db connection to the + thread library running in the child process. */ + ret = p_td_ta_new (&main_prochandle, &main_threadagent); + switch (ret) { + default: + warning ("Unexpected error initializing thread_db: %s", + thr_err_string (ret)); + break; + case TD_NOLIBTHREAD: /* expected: no libthread in child process (yet) */ + break; + case TD_OK: /* libthread detected in child: we go live now! */ + thread_db_push_target (); + event_pid = inferior_pid; /* for resume */ + + /* Now stop everyone else, and attach any new threads you find. */ + p_td_ta_thr_iter (main_threadagent, + stop_or_attach_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS); + + /* Now go call wait on all the threads you've stopped: + This allows us to absorb the SIGKILL event, and to make sure + that the thread knows that it is stopped (Linux peculiarity). */ + p_td_ta_thr_iter (main_threadagent, + wait_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS); + + break; + } +quit: + if (target_new_objfile_chain) + target_new_objfile_chain (objfile); +} + + +/* + + LOCAL FUNCTION + + thread_db_alive - test thread for "aliveness" + + SYNOPSIS + + static bool thread_db_alive (int pid); + + DESCRIPTION + + returns true if thread still active in inferior. + + */ + +static int +thread_db_alive (pid) + int pid; +{ + if (is_thread (pid)) /* user-space (non-kernel) thread */ + { + td_thrhandle_t th; + td_err_e ret; + + pid = GET_THREAD (pid); + if ((ret = p_td_ta_map_id2thr (main_threadagent, pid, &th)) != TD_OK) + return 0; /* thread not found */ + if ((ret = p_td_thr_validate (&th)) != TD_OK) + return 0; /* thread not valid */ + return 1; /* known thread: return true */ + } + else if (target_beneath->to_thread_alive) + return target_beneath->to_thread_alive (pid); + else + return 0; /* default to "not alive" (shouldn't happen anyway) */ +} + +/* + * get_lwp_from_thread_handle + */ + +static int /* lwpid_t or pid_t */ +get_lwp_from_thread_handle (th) + td_thrhandle_t *th; +{ + td_thrinfo_t ti; + td_err_e ret; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + error ("get_lwp_from_thread_handle: thr_get_info failed: %s", + thr_err_string (ret)); + + return ti.ti_lid; +} + +/* + * get_lwp_from_thread_id + */ + +static int /* lwpid_t or pid_t */ +get_lwp_from_thread_id (tid) + int tid; /* thread_t? */ +{ + td_thrhandle_t th; + td_err_e ret; + + if ((ret = p_td_ta_map_id2thr (main_threadagent, tid, &th)) != TD_OK) + error ("get_lwp_from_thread_id: map_id2thr failed: %s", + thr_err_string (ret)); + + return get_lwp_from_thread_handle (&th); +} + +/* + * pid_to_str has to handle user-space threads. + * If not a user-space thread, then pass the request on to the + * underlying stratum if it can handle it: else call normal_pid_to_str. + */ + +static char * +thread_db_pid_to_str (int pid) +{ + static char buf[100]; + td_thrhandle_t th; + td_thrinfo_t ti; + td_err_e ret; + + if (is_thread (pid)) + { + if ((ret = p_td_ta_map_id2thr (main_threadagent, + GET_THREAD (pid), + &th)) != TD_OK) + error ("thread_db: map_id2thr failed: %s", thr_err_string (ret)); + + if ((ret = p_td_thr_get_info (&th, &ti)) != TD_OK) + error ("thread_db: thr_get_info failed: %s", thr_err_string (ret)); + + if (ti.ti_state == TD_THR_ACTIVE && + ti.ti_lid != 0) + sprintf (buf, "Thread %d (LWP %d)", ti.ti_tid, ti.ti_lid); + else + sprintf (buf, "Thread %d (%s)", ti.ti_tid, + thr_state_string (ti.ti_state)); + } + else if (GET_LWP (pid)) + sprintf (buf, "LWP %d", GET_LWP (pid)); + else return normal_pid_to_str (pid); + + return buf; +} + +/* + * thread_db target vector functions: + */ + +static void +thread_db_files_info (struct target_ops *tgt_vector) +{ + /* This function will be unnecessary in real life. */ + printf_filtered ("thread_db stratum:\n"); + target_beneath->to_files_info (tgt_vector); +} + +/* + * xfer_memory has to munge the inferior_pid before passing the call + * down to the target layer. + */ + +static int +thread_db_xfer_memory (memaddr, myaddr, len, dowrite, target) + CORE_ADDR memaddr; + char *myaddr; + int len; + int dowrite; + struct target_ops *target; /* ignored */ +{ + struct cleanup *old_chain; + int ret; + + old_chain = save_inferior_pid (); + + if (is_thread (inferior_pid) || + !target_thread_alive (inferior_pid)) + { + /* FIXME: use the LID/LWP, so that underlying process layer + can read memory from specific threads? */ + inferior_pid = main_prochandle.pid; + } + + ret = target_beneath->to_xfer_memory (memaddr, myaddr, len, + dowrite, target); + do_cleanups (old_chain); + return ret; +} + +/* + * fetch_registers has to determine if inferior_pid is a user-space thread. + * If so, we use the thread_db API to get the registers. + * And if not, we call the underlying process stratum. + */ + +static void +thread_db_fetch_registers (regno) + int regno; +{ + td_thrhandle_t thandle; + prfpregset_t fpregset; + prgregset_t gregset; + thread_t thread; + td_err_e ret; + + if (!is_thread (inferior_pid)) /* kernel thread */ + { /* pass the request on to the target underneath. */ + target_beneath->to_fetch_registers (regno); + return; + } + + /* convert inferior_pid into a td_thrhandle_t */ + + if ((thread = GET_THREAD (inferior_pid)) == 0) + error ("fetch_registers: thread == 0"); + + if ((ret = p_td_ta_map_id2thr (main_threadagent, thread, &thandle)) != TD_OK) + error ("fetch_registers: td_ta_map_id2thr: %s", thr_err_string (ret)); + + /* Get the integer regs: + For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, + pc and sp are saved (by a thread context switch). */ + if ((ret = p_td_thr_getgregs (&thandle, gregset)) != TD_OK && + ret != TD_PARTIALREG) + error ("fetch_registers: td_thr_getgregs %s", thr_err_string (ret)); + + /* And, now the fp regs */ + if ((ret = p_td_thr_getfpregs (&thandle, &fpregset)) != TD_OK && + ret != TD_NOFPREGS) + error ("fetch_registers: td_thr_getfpregs %s", thr_err_string (ret)); + +/* Note that we must call supply_{g fp}regset *after* calling the td routines + because the td routines call ps_lget* which affect the values stored in the + registers array. */ + + supply_gregset (gregset); + supply_fpregset (&fpregset); + +} + +/* + * store_registers has to determine if inferior_pid is a user-space thread. + * If so, we use the thread_db API to get the registers. + * And if not, we call the underlying process stratum. + */ + +static void +thread_db_store_registers (regno) + int regno; +{ + td_thrhandle_t thandle; + prfpregset_t fpregset; + prgregset_t gregset; + thread_t thread; + td_err_e ret; + + if (!is_thread (inferior_pid)) /* Kernel thread: */ + { /* pass the request on to the underlying target vector. */ + target_beneath->to_store_registers (regno); + return; + } + + /* convert inferior_pid into a td_thrhandle_t */ + + if ((thread = GET_THREAD (inferior_pid)) == 0) + error ("store_registers: thread == 0"); + + if ((ret = p_td_ta_map_id2thr (main_threadagent, thread, &thandle)) != TD_OK) + error ("store_registers: td_ta_map_id2thr %s", thr_err_string (ret)); + + if (regno != -1) + { /* Not writing all the regs */ + /* save new register value */ + /* MVS: I don't understand this... */ + char old_value[REGISTER_SIZE]; + + memcpy (old_value, ®isters[REGISTER_BYTE (regno)], REGISTER_SIZE); + + if ((ret = p_td_thr_getgregs (&thandle, gregset)) != TD_OK) + error ("store_registers: td_thr_getgregs %s", thr_err_string (ret)); + if ((ret = p_td_thr_getfpregs (&thandle, &fpregset)) != TD_OK) + error ("store_registers: td_thr_getfpregs %s", thr_err_string (ret)); + + /* restore new register value */ + memcpy (®isters[REGISTER_BYTE (regno)], old_value, REGISTER_SIZE); + + } + + fill_gregset (gregset, regno); + fill_fpregset (&fpregset, regno); + + if ((ret = p_td_thr_setgregs (&thandle, gregset)) != TD_OK) + error ("store_registers: td_thr_setgregs %s", thr_err_string (ret)); + if ((ret = p_td_thr_setfpregs (&thandle, &fpregset)) != TD_OK && + ret != TD_NOFPREGS) + error ("store_registers: td_thr_setfpregs %s", thr_err_string (ret)); +} + +static void +handle_new_thread (tid, lid, verbose) + int tid; /* user thread id */ + int lid; /* kernel thread id */ + int verbose; +{ + int gdb_pid = BUILD_THREAD (tid, main_prochandle.pid); + int wait_pid, wait_status; + + if (verbose) + printf_filtered ("[New %s]\n", target_pid_to_str (gdb_pid)); + add_thread (gdb_pid); + + if (lid != main_prochandle.pid) + { + attach_thread (lid); + /* According to the Eric Paire model, we now have to send + the restart signal to the new thread -- however, empirically, + I do not find that to be necessary. */ + attach_pid = lid; + } +} + +static void +test_for_new_thread (tid, lid, verbose) + int tid; + int lid; + int verbose; +{ + if (!in_thread_list (BUILD_THREAD (tid, main_prochandle.pid))) + handle_new_thread (tid, lid, verbose); +} + +/* + * Callback function that gets called once per USER thread + * (i.e., not kernel) thread by td_ta_thr_iter. + */ + +static int +find_new_threads_callback (th, ignored) + const td_thrhandle_t *th; + void *ignored; +{ + td_thrinfo_t ti; + td_err_e ret; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("find_new_threads_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + + /* FIXME: + As things now stand, this should never detect a new thread. + But if it does, we could be in trouble because we aren't calling + wait_thread_callback for it. */ + test_for_new_thread (ti.ti_tid, ti.ti_lid, 0); + return 0; +} + +/* + * find_new_threads uses the thread_db iterator function to discover + * user-space threads. Then if the underlying process stratum has a + * find_new_threads method, we call that too. + */ + +static void +thread_db_find_new_threads () +{ + if (inferior_pid == -1) /* FIXME: still necessary? */ + { + printf_filtered ("No process.\n"); + return; + } + p_td_ta_thr_iter (main_threadagent, + find_new_threads_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS); + if (target_beneath->to_find_new_threads) + target_beneath->to_find_new_threads (); +} + +/* + * Resume all threads, or resume a single thread. + * If step is true, then single-step the appropriate thread + * (or single-step inferior_pid, but continue everyone else). + * If signo is true, then send that signal to at least one thread. + */ + +/* + * This function is called once for each thread before resuming. + * It sends continue (no step, and no signal) to each thread except + * the main thread, and + * the event thread (the one that stopped at a breakpoint etc.) + * + * The event thread is handled separately so that it can be sent + * the stepping and signal args with which target_resume was called. + * + * The main thread is resumed last, so that the thread_db proc_service + * callbacks will still work during the iterator function. + */ + +static int +resume_thread_callback (th, data) + const td_thrhandle_t *th; + void *data; +{ + td_thrinfo_t ti; + td_err_e ret; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("resume_thread_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + /* FIXME: + As things now stand, this should never detect a new thread. + But if it does, we could be in trouble because we aren't calling + wait_thread_callback for it. */ + test_for_new_thread (ti.ti_tid, ti.ti_lid, 1); + + if (ti.ti_lid != main_prochandle.pid && + ti.ti_lid != event_pid) + { + /* Unconditionally continue the thread with no signal. + Only the event thread will get a signal of any kind. */ + + target_beneath->to_resume (ti.ti_lid, 0, 0); + } + return 0; +} + +static int +new_resume_thread_callback (thread, data) + threadinfo *thread; + void *data; +{ + if (thread->lid != event_pid && + thread->lid != main_prochandle.pid) + { + /* Unconditionally continue the thread with no signal (for now). */ + + target_beneath->to_resume (thread->lid, 0, 0); + } + return 0; +} + +static int last_resume_pid; +static int last_resume_step; +static int last_resume_signo; + +static void +thread_db_resume (pid, step, signo) + int pid; + int step; + enum target_signal signo; +{ + last_resume_pid = pid; + last_resume_step = step; + last_resume_signo = signo; + + /* resuming a specific pid? */ + if (pid != -1) + { + if (is_thread (pid)) + pid = get_lwp_from_thread_id (GET_THREAD (pid)); + else if (GET_LWP (pid)) + pid = GET_LWP (pid); + } + + /* Apparently the interpretation of 'pid' is dependent on 'step': + If step is true, then a specific pid means 'step only this pid'. + But if step is not true, then pid means 'continue ALL pids, but + give the signal only to this one'. */ + if (pid != -1 && step) + { + /* FIXME: is this gonna work in all circumstances? */ + target_beneath->to_resume (pid, step, signo); + } + else + { + /* 1) Continue all threads except the event thread and the main thread. + 2) resume the event thread with step and signo. + 3) If event thread != main thread, continue the main thread. + + Note: order of 2 and 3 may need to be reversed. */ + + threadlist_iter (new_resume_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_ANY_TYPE); + /* now resume event thread, and if necessary also main thread. */ + if (event_pid) + { + target_beneath->to_resume (event_pid, step, signo); + } + if (event_pid != main_prochandle.pid) + { + target_beneath->to_resume (main_prochandle.pid, 0, 0); + } + } +} + +/* All new threads will be attached. + All previously known threads will be stopped using kill (SIGKILL). */ + +static int +stop_or_attach_thread_callback (const td_thrhandle_t *th, void *data) +{ + td_thrinfo_t ti; + td_err_e ret; + int gdb_pid; + int on_off = 1; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("stop_or_attach_thread_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + + /* First add it to our internal list. + We build this list anew at every wait event. */ + insert_thread (ti.ti_tid, ti.ti_lid, ti.ti_state, ti.ti_type); + /* Now: if we've already seen it, stop it, else add it and attach it. */ + gdb_pid = BUILD_THREAD (ti.ti_tid, main_prochandle.pid); + if (!in_thread_list (gdb_pid)) /* new thread */ + { + handle_new_thread (ti.ti_tid, ti.ti_lid, 1); + /* Enable thread events */ + if (p_td_thr_event_enable) + if ((ret = p_td_thr_event_enable (th, on_off)) != TD_OK) + warning ("stop_or_attach_thread: %s", thr_err_string (ret)); + } + else if (ti.ti_lid != event_pid && + ti.ti_lid != main_prochandle.pid) + { + ret = (td_err_e) kill (ti.ti_lid, SIGSTOP); + } + + return 0; +} + +/* + * Wait for signal N from pid PID. + * If wait returns any other signals, put them back before returning. + */ + +static void +wait_for_stop (pid) + int pid; +{ + int i; + int retpid; + int status; + + /* Array of wait/signal status */ + /* FIXME: wrong data structure, we need a queue. + Realtime signals may be delivered more than once. + And at that, we really can't handle them (see below). */ +#if defined (NSIG) + static int wstatus [NSIG]; +#elif defined (_NSIG) + static int wstatus [_NSIG]; +#else +#error No definition for number of signals! +#endif + + /* clear wait/status list */ + memset (&wstatus, 0, sizeof (wstatus)); + + /* Now look for SIGSTOP event on all threads except event thread. */ + do { + errno = 0; + if (pid == main_prochandle.pid) + retpid = waitpid (pid, &status, 0); + else + retpid = waitpid (pid, &status, __WCLONE); + + if (retpid > 0) + if (WSTOPSIG (status) == SIGSTOP) + { + /* Got the SIGSTOP event we're looking for. + Throw it away, and throw any other events back! */ + for (i = 0; i < sizeof(wstatus) / sizeof (wstatus[0]); i++) + if (wstatus[i]) + if (i != SIGSTOP) + { + kill (retpid, i); + } + break; /* all done */ + } + else + { + int signo; + /* Oops, got an event other than SIGSTOP. + Save it, and throw it back after we find the SIGSTOP event. */ + + /* FIXME (how?) This method is going to fail for realtime + signals, which cannot be put back simply by using kill. */ + + if (WIFEXITED (status)) + error ("Ack! Thread Exited event. What do I do now???"); + else if (WIFSTOPPED (status)) + signo = WSTOPSIG (status); + else + signo = WTERMSIG (status); + + /* If a thread other than the event thread has hit a GDB + breakpoint (as opposed to some random trap signal), then + just arrange for it to hit it again later. Back up the + PC if necessary. Don't forward the SIGTRAP signal to + the thread. We will handle the current event, eventually + we will resume all the threads, and this one will get + it's breakpoint trap again. + + If we do not do this, then we run the risk that the user + will delete or disable the breakpoint, but the thread will + have already tripped on it. */ + + if (retpid != event_pid && + signo == SIGTRAP && + breakpoint_inserted_here_p (read_pc_pid (retpid) - + DECR_PC_AFTER_BREAK)) + { + /* Set the pc to before the trap and DO NOT re-send the signal */ + if (DECR_PC_AFTER_BREAK) + write_pc_pid (read_pc_pid (retpid) - DECR_PC_AFTER_BREAK, + retpid); + } + + /* Since SIGINT gets forwarded to the entire process group + (in the case where ^C is typed at the tty / console), + just ignore all SIGINTs from other than the event thread. */ + else if (retpid != event_pid && signo == SIGINT) + { /* do nothing. Signal will disappear into oblivion! */ + ; + } + + else /* This is some random signal other than a breakpoint. */ + { + wstatus [signo] = 1; + } + child_resume (retpid, 0, TARGET_SIGNAL_0); + continue; + } + + } while (errno == 0 || errno == EINTR); +} + +/* + * wait_thread_callback + * + * Calls waitpid for each thread, repeatedly if necessary, until + * SIGSTOP is returned. Afterward, if any other signals were returned + * by waitpid, return them to the thread's pending queue by calling kill. + */ + +static int +wait_thread_callback (const td_thrhandle_t *th, void *data) +{ + td_thrinfo_t ti; + td_err_e ret; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("wait_thread_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + + /* This callback to act on all threads except the event thread: */ + if (ti.ti_lid == event_pid || /* no need to wait (no sigstop) */ + ti.ti_lid == main_prochandle.pid) /* no need to wait (already waited) */ + return 0; /* don't wait on the event thread. */ + + wait_for_stop (ti.ti_lid); + return 0; /* finished: next thread. */ +} + +static int +new_wait_thread_callback (thread, data) + threadinfo *thread; + void *data; +{ + /* don't wait on the event thread -- it's already stopped and waited. + Ditto the main thread. */ + if (thread->lid != event_pid && + thread->lid != main_prochandle.pid) + { + wait_for_stop (thread->lid); + } + return 0; +} + +/* + * Wait for any thread to stop, by calling the underlying wait method. + * The PID returned by the underlying target may be a kernel thread, + * in which case we will want to convert it to the corresponding + * user-space thread. + */ + +static int +thread_db_wait (int pid, struct target_waitstatus *ourstatus) +{ + td_thrhandle_t thandle; + td_thrinfo_t ti; + td_err_e ret; + lwpid_t lwp; + int retpid; + int status; + int save_errno; + + /* OK, we're about to wait for an event from the running inferior. + Make sure we're ignoring the right signals. */ + + check_all_signal_numbers (); /* see if magic signals changed. */ + + event_pid = 0; + attach_pid = 0; + + /* FIXME: should I do the wait right here inline? */ +#if 0 + if (pid == -1) + lwp = -1; + else + lwp = get_lwp_from_thread_id (GET_THREAD (pid)); +#endif + + + save_errno = linux_child_wait (-1, &retpid, &status); + store_waitstatus (ourstatus, status); + + /* Thread ID is irrelevant if the target process exited. + FIXME: do I have any killing to do? + Can I get this event mistakenly from a thread? */ + if (ourstatus->kind == TARGET_WAITKIND_EXITED) + return retpid; + + /* OK, we got an event of interest. + Go stop all threads and look for new ones. + FIXME: maybe don't do this for the restart signal? Optimization... */ + event_pid = retpid; + + /* If the last call to resume was for a specific thread, then we don't + need to stop everyone else: they should already be stopped. */ + if (last_resume_step == 0 || last_resume_pid == -1) + { + /* Main thread must be stopped before calling the iterator. */ + if (retpid != main_prochandle.pid) + { + kill (main_prochandle.pid, SIGSTOP); + wait_for_stop (main_prochandle.pid); + } + + empty_threadlist (); + /* Now stop everyone else, and attach any new threads you find. */ + p_td_ta_thr_iter (main_threadagent, + stop_or_attach_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS); + + /* Now go call wait on all the threads we've stopped: + This allows us to absorb the SIGKILL event, and to make sure + that the thread knows that it is stopped (Linux peculiarity). */ + + threadlist_iter (new_wait_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_ANY_TYPE); + } + + /* Convert the kernel thread id to the corresponding thread id. */ + + /* If the process layer does not furnish an lwp, + then perhaps the returned pid IS the lwp... */ + if ((lwp = GET_LWP (retpid)) == 0) + lwp = retpid; + + if ((ret = p_td_ta_map_lwp2thr (main_threadagent, lwp, &thandle)) != TD_OK) + return retpid; /* LWP is not mapped onto a user-space thread. */ + + if ((ret = p_td_thr_validate (&thandle)) != TD_OK) + return retpid; /* LWP is not mapped onto a valid thread. */ + + if ((ret = p_td_thr_get_info (&thandle, &ti)) != TD_OK) + { + warning ("thread_db: thr_get_info failed ('%s')", thr_err_string (ret)); + return retpid; + } + + retpid = BUILD_THREAD (ti.ti_tid, main_prochandle.pid); + /* If this is a new user thread, notify GDB about it. */ + if (!in_thread_list (retpid)) + { + printf_filtered ("[New %s]\n", target_pid_to_str (retpid)); + add_thread (retpid); + } + +#if 0 + /* Now detect if this is a thread creation/deletion event: */ + check_for_thread_event (ourstatus, retpid); +#endif + return retpid; +} + +/* + * kill has to call the underlying kill. + * FIXME: I'm not sure if it's necessary to check inferior_pid any more, + * but we might need to fix inferior_pid up if it's a user thread. + */ + +static int +kill_thread_callback (th, data) + td_thrhandle_t *th; + void *data; +{ + td_thrinfo_t ti; + td_err_e ret; + + /* Fixme: + For Linux, threads may need to be waited. */ + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("kill_thread_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + + if (ti.ti_lid != main_prochandle.pid) + { + kill (ti.ti_lid, SIGKILL); + } + return 0; +} + + +static void thread_db_kill (void) +{ + int rpid; + int status; + + /* Fixme: + For Linux, threads may need to be waited. */ + if (inferior_pid != 0) + { + /* Go kill the children first. Save the main thread for last. */ + p_td_ta_thr_iter (main_threadagent, + kill_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS); + + /* Turn off thread_db event-reporting API *before* killing the + main thread, since this operation requires child memory access. + Can't move this into thread_db_unpush target because then + detach would not work. */ + disable_thread_event_reporting (main_threadagent); + + inferior_pid = main_prochandle.pid; + + /* + * Since both procfs_kill and ptrace_kill call target_mourn, + * it should be sufficient for me to call one of them. + * That will result in my mourn being called, which will both + * unpush me and call the underlying mourn. + */ + target_beneath->to_kill (); + } + + /* Wait for all threads. */ + /* FIXME: need a universal wait_for_signal func? */ + do + { + rpid = waitpid (-1, &status, __WCLONE | WNOHANG); + } + while (rpid > 0 || errno == EINTR); + + do + { + rpid = waitpid (-1, &status, WNOHANG); + } + while (rpid > 0 || errno == EINTR); +} + +/* + * Mourn has to remove us from the target stack, + * and then call the underlying mourn. + */ + +static void thread_db_mourn_inferior (void) +{ + thread_db_unpush_target (); + target_mourn_inferior (); /* call the underlying mourn */ +} + +/* + * Detach has to remove us from the target stack, + * and then call the underlying detach. + * + * But first, it has to detach all the cloned threads! + */ + +static int +detach_thread_callback (th, data) + td_thrhandle_t *th; + void *data; +{ + /* Called once per thread. */ + td_thrinfo_t ti; + td_err_e ret; + + if ((ret = p_td_thr_get_info (th, &ti)) != TD_OK) + { + warning ("detach_thread_callback: %s", thr_err_string (ret)); + return -1; /* bail out, get_info failed. */ + } + + if (!in_thread_list (BUILD_THREAD (ti.ti_tid, main_prochandle.pid))) + return 0; /* apparently we don't know this one. */ + + /* Save main thread for last, or the iterator will fail! */ + if (ti.ti_lid != main_prochandle.pid) + { + struct cleanup *old_chain; + int off = 0; + + /* Time to detach this thread. + First disable thread_db event reporting for the thread. */ + if (p_td_thr_event_enable && + (ret = p_td_thr_event_enable (th, off)) != TD_OK) + { + warning ("detach_thread_callback: %s\n", thr_err_string (ret)); + return 0; + } + + /* Now cancel any pending SIGTRAPS. FIXME! */ + + /* Call underlying detach method. FIXME just detach it. */ + old_chain = save_inferior_pid (); + inferior_pid = ti.ti_lid; + detach (TARGET_SIGNAL_0); + do_cleanups (old_chain); + } + return 0; +} + +static void +thread_db_detach (char *args, int from_tty) +{ + td_err_e ret; + + if ((ret = p_td_ta_thr_iter (main_threadagent, + detach_thread_callback, + (void *) 0, + TD_THR_ANY_STATE, + TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, + TD_THR_ANY_USER_FLAGS)) + != TD_OK) + warning ("detach (thr_iter): %s", thr_err_string (ret)); + + /* Turn off thread_db event-reporting API + (before detaching the main thread) */ + disable_thread_event_reporting (main_threadagent); + + thread_db_unpush_target (); + + /* above call nullifies target_beneath, so don't use that! */ + inferior_pid = PIDGET (inferior_pid); + target_detach (args, from_tty); +} + + +/* + * We never want to actually create the inferior! + * + * If this is ever called, it means we were on the target stack + * when the user said "run". But we don't want to be on the new + * inferior's target stack until the thread_db / libthread + * connection is ready to be made. + * + * So, what shall we do? + * Unpush ourselves from the stack, and then invoke + * find_default_create_inferior, which will invoke the + * appropriate process_stratum target to do the create. + */ + +static void +thread_db_create_inferior (exec_file, allargs, env) + char *exec_file; + char *allargs; + char **env; +{ + thread_db_unpush_target (); + find_default_create_inferior (exec_file, allargs, env); +} + +/* + * Thread_db target vector initializer. + */ + +void +init_thread_db_ops () +{ + thread_db_ops.to_shortname = "multi-thread"; + thread_db_ops.to_longname = "multi-threaded child process."; + thread_db_ops.to_doc = "Threads and pthreads support."; + thread_db_ops.to_files_info = thread_db_files_info; + thread_db_ops.to_create_inferior = thread_db_create_inferior; + thread_db_ops.to_detach = thread_db_detach; + thread_db_ops.to_wait = thread_db_wait; + thread_db_ops.to_resume = thread_db_resume; + thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior; + thread_db_ops.to_kill = thread_db_kill; + thread_db_ops.to_xfer_memory = thread_db_xfer_memory; + thread_db_ops.to_fetch_registers = thread_db_fetch_registers; + thread_db_ops.to_store_registers = thread_db_store_registers; + thread_db_ops.to_thread_alive = thread_db_alive; + thread_db_ops.to_find_new_threads = thread_db_find_new_threads; + thread_db_ops.to_pid_to_str = thread_db_pid_to_str; + thread_db_ops.to_stratum = thread_stratum; + thread_db_ops.to_has_thread_control = tc_schedlock; + thread_db_ops.to_magic = OPS_MAGIC; +} +#endif /* HAVE_STDINT_H */ + +/* + * Module constructor / initializer function. + * If connection to thread_db dynamic library is successful, + * then initialize this module's target vectors and the + * new_objfile hook. + */ + + +void +_initialize_thread_db () +{ +#ifdef HAVE_STDINT_H /* stub out entire module, leave initializer empty */ + if (init_thread_db_library ()) + { + init_thread_db_ops (); + add_target (&thread_db_ops); + /* + * Hook up to the new_objfile event. + * If someone is already there, arrange for him to be called + * after we are. + */ + target_new_objfile_chain = target_new_objfile_hook; + target_new_objfile_hook = thread_db_new_objfile; + } +#endif /* HAVE_STDINT_H */ +} + diff --git a/gdb/linux-thread.c b/gdb/linux-thread.c index de5cdd74a04..df982a6f777 100644 --- a/gdb/linux-thread.c +++ b/gdb/linux-thread.c @@ -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); } diff --git a/gdb/lynx-nat.c b/gdb/lynx-nat.c index 2da61ed8cef..2477b1ff0ea 100644 --- a/gdb/lynx-nat.c +++ b/gdb/lynx-nat.c @@ -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]; diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 13193dfb5d2..5940f8422f7 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -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: diff --git a/gdb/procfs.c b/gdb/procfs.c index 4f1c54f0d08..6abc092f121 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -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; diff --git a/gdb/remote.c b/gdb/remote.c index 402c95c5124..5264d17dcf4 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -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; } diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c index 2ab04b3890b..d896f8e2b59 100644 --- a/gdb/sol-thread.c +++ b/gdb/sol-thread.c @@ -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; diff --git a/gdb/target.c b/gdb/target.c index a74e3623b6d..1b16a2e76f5 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -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; } diff --git a/gdb/target.h b/gdb/target.h index 4115eeeafd2..fce6cf9a785 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -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. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 47d33a2f3b1..578841d21b7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,8 +1,11 @@ -1999-12-13n Fernando Nasser <fnasser@totem.to.cygnus.com> +1999-12-16 Stan Shebs <shebs@andros.cygnus.com> - * gdb.base/watchpoint.exp: Add missing "(timeout)" to test message. + * gdb.base/default.exp: Match arm* etc instead of arm in "info + float" test. + +1999-12-13 Fernando Nasser <fnasser@totem.to.cygnus.com> -1999-12-13n Fernando Nasser <fnasser@totem.to.cygnus.com> + * gdb.base/watchpoint.exp: Add missing "(timeout)" to test message. * gdb.base/break.exp: Add missing anchor to reg exp on "finish from outermost frame disallowed". diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp index 6f109fe9072..9395ed98376 100644 --- a/gdb/testsuite/gdb.base/default.exp +++ b/gdb/testsuite/gdb.base/default.exp @@ -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" diff --git a/gdb/testsuite/gdb.threads/linux-dp.exp b/gdb/testsuite/gdb.threads/linux-dp.exp index 18febdc2411..e8285f5f8b5 100644 --- a/gdb/testsuite/gdb.threads/linux-dp.exp +++ b/gdb/testsuite/gdb.threads/linux-dp.exp @@ -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" diff --git a/gdb/utils.c b/gdb/utils.c index cbaf0cc9dfd..596c0aee3b9 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -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 diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c index b95ec6d2a75..b5ef062ed42 100644 --- a/gdb/win32-nat.c +++ b/gdb/win32-nat.c @@ -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 *) ¤t_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; } -CORE_ADDR -child_frame_chain(struct frame_info *thisframe) +static DWORD __stdcall +sgmb(HANDLE h, DWORD d) { - 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; + return 4; +#else + return SymGetModuleBase (h, d) ?: 4; #endif +} + +CORE_ADDR +child_frame_chain(struct frame_info *f) +{ + 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 diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 01ef1be00e1..428f4572e8a 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -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> diff --git a/sim/common/sim-profile.c b/sim/common/sim-profile.c index 5d075d15bd1..9129a38a147 100644 --- a/sim/common/sim-profile.c +++ b/sim/common/sim-profile.c @@ -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; diff --git a/sim/common/sim-profile.h b/sim/common/sim-profile.h index 8f8d95f43a1..4ffe8503766 100644 --- a/sim/common/sim-profile.h +++ b/sim/common/sim-profile.h @@ -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 |