From: Stu Grossman Date: Sat, 4 Nov 1995 19:02:42 +0000 (+0000) Subject: * Makefile.in (INTERNAL_CFLAGS): Add ENABLE_CFLAGS. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=188c635fbb8b6b15ffd3a12f2665dc17d09ff947;p=binutils-gdb.git * Makefile.in (INTERNAL_CFLAGS): Add ENABLE_CFLAGS. * fork-child.c (fork_inferior): Add call to TARGET_CREATE_INFERIOR_HOOK to allow target specific code to get control just before the new process executes it's first instruction. * remote-mips.c (mips_initialize): Cleanup a bit. Don't try to receive a packet at first. This speeds up initialization a lot. Use TARGET_MONITOR_PROMPT instead of "". (common_breakpoint): Use rresponse instead of rerrflg to inspect error code. * symfile.c (syms_from_objfile reread_symbols): Call TARGET_SYMFILE_POSTREAD to allow target specific code to get control after reading new symbols. * target.h: New macros TARGET_SYMFILE_POSTREAD, and TARGET_CREATE_INFERIOR_HOOK. See above for descriptions. * config/mips/{irix5.mh nm-irix5.h}: Delete nm-irix5.h. Make NAT_FILE point directly at ../nm-sysv4.h. * config/mips/{mipsm3.mh nm-m3.h}: Delete nm-m3.h. Make NAT_FILE point directly at ../nm-m3.h. * config/mips/{mipsv4.mh nm-sysv4.h}: Delete nm-sysv4.h. Make NAT_FILE point directly at ../nm-sysv4.h. * config/mips/nm-mips.h: Improve comment at top of file. * config/mips/tm-mips.h (TARGET_MONITOR_PROMPT): Change definition into a proper string. start-sanitize-gm * configure configure.in: Add support for --enable-gm. (mips*-*-magic*): Change target from magic to idt. * eval.c expprint.c expression.h parse.c remote-mips.c utils.c: Change GENERAL_MAGIC_HACKS to GENERAL_MAGIC. * magic.c magic.h: Update files from GM. * config/mips/magic.mt: Delete. No longer necessary now that we use --enable mechanism. * config/mips/tm-idt.h: Add GM stuff needed for remote GM box. * config/mips/tm-irix5.h: Add GM stuff needed for native Irix box. * config/mips/tm-magic.h: Move up to config/tm-magic.h. Move all platform specific stuff into tm-irix.h and tm-idt.h. Add defs for TARGET_SYMFILE_POSTREAD and TARGET_CREATE_INFERIOR_HOOK. end-sanitize-gm --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2b526c6aa6b..38ddf949035 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,43 @@ +Sat Nov 4 10:21:58 1995 Stu Grossman (grossman@cygnus.com) + + * Makefile.in (INTERNAL_CFLAGS): Add ENABLE_CFLAGS. + * fork-child.c (fork_inferior): Add call to + TARGET_CREATE_INFERIOR_HOOK to allow target specific code to get + control just before the new process executes it's first instruction. + * remote-mips.c (mips_initialize): Cleanup a bit. Don't try to + receive a packet at first. This speeds up initialization a lot. + Use TARGET_MONITOR_PROMPT instead of "". + (common_breakpoint): Use rresponse instead of rerrflg to inspect + error code. + * symfile.c (syms_from_objfile reread_symbols): Call + TARGET_SYMFILE_POSTREAD to allow target specific code to get + control after reading new symbols. + * target.h: New macros TARGET_SYMFILE_POSTREAD, and + TARGET_CREATE_INFERIOR_HOOK. See above for descriptions. + * config/mips/{irix5.mh nm-irix5.h}: Delete nm-irix5.h. Make + NAT_FILE point directly at ../nm-sysv4.h. + * config/mips/{mipsm3.mh nm-m3.h}: Delete nm-m3.h. Make + NAT_FILE point directly at ../nm-m3.h. + * config/mips/{mipsv4.mh nm-sysv4.h}: Delete nm-sysv4.h. Make + NAT_FILE point directly at ../nm-sysv4.h. + * config/mips/nm-mips.h: Improve comment at top of file. + * config/mips/tm-mips.h (TARGET_MONITOR_PROMPT): Change + definition into a proper string. +start-sanitize-gm + * configure configure.in: Add support for --enable-gm. + (mips*-*-magic*): Change target from magic to idt. + * eval.c expprint.c expression.h parse.c remote-mips.c utils.c: + Change GENERAL_MAGIC_HACKS to GENERAL_MAGIC. + * magic.c magic.h: Update files from GM. + * config/mips/magic.mt: Delete. No longer necessary now that we + use --enable mechanism. + * config/mips/tm-idt.h: Add GM stuff needed for remote GM box. + * config/mips/tm-irix5.h: Add GM stuff needed for native Irix box. + * config/mips/tm-magic.h: Move up to config/tm-magic.h. Move all + platform specific stuff into tm-irix.h and tm-idt.h. Add defs for + TARGET_SYMFILE_POSTREAD and TARGET_CREATE_INFERIOR_HOOK. +end-sanitize-gm + Wed Nov 1 20:18:08 1995 Fred Fish * config/i386/tm-i386.h: New file containing generic i*86 target diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ff0ec6498af..211a40750c1 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -174,7 +174,7 @@ CXXFLAGS = -g -O # INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros. INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \ $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \ - $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) + $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) $(ENABLE_CFLAGS) # LDFLAGS is specifically reserved for setting from the command line # when running make. diff --git a/gdb/config/.Sanitize b/gdb/config/.Sanitize index 18251263f09..f54894db581 100644 --- a/gdb/config/.Sanitize +++ b/gdb/config/.Sanitize @@ -21,6 +21,20 @@ else lose_these_too="arc ${lose_these_too}" fi +gm_files="tm-magic.h" + +if ( echo $* | grep keep\-gm > /dev/null ) ; then + keep_these_too="${gm_files} ${keep_these_too}" + if [ -n "${verbose}" ] ; then + echo Keeping ${gm_files} + fi +else + lose_these_too="${gm_files} ${lose_these_too}" + if [ -n "${verbose}" ] ; then + echo Deleting ${gm_files} + fi +fi + # All files listed between the "Things-to-keep:" line and the # "Files-to-sed:" line will be kept. All other files will be removed. # Directories listed in this section will have their own Sanitize diff --git a/gdb/config/mips/.Sanitize b/gdb/config/mips/.Sanitize index 67b41b878ba..c4c5bd253e2 100644 --- a/gdb/config/mips/.Sanitize +++ b/gdb/config/mips/.Sanitize @@ -15,20 +15,6 @@ Do-first: -gm_files="magic.mt tm-magic.h" - -if ( echo $* | grep keep\-gm > /dev/null ) ; then - keep_these_too="${gm_files} ${keep_these_too}" - if [ -n "${verbose}" ] ; then - echo Keeping ${gm_files} - fi -else - lose_these_too="${gm_files} ${lose_these_too}" - if [ -n "${verbose}" ] ; then - echo Deleting ${gm_files} - fi -fi - # All files listed between the "Things-to-keep:" line and the # "Files-to-sed:" line will be kept. All other files will be removed. # Directories listed in this section will have their own Sanitize @@ -97,4 +83,31 @@ Things-to-lose: Do-last: +if ( echo $* | grep keep\-gm > /dev/null ) ; then + for i in * ; do + if test ! -d $i && (grep sanitize-gm $i > /dev/null) ; then + if [ -n "${verbose}" ] ; then + echo Keeping gm stuff in $i + fi + fi + done +else + for i in * ; do + if test ! -d $i && (grep sanitize-gm $i > /dev/null) ; then + if [ -n "${verbose}" ] ; then + echo Removing traces of \"gm\" from $i... + fi + cp $i new + sed '/start\-sanitize\-gm/,/end-\sanitize\-gm/d' < $i > new + if [ -n "${safe}" -a ! -f .Recover/$i ] ; then + if [ -n "${verbose}" ] ; then + echo Caching $i in .Recover... + fi + mv $i .Recover + fi + mv new $i + fi + done +fi + # End of file. diff --git a/gdb/config/mips/magic.mt b/gdb/config/mips/magic.mt deleted file mode 100644 index 8327a2b6f8b..00000000000 --- a/gdb/config/mips/magic.mt +++ /dev/null @@ -1,3 +0,0 @@ -# Target: Big-endian IDT board running MagiCAP -TDEPFILES= mips-tdep.o remote-mips.o magic.o -TM_FILE= tm-magic.h diff --git a/gdb/config/mips/mipsm3.mh b/gdb/config/mips/mipsm3.mh index 08c8392f174..fe7cbad2631 100644 --- a/gdb/config/mips/mipsm3.mh +++ b/gdb/config/mips/mipsm3.mh @@ -4,7 +4,7 @@ XDEPFILES= coredep.o NATDEPFILES= mipsm3-nat.o m3-nat.o XM_FILE= xm-mipsm3.h -NAT_FILE= nm-m3.h +NAT_FILE= ../nm-m3.h # Don't use the mmalloc library in Mach 3. MMALLOC = diff --git a/gdb/config/mips/mipsv4.mh b/gdb/config/mips/mipsv4.mh index c01bfcbe65b..d6b328bd66a 100644 --- a/gdb/config/mips/mipsv4.mh +++ b/gdb/config/mips/mipsv4.mh @@ -1,4 +1,4 @@ # Host: Mips running SVR4 XM_FILE= xm-mipsv4.h -NAT_FILE= nm-sysv4.h +NAT_FILE= ../nm-sysv4.h NATDEPFILES= fork-child.o procfs.o mipsv4-nat.o corelow.o core-svr4.o solib.o diff --git a/gdb/config/mips/nm-m3.h b/gdb/config/mips/nm-m3.h deleted file mode 100644 index 0fe7cf2ddb4..00000000000 --- a/gdb/config/mips/nm-m3.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Native-dependent definitions for mips running Mach 3. - Copyright 1994 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Include the generic Mach 3 definitions. */ - -#include "nm-m3.h" diff --git a/gdb/config/mips/nm-mips.h b/gdb/config/mips/nm-mips.h index ac777829a19..0f49e342466 100644 --- a/gdb/config/mips/nm-mips.h +++ b/gdb/config/mips/nm-mips.h @@ -1,4 +1,4 @@ -/* Definitions for GDB on mips. +/* Native definitions for GDB on DECstations, Sony News. and MIPS Riscos systems Copyright (C) 1986, 1987, 1989, 1992 Free Software Foundation, Inc. Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin and by Alessandro Forin(af@cs.cmu.edu) at CMU diff --git a/gdb/config/mips/nm-sysv4.h b/gdb/config/mips/nm-sysv4.h deleted file mode 100644 index a1c6bc6378f..00000000000 --- a/gdb/config/mips/nm-sysv4.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Native-dependent definitions for mips running SVR4. - Copyright 1994 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Include the generic SVR4 definitions. */ - -#include "nm-sysv4.h" diff --git a/gdb/config/mips/tm-idt.h b/gdb/config/mips/tm-idt.h index 47bcfb5082d..f3d2cc88686 100644 --- a/gdb/config/mips/tm-idt.h +++ b/gdb/config/mips/tm-idt.h @@ -22,3 +22,39 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #undef DEFAULT_MIPS_TYPE #define DEFAULT_MIPS_TYPE "r3051" + +/* start-sanitize-gm */ +#ifdef GENERAL_MAGIC + +#include "tm-magic.h" /* Include generic stuff */ + +/* For some reason GM can't hack this... */ + +#undef GET_LONGJMP_TARGET + +/* Watchpoint support */ + +#define TARGET_HAS_HARDWARE_WATCHPOINTS + +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ + (1 == 1) /* We allow all types of hardware watchpoints */ + +/* Use these macros for watchpoint insertion/deletion. */ +/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ + +#define target_insert_watchpoint(addr, len, type) \ + remote_mips_set_watchpoint (addr, len, type) + +#define target_remove_watchpoint(addr, len, type) \ + remote_mips_remove_watchpoint (addr, len, type) + +/* We need to remove watchpoints when stepping, else we hit them again! */ + +#define HAVE_NONSTEPPABLE_WATCHPOINT + +#define STOPPED_BY_WATCHPOINT(w) remote_mips_stopped_by_watchpoint () + +#define FLUSH_CACHED_MEMORY() flush_cached_memory() + +#endif /* GENERAL_MAGIC */ +/* end-sanitize-gm */ diff --git a/gdb/config/mips/tm-irix5.h b/gdb/config/mips/tm-irix5.h index faf6d4516c4..3cda7b7cdc7 100644 --- a/gdb/config/mips/tm-irix5.h +++ b/gdb/config/mips/tm-irix5.h @@ -44,3 +44,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #undef SIGFRAME_FPREGSAVE_OFF #define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_BASE + 2 * 4 + 8 + 32 * 8 + 4) #define SIGFRAME_REG_SIZE 8 + +/* start-sanitize-gm */ +#ifdef GENERAL_MAGIC +#include "tm-magic.h" +#endif /* GENERAL_MAGIC */ +/* end-sanitize-gm */ diff --git a/gdb/config/mips/tm-magic.h b/gdb/config/mips/tm-magic.h deleted file mode 100644 index c333f73812a..00000000000 --- a/gdb/config/mips/tm-magic.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Definitions for General Magic MIPS target. - Copyright (C) 1995 Free Software Foundation, Inc. - -This file is part of GDB. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include "mips/tm-idt.h" - -/* For some reason GM can't hack this... */ - -#undef GET_LONGJMP_TARGET - -#define GENERAL_MAGIC_HACKS - -#define SEND_BREAK_ON_QUIT - - -/* Watchpoint support */ - -#define TARGET_HAS_HARDWARE_WATCHPOINTS - -#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ - (1 == 1) /* We allow all types of hardware watchpoints */ - -/* Use these macros for watchpoint insertion/deletion. */ -/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ - -#define target_insert_watchpoint(addr, len, type) \ - remote_mips_set_watchpoint (addr, len, type) - -#define target_remove_watchpoint(addr, len, type) \ - remote_mips_remove_watchpoint (addr, len, type) - -/* We need to remove watchpoints when stepping, else we hit them again! */ - -#define HAVE_NONSTEPPABLE_WATCHPOINT - -#define STOPPED_BY_WATCHPOINT(w) remote_mips_stopped_by_watchpoint () - -#define FLUSH_CACHED_MEMORY() flush_cached_memory() diff --git a/gdb/config/mips/tm-mips.h b/gdb/config/mips/tm-mips.h index afbb2e016fc..d8b2bd16b31 100644 --- a/gdb/config/mips/tm-mips.h +++ b/gdb/config/mips/tm-mips.h @@ -33,7 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif #if !defined (TARGET_MONITOR_PROMPT) -#define TARGET_MONITOR_PROMPT { '<', 'I', 'D', 'T', '>' } +#define TARGET_MONITOR_PROMPT "" #endif /* Floating point is IEEE compliant */ diff --git a/gdb/config/tm-magic.h b/gdb/config/tm-magic.h new file mode 100644 index 00000000000..04360369183 --- /dev/null +++ b/gdb/config/tm-magic.h @@ -0,0 +1,40 @@ +/* Definitions for General Magic target. + Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "magic.h" + +#define TARGET_SYMFILE_POSTREAD(OBJFILE) init_magic () + +#define TARGET_CREATE_INFERIOR_HOOK(PID) magic_create_inferior_hook () + +/* Magic Cap method stepping support. + We use the shared library trampoline support to implement stepping over + the method dispatcher. We consider the entire dispatcher to be one big + trampoline, and use SKIP_TRAMPOLINE_CODE() to skip from a dispatcher + entry point to the dispatcher exit site, or from the exit site to the + first instruction of the dispatched-to method. */ + +#define SKIP_TRAMPOLINE_CODE(pc) \ + magic_skip_dispatcher(pc) + +#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \ + magic_in_dispatcher(pc, name) + +#define IN_SOLIB_RETURN_TRAMPOLINE(pc, name) \ + magic_in_dispatcher(pc, name) diff --git a/gdb/configure b/gdb/configure index 13a17f0bd9c..3a45c918728 100755 --- a/gdb/configure +++ b/gdb/configure @@ -1,7 +1,7 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.4 +# Generated automatically using autoconf version 2.4.2 # Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -13,6 +13,8 @@ ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --enable-netrom " +ac_help="$ac_help + --enable-gm " ac_help="$ac_help --enable-gdbtk " ac_help="$ac_help @@ -39,6 +41,18 @@ target=NONE verbose= x_includes=NONE x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' # Initialize some other variables. subdirs= @@ -63,9 +77,14 @@ do case "$ac_option" in - -build | --build | --buil | --bui | --bu | --b) + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ @@ -75,6 +94,12 @@ do | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. @@ -125,12 +150,26 @@ Configuration: Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] - --exec-prefix=PREFIX install architecture-dependent files in PREFIX + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names +EOF + cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] @@ -151,6 +190,44 @@ EOF -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; @@ -163,6 +240,15 @@ EOF | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) @@ -203,6 +289,23 @@ EOF | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) @@ -213,6 +316,13 @@ EOF -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) @@ -222,7 +332,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.4" + echo "configure generated by autoconf version 2.4.2" exit 0 ;; -with-* | --with-*) @@ -387,9 +497,12 @@ fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5' +ac_cpp='echo $CPP $CPPFLAGS 1>&5; +$CPP $CPPFLAGS' +ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5; +${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5' +ac_link='echo ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5; +${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5' if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. @@ -416,7 +529,7 @@ else ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do + for ac_dir in cc; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" @@ -450,6 +563,7 @@ else ac_cv_prog_gcc=no fi fi + echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes @@ -467,7 +581,8 @@ fi rm -f conftest* fi - echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 + +echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 if test $ac_cv_prog_gcc_g = yes; then CFLAGS="-g -O" else @@ -494,7 +609,7 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error @@ -508,7 +623,7 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error @@ -535,7 +650,7 @@ echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for AIX""... $ac_c" 1>&6 cat > conftest.$ac_ext <&6 else cat > conftest.$ac_ext < EOF @@ -680,10 +795,17 @@ else esac done IFS="$ac_save_ifs" - # As a last resort, use the slow shell script. - test -z "$ac_cv_path_install" && ac_cv_path_install="$ac_install_sh" + fi - INSTALL="$ac_cv_path_install" + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi fi echo "$ac_t""$INSTALL" 1>&6 @@ -703,7 +825,7 @@ else ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" - for ac_dir in $PATH; do + for ac_dir in :; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_RANLIB="ranlib" @@ -887,7 +1009,7 @@ else ac_cv_c_cross=yes else cat > conftest.$ac_ext <&6 +cross_compiling=$ac_cv_c_cross echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -930,7 +1053,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 @@ -948,7 +1071,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 @@ -969,7 +1092,7 @@ if test "$cross_compiling" = yes; then ac_cv_header_stdc=no else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -990,6 +1113,7 @@ fi rm -fr conftest* fi fi + echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF @@ -1006,7 +1130,7 @@ 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 @@ -1024,7 +1148,7 @@ rm -f conftest* fi if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then echo "$ac_t""yes" 1>&6 - ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'` + ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'` cat >> confdefs.h <&6 else cat > conftest.$ac_ext < #include @@ -1080,6 +1204,7 @@ fi rm -f conftest* fi + echo "$ac_t""$ac_cv_header_stat_broken" 1>&6 if test $ac_cv_header_stat_broken = yes; then cat >> confdefs.h <<\EOF @@ -1097,7 +1222,7 @@ else ac_cv_func_mmap=no else cat > conftest.$ac_ext <&6 if test $ac_cv_func_mmap = yes; then cat >> confdefs.h <<\EOF @@ -1195,8 +1321,8 @@ ENABLE_CLIBS= ENABLE_OBS= # Check whether --enable-netrom or --disable-netrom was given. -enableval="$enable_netrom" -if test -n "$enableval"; then +if test "${enable_netrom+set}" = set; then + enableval="$enable_netrom" case "${enableval}" in yes) enable_netrom=yes ;; no) enable_netrom=no ;; @@ -1209,12 +1335,30 @@ if test "${enable_netrom}" = "yes"; then ENABLE_OBS="${ENABLE_OBS} remote-nrom.o" fi +# start-sanitize-gm +ENABLE_GM= + +# Check whether --enable-gm or --disable-gm was given. +if test "${enable_gm+set}" = set; then + enableval="$enable_gm" + case "${enableval}" in +yes) ENABLE_OBS="${ENABLE_OBS} magic.o" + ENABLE_CFLAGS=-DGENERAL_MAGIC + ;; +no) ;; +*) { echo "configure: error: bad value ${enableval} given for gm option" 1>&2; exit 1; } ;; +esac +fi + + +# end-sanitize-gm + # start-sanitize-gdbtk ENABLE_GDBTK= # Check whether --enable-gdbtk or --disable-gdbtk was given. -enableval="$enable_gdbtk" -if test -n "$enableval"; then +if test "${enable_gdbtk+set}" = set; then + enableval="$enable_gdbtk" case "${enableval}" in yes) enable_gdbtk=yes ;; no) enable_gdbtk=no ;; @@ -1231,8 +1375,8 @@ if test "${enable_gdbtk}" = "yes"; then echo $ac_n "checking for X""... $ac_c" 1>&6 # Check whether --with-x or --without-x was given. -withval="$with_x" -if test -n "$withval"; then +if test "${with_x+set}" = set; then + withval="$with_x" : fi @@ -1285,7 +1429,7 @@ test -z "$x_direct_test_library" && x_direct_test_library=Xt test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h cat > conftest.$ac_ext < EOF @@ -1348,7 +1492,7 @@ rm -f conftest* ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&6 -if eval "test \"`echo '$''{'ac_cv_lib_ICE'+set}'`\" = set"; then +ac_lib_var=`echo ICE | tr '+./' 'p__'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lICE $LIBS" cat > conftest.$ac_ext <&6 X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" else @@ -1503,13 +1648,14 @@ fi # libraries were built with DECnet support. And karl@cs.umb.edu says # the Alpha needs dnet_stub (dnet does not exist). echo $ac_n "checking for -ldnet""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_lib_dnet'+set}'`\" = set"; then +ac_lib_var=`echo dnet | tr '+./' 'p__'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldnet $LIBS" cat > conftest.$ac_ext <&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" else @@ -1537,13 +1683,14 @@ fi if test $ac_cv_lib_dnet = no; then echo $ac_n "checking for -ldnet_stub""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_lib_dnet_stub'+set}'`\" = set"; then +ac_lib_var=`echo dnet_stub | tr '+./' 'p__'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-ldnet_stub $LIBS" cat > conftest.$ac_ext <&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" else @@ -1576,13 +1723,14 @@ fi # Not sure which flavor of 386 UNIX this is, but it seems harmless to # check for it. echo $ac_n "checking for -lnsl""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_lib_nsl'+set}'`\" = set"; then +ac_lib_var=`echo nsl | tr '+./' 'p__'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" else @@ -1614,13 +1762,14 @@ fi # But -lsocket is broken on IRIX, according to simon@lia.di.epfl.ch. if test "`(uname) 2>/dev/null`" != IRIX; then echo $ac_n "checking for -lsocket""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_lib_socket'+set}'`\" = set"; then +ac_lib_var=`echo socket | tr '+./' 'p__'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&6 X_EXTRA_LIBS="$X_EXTRA_LIBS -lsocket" else @@ -1677,7 +1826,7 @@ 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 @@ -1779,7 +1928,7 @@ 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 @@ -2208,7 +2357,7 @@ mips64*-*-elf*) gdb_target=idt64 ;; mips*el-*-ecoff*) gdb_target=idtl ;; mips*-*-ecoff*) gdb_target=idt ;; # start-sanitize-gm -mips*-*-magic*) gdb_target=magic ;; +mips*-*-magic*) gdb_target=idt ;; # end-sanitize-gm mips*el-*-elf*) gdb_target=idtl ;; mips*-*-elf*) gdb_target=idt ;; @@ -2438,7 +2587,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.4" + echo "$CONFIG_STATUS generated by autoconf version 2.4.2" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -2465,6 +2614,18 @@ s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g s%@CC@%$CC%g s%@CPP@%$CPP%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g diff --git a/gdb/configure.in b/gdb/configure.in index 38114d1380f..4c2331ad991 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -39,6 +39,21 @@ if test "${enable_netrom}" = "yes"; then ENABLE_OBS="${ENABLE_OBS} remote-nrom.o" fi +# start-sanitize-gm +ENABLE_GM= + +AC_ARG_ENABLE(gm, +[ --enable-gm ], +[case "${enableval}" in +yes) ENABLE_OBS="${ENABLE_OBS} magic.o" + ENABLE_CFLAGS=-DGENERAL_MAGIC + ;; +no) ;; +*) AC_MSG_ERROR(bad value ${enableval} given for gm option) ;; +esac]) + +# end-sanitize-gm + # start-sanitize-gdbtk ENABLE_GDBTK= @@ -418,7 +433,7 @@ mips64*-*-elf*) gdb_target=idt64 ;; mips*el-*-ecoff*) gdb_target=idtl ;; mips*-*-ecoff*) gdb_target=idt ;; # start-sanitize-gm -mips*-*-magic*) gdb_target=magic ;; +mips*-*-magic*) gdb_target=idt ;; # end-sanitize-gm mips*el-*-elf*) gdb_target=idtl ;; mips*-*-elf*) gdb_target=idt ;; diff --git a/gdb/fork-child.c b/gdb/fork-child.c index 41e46af66fb..df289d43d35 100644 --- a/gdb/fork-child.c +++ b/gdb/fork-child.c @@ -238,6 +238,12 @@ fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun, /* We are now in the child process of interest, having exec'd the correct program, and are poised at the first instruction of the new program. */ + + /* Allow target dependant code to play with the new process. This might be + used to have target-specific code initialize a variable in the new process + prior to executing the first instruction. */ + TARGET_CREATE_INFERIOR_HOOK (pid); + #ifdef SOLIB_CREATE_INFERIOR_HOOK SOLIB_CREATE_INFERIOR_HOOK (pid); #endif diff --git a/gdb/magic.c b/gdb/magic.c index 6576e232801..d8812cd1910 100644 --- a/gdb/magic.c +++ b/gdb/magic.c @@ -2,419 +2,1241 @@ #include "gdbcmd.h" #include "symtab.h" #include "value.h" +#include "frame.h" +#include "breakpoint.h" +#include "inferior.h" +#include "gdbcore.h" +#include "magic.h" #include #include + #ifdef DYNAMIC_COMMAND_SUPPORT #include #endif -typedef unsigned long ulong; +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif + + +/* Maximum number of bytes of extra data to print, or UINT_MAX for no limit. + Note that "set extra-data-max 0" stores UINT_MAX in extra_data_max, which + displays in a show command as "unlimited." */ + +static unsigned int extra_data_max; +#define EXTRA_DATA_MAX_DEFAULT 1024 + +/* Return the number of elements in ARRAY. */ + +#define ARRAY_NELEMENTS(array) (sizeof (array) / sizeof (array[0])) + +/* Basic information about a text label */ + +struct text_label +{ + char *name; /* label name */ + CORE_ADDR addr; /* label value or 0 if label not found */ +}; + +/* Labels within the Magic Cap dispatcher that we need to know about + in order to implement "magic stepping" (that is, stepping over + Magic Cap method dispatches). The label addresses are refreshed + whenever a new symbol table is loaded. */ + +struct text_label dispatch_labels[] = +{ + {"__DispatchMethod", 0}, /* normal dispatch entry point */ + {"__DispatchInherited", 0}, /* inherited dispatch entry point */ + {"__DispatchDelegated", 0}, /* delegated dispatch entry point */ + {"__DispatchIntrinsic", 0}, /* intrinsic dispatch entry point */ + {"__DoDispatchMethodBpSite", 0}, /* do dispatch site */ +}; + +/* Accessors for the array above. */ + +#define DISPATCH_METHOD_ADDR dispatch_labels[0].addr +#define DISPATCH_INHERITED_ADDR dispatch_labels[1].addr +#define DISPATCH_DELEGATED_ADDR dispatch_labels[2].addr +#define DISPATCH_INTRINSIC_ADDR dispatch_labels[3].addr +#define DO_DISPATCH_METHOD_ADDR dispatch_labels[4].addr + +/* Cached value objects describing functions in the target program that + we call frequently. These are refreshed whenever a new symbol table + is loaded. */ + +static value_ptr remote_get_class_name_val; +static value_ptr remote_get_base_ptr_val; + +/* Nonzero means that "magic step" (stepping through the Magic Cap method + dispatcher to the dispatch target) is enabled. */ + +static int magic_step_enabled; + +/* function prototypes */ -#ifdef DYNAMIC_COMMAND_SUPPORT static void -dlopen_command PARAMS ((char *, int)); -#endif +print_object PARAMS ((char *args, int dump)); + +static void +get_class_name PARAMS ((unsigned long objectID, char **name, int *is_scripted)); + +static CORE_ADDR +get_base_ptr PARAMS ((unsigned long objectID)); + +static int +should_dump_extra_data PARAMS ((char *class_name)); + +static void +dump_extra_data PARAMS ((CORE_ADDR addr, unsigned long length)); + +static value_ptr +call_function_by_name PARAMS ((char *function_name, int nargs, ...)); + +static value_ptr +call_function_by_value PARAMS ((value_ptr function_value, int nargs, ...)); + +static value_ptr +vcall_function_by_value PARAMS ((value_ptr function_value, int nargs, + va_list args)); +static void +local_shell_escape PARAMS ((char *arg)); + +static CORE_ADDR +lookup_text_label PARAMS ((char *name, value_ptr *val_ptrptr)); + +static int +is_dispatcher_entry PARAMS ((CORE_ADDR pc)); + +static int +is_dispatcher_exit PARAMS ((CORE_ADDR pc)); + + +/* This is the GDB handler for the "dobj" command, which prints a + verbose description of an object. ARGS is a string containing an + expression for the object ID, and FROM_TTY is nonzero if the + command was issued interactively. */ -#ifdef DYNAMIC_COMMAND_SUPPORT /* ARGSUSED */ static void -dlopen_command (arg, from_tty) - char *arg; +dobj_command (args, from_tty) + char *args; int from_tty; { - char *p; - void *hdl; - void (*sym)(); + if (remote_get_class_name_val == NULL) + error ("This version of Magic Cap lacks the runtime support for \"dobj\"."); - if (arg == 0) { - error ("No arguments specified."); - return; - } - p = arg; - while(*p != ' ' && *p != '\0') - p++; - if (*p != ' ') { - error ("Not enough arguments."); - return; - } - *p++ = '\0'; + print_object (args, 1); +} - hdl = dlopen(arg, RTLD_NOW); - if (hdl == NULL) { - fprintf(stderr, "%s: %s\n", arg, dlerror()); - return; - } - sym = dlsym(hdl, p); +/* This is the GDB handler for the "pobj" command, which prints a + brief description of an object. ARGS is a string containing an + expression for the object ID, and FROM_TTY is nonzero if the + command was issued interactively. */ - if (sym == NULL) { - fprintf(stderr, "%s: %s\n", p, dlerror()); - return; - } +/* ARGSUSED */ +static void +pobj_command (args, from_tty) + char *args; + int from_tty; +{ + if (remote_get_class_name_val == NULL) + error ("This version of Magic Cap lacks the runtime support for \"pobj\"."); - sym(); + print_object (args, 0); } -#endif +/* This is the GDB handler for the "cdump" command, which prints a + description of a cluster. ARGS is a string containing a cluster + selector, and FROM_TTY is nonzero if the command was issued + interactively. + + cdump [/l[ocked]] [/s[tartAddr] ] + [/c[lass] | ] */ + +/* ARGSUSED */ static void -local_shell_escape (char *arg) +cdump_command (args, from_tty) + char *args; + int from_tty; { -#ifdef CANT_FORK - /* FIXME: what about errors (I don't know how GO32 system() handles - them)? */ - system (arg); -#else /* Can fork. */ - int rc, status, pid; - char *p, *user_shell; + char *token; + unsigned long cluster; + CORE_ADDR min_object; + long display_only_locked; + long filter_classes; + long display_only_class_number; + char *display_only_class_name; - if ((user_shell = (char *) getenv ("SHELL")) == NULL) - user_shell = "/bin/sh"; + if (args == NULL) + error_no_arg ("expression for context slot to dump"); - /* Get the name of the shell for arg0 */ - if ((p = strrchr (user_shell, '/')) == NULL) - p = user_shell; - else - p++; /* Get past '/' */ + token = strtok (args, " \t"); + if (token[0] == '/') + error ("The first argument to cdump must be an expression for the context slot to dump."); - if ((pid = fork()) == 0) + cluster = parse_and_eval_address (token); + + /* Initialize option values. Note that we assume that + sizeof (long) == sizeof (void *) here, in that we pass + min_object as a long, even though it is a pointer. */ + + min_object = 0; + display_only_locked = 0; + filter_classes = 0; + display_only_class_name = NULL; + display_only_class_number = 0; + + while ((token = strtok (NULL, " \t")) != NULL) { - if (!arg) - execl (user_shell, p, 0); - else - execl (user_shell, p, "-c", arg, 0); + if (token[0] != '/') + goto bad_option; - fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell, - safe_strerror (errno)); - gdb_flush (gdb_stderr); - _exit (0177); + switch (token[1]) + { + case 'l': + if (token[2] && strcmp (token + 1, "locked")) + goto bad_option; + + display_only_locked = 1; + break; + + case 's': + if (token[2] && strcmp (token + 1, "startAddr")) + goto bad_option; + + if ((token = strtok (NULL, " \t")) == NULL) + error ("Missing start address expression for `/s' option."); + + min_object = parse_and_eval_address (token); + break; + + case 'c': + if (token[2] && strcmp (token + 1, "class")) + goto bad_option; + + if ((token = strtok (NULL, " \t")) == NULL) + error ("Missing class name or number for `/c' option."); + + filter_classes = 1; + if (isdigit (token[0])) + display_only_class_number = parse_and_eval_address (token); + else + display_only_class_name = token; + + break; + + default: + goto bad_option; + } } - if (pid != -1) - while ((rc = wait (&status)) != pid && rc != -1) - ; + if (display_only_class_name != NULL) + error ("Sorry, `/c ' isn't supported yet."); + + (void)call_function_by_name ("cdump", 6, cluster, min_object, + display_only_locked, + filter_classes, display_only_class_number, + display_only_class_name); + return; + +bad_option: + error ("Invalid option: `%s'.", token); +} + +/* This is the GDB handler for the "esc" command, which lists the + exception handlers for a given actor. ARGS is a string containing + an expression for the objectID of the actor in question, and FROM_TTY + is nonzero if the command was issued interactively. */ + +/* ARGSUSED */ +static void +esc_command (args, from_tty) + char *args; + int from_tty; +{ + unsigned long object; + + if (args == NULL) + error_no_arg ("expression for actor's object ID"); + + object = parse_and_eval_address (args); + (void)call_function_by_name ("esc", 1, object); +} + +/* This is the GDB handler for the "cnum" command, which converts + a class number to a class name. ARGS is a string containing an + expression for the class number, and FROM_TTY is nonzero if the + command was issued interactively. */ + +/* ARGSUSED */ +static void +cnum_command (args, from_tty) + char *args; + int from_tty; +{ + unsigned long cnum; + + if (args == NULL) + error_no_arg ("expression for class number"); + + cnum = parse_and_eval_address (args); + (void)call_function_by_name ("cnum", 1, cnum); +} + +/* This is the GDB handler for the "getint" command, which converts an + intrinsic operation number to the corresponding intrinsic operation name, + or vice-versa. ARGS is a string containing the intrinsic number or name, + and FROM_TTY is nonzero if the command was issued interactively. */ + +/* ARGSUSED */ +static void +getint_command (args, from_tty) + char *args; + int from_tty; +{ + char shell_command[256]; + + if (args == NULL) + error_no_arg ("intrinsic operation number or name"); + + if (isdigit (args[0])) + sprintf (shell_command, "getint %ld", parse_and_eval_address (args)); else - error ("Fork failed"); -#endif /* Can fork. */ + sprintf (shell_command, "getint %s", args); + + local_shell_escape (shell_command); } +/* This is the GDB handler for the "getop" command, which converts an + operation number to the corresponding operation name, or vice-versa. + ARGS is a string containing the operation number or name, and FROM_TTY + is nonzero if the command was issued interactively. */ + +/* ARGSUSED */ static void -GetClassName(long objectID, char* name) +getop_command (args, from_tty) + char *args; + int from_tty; { - register value_ptr val; - register struct symbol *sym; - struct minimal_symbol *msymbol; - struct type *type; - value_ptr blocklen; - LONGEST maddr; + char shell_command[256]; + CORE_ADDR op_number; - /* Find the address of RemoteGetClassName in the inferior. */ + if (args == NULL) + error_no_arg ("operation number or name"); - sym = lookup_symbol ("RemoteGetClassName", 0, VAR_NAMESPACE, 0, NULL); - if (sym != NULL) + if (isdigit (args[0])) + sprintf (shell_command, "getop %ld", parse_and_eval_address (args)); + else + sprintf (shell_command, "getop %s", args); + + local_shell_escape (shell_command); +} + +/* This is the GDB handler for the "getindexical" command, which converts + an indexical number to the corresponding indexical name, or vice-versa. + ARGS is a string containing the indexical number or name, and FROM_TTY + is nonzero if the command was issued interactively. */ + +/* ARGSUSED */ +static void +getindexical_command (args, from_tty) + char *args; + int from_tty; +{ + char shell_command[256]; + + if (args == NULL) + error_no_arg ("indexical number or name"); + + if (isdigit (args[0])) + sprintf (shell_command, "getindexical 0x%lx", + parse_and_eval_address (args)); + else + sprintf (shell_command, "getindexical %s", args); + + local_shell_escape (shell_command); +} + +/* This is the GDB handler for the "exc" command, which converts an + exception number to the corresponding exception name, or vice-versa. + ARGS is a string containing the exception number or name, and FROM_TTY + is nonzero if the command was issued interactively. + + FIXME why is this one "exc" instead of "getexc?" (inconsistent naming). */ + +/* ARGSUSED */ +static void +exc_command (args, from_tty) + char *args; + int from_tty; +{ + char shell_command[256]; + + if (args == NULL) + error_no_arg ("exception number or name"); + + if (isdigit (args[0])) + sprintf (shell_command, "getexc %ld", parse_and_eval_address (args)); + else + sprintf (shell_command, "getexc %s", args); + + local_shell_escape (shell_command); +} + +#ifdef DYNAMIC_COMMAND_SUPPORT +/* Open a dynamic library and invoke an entry point within it. + ARGS is a string containing the names of the dynamic library + and the symbolic entry point, separated by whitespace. */ + +/* ARGSUSED */ +static void +dlopen_command (args, from_tty) + char *args; + int from_tty; +{ + char *p; + void *hdl; + void (*sym)(); + + if (args == 0) { - if (SYMBOL_CLASS (sym) != LOC_BLOCK) - { - error ("\"RemoteGetClassName\" exists in this program but is not a function."); - } - val = value_of_variable (sym, NULL); + error ("No arguments specified."); + return; } - else + + p = args; + while (*p != ' ' && *p != '\0') + p++; + + if (*p != ' ') { - msymbol = lookup_minimal_symbol ("RemoteGetClassName", "", (struct objfile *) NULL); - if (msymbol != NULL) - { - type = lookup_pointer_type (builtin_type_char); - type = lookup_function_type (type); - type = lookup_pointer_type (type); - maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol); - val = value_from_longest (type, maddr); - } - else - { - error ("evaluation of this expression requires the program to have a function \"RemoteGetClassName\"."); - } + error ("Not enough arguments."); + return; } + *p++ = '\0'; - blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID); - val = call_function_by_hand (val, 1, &blocklen); - if (value_logical_not (val)) + hdl = dlopen (args, RTLD_NOW); + if (hdl == NULL) { - error ("Could not get class name."); + fprintf (stderr, "%s: %s\n", args, dlerror ()); + return; } - read_memory(value_as_pointer(val), name, 32); - + + sym = dlsym (hdl, p); + if (sym == NULL) + { + fprintf (stderr, "%s: %s\n", p, dlerror ()); + return; + } + + sym(); } +#endif /* DYNAMIC_COMMAND_SUPPORT */ -static CORE_ADDR -GetBasePtr(long objectID) +/* Given an object ID OBJECT, return a pointer to a type structure + representing the GDB type that describes the layout of the object's + fields in memory (i.e., the "_AllFields" structure corresponding + to the object's class). */ + +struct type * +type_of_object (object) + CORE_ADDR object; { - register value_ptr val; - register struct symbol *sym; - struct minimal_symbol *msymbol; + char *class_name = NULL; + char classAllFieldsName[128]; + struct type *type = NULL; + int is_scripted; + + get_class_name (object, &class_name, &is_scripted); + sprintf (classAllFieldsName, "%s_AllFields", class_name); + free (class_name); + + type = lookup_typename (classAllFieldsName, (struct block *)NULL, 0); + return lookup_pointer_type (type); +} + +/* Given OBJECT, an object ID, return the address of the object's + fixed fields. */ + +CORE_ADDR +baseptr_of_object (object) + unsigned long object; +{ + return get_base_ptr (object) + kSizeOfObjectHeader; +} + +/* Given an expression for an object ID, ARGS, print information about + the object--including its class, the values of its fixed fields, and + the values in its extra data block. */ + +/* ARGSUSED */ +static void +print_object (args, dump) + char *args; + int dump; +{ + CORE_ADDR addr; + unsigned long object, object_length; + char *class_name = NULL; + char class_all_fields_name[128]; struct type *type; - value_ptr blocklen; - LONGEST maddr; + int is_scripted; + struct cleanup *old_chain; - /* Find the address of RemoteGetBasePtr in the inferior. */ + if (args == NULL) + error_no_arg ("expression for object ID"); - sym = lookup_symbol ("RemoteGetBasePtr", 0, VAR_NAMESPACE, 0, NULL); - if (sym != NULL) + object = parse_and_eval_address (args); + + /* check for nilObject */ + + if (!object) { - if (SYMBOL_CLASS (sym) != LOC_BLOCK) - { - error ("\"RemoteGetBasePtr\" exists in this program but is not a function."); - } - val = value_of_variable (sym, NULL); + printf_filtered ("\"%s\" evaluates to nilObject.\n", args); + return; } - else + + /* allow shortcut for system object ids */ + + if (IsObjectID (object)) + object |= 1 << kIDBitUsable; + else if (object < 0x5000) + object |= (1 << kIDBitObject) | (1 << kIDBitUsable); /* 0x84000000 */ + + /* Get the name of the object's class, as well as the GDB type that + describes the layout of the object's fixed fields. */ + + get_class_name (object, &class_name, &is_scripted); + old_chain = make_cleanup (free_current_contents, &class_name); + + sprintf (class_all_fields_name, "%s_AllFields", class_name); + type = lookup_typename (class_all_fields_name, (struct block *)NULL, 1); + + /* Get pointer to object's fields. + FIXME: ADDR is actually an (ObjectHeader *); should use normal expression + evaluator to extract the length member, rather than hardwiring the + format of the structure in this code. */ + + addr = get_base_ptr (object); + object_length = read_memory_unsigned_integer (addr, 4); + object_length -= kSizeOfObjectHeader; + addr += kSizeOfObjectHeader; + + if (type == NULL || (TYPE_CODE (type) != TYPE_CODE_UNDEF + && !(TYPE_FLAGS (type) & TYPE_FLAG_STUB))) { - msymbol = lookup_minimal_symbol ("RemoteGetBasePtr", "", (struct objfile *) NULL); - if (msymbol != NULL) + if (dump) { - type = lookup_pointer_type (builtin_type_char); - type = lookup_function_type (type); - type = lookup_pointer_type (type); - maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol); - val = value_from_longest (type, maddr); + unsigned long fixed_length; + + printf_filtered ("Object 0x%08lx%s at address 0x%08lx of class %s\n", + object, (is_scripted) ? " (scripted)" : "", + addr, class_name); + + /* If the object has fixed fields, dump them. */ + + if (type != NULL) + { + value_ptr valptr = value_at_lazy (type, addr); + int histindex = record_latest_value (valptr); + + if (histindex >= 0) + printf_filtered ("$%d = ", histindex); + + value_print (valptr, gdb_stdout, 0, Val_prettyprint); + puts_filtered ("\n"); + fixed_length = TYPE_LENGTH (type); + } + else + fixed_length = 0; + + /* If the object's length is less than that of its fixed fields, + warn the user. */ + + if (object_length < fixed_length) + { + error ("Warning: object is too small (should be at least %d bytes, is %d bytes).", + fixed_length, object_length); + } + + /* Dump the object's extra data, if any. should_dump_extra_data () + filters out classes (e.g. Cluster) that have too much extra data + to be dumped usefully in this format. */ + + if (should_dump_extra_data (class_name)) + { + dump_extra_data (addr + fixed_length, + object_length - fixed_length); + } } else { - error ("evaluation of this expression requires the program to have a function \"RemoteGetBasePtr\"."); - } - } + struct type *pointer_type; + value_ptr valptr; + int histindex; - blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID); - val = call_function_by_hand (val, 1, &blocklen); - if (value_logical_not (val)) - { - error ("Could not get base pointer to object."); + pointer_type = lookup_pointer_type ((type == NULL) ? + builtin_type_void : type); + valptr = value_from_longest (pointer_type, addr); + + histindex = record_latest_value (valptr); + if (histindex >= 0) + printf_filtered ("$%d = ", histindex); + + value_print (valptr, gdb_stdout, 0, Val_prettyprint); + puts_filtered ("\n"); + } } - return value_as_pointer(val); + do_cleanups (old_chain); } +/* Get the name of the class of the object referenced by OBJECTID. + *NAME is set to a pointer to the string containing the class + name; it is the caller's responsibility to free the memory for + the string. *IS_SCRIPTED is set to nonzero if the object is + scripted, zero otherwise. */ + static void -dump_extra_data(CORE_ADDR addr, ulong length) +get_class_name (objectID, name, is_scripted) + unsigned long objectID; + char **name; + int *is_scripted; { - ulong buf[5], chunk, i; - char *p; - - while (length > 3) { - chunk = (length > 16) ? 16 : length; - - memset(buf, 0, 5*sizeof(long)); - read_memory(addr, &buf, chunk); - fprintf(gdb_stdout, "%08lx %08lx %08lx %08lx | ", buf[0], - buf[1], buf[2], buf[3]); - for (i = 0, p = (char*)buf; i < chunk; i++, p++) { - if (!isprint(*p)) - *p = '.'; - } - fprintf(gdb_stdout, "%s |\n", buf); - addr += chunk; - length -= chunk; + value_ptr val; + int errno_val; + + val = call_function_by_value (remote_get_class_name_val, 1, objectID); + + /* As RemoteGetClassName() is currently (9/21/95) written, an empty string, + rather than a nil pointer, is returned upon failure. I'm leaving the + value_logical_not test in anyway, though, just for added robustness. */ + + if (!value_logical_not (val)) + { + (void)target_read_string (value_as_pointer (val), name, 256, &errno_val); + if (errno_val) + error ("Can't read class name for object 0x%08lx.", objectID); + + if (**name) + { + char *scripted_suffix; + + if ((scripted_suffix = strstr (*name, " (scripted)")) != NULL) + { + *scripted_suffix = '\0'; + *is_scripted = 1; + } + else + *is_scripted = 0; + + return; } + else + free (*name); + } + + error ("Bad object ID: 0x%08lx.", objectID); } -struct type *type_of_object(CORE_ADDR object) +/* Given an object ID, return a pointer to the object's data. */ + +static CORE_ADDR +get_base_ptr (objectID) + unsigned long objectID; { - char className[32], classAllFieldsName[128]; - struct type *type = NULL; - GetClassName(object, className); - sprintf(classAllFieldsName, "%s_AllFields", className); + register value_ptr val; + + val = call_function_by_value (remote_get_base_ptr_val, 1, objectID); + + if (value_logical_not (val)) + error ("Could not get base pointer to object."); - type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0); - return lookup_pointer_type(type); + return value_as_pointer (val); } -CORE_ADDR baseptr_of_object(ulong object) +/* Return nonzero if we should dump the extra data for an object + of class CLASS_NAME. + + FIXME this only works for explicitly named classes, and doesn't + handle subclasses. */ + +static int +should_dump_extra_data (class_name) + char *class_name; { - return GetBasePtr(object) + 12; + int i; + char **name; + static char *dont_dump_extra_classes[] = + { + "Cluster" + }; + + for (i = 0, name = dont_dump_extra_classes; + i < ARRAY_NELEMENTS(dont_dump_extra_classes); + i++, name++) + { + if (!strcmp (class_name, *name)) + return 0; + } + + return 1; } -/* ARGSUSED */ +/* Given ADDR, the address of an object's extra data block, and LENGTH, + the length of that block in bytes, dump the object's extra data to + standard output. */ + static void -print_object (arg, dump) - char *arg; - int dump; +dump_extra_data (addr, length) + CORE_ADDR addr; + unsigned long length; { - CORE_ADDR addr; - ulong object, objectLength, typeLength = 0; - char className[32], classAllFieldsName[128]; - struct type* type = NULL; - - object = parse_and_eval_address(arg); - - GetClassName(object, className); - sprintf(classAllFieldsName, "%s_AllFields", className); - - type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0); - typeLength = TYPE_LENGTH(type); - addr = GetBasePtr(object); - read_memory(addr, &objectLength, 4); - objectLength -= 12; - addr += 12; - if (TYPE_CODE(type) != TYPE_CODE_UNDEF && !(TYPE_FLAGS(type)&TYPE_FLAG_STUB)) { - if (dump) { - value_ptr valptr = value_at_lazy(type, addr); - int histindex = record_latest_value(valptr); - printf_filtered("Object 0x%08lx at address 0x%08lx of class %s\n", - object, addr, className); - if (histindex >= 0) printf_filtered ("$%d = ", histindex); - value_print(valptr, gdb_stdout, 0, Val_prettyprint); - objectLength -= typeLength; - addr += typeLength; - printf_filtered("\n"); - dump_extra_data(addr, objectLength); - printf_filtered("\n"); - } else { - value_ptr valptr = value_from_longest(lookup_pointer_type(type), addr); - int histindex = record_latest_value(valptr); - if (histindex >= 0) printf_filtered ("$%d = ", histindex); - value_print(valptr, gdb_stdout, 0, Val_prettyprint); - printf_filtered("\n"); - } + unsigned long buf[5]; + int chunk; + int chunk_longs; + int i; + int bytes_printed; + char *p; + + bytes_printed = 0; + + while (length > 3 && bytes_printed < extra_data_max) + { + QUIT; /* allow user to interrupt dump */ + + /* read a chunk of extra data */ + + chunk = (length > 16) ? 16 : length; + memset (buf, 0, sizeof (buf)); + read_memory (addr, (char *) &buf, chunk); + + /* format data as hex longwords */ + + chunk_longs = chunk >> 2; + for (i = 0; i < chunk_longs; i++) + printf_filtered ("%08lx ", + extract_unsigned_integer (buf + i, sizeof (long))); + + /* pad to 4 longs */ + + for (i = chunk_longs; i < 4; i++) + puts_filtered (" "); + + puts_filtered ("| "); + + /* format data as ascii bytes */ + + for (i = 0, p = (char*)buf; i < chunk; i++, p++) + { + if (!isprint (*p)) + *p = '.'; } -} + printf_filtered ("%s |\n", buf); -/* ARGSUSED */ -static void -dobj_command (arg, from_tty) - char *arg; - int from_tty; -{ - print_object(arg, 1); + addr += chunk; + length -= chunk; + bytes_printed += chunk; + } + + if (length > 0) + printf_filtered ("(%d bytes of extra data remaining but not displayed.)\n", + length); } -/* ARGSUSED */ -static void -pobj_command (arg, from_tty) - char *arg; - int from_tty; +/* Given the name of a function in the target program and a list of + long arguments, call the function and return a pointer to a value + object describing the function's return value. NAME is a string + containing the name of the function to be called; NARGS is the + number of arguments to the function; and the remaining parameters + are the arguments to passed to the function, all assumed to be of + type long. */ + +static value_ptr +#ifdef ANSI_PROTOTYPES +call_function_by_name (char *function_name, int nargs, ...) +#else +call_function_by_name (va_alist) + va_dcl +#endif { - print_object(arg, 0); + va_list args; + value_ptr return_value; + value_ptr function_value; +#ifndef ANSI_PROTOTYPES + char *function_name; + int nargs; + + va_start (args); + function_name = va_arg (args, char *); + nargs = va_arg (args, int); +#else + va_start (args, nargs); +#endif + + /* Find the address of function NAME in the inferior. */ + + if (!lookup_text_label (function_name, &function_value)) + error ("Execution of this command requires the debugged program to have a function \"%s.\"", + function_name); + + /* Call the function. */ + + return_value = vcall_function_by_value (function_value, nargs, args); + va_end (args); + + return return_value; } -/* ARGSUSED */ -static void -getint_command (arg, from_tty) - char *arg; - int from_tty; +/* Given a value object describing a function in the target program and + a list of long arguments, call the function and return a pointer to a + value object describing the function's return value. FUNCTION_VALUE + is a pointer to a value struct describing the function; NARGS is the + number of arguments to the function; and the remaining parameters are + the arguments to passed to the function, all assumed to be of type long. */ + +static value_ptr +#ifdef ANSI_PROTOTYPES +call_function_by_value (value_ptr function_value, int nargs, ...) +#else +call_function_by_value (va_alist) + va_dcl +#endif { - char shellCommand[128]; - - sprintf(shellCommand, "getint %s", arg); - local_shell_escape(shellCommand); + va_list args; + value_ptr return_value; +#ifndef ANSI_PROTOTYPES + value_ptr function_value; + int nargs; + + va_start (args); + function_value = va_arg (args, value_ptr); + nargs = va_arg (args, int); +#else + va_start (args, nargs); +#endif + + /* Call the function and return its return value. */ + + return_value = vcall_function_by_value (function_value, nargs, args); + va_end (args); + + return return_value; } -/* ARGSUSED */ -static void -getindexical_command (arg, from_tty) - char *arg; - int from_tty; +/* Helper routine for call_function_by_name and call_function_by_value + above. This function does the work of collecting the function + arguments into an array of value objects, and then invoking + call_function_by_hand to do the real work. FUNCTION_VALUE is a + pointer to a value object describing the function to be called, + NARGS is the number of arguments to the function, and ARGS is a + list (va_list) of the arguments to the function, all assumed to + be of type long. + + Returns a pointer to a value object describing the return value + of the function. */ + +static value_ptr +vcall_function_by_value (function_value, nargs, args) + value_ptr function_value; + int nargs; + va_list args; { - char shellCommand[128]; + value_ptr *arg_values; + value_ptr return_value; + struct cleanup *old_chain; + int i; + + /* Construct a vector of value objects describing the arguments + to the function to be called. */ + + arg_values = (value_ptr *) xmalloc (nargs * sizeof (value_ptr)); + old_chain = make_cleanup (free_current_contents, &arg_values); + + for (i = 0; i < nargs; i++) + arg_values[i] = value_from_longest (builtin_type_long, + (LONGEST) va_arg (args, unsigned long)); + + /* Call the function and return its return value. */ - sprintf(shellCommand, "getindexical %s", arg); - local_shell_escape(shellCommand); + return_value = call_function_by_hand (function_value, nargs, arg_values); + do_cleanups (old_chain); + return return_value; } -/* ARGSUSED */ +/* Invoke a shell, supplying ARG as the command to be executed. */ + static void -exc_command (arg, from_tty) +local_shell_escape (arg) char *arg; - int from_tty; { - char shellCommand[128]; - ulong exception; - - sprintf(shellCommand, "getexc %s", arg); - local_shell_escape(shellCommand); +#ifdef CANT_FORK + /* FIXME: what about errors (I don't know how GO32 system() handles + them)? */ + system (arg); +#else /* Can fork. */ + int rc, status, pid; + char *p, *user_shell; + + if ((user_shell = (char *) getenv ("SHELL")) == NULL) + user_shell = "/bin/sh"; + + /* Get the name of the shell for arg0 */ + if ((p = strrchr (user_shell, '/')) == NULL) + p = user_shell; + else + p++; /* Get past '/' */ + + if ((pid = fork()) == 0) + { + if (!arg) + execl (user_shell, p, 0); + else + execl (user_shell, p, "-c", arg, 0); + + fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell, + safe_strerror (errno)); + gdb_flush (gdb_stderr); + _exit (0177); + } + + if (pid != -1) + while ((rc = wait (&status)) != pid && rc != -1) + ; + else + error ("Fork failed"); +#endif /* Can fork. */ } -static CORE_ADDR dispatch_method_addr = -1, dispatch_inherited_addr = -1, dispatch_delegated_addr = -1, dispatch_intrinsic_addr = -1; -CORE_ADDR do_dispatch_method_addr = -1, do_dispatch_intrinsic_addr = -1; +/* Lookup NAME as a text label in the target program. If NAME is the + name of a function, and VAL_PTRPTR is not NULL, a pointer to a value + object describing the function is stored at VAL_PTRPTR. + + Returns the text address to which the label refers, or 0 if the + label is not found in the target program. */ static CORE_ADDR -lookup_address(const char *name) +lookup_text_label (name, val_ptrptr) + char *name; + value_ptr *val_ptrptr; { - struct symbol *sym = lookup_symbol(name, NULL, VAR_NAMESPACE, NULL, NULL); - if (sym) - return BLOCK_START(SYMBOL_BLOCK_VALUE(sym)); + struct symbol *sym; + CORE_ADDR addr; + + addr = 0; + + /* Try looking up NAME as a first-class symbol. */ + + sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL); + if (sym != NULL) + { + switch (SYMBOL_CLASS (sym)) + { + case LOC_BLOCK: + addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); + if (val_ptrptr != NULL) + *val_ptrptr = value_of_variable (sym, NULL); + + break; + + case LOC_STATIC: + case LOC_LABEL: + addr = SYMBOL_VALUE_ADDRESS (sym); + break; + } + } else { -/* printf("Couldn't find %s!\n", name); */ - return -1; + struct minimal_symbol *msymbol; + struct type *type; + + /* Try to find a minimal symbol for NAME. */ + + msymbol = lookup_minimal_symbol (name, "", (struct objfile *) NULL); + if (msymbol != NULL) + { + addr = SYMBOL_VALUE_ADDRESS (msymbol); + if (val_ptrptr != NULL) + { + type = lookup_pointer_type (builtin_type_char); + type = lookup_function_type (type); + type = lookup_pointer_type (type); + *val_ptrptr = value_from_longest (type, addr); + } + } } + return addr; } -void -init_magic() -{ - dispatch_method_addr = lookup_address("__DispatchMethod"); - dispatch_inherited_addr = lookup_address("__DispatchInherited"); - dispatch_delegated_addr = lookup_address("__DispatchDelegated"); - dispatch_intrinsic_addr = lookup_address("__DispatchIntrinsic"); - do_dispatch_method_addr = lookup_address("__DoTheDispatch"); - do_dispatch_intrinsic_addr = lookup_address("__DoDispatchIntrinsic"); -} +/* The following two routines adapt GDB's framework for stepping over + shared library trampoline code to the problem of stepping over the + Magic Cap method dispatcher. While the method dispatcher is not a + shared library trampoline, we can use the interfaces for controlling + stepping over trampolines to do what we want. */ -int -is_dispatch(CORE_ADDR pc) -{ - return (pc == dispatch_method_addr) || (pc == dispatch_inherited_addr) || (pc == dispatch_delegated_addr); -} +/* Return nonzero if STOP_PC is within the Magic Cap method dispatcher. + NAME is unused. This function serves as the implementation of both + IN_SOLIB_CALL_TRAMPOLINE() and IN_SOLIB_RETURN_TRAMPOLINE() when GDB + is configured to target Magic Cap. We don't need to distinguish + between the two types of trampolines (because they're not really + trampolines); we just need to tell GDB to set a breakpoint at the + site of the next "hop" on our way through the dispatcher, and to + keep going. */ int -is_dispatch_intrinsic(CORE_ADDR pc) +magic_in_dispatcher (stop_pc, name) + CORE_ADDR stop_pc; + char *name; { - return pc == dispatch_intrinsic_addr; + return magic_step_enabled + && (is_dispatcher_entry (stop_pc) || is_dispatcher_exit (stop_pc)); } -/* If we are stopped at one of the entry points to the dispatcher, we want to continue until just - before we jump to the implementation. If we are at that point, we want to continue until we - actually get to the implementation. Likewise for the intrinsic dispatcher - */ +/* Determine if STOP_PC is an address within the Magic Cap method + dispatcher, and if so, return the address at which GDB should set + a step resume breakpoint in order to skip over the dispatcher code. + In fact, we have to skip over the dispatcher in two separate "hops:" + the first hop gets us from a dispatcher entry point to the dispatcher + exit site; the second hop gets us from this exit site to the first + instruction of the method. + + This function serves as the implementation of SKIP_TRAMPOLINE_CODE() + when GDB is configured to target Magic Cap. */ + CORE_ADDR -deal_with_dispatch(CORE_ADDR stop_pc) +magic_skip_dispatcher (stop_pc) + CORE_ADDR stop_pc; { - if (is_dispatch(stop_pc)) - return do_dispatch_method_addr; - else if (is_dispatch_intrinsic(stop_pc)) - return do_dispatch_intrinsic_addr; - else if (stop_pc == do_dispatch_method_addr) - /* This assumes that we branch through t6 */ - return read_register(14); - else if (stop_pc == do_dispatch_intrinsic_addr) - /* This assumes that we branch through t0 */ - return read_register(8); + /* If magic stepping is disabled, return 0, indicating that GDB should + process this step event normally. This will have the effect of + allowing the user to step through the dispatcher code itself. */ + + if (!magic_step_enabled) + return 0; + + /* If the program is stopped at an entry point to the dispatcher, + tell GDB to set a breakpoint at a well-known label in the + dispatcher where we will be able to determine the address of + the method to which we are dispatching. Note that the dispatcher + has hair to ensure that the code at this label is executed when we + are completing a top-level dispatch; recursive dispatches generated + from within the dispatcher do not exit through this code. */ + + if (is_dispatcher_entry (stop_pc)) + return DO_DISPATCH_METHOD_ADDR; + + /* If we have hit the breakpoint set previously at a dispatcher exit site, + determine the method address and tell GDB to set a breakpoint there. */ + + else if (is_dispatcher_exit (stop_pc)) + return read_register (14); /* assumes that we branch through t6 */ else return 0; } +/* Return nonzero if PC is an entry point to the Magic Cap method + dispatcher. */ + +static int +is_dispatcher_entry (pc) + CORE_ADDR pc; +{ + return pc == DISPATCH_METHOD_ADDR + || pc == DISPATCH_INTRINSIC_ADDR + || pc == DISPATCH_INHERITED_ADDR + || pc == DISPATCH_DELEGATED_ADDR; +} + +/* Return nonzero if PC is an exit site from the Magic Cap method + dispatcher. */ + +static int +is_dispatcher_exit (pc) + CORE_ADDR pc; +{ + return pc == DO_DISPATCH_METHOD_ADDR; +} + +/* Store away addresses in the inferior we need to control single-stepping + through Magic Cap method dispatches, as well as other addresses of + interest in Magic Cap. */ + void -magic_create_inferior_hook() +init_magic () { - struct symbol *sym = lookup_symbol("gHandleError", NULL, VAR_NAMESPACE, NULL, NULL); - if (sym) - { - CORE_ADDR addr = SYMBOL_VALUE(sym); - unsigned long errorDebugger = 2; - target_write_memory(addr, &errorDebugger, 4); - } - - init_magic (); + struct text_label *label; + int i; + + /* Cache method dispatch label addresses. */ + + for (i = 0, label = dispatch_labels; + i < ARRAY_NELEMENTS (dispatch_labels); + i++, label++) + { + if (!(label->addr = lookup_text_label (label->name, NULL))) + { + /* If we can't find all of the dispatcher addresses, don't attempt + to do magic stepping. */ + + magic_step_enabled = 0; + break; + } + } + + /* Cache value objects for RemoteGetClassName () and RemoteGetBasePtr (), + which are used to implement the "dobj" and "pobj" commands. Note that + we must call release_value () on these values to prevent GDB from freeing + them automatically. */ + + if (remote_get_class_name_val != NULL) + { + value_free (remote_get_class_name_val); + remote_get_class_name_val = NULL; + } + + if (remote_get_base_ptr_val != NULL) + { + value_free (remote_get_base_ptr_val); + remote_get_base_ptr_val = NULL; + } + + if (lookup_text_label ("RemoteGetClassName", &remote_get_class_name_val)) + { + release_value (remote_get_class_name_val); + + if (lookup_text_label ("RemoteGetBasePtr", &remote_get_base_ptr_val)) + release_value (remote_get_base_ptr_val); + } +} + +/* Hook routine called when an inferior (i.e., debugged) process is + created. */ + +void +magic_create_inferior_hook () +{ + struct symbol *sym = lookup_symbol ("gHandleError", NULL, VAR_NAMESPACE, + NULL, NULL); + if (sym) + { + CORE_ADDR addr = SYMBOL_VALUE (sym); + unsigned long errorDebugger = 2; + + target_write_memory (addr, (char *) &errorDebugger, 4); + } } +/* Initialization routine for magic.c. This is where we define debugger + commands specific to Magic Cap. */ +void _initialize_magic () { - add_com ("dobj", class_support, dobj_command, "Display Object Contents"); - add_com ("pobj", class_support, pobj_command, "Print object base pointer"); - add_com ("getint", class_support, getint_command, "Convert intrinsic name to number or vice versa."); - add_com ("getindexical", class_support, getindexical_command, "Convert indexical name to number or vice versa."); - add_com ("exc", class_support, exc_command, "Convert exception name to number or vice versa."); + add_com ("dobj", class_support, dobj_command, + "Display object contents.\n\ +Usage: dobj \n\ +Where: is an expression for the object ID to dump."); + + add_com ("pobj", class_support, pobj_command, + "Print object base pointer.\n\ +Usage: pobj \n\ +Where: is an expression for the object ID to examine."); + + add_com ("cdump", class_support, cdump_command, + concat ("Display the contents of a cluster.\n\ +Usage: cdump [/l[ocked]] [/s[tartAddr] ]\n\ + [/c[lass] ]\n\ +Where: is an expression describing the cluster to dump;\n\ + if is a number between 0x8 and 0xf, it is \n\ + interpreted as the high-order nibble of an object ID\n\ + belonging to the cluster to dump, with the second highest-\n\ + order nibble assumed to be 0. (For example, \"cdump 8\" and \n\ + \"cdump 0xa\" dump the System Persistent and Persistent RAM\n\ + clusters, respectively.)\n", + "\n\ + if is a number between 0xf0 and 0x100, it is\n\ + interpreted as the high-order byte of an object ID belonging to\n\ + the cluster to dump. (For example, \"cdump 0x88\" and \n\ + \"cdump 0xa8\" dump the Locked Persistent and Transient RAM\n\ + clusters, respectively.)\n", + "\n\ + /locked or /l indicates that only locked objects are to be displayed.\n\ +\n\ + /startAddr or /s indicates that only objects whose base pointers are\n\ + greater than or equal to the address specified by the following\n\ + expression () are to be displayed.\n\ +\n\ + /class or /c indicates that only objects of the class specified by\n\ + the following expression are to be displayed.", + NULL)); + + add_com ("esc", class_support, esc_command, + "List all the exception handlers for a given actor.\n\ +Usage: esc \n\ +Where: is an expression for the object ID of the actor\n\ + whose exception handlers are to be listed."); + + add_com ("cnum", class_support, cnum_command, + "Convert class number to name.\n\ +Usage: cnum \n\ +Where: is an expression for the class number to convert."); + + add_com ("getint", class_support, getint_command, + "Convert intrinsic name to number or vice versa.\n\ +Usage: getint | \n\ +Where: | is an intrinsic operation name\n\ + to be converted to an operation number, or an intrinsic operation\n\ + number to be converted to an operation name."); + + add_com ("getop", class_support, getop_command, + "Convert operation name to number or vice versa.\n\ +Usage: getop | \n\ +Where: | is an operation name to be\n\ + converted to an operation number, or an operation number to\n\ + be converted to an operation name."); + + add_com ("getindexical", class_support, getindexical_command, + "Convert indexical name to number or vice versa.\n\ +Usage: getindexical | \n\ +Where: | is an indexical name to be\n\ + converted to an an indexical number, or an indexical number\n\ + to be converted to an indexical name."); + + add_com ("exc", class_support, exc_command, + "Convert exception name to number or vice versa.\n\ +Usage: exc | \n\ +Where: | is an exception name to be\n\ + converted to an an exception number, or an exception number\n\ + to be converted to an exception name."); + + add_show_from_set + (add_set_cmd ("extra-data-max", class_support, var_uinteger, + (char *) &extra_data_max, + "Set limit on number of bytes of extra data to print.\n\ +This command sets an upper limit on the number of bytes of extra\n\ +data displayed by the \"dobj\" command when dumping a Magic Cap\n\ +object. \"set extra-data-max 0\" causes there to be no limit.", + &setlist), + &showlist); + + extra_data_max = EXTRA_DATA_MAX_DEFAULT; + + add_show_from_set + (add_set_cmd ("magic-step", class_support, var_boolean, + (char *) &magic_step_enabled, + "Set stepping over Magic Cap method dispatches.\n\ +When set to \"on\" (the default), issuing a \"step\" command at a Magic Cap\n\ +operation call site will cause the program to stop at the first line of\n\ +the corresponding method. Set this to \"off\" only if you need to debug\n\ +the dispatcher itself.", + &setlist), + &showlist); + + magic_step_enabled = 1; #ifdef DYNAMIC_COMMAND_SUPPORT add_com ("dlopen", class_support, dlopen_command, - "Load the dynamic library specified and execute the specified symbol"); + "Load the dynamic library specified and execute the specified symbol"); #endif } diff --git a/gdb/magic.h b/gdb/magic.h index 7ff366c75f0..ef8cf2eae48 100644 --- a/gdb/magic.h +++ b/gdb/magic.h @@ -1,6 +1,32 @@ /* magic.h - Interface to the General Magic debugger extras */ -extern void init_magic(); -extern CORE_ADDR deal_with_dispatch(CORE_ADDR pc); -extern struct type *type_of_object(CORE_ADDR object); -extern CORE_ADDR baseptr_of_object(CORE_ADDR object); +/* object framework definitions, from FrameworkDefines.asm.h and Generic.h */ + +#define kIDBitObject 31 /* set for valid object IDs */ +#define kIDBitUsable 26 /* set if objectID is usable */ + +/* Return nonzero if is a valid ObjectID */ + +#define IsObjectID(object) (((unsigned long)(object) & 0x80000000) != 0) + +#define kSizeOfObjectHeader 12 /* size of object header in bytes */ + +/* public interfaces */ + +extern void +init_magic PARAMS ((void)); + +extern void +magic_create_inferior_hook PARAMS ((void)); + +extern struct type * +type_of_object PARAMS ((CORE_ADDR object)); + +extern CORE_ADDR +baseptr_of_object PARAMS ((CORE_ADDR object)); + +extern int +magic_in_dispatcher PARAMS ((CORE_ADDR stop_pc, char *name)); + +extern CORE_ADDR +magic_skip_dispatcher PARAMS ((CORE_ADDR stop_pc)); diff --git a/gdb/parse.c b/gdb/parse.c index f22814b3502..316ab53c93c 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -600,9 +600,9 @@ length_of_subexp (expr, endpos) case STRUCTOP_STRUCT: case STRUCTOP_PTR: /* start-sanitize-gm */ -#ifdef GENERAL_MAGIC_HACKS +#ifdef GENERAL_MAGIC case STRUCTOP_FIELD: -#endif /* GENERAL_MAGIC_HACKS */ +#endif /* GENERAL_MAGIC */ /* end-sanitize-gm */ args = 1; /* fall through */ diff --git a/gdb/remote-mips.c b/gdb/remote-mips.c index 7514aa935fb..32655996fd1 100644 --- a/gdb/remote-mips.c +++ b/gdb/remote-mips.c @@ -1016,14 +1016,15 @@ mips_initialize_cleanups (arg) static void mips_initialize () { - char cr, cc; char buff[DATA_MAXLEN + 1]; int err; struct cleanup *old_cleanups = make_cleanup (mips_initialize_cleanups, NULL); + int j; /* What is this code doing here? I don't see any way it can happen, and it might mean mips_initializing didn't get cleared properly. So I'll make it a warning. */ + if (mips_initializing) { warning ("internal error: mips_initialize called twice"); @@ -1036,50 +1037,50 @@ mips_initialize () mips_send_seq = 0; mips_receive_seq = 0; - if (mips_receive_packet (buff, 0, 3) < 0) - { - char cc; - int i, j; - char srec[10]; - - /* We did not receive the packet we expected; try resetting the - board and trying again. */ + /* At this point, the packit protocol isn't responding. We'll try getting + into the monitor, and restarting the protocol. */ - /* Force the system into the IDT monitor. After this we *should* be at - the prompt. */ + /* Force the system into the IDT monitor. After this we *should* be at the + prompt. */ - for (j = 1; j <= 4; j++) + for (j = 1; j <= 4; j++) + { + switch (j) { - switch (j) - { - case 1: /* First, try sending a break */ - SERIAL_SEND_BREAK (mips_desc); - break; - case 2: /* Then, try a ^C */ - SERIAL_WRITE (mips_desc, "\003", 1); /* Send a ^C to wake up the monitor */ - break; - case 3: /* Then, try escaping from download */ - /* We are possibly in binary download mode, having aborted in the middle - of an S-record. ^C won't work because of binary mode. The only - reliable way out is to send enough termination packets (8 bytes) to - fill up and then overflow the largest size S-record (255 bytes in this - case). This amounts to 256/8 + 1 packets. */ - - mips_make_srec (srec, '7', 0, NULL, 0); - - for (i = 1; i <= 33; i++) - { - SERIAL_WRITE (mips_desc, srec, 8); - - if (SERIAL_READCHAR (mips_desc, 0) >= 0) - break; /* Break immediatly if we get something from + case 1: /* First, try sending a break */ + SERIAL_SEND_BREAK (mips_desc); + break; + case 2: /* Then, try a ^C */ + SERIAL_WRITE (mips_desc, "\003", 1); + break; + case 3: /* Then, try escaping from download */ + { + int i; + char srec[10]; + + /* We are possibly in binary download mode, having aborted in the + middle of an S-record. ^C won't work because of binary mode. + The only reliable way out is to send enough termination packets + (8 bytes) to fill up and then overflow the largest size S-record + (255 bytes in this case). This amounts to 256/8 + 1 packets. + */ + + mips_make_srec (srec, '7', 0, NULL, 0); + + for (i = 1; i <= 33; i++) + { + SERIAL_WRITE (mips_desc, srec, 8); + + if (SERIAL_READCHAR (mips_desc, 0) >= 0) + break; /* Break immediatly if we get something from the board. */ - } - break; - case 4: - mips_error ("Failed to initialize."); - } - if (mips_expect ("\015\012")) + } + break; + case 4: + mips_error ("Failed to initialize."); + } + + if (mips_expect (TARGET_MONITOR_PROMPT)) break; } @@ -1101,6 +1102,7 @@ mips_initialize () /* If this doesn't call error, we have connected; we don't care if the request itself succeeds or fails. */ + mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err, mips_receive_wait, NULL); set_current_frame (create_new_frame (read_fp (), read_pc ())); @@ -1219,12 +1221,12 @@ mips_resume (pid, step, siggnal) { /* start-sanitize-gm */ -#ifndef GENERAL_MAGIC_HACKS +#ifndef GENERAL_MAGIC if (siggnal != TARGET_SIGNAL_0) warning ("Can't send signals to a remote system. Try `handle %s ignore'.", target_signal_to_name (siggnal)); -#endif /* GENERAL_MAGIC_HACKS */ +#endif /* GENERAL_MAGIC */ /* end-sanitize-gm */ mips_request (step ? 's' : 'c', @@ -1677,14 +1679,14 @@ Can't pass arguments to remote MIPS board; arguments ignored."); /* FIXME: Should we set inferior_pid here? */ /* start-sanitize-gm */ -#ifdef GENERAL_MAGIC_HACKS +#ifdef GENERAL_MAGIC magic_create_inferior_hook (); proceed (entry_pt, TARGET_SIGNAL_PWR, 0); #else /* end-sanitize-gm */ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); /* start-sanitize-gm */ -#endif +#endif /* GENERAL_MAGIC */ /* end-sanitize-gm */ } @@ -1863,7 +1865,7 @@ common_breakpoint (cmd, addr, mask, flags) if (rerrflg != 0) { - if (rerrflg != EINVAL) + if (rresponse != EINVAL) fprintf_unfiltered (stderr, "common_breakpoint (0x%x): Got error: 0x%x\n", addr, rresponse); return 1;