diff options
author | nobody <> | 2002-05-06 21:00:22 +0000 |
---|---|---|
committer | nobody <> | 2002-05-06 21:00:22 +0000 |
commit | 275602c398b33b8475860af024b006bbbbd495ac (patch) | |
tree | 22412a7722268bd297101bcf3e788a3d585c020c /gdb/gdbserver | |
parent | 694b26b8e881dd7336e3c0634731f2eee1c1cda6 (diff) | |
download | gdb-275602c398b33b8475860af024b006bbbbd495ac.zip gdb-275602c398b33b8475860af024b006bbbbd495ac.tar.gz gdb-275602c398b33b8475860af024b006bbbbd495ac.tar.bz2 |
This commit was manufactured by cvs2svn to create branch 'jimb-jimb-macro-020506-branchpoint
macro-020506-branch'.
Sprout from gdb_5_2-branch 2002-03-27 05:12:36 UTC nobody 'This commit was manufactured by cvs2svn to create branch 'gdb_5_2-branch'.'
Cherrypick from gdb_5_2-branch 2002-03-02 23:00:05 UTC nobody 'This commit was manufactured by cvs2svn to create branch 'gdb_5_2-branch'.':
intl/ChangeLog
intl/Makefile.in
Cherrypick from master 2002-05-06 21:00:21 UTC Jim Blandy <jimb@codesourcery.com> 'Separate the job of reading the line number info statement program':
ChangeLog
MAINTAINERS
Makefile.in
bfd/ChangeLog
bfd/ChangeLog-9495
bfd/Makefile.am
bfd/Makefile.in
bfd/aix5ppc-core.c
bfd/aout-adobe.c
bfd/aout-target.h
bfd/aout-tic30.c
bfd/aoutx.h
bfd/archive.c
bfd/archures.c
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/bfd.c
bfd/binary.c
bfd/bout.c
bfd/coff-arm.c
bfd/coff-h8300.c
bfd/coff-mcore.c
bfd/coff-ppc.c
bfd/coff-rs6000.c
bfd/coff-sh.c
bfd/coff-z8k.c
bfd/coff64-rs6000.c
bfd/coffcode.h
bfd/cofflink.c
bfd/coffswap.h
bfd/config.bfd
bfd/configure
bfd/configure.in
bfd/cpu-h8300.c
bfd/cpu-i370.c
bfd/cpu-i386.c
bfd/cpu-mips.c
bfd/cpu-powerpc.c
bfd/cpu-s390.c
bfd/cpu-sh.c
bfd/cpu-sparc.c
bfd/dep-in.sed
bfd/doc/ChangeLog
bfd/doc/Makefile.in
bfd/dwarf2.c
bfd/ecoff.c
bfd/elf-bfd.h
bfd/elf-eh-frame.c
bfd/elf-hppa.h
bfd/elf-m10300.c
bfd/elf.c
bfd/elf32-arm.h
bfd/elf32-cris.c
bfd/elf32-hppa.c
bfd/elf32-hppa.h
bfd/elf32-i370.c
bfd/elf32-i386.c
bfd/elf32-m32r.c
bfd/elf32-m68k.c
bfd/elf32-mips.c
bfd/elf32-ppc.c
bfd/elf32-s390.c
bfd/elf32-sh.c
bfd/elf32-sh64.c
bfd/elf32-sparc.c
bfd/elf32-xstormy16.c
bfd/elf64-alpha.c
bfd/elf64-hppa.c
bfd/elf64-mips.c
bfd/elf64-mmix.c
bfd/elf64-ppc.c
bfd/elf64-ppc.h
bfd/elf64-s390.c
bfd/elf64-sh64.c
bfd/elf64-sparc.c
bfd/elf64-x86-64.c
bfd/elfarm-nabi.c
bfd/elflink.c
bfd/elflink.h
bfd/elfxx-ia64.c
bfd/elfxx-mips.c
bfd/elfxx-mips.h
bfd/elfxx-target.h
bfd/i386linux.c
bfd/i386msdos.c
bfd/i386os9k.c
bfd/ieee.c
bfd/ihex.c
bfd/libbfd-in.h
bfd/libbfd.c
bfd/libbfd.h
bfd/libcoff-in.h
bfd/libcoff.h
bfd/libecoff.h
bfd/libxcoff.h
bfd/linker.c
bfd/m68klinux.c
bfd/merge.c
bfd/mmo.c
bfd/nlm-target.h
bfd/oasys.c
bfd/opncls.c
bfd/pdp11.c
bfd/po/SRC-POTFILES.in
bfd/po/fr.po
bfd/ppcboot.c
bfd/reloc.c
bfd/rs6000-core.c
bfd/som.c
bfd/sparclinux.c
bfd/srec.c
bfd/sunos.c
bfd/syms.c
bfd/targets.c
bfd/tekhex.c
bfd/versados.c
bfd/version.h
bfd/vms.c
bfd/xcofflink.c
config.guess
config.sub
config/ChangeLog
config/acinclude.m4
config/mh-a68bsd
config/mh-apollo68
config/mh-cxux
config/mh-decstation
config/mh-dgux
config/mh-dgux386
config/mh-djgpp
config/mh-hp300
config/mh-hpux
config/mh-hpux8
config/mh-interix
config/mh-irix5
config/mh-irix6
config/mh-lynxrs6k
config/mh-mingw32
config/mh-ncr3000
config/mh-ncrsvr43
config/mh-necv4
config/mh-openedition
config/mh-riscos
config/mh-sco
config/mh-solaris
config/mh-sysv
config/mh-sysv4
config/mh-sysv5
config/mt-aix43
config/mt-alphaieee
config/mt-linux
configure
configure.in
gdb/ChangeLog
gdb/MAINTAINERS
gdb/Makefile.in
gdb/NEWS
gdb/PROBLEMS
gdb/README
gdb/acconfig.h
gdb/acinclude.m4
gdb/aclocal.m4
gdb/alpha-linux-tdep.c
gdb/alpha-nat.c
gdb/alpha-osf1-tdep.c
gdb/alpha-tdep.c
gdb/alpha-tdep.h
gdb/alphabsd-nat.c
gdb/alphafbsd-tdep.c
gdb/alphanbsd-nat.c
gdb/alphanbsd-tdep.c
gdb/arc-tdep.c
gdb/arch-utils.c
gdb/arch-utils.h
gdb/arm-tdep.c
gdb/arm-tdep.h
gdb/avr-tdep.c
gdb/bcache.c
gdb/blockframe.c
gdb/breakpoint.c
gdb/builtin-regs.c
gdb/builtin-regs.h
gdb/c-exp.y
gdb/c-lang.c
gdb/cli-out.c
gdb/cli/cli-cmds.c
gdb/cli/cli-decode.c
gdb/cli/cli-decode.h
gdb/cli/cli-dump.c
gdb/cli/cli-dump.h
gdb/cli/cli-script.c
gdb/coffread.c
gdb/command.h
gdb/completer.c
gdb/config.in
gdb/config/alpha/alpha-linux.mt
gdb/config/alpha/alpha-osf1.mt
gdb/config/alpha/nbsd.mh
gdb/config/alpha/nbsd.mt
gdb/config/alpha/nm-linux.h
gdb/config/alpha/nm-nbsd.h
gdb/config/alpha/nm-osf.h
gdb/config/alpha/tm-alpha.h
gdb/config/alpha/tm-alphalinux.h
gdb/config/alpha/tm-fbsd.h
gdb/config/alpha/tm-nbsd.h
gdb/config/arc/tm-arc.h
gdb/config/avr/avr.mt
gdb/config/djgpp/README
gdb/config/h8500/tm-h8500.h
gdb/config/i386/fbsd.mh
gdb/config/i386/i386gnu.mh
gdb/config/i386/i386lynx.mh
gdb/config/i386/i386v42mp.mh
gdb/config/i386/nbsd.mt
gdb/config/i386/nbsdelf.mt
gdb/config/i386/nm-fbsd.h
gdb/config/i386/nm-x86-64.h
gdb/config/i386/tm-linux.h
gdb/config/i386/x86-64linux.mt
gdb/config/i960/tm-i960.h
gdb/config/m32r/m32r.mt
gdb/config/m68k/m68klynx.mh
gdb/config/m68k/nbsd.mt
gdb/config/m68k/sun3os4.mh
gdb/config/m68k/tm-nbsd.h
gdb/config/mcore/tm-mcore.h
gdb/config/mips/vr5000.mt
gdb/config/mn10200/tm-mn10200.h
gdb/config/ns32k/nbsd.mt
gdb/config/pa/hppabsd.mh
gdb/config/pa/hppaosf.mh
gdb/config/pa/hpux1020.mh
gdb/config/pa/hpux11.mh
gdb/config/pa/hpux11w.mh
gdb/config/pa/tm-hppa.h
gdb/config/powerpc/nbsd.mt
gdb/config/powerpc/tm-ppc-eabi.h
gdb/config/rs6000/rs6000lynx.mh
gdb/config/rs6000/tm-rs6000.h
gdb/config/s390/s390.mh
gdb/config/s390/s390.mt
gdb/config/s390/s390x.mt
gdb/config/sparc/fbsd.mh
gdb/config/sparc/fbsd.mt
gdb/config/sparc/linux.mh
gdb/config/sparc/sparclynx.mh
gdb/config/sparc/sun4os4.mh
gdb/config/sparc/tm-linux.h
gdb/config/sparc/tm-sp64.h
gdb/config/sparc/tm-sp64linux.h
gdb/config/sparc/tm-sparc.h
gdb/config/v850/tm-v850.h
gdb/config/vax/tm-vax.h
gdb/configure
gdb/configure.host
gdb/configure.in
gdb/configure.tgt
gdb/core-sol2.c
gdb/corefile.c
gdb/corelow.c
gdb/cp-valprint.c
gdb/cris-tdep.c
gdb/d10v-tdep.c
gdb/d30v-tdep.c
gdb/dbxread.c
gdb/defs.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/doc/gdbint.texinfo
gdb/dwarf2cfi.c
gdb/dwarf2read.c
gdb/elfread.c
gdb/eval.c
gdb/event-top.c
gdb/exec.c
gdb/f-exp.y
gdb/f-lang.c
gdb/fbsd-proc.c
gdb/findvar.c
gdb/frame.c
gdb/frame.h
gdb/gcore.c
gdb/gdb-events.c
gdb/gdb-events.h
gdb/gdb-events.sh
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/gdbserver/Makefile.in
gdb/gdbserver/config.in
gdb/gdbserver/configure
gdb/gdbserver/configure.in
gdb/gdbserver/gdbreplay.c
gdb/gdbserver/inferiors.c
gdb/gdbserver/linux-arm-low.c
gdb/gdbserver/linux-i386-low.c
gdb/gdbserver/linux-ia64-low.c
gdb/gdbserver/linux-low.c
gdb/gdbserver/linux-low.h
gdb/gdbserver/linux-m68k-low.c
gdb/gdbserver/linux-mips-low.c
gdb/gdbserver/linux-ppc-low.c
gdb/gdbserver/linux-s390-low.c
gdb/gdbserver/linux-sh-low.c
gdb/gdbserver/linux-x86-64-low.c
gdb/gdbserver/mem-break.c
gdb/gdbserver/mem-break.h
gdb/gdbserver/regcache.c
gdb/gdbserver/regcache.h
gdb/gdbserver/remote-utils.c
gdb/gdbserver/server.c
gdb/gdbserver/server.h
gdb/gdbserver/target.c
gdb/gdbserver/target.h
gdb/gdbserver/utils.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/gnu-nat.c
gdb/gnu-v3-abi.c
gdb/go32-nat.c
gdb/gregset.h
gdb/h8300-tdep.c
gdb/h8500-tdep.c
gdb/hppa-tdep.c
gdb/hpread.c
gdb/i386-linux-tdep.c
gdb/i386-tdep.c
gdb/i386gnu-nat.c
gdb/i387-nat.c
gdb/i960-tdep.c
gdb/ia64-tdep.c
gdb/infcmd.c
gdb/inferior.h
gdb/inflow.c
gdb/infrun.c
gdb/jv-exp.y
gdb/kod.c
gdb/language.c
gdb/lin-lwp.c
gdb/linespec.c
gdb/linux-proc.c
gdb/m2-exp.y
gdb/m3-nat.c
gdb/m68hc11-tdep.c
gdb/m68klinux-nat.c
gdb/maint.c
gdb/mcore-tdep.c
gdb/mdebugread.c
gdb/mem-break.c
gdb/mi/ChangeLog
gdb/mi/mi-cmd-break.c
gdb/mi/mi-cmd-disas.c
gdb/mi/mi-cmd-stack.c
gdb/mi/mi-cmd-var.c
gdb/mi/mi-console.c
gdb/mi/mi-main.c
gdb/mi/mi-out.c
gdb/mi/mi-parse.c
gdb/minsyms.c
gdb/mips-tdep.c
gdb/mipsread.c
gdb/mn10300-tdep.c
gdb/monitor.c
gdb/ocd.c
gdb/p-exp.y
gdb/p-lang.c
gdb/p-lang.h
gdb/p-typeprint.c
gdb/p-valprint.c
gdb/parse.c
gdb/parser-defs.h
gdb/ppc-bdm.c
gdb/ppc-linux-nat.c
gdb/ppc-linux-tdep.c
gdb/ppc-tdep.h
gdb/printcmd.c
gdb/proc-api.c
gdb/regcache.c
gdb/regformats/reg-ppc.dat
gdb/regformats/reg-x86-64.dat
gdb/remote-array.c
gdb/remote-e7000.c
gdb/remote-es.c
gdb/remote-mips.c
gdb/remote-os9k.c
gdb/remote-rdi.c
gdb/remote-rdp.c
gdb/remote-st.c
gdb/remote-utils.c
gdb/remote-vxsparc.c
gdb/remote.c
gdb/rs6000-nat.c
gdb/rs6000-tdep.c
gdb/s390-tdep.c
gdb/scm-lang.c
gdb/ser-unix.h
gdb/serial.c
gdb/sh-tdep.c
gdb/solib-legacy.c
gdb/solib-svr4.c
gdb/solib.c
gdb/somread.c
gdb/source.c
gdb/sparc-nat.c
gdb/sparc-tdep.c
gdb/stabsread.c
gdb/stack.c
gdb/std-regs.c
gdb/symfile.c
gdb/symfile.h
gdb/symmisc.c
gdb/symtab.c
gdb/symtab.h
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/config/sid.exp
gdb/testsuite/gdb.asm/Makefile.in
gdb/testsuite/gdb.asm/asm-source.exp
gdb/testsuite/gdb.asm/configure
gdb/testsuite/gdb.asm/configure.in
gdb/testsuite/gdb.asm/powerpc.inc
gdb/testsuite/gdb.asm/sparc64.inc
gdb/testsuite/gdb.base/annota1.exp
gdb/testsuite/gdb.base/attach.exp
gdb/testsuite/gdb.base/bar.c
gdb/testsuite/gdb.base/baz.c
gdb/testsuite/gdb.base/completion.exp
gdb/testsuite/gdb.base/cvexpr.c
gdb/testsuite/gdb.base/dbx.exp
gdb/testsuite/gdb.base/default.exp
gdb/testsuite/gdb.base/dump.c
gdb/testsuite/gdb.base/dump.exp
gdb/testsuite/gdb.base/ending-run.exp
gdb/testsuite/gdb.base/foo.c
gdb/testsuite/gdb.base/funcargs.c
gdb/testsuite/gdb.base/funcargs.exp
gdb/testsuite/gdb.base/gcore.exp
gdb/testsuite/gdb.base/grbx.c
gdb/testsuite/gdb.base/help.exp
gdb/testsuite/gdb.base/list.exp
gdb/testsuite/gdb.base/long_long.exp
gdb/testsuite/gdb.base/maint.exp
gdb/testsuite/gdb.base/opaque.exp
gdb/testsuite/gdb.base/overlays.exp
gdb/testsuite/gdb.base/ovlymgr.c
gdb/testsuite/gdb.base/printcmds.exp
gdb/testsuite/gdb.base/ptype.exp
gdb/testsuite/gdb.base/relocate.c
gdb/testsuite/gdb.base/relocate.exp
gdb/testsuite/gdb.base/scope.exp
gdb/testsuite/gdb.base/shlib-call.exp
gdb/testsuite/gdb.base/step-test.exp
gdb/testsuite/gdb.base/watchpoint.exp
gdb/testsuite/gdb.base/whatis.exp
gdb/testsuite/gdb.c++/classes.exp
gdb/testsuite/gdb.c++/cplusfuncs.exp
gdb/testsuite/gdb.c++/hang.H
gdb/testsuite/gdb.c++/hang.exp
gdb/testsuite/gdb.c++/hang1.C
gdb/testsuite/gdb.c++/hang2.C
gdb/testsuite/gdb.c++/hang3.C
gdb/testsuite/gdb.c++/local.cc
gdb/testsuite/gdb.c++/local.exp
gdb/testsuite/gdb.c++/method.exp
gdb/testsuite/gdb.c++/misc.exp
gdb/testsuite/gdb.c++/ovldbreak.exp
gdb/testsuite/gdb.gdb/xfullpath.exp
gdb/testsuite/gdb.java/jmisc1.exp
gdb/testsuite/gdb.java/jmisc2.exp
gdb/testsuite/gdb.mi/ChangeLog
gdb/testsuite/gdb.mi/mi-var-cmd.exp
gdb/testsuite/gdb.mi/mi0-var-cmd.exp
gdb/testsuite/gdb.threads/linux-dp.exp
gdb/testsuite/gdb.trace/gdb_c_test.c
gdb/testsuite/lib/gdb.exp
gdb/thread-db.c
gdb/thread.c
gdb/top.c
gdb/top.h
gdb/tracepoint.c
gdb/tui/ChangeLog
gdb/tui/tui-out.c
gdb/ui-file.c
gdb/ui-out.c
gdb/utils.c
gdb/valarith.c
gdb/valops.c
gdb/valprint.c
gdb/value.h
gdb/varobj.c
gdb/vax-tdep.c
gdb/vax-tdep.h
gdb/version.in
gdb/win32-nat.c
gdb/x86-64-linux-nat.c
gdb/x86-64-tdep.c
gdb/x86-64-tdep.h
gdb/xcoffread.c
gdb/xstormy16-tdep.c
gdb/z8k-tdep.c
include/ChangeLog
include/coff/ChangeLog
include/coff/rs6k64.h
include/dyn-string.h
include/elf/ChangeLog
include/elf/dwarf2.h
include/floatformat.h
include/opcode/ChangeLog
include/opcode/i386.h
include/opcode/mips.h
include/opcode/pdp11.h
include/xregex2.h
libiberty/ChangeLog
libiberty/Makefile.in
libiberty/config.table
libiberty/configure
libiberty/configure.in
libiberty/cp-demangle.c
libiberty/dyn-string.c
libiberty/floatformat.c
libiberty/functions.texi
libiberty/hashtab.c
libiberty/hex.c
libiberty/splay-tree.c
libiberty/strtod.c
libiberty/xatexit.c
libiberty/xmalloc.c
ltmain.sh
mmalloc/ChangeLog
mmalloc/mmap-sup.c
opcodes/ChangeLog
opcodes/Makefile.am
opcodes/Makefile.in
opcodes/configure
opcodes/configure.in
opcodes/dep-in.sed
opcodes/i386-dis.c
opcodes/mips-dis.c
opcodes/mips-opc.c
opcodes/pdp11-dis.c
opcodes/pdp11-opc.c
opcodes/po/fr.po
opcodes/po/id.po
opcodes/ppc-opc.c
opcodes/s390-dis.c
opcodes/z8k-dis.c
opcodes/z8k-opc.h
opcodes/z8kgen.c
sim/ChangeLog
sim/MAINTAINERS
sim/arm/ChangeLog
sim/arm/wrapper.c
sim/common/ChangeLog
sim/common/callback.c
sim/igen/ChangeLog
sim/igen/gen.c
sim/igen/igen.c
sim/m68hc11/ChangeLog
sim/m68hc11/dv-m68hc11.c
sim/m68hc11/dv-m68hc11spi.c
sim/m68hc11/dv-m68hc11tim.c
sim/m68hc11/interp.c
sim/m68hc11/interrupts.c
sim/m68hc11/interrupts.h
sim/m68hc11/m68hc11_sim.c
sim/m68hc11/sim-main.h
sim/mips/ChangeLog
sim/mips/Makefile.in
sim/mips/configure
sim/mips/configure.in
sim/mips/cp1.c
sim/mips/interp.c
sim/mips/mips.igen
sim/mips/sim-main.h
sim/ppc/ChangeLog
sim/ppc/hw_disk.c
sim/ppc/ppc-instructions
sim/ppc/sim_calls.c
sim/z8k/ChangeLog
sim/z8k/writecode.c
Delete:
config/mh-irix4
config/mh-lynxos
config/mh-sun3
config/mh-vaxult2
config/mt-armpic
config/mt-elfalphapic
config/mt-i370pic
config/mt-ia64pic
config/mt-m68kpic
config/mt-papic
config/mt-ppcpic
config/mt-s390pic
config/mt-sparcpic
config/mt-x86pic
gdb/a29k-tdep.c
gdb/config/a29k/a29k-udi.mt
gdb/config/a29k/a29k.mt
gdb/config/a29k/tm-a29k.h
gdb/config/a29k/tm-vx29k.h
gdb/config/a29k/vx29k.mt
gdb/remote-adapt.c
gdb/remote-eb.c
gdb/remote-mm.c
gdb/remote-udi.c
gdb/signals.c
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthbasic.c
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthbasic.exp
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthcore.c
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthcore.exp
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthfork.c
gdb/testsuite/gdb.hp/gdb.threads-hp/usrthfork.exp
Diffstat (limited to 'gdb/gdbserver')
27 files changed, 1296 insertions, 205 deletions
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 9ed226eb..2c8cd33 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -83,20 +83,22 @@ READLINE_DEP = $$(READLINE_DIR) # -I. for config files. # -I${srcdir} for our headers. # -I$(srcdir)/../regformats for regdef.h. -INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../regformats +INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../regformats -I$(INCLUDE_DIR) # M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS # from the config/ directory. GLOBAL_CFLAGS = ${MT_CFLAGS} ${MH_CFLAGS} #PROFILE_CFLAGS = -pg +WARN_CFLAGS = -Wall + # CFLAGS is specifically reserved for setting from the command line # when running make. I.E. "make CFLAGS=-Wmissing-prototypes". CFLAGS = @CFLAGS@ # INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros. -INTERNAL_CFLAGS = ${CFLAGS} ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} \ - ${INCLUDE_CFLAGS} ${BFD_CFLAGS} +INTERNAL_CFLAGS = $(WARN_CFLAGS) ${CFLAGS} ${GLOBAL_CFLAGS} \ + ${PROFILE_CFLAGS} ${INCLUDE_CFLAGS} ${BFD_CFLAGS} # LDFLAGS is specifically reserved for setting from the command line # when running make. @@ -120,7 +122,10 @@ DEPFILES = @GDBSERVER_DEPFILES@ SOURCES = $(SFILES) TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS} -OBS = utils.o $(DEPFILES) server.o remote-utils.o regcache.o +OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \ + utils.o \ + mem-break.o \ + $(DEPFILES) # Prevent Sun make from putting in the machine type. Setting # TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1. @@ -195,8 +200,12 @@ maintainer-clean realclean: clean STAGESTUFF=${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES} init.c init.o version.c gdb +config.h: stamp-h ; @true +stamp-h: config.in config.status + CONFIG_FILES="" $(SHELL) ./config.status + Makefile: Makefile.in config.status - $(SHELL) ./config.status + CONFIG_HEADERS="" $(SHELL) ./config.status config.status: configure configure.srv $(SHELL) ./config.status --recheck @@ -225,12 +234,19 @@ unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET : regdat_sh = $(srcdir)/../regformats/regdat.sh regdef_h = $(srcdir)/../regformats/regdef.h regcache_h = $(srcdir)/regcache.h -server_h = $(srcdir)/server.h $(regcache_h) config.h +server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \ + $(srcdir)/mem-break.h -server.o: server.c $(server_h) +inferiors.o: inferiors.c $(server_h) +mem-break.o: mem-break.c $(server_h) +regcache.o: regcache.c $(server_h) $(regdef_h) remote-utils.o: remote-utils.c terminal.h $(server_h) +server.o: server.c $(server_h) +target.o: target.c $(server_h) utils.o: utils.c $(server_h) -regcache.o: regcache.c $(server_h) $(regdef_h) + +signals.o: ../signals/signals.c $(server_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER i387-fp.o: i387-fp.c $(server_h) @@ -246,14 +262,6 @@ linux-s390-low.o: linux-s390-low.c $(linux_low_h) $(server_h) linux-sh-low.o: linux-sh-low.c $(linux_low_h) $(server_h) linux-x86-64-low.o: linux-x86-64-low.c $(linux_low_h) $(server_h) -# OBSOLETE TARGETS -# OBSOLETE # low-lynx.o : ${srcdir}/low-lynx.c ${srcdir}/server.h -# OBSOLETE # low-nbsd.o : ${srcdir}/low-nbsd.c ${srcdir}/server.h -# OBSOLETE # low-sim.o : ${srcdir}/low-sim.c ${srcdir}/server.h -# OBSOLETE # low-sparc.o : $(srcdir)/low-sparc.c $(srcdir)/server.h -# OBSOLETE # low-sun3.o : $(srcdir)/low-sun3.c $(srcdir)/server.h -# OBSOLETE # low-hppabsd.o : $(srcdir)/low-hppabsd.c $(srcdir)/server.h - reg-arm.o : reg-arm.c $(regdef_h) reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh) sh $(regdat_sh) $(srcdir)/../regformats/reg-arm.dat reg-arm.c diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index e77d5a7..9d553f2 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -16,6 +16,9 @@ /* Define if you have the <sgtty.h> header file. */ #undef HAVE_SGTTY_H +/* Define if you have the <string.h> header file. */ +#undef HAVE_STRING_H + /* Define if you have the <sys/reg.h> header file. */ #undef HAVE_SYS_REG_H diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index c08d5c2..758d483 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -1105,7 +1105,7 @@ EOF fi -for ac_hdr in sgtty.h termio.h termios.h sys/reg.h +for ac_hdr in sgtty.h termio.h termios.h sys/reg.h string.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 @@ -1593,6 +1593,10 @@ cat >> $CONFIG_STATUS <<EOF EOF cat >> $CONFIG_STATUS <<\EOF +case x$CONFIG_HEADERS in +xconfig.h:config.in) +echo > stamp-h ;; +esac exit 0 EOF diff --git a/gdb/gdbserver/configure.in b/gdb/gdbserver/configure.in index 744aac2..db7e301 100644 --- a/gdb/gdbserver/configure.in +++ b/gdb/gdbserver/configure.in @@ -30,7 +30,7 @@ AC_PROG_INSTALL AC_HEADER_STDC -AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h) +AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h) . ${srcdir}/configure.srv @@ -66,4 +66,9 @@ GDBSERVER_DEPFILES="$srv_regobj $srv_tgtobj" AC_SUBST(GDBSERVER_DEPFILES) -AC_OUTPUT(Makefile) +AC_OUTPUT(Makefile, +[case x$CONFIG_HEADERS in +xconfig.h:config.in) +echo > stamp-h ;; +esac +]) diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c index ca10a06..65831b1 100644 --- a/gdb/gdbserver/gdbreplay.c +++ b/gdb/gdbserver/gdbreplay.c @@ -30,6 +30,12 @@ #include <ctype.h> #include <fcntl.h> #include <errno.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef HAVE_STRING_H +#include <string.h> +#endif /* Sort of a hack... */ #define EOL (EOF - 1) @@ -83,8 +89,6 @@ remote_close (void) void remote_open (char *name) { - extern char *strchr (); - if (!strchr (name, ':')) { fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); @@ -97,7 +101,6 @@ remote_open (char *name) int port; struct sockaddr_in sockaddr; int tmp; - struct protoent *protoent; int tmp_desc; port_str = strchr (name, ':'); @@ -126,10 +129,6 @@ remote_open (char *name) if (remote_desc == -1) perror_with_name ("Accept failed"); - protoent = getprotobyname ("tcp"); - if (!protoent) - perror_with_name ("getprotobyname"); - /* Enable TCP keep alive process. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); @@ -137,7 +136,7 @@ remote_open (char *name) /* Tell TCP not to delay small packets. This greatly speeds up interactive response. */ tmp = 1; - setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY, + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, (char *) &tmp, sizeof (tmp)); close (tmp_desc); /* No longer need this */ diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c new file mode 100644 index 0000000..774798d --- /dev/null +++ b/gdb/gdbserver/inferiors.c @@ -0,0 +1,105 @@ +/* Inferior process information for the remote server for GDB. + Copyright 2002 + Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + 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 <stdlib.h> + +#include "server.h" + +struct inferior_info +{ + int pid; + void *target_data; + void *regcache_data; + struct inferior_info *next; +}; + +static struct inferior_info *inferiors; +struct inferior_info *current_inferior; +int signal_pid; + +void +add_inferior (int pid) +{ + struct inferior_info *new_inferior + = (struct inferior_info *) malloc (sizeof (*new_inferior)); + + memset (new_inferior, 0, sizeof (*new_inferior)); + + new_inferior->pid = pid; + + new_inferior->next = inferiors; + inferiors = new_inferior; + + if (current_inferior == NULL) + current_inferior = inferiors; + + create_register_cache (new_inferior); + + if (signal_pid == 0) + signal_pid = pid; +} + +void +clear_inferiors (void) +{ + struct inferior_info *inf = inferiors, *next_inf; + + while (inf) + { + next_inf = inf->next; + + if (inf->target_data) + free (inf->target_data); + if (inf->regcache_data) + free_register_cache (inf); + + free (inf); + inf = next_inf; + } + + inferiors = NULL; +} + +void * +inferior_target_data (struct inferior_info *inferior) +{ + return inferior->target_data; +} + +void +set_inferior_target_data (struct inferior_info *inferior, void *data) +{ + inferior->target_data = data; +} + +void * +inferior_regcache_data (struct inferior_info *inferior) +{ + return inferior->regcache_data; +} + +void +set_inferior_regcache_data (struct inferior_info *inferior, void *data) +{ + inferior->regcache_data = data; +} diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index f873b07..2958fdf 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -26,22 +26,28 @@ #include <sys/reg.h> #endif -int num_regs = 16; +#define arm_num_regs 16 -int regmap[] = { +static int arm_regmap[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, }; -int -cannot_store_register (int regno) +static int +arm_cannot_store_register (int regno) { - return (regno >= num_regs); + return (regno >= arm_num_regs); } -int -cannot_fetch_register (int regno) +static int +arm_cannot_fetch_register (int regno) { - return (regno >= num_regs); + return (regno >= arm_num_regs); } +struct linux_target_ops the_low_target = { + arm_num_regs, + arm_regmap, + arm_cannot_fetch_register, + arm_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-i386-low.c b/gdb/gdbserver/linux-i386-low.c index 2a66efa..7126432 100644 --- a/gdb/gdbserver/linux-i386-low.c +++ b/gdb/gdbserver/linux-i386-low.c @@ -29,13 +29,13 @@ /* This module only supports access to the general purpose registers. */ -int num_regs = 16; +#define i386_num_regs 16 /* This stuff comes from i386-linux-nat.c. */ /* Mapping between the general-purpose registers in `struct user' format and GDB's register array layout. */ -int regmap[] = +static int i386_regmap[] = { EAX * 4, ECX * 4, EDX * 4, EBX * 4, UESP * 4, EBP * 4, ESI * 4, EDI * 4, @@ -43,16 +43,16 @@ int regmap[] = DS * 4, ES * 4, FS * 4, GS * 4 }; -int -cannot_store_register (int regno) +static int +i386_cannot_store_register (int regno) { - return (regno >= num_regs); + return (regno >= i386_num_regs); } -int -cannot_fetch_register (int regno) +static int +i386_cannot_fetch_register (int regno) { - return (regno >= num_regs); + return (regno >= i386_num_regs); } @@ -65,8 +65,8 @@ i386_fill_gregset (void *buf) { int i; - for (i = 0; i < num_regs; i++) - collect_register (i, ((char *) buf) + regmap[i]); + for (i = 0; i < i386_num_regs; i++) + collect_register (i, ((char *) buf) + i386_regmap[i]); collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); } @@ -76,8 +76,8 @@ i386_store_gregset (void *buf) { int i; - for (i = 0; i < num_regs; i++) - supply_register (i, ((char *) buf) + regmap[i]); + for (i = 0; i < i386_num_regs; i++) + supply_register (i, ((char *) buf) + i386_regmap[i]); supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4); } @@ -121,3 +121,37 @@ struct regset_info target_regsets[] = { #endif /* HAVE_LINUX_REGSETS */ +static const char i386_breakpoint[] = { 0xCC }; +#define i386_breakpoint_len 1 + +static CORE_ADDR +i386_stop_pc () +{ + unsigned long pc; + + /* Overkill */ + fetch_inferior_registers (0); + + collect_register_by_name ("eip", &pc); + return pc - 1; +} + +static void +i386_set_pc (CORE_ADDR newpc) +{ + supply_register_by_name ("eip", &newpc); + + /* Overkill */ + store_inferior_registers (0); +} + +struct linux_target_ops the_low_target = { + i386_num_regs, + i386_regmap, + i386_cannot_fetch_register, + i386_cannot_store_register, + i386_stop_pc, + i386_set_pc, + i386_breakpoint, + i386_breakpoint_len, +}; diff --git a/gdb/gdbserver/linux-ia64-low.c b/gdb/gdbserver/linux-ia64-low.c index f0f238f9..9407e6c 100644 --- a/gdb/gdbserver/linux-ia64-low.c +++ b/gdb/gdbserver/linux-ia64-low.c @@ -26,11 +26,11 @@ #include <sys/reg.h> #endif -int num_regs = 590; +#define ia64_num_regs 590 #include <asm/ptrace_offsets.h> -int regmap[] = +static int ia64_regmap[] = { /* general registers */ -1, /* gr0 not available; i.e, it's always zero */ @@ -283,15 +283,21 @@ int regmap[] = -1, -1, -1, -1, -1, -1, -1, -1, }; -int -cannot_store_register (int regno) +static int +ia64_cannot_store_register (int regno) { return 0; } -int -cannot_fetch_register (int regno) +static int +ia64_cannot_fetch_register (int regno) { return 0; } +struct linux_target_ops the_low_target = { + ia64_num_regs, + ia64_regmap, + ia64_cannot_fetch_register, + ia64_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 4e40d07..6cfe0d5 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -35,6 +35,10 @@ #include <stdlib.h> #include <unistd.h> +static CORE_ADDR linux_bp_reinsert; + +static void linux_resume (int step, int signal); + #define PTRACE_ARG3_TYPE long #define PTRACE_XFER_TYPE long @@ -44,17 +48,20 @@ static int use_regsets_p = 1; extern int errno; -#ifdef HAVE_LINUX_USRREGS -extern int num_regs; -extern int regmap[]; -#endif +static int inferior_pid; + +struct inferior_linux_data +{ + int pid; +}; /* Start an inferior process and returns its pid. ALLARGS is a vector of program-name and args. */ -int -create_inferior (char *program, char **allargs) +static int +linux_create_inferior (char *program, char **allargs) { + struct inferior_linux_data *tdata; int pid; pid = fork (); @@ -73,14 +80,23 @@ create_inferior (char *program, char **allargs) _exit (0177); } - return pid; + add_inferior (pid); + tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata)); + tdata->pid = pid; + set_inferior_target_data (current_inferior, tdata); + + /* FIXME remove */ + inferior_pid = pid; + return 0; } /* Attach to an inferior process. */ -int -myattach (int pid) +static int +linux_attach (int pid) { + struct inferior_linux_data *tdata; + if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0) { fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid, @@ -90,50 +106,113 @@ myattach (int pid) _exit (0177); } + add_inferior (pid); + tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata)); + tdata->pid = pid; + set_inferior_target_data (current_inferior, tdata); return 0; } /* Kill the inferior process. Make us have no inferior. */ -void -kill_inferior (void) +static void +linux_kill (void) { if (inferior_pid == 0) return; ptrace (PTRACE_KILL, inferior_pid, 0, 0); wait (0); + clear_inferiors (); } /* Return nonzero if the given thread is still alive. */ -int -mythread_alive (int pid) +static int +linux_thread_alive (int pid) { return 1; } +static int +linux_wait_for_one_inferior (struct inferior_info *child) +{ + struct inferior_linux_data *child_data = inferior_target_data (child); + int pid, wstat; + + while (1) + { + pid = waitpid (child_data->pid, &wstat, 0); + + if (pid != child_data->pid) + perror_with_name ("wait"); + + /* If this target supports breakpoints, see if we hit one. */ + if (the_low_target.stop_pc != NULL + && WIFSTOPPED (wstat) + && WSTOPSIG (wstat) == SIGTRAP) + { + CORE_ADDR stop_pc; + + if (linux_bp_reinsert != 0) + { + reinsert_breakpoint (linux_bp_reinsert); + linux_bp_reinsert = 0; + linux_resume (0, 0); + continue; + } + + fetch_inferior_registers (0); + stop_pc = (*the_low_target.stop_pc) (); + + if (check_breakpoints (stop_pc) != 0) + { + if (the_low_target.set_pc != NULL) + (*the_low_target.set_pc) (stop_pc); + + if (the_low_target.breakpoint_reinsert_addr == NULL) + { + linux_bp_reinsert = stop_pc; + uninsert_breakpoint (stop_pc); + linux_resume (1, 0); + } + else + { + reinsert_breakpoint_by_bp + (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ()); + linux_resume (0, 0); + } + + continue; + } + } + + return wstat; + } + /* NOTREACHED */ + return 0; +} + /* Wait for process, returns status */ -unsigned char -mywait (char *status) +static unsigned char +linux_wait (char *status) { - int pid; int w; enable_async_io (); - pid = waitpid (inferior_pid, &w, 0); + w = linux_wait_for_one_inferior (current_inferior); disable_async_io (); - if (pid != inferior_pid) - perror_with_name ("wait"); if (WIFEXITED (w)) { fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w)); *status = 'W'; + clear_inferiors (); return ((unsigned char) WEXITSTATUS (w)); } else if (!WIFSTOPPED (w)) { fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w)); + clear_inferiors (); *status = 'X'; return ((unsigned char) WTERMSIG (w)); } @@ -148,8 +227,8 @@ mywait (char *status) If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ -void -myresume (int step, int signal) +static void +linux_resume (int step, int signal) { errno = 0; ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal); @@ -167,10 +246,10 @@ register_addr (int regnum) { int addr; - if (regnum < 0 || regnum >= num_regs) + if (regnum < 0 || regnum >= the_low_target.num_regs) error ("Invalid register number %d.", regnum); - addr = regmap[regnum]; + addr = the_low_target.regmap[regnum]; if (addr == -1) addr = 0; @@ -184,9 +263,9 @@ fetch_register (int regno) CORE_ADDR regaddr; register int i; - if (regno >= num_regs) + if (regno >= the_low_target.num_regs) return; - if (cannot_fetch_register (regno)) + if ((*the_low_target.cannot_fetch_register) (regno)) return; regaddr = register_addr (regno); @@ -217,7 +296,7 @@ static void usr_fetch_inferior_registers (int regno) { if (regno == -1 || regno == 0) - for (regno = 0; regno < num_regs; regno++) + for (regno = 0; regno < the_low_target.num_regs; regno++) fetch_register (regno); else fetch_register (regno); @@ -234,10 +313,10 @@ usr_store_inferior_registers (int regno) if (regno >= 0) { - if (regno >= num_regs) + if (regno >= the_low_target.num_regs) return; - if (cannot_store_register (regno)) + if ((*the_low_target.cannot_store_register) (regno) == 1) return; regaddr = register_addr (regno); @@ -251,20 +330,21 @@ usr_store_inferior_registers (int regno) *(int *) (register_data (regno) + i)); if (errno != 0) { - /* Warning, not error, in case we are attached; sometimes the - kernel doesn't let us at the registers. */ - char *err = strerror (errno); - char *msg = alloca (strlen (err) + 128); - sprintf (msg, "writing register %d: %s", - regno, err); - error (msg); - return; + if ((*the_low_target.cannot_store_register) (regno) == 0) + { + char *err = strerror (errno); + char *msg = alloca (strlen (err) + 128); + sprintf (msg, "writing register %d: %s", + regno, err); + error (msg); + return; + } } regaddr += sizeof (int); } } else - for (regno = 0; regno < num_regs; regno++) + for (regno = 0; regno < the_low_target.num_regs; regno++) store_inferior_registers (regno); } #endif /* HAVE_LINUX_USRREGS */ @@ -292,7 +372,7 @@ regsets_fetch_inferior_registers (void) } buf = malloc (regset->size); - res = ptrace (regset->get_request, inferior_pid, 0, (int) buf); + res = ptrace (regset->get_request, inferior_pid, 0, buf); if (res < 0) { if (errno == EIO) @@ -318,6 +398,7 @@ regsets_fetch_inferior_registers (void) regset->store_function (buf); regset ++; } + return 0; } static int @@ -340,7 +421,7 @@ regsets_store_inferior_registers (void) buf = malloc (regset->size); regset->fill_function (buf); - res = ptrace (regset->set_request, inferior_pid, 0, (int) buf); + res = ptrace (regset->set_request, inferior_pid, 0, buf); if (res < 0) { if (errno == EIO) @@ -360,18 +441,19 @@ regsets_store_inferior_registers (void) } else { - perror ("Warning: ptrace(regsets_fetch_inferior_registers)"); + perror ("Warning: ptrace(regsets_store_inferior_registers)"); } } regset ++; } + return 0; } #endif /* HAVE_LINUX_REGSETS */ void -fetch_inferior_registers (int regno) +linux_fetch_registers (int regno) { #ifdef HAVE_LINUX_REGSETS if (use_regsets_p) @@ -386,7 +468,7 @@ fetch_inferior_registers (int regno) } void -store_inferior_registers (int regno) +linux_store_registers (int regno) { #ifdef HAVE_LINUX_REGSETS if (use_regsets_p) @@ -404,8 +486,8 @@ store_inferior_registers (int regno) /* Copy LEN bytes from inferior's memory starting at MEMADDR to debugger memory starting at MYADDR. */ -void -read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) +static void +linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len) { register int i; /* Round starting address down to longword boundary. */ @@ -433,8 +515,8 @@ read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) On failure (cannot write the inferior) returns the value of errno. */ -int -write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) +static int +linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len) { register int i; /* Round starting address down to longword boundary. */ @@ -476,9 +558,33 @@ write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) return 0; } + +static void +linux_look_up_symbols (void) +{ + /* Don't need to look up any symbols yet. */ +} + +static struct target_ops linux_target_ops = { + linux_create_inferior, + linux_attach, + linux_kill, + linux_thread_alive, + linux_resume, + linux_wait, + linux_fetch_registers, + linux_store_registers, + linux_read_memory, + linux_write_memory, + linux_look_up_symbols, +}; + void initialize_low (void) { + set_target_ops (&linux_target_ops); + set_breakpoint_data (the_low_target.breakpoint, + the_low_target.breakpoint_len); init_registers (); } diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 421fa22..b484982 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -18,13 +18,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifdef HAVE_LINUX_USR_REGISTERS -extern int regmap[]; -extern int num_regs; -int cannot_fetch_register (int regno); -int cannot_store_register (int regno); -#endif - #ifdef HAVE_LINUX_REGSETS typedef void (*regset_func) (void *); struct regset_info @@ -35,3 +28,22 @@ struct regset_info }; extern struct regset_info target_regsets[]; #endif + +struct linux_target_ops +{ + int num_regs; + int *regmap; + int (*cannot_fetch_register) (int); + + /* Returns 0 if we can store the register, 1 if we can not + store the register, and 2 if failure to store the register + is acceptable. */ + int (*cannot_store_register) (int); + CORE_ADDR (*stop_pc) (void); + void (*set_pc) (CORE_ADDR newpc); + const char *breakpoint; + int breakpoint_len; + CORE_ADDR (*breakpoint_reinsert_addr) (void); +}; + +extern struct linux_target_ops the_low_target; diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c index 9e59fbd..760de6e 100644 --- a/gdb/gdbserver/linux-m68k-low.c +++ b/gdb/gdbserver/linux-m68k-low.c @@ -26,10 +26,10 @@ #include <sys/reg.h> #endif -int num_regs = 31; +#define m68k_num_regs 31 /* This table must line up with REGISTER_NAMES in tm-m68k.h */ -int regmap[] = +static int m68k_regmap[] = { #ifdef PT_D0 PT_D0 * 4, PT_D1 * 4, PT_D2 * 4, PT_D3 * 4, @@ -52,14 +52,21 @@ int regmap[] = #endif }; -int -cannot_store_register (int regno) +static int +m68k_cannot_store_register (int regno) { - return (regno >= num_regs); + return (regno >= m68k_num_regs); } -int -cannot_fetch_register (int regno) +static int +m68k_cannot_fetch_register (int regno) { - return (regno >= num_regs); + return (regno >= m68k_num_regs); } + +struct linux_target_ops the_low_target = { + m68k_num_regs, + m68k_regmap, + m68k_cannot_fetch_register, + m68k_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index a9114d3..f721ec9 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -26,14 +26,14 @@ #include <sys/reg.h> #endif -int num_regs = 90; +#define mips_num_regs 90 #include <asm/ptrace.h> /* Return the ptrace ``address'' of register REGNO. */ /* Matches mips_generic32_regs */ -int regmap[] = { +static int mips_regmap[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, @@ -63,10 +63,10 @@ int regmap[] = { ZERO_REGNUM. We also can not set BADVADDR, CAUSE, or FCRIR via ptrace(). */ -int -cannot_fetch_register (int regno) +static int +mips_cannot_fetch_register (int regno) { - if (regmap[regno] == -1) + if (mips_regmap[regno] == -1) return 1; if (find_regno ("zero") == regno) @@ -75,10 +75,10 @@ cannot_fetch_register (int regno) return 0; } -int -cannot_store_register (int regno) +static int +mips_cannot_store_register (int regno) { - if (regmap[regno] == -1) + if (mips_regmap[regno] == -1) return 1; if (find_regno ("zero") == regno) @@ -95,3 +95,10 @@ cannot_store_register (int regno) return 0; } + +struct linux_target_ops the_low_target = { + mips_num_regs, + mips_regmap, + mips_cannot_fetch_register, + mips_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index dcefa59..7cb315a 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -25,10 +25,10 @@ #include <asm/ptrace.h> -int num_regs = 71; +#define ppc_num_regs 71 /* Currently, don't check/send MQ. */ -int regmap[] = +static int ppc_regmap[] = {PT_R0 * 4, PT_R1 * 4, PT_R2 * 4, PT_R3 * 4, PT_R4 * 4, PT_R5 * 4, PT_R6 * 4, PT_R7 * 4, PT_R8 * 4, PT_R9 * 4, PT_R10 * 4, PT_R11 * 4, @@ -46,17 +46,27 @@ int regmap[] = PT_FPR0*4+192, PT_FPR0*4+200, PT_FPR0*4+208, PT_FPR0*4+216, PT_FPR0*4+224, PT_FPR0*4+232, PT_FPR0*4+240, PT_FPR0*4+248, PT_NIP * 4, PT_MSR * 4, PT_CCR * 4, PT_LNK * 4, - PT_CTR * 4, PT_XER * 4, -1, }; + PT_CTR * 4, PT_XER * 4, PT_FPSCR * 4, }; -int -cannot_store_register (int regno) +static int +ppc_cannot_store_register (int regno) { + /* Some kernels do not allow us to store fpscr. */ + if (regno == find_regno ("fpscr")) + return 2; + return 0; } -int -cannot_fetch_register (int regno) +static int +ppc_cannot_fetch_register (int regno) { return 0; } +struct linux_target_ops the_low_target = { + ppc_num_regs, + ppc_regmap, + ppc_cannot_fetch_register, + ppc_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 1920b9c..8d800ae 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -27,9 +27,9 @@ #include <asm/ptrace.h> -int num_regs = 67; +#define s390_num_regs 67 -int regmap[] = { +static int s390_regmap[] = { PT_PSWMASK, PT_PSWADDR, PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3, @@ -62,20 +62,27 @@ int regmap[] = { #endif }; -int -cannot_fetch_register (int regno) +static int +s390_cannot_fetch_register (int regno) { - if (regmap[regno] == -1) + if (s390_regmap[regno] == -1) return 1; return 0; } -int -cannot_store_register (int regno) +static int +s390_cannot_store_register (int regno) { - if (regmap[regno] == -1) + if (s390_regmap[regno] == -1) return 1; return 0; } + +struct linux_target_ops the_low_target = { + s390_num_regs, + s390_regmap, + s390_cannot_fetch_register, + s390_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c index f763339..cdc390d 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -28,10 +28,10 @@ #include <asm/ptrace.h> -int num_regs = 41; +#define sh_num_regs 41 /* Currently, don't check/send MQ. */ -int regmap[] = { +static int sh_regmap[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, @@ -45,15 +45,21 @@ int regmap[] = { REG_FPREG0+48, REG_FPREG0+52, REG_FPREG0+56, REG_FPREG0+60, }; -int -cannot_store_register (int regno) +static int +sh_cannot_store_register (int regno) { return 0; } -int -cannot_fetch_register (int regno) +static int +sh_cannot_fetch_register (int regno) { return 0; } +struct linux_target_ops the_low_target = { + sh_num_regs, + sh_regmap, + sh_cannot_fetch_register, + sh_cannot_store_register, +}; diff --git a/gdb/gdbserver/linux-x86-64-low.c b/gdb/gdbserver/linux-x86-64-low.c index ffb0ce7..e124890 100644 --- a/gdb/gdbserver/linux-x86-64-low.c +++ b/gdb/gdbserver/linux-x86-64-low.c @@ -28,12 +28,15 @@ #include <sys/procfs.h> #include <sys/ptrace.h> -static int regmap[] = { - RAX, RDX, RCX, RBX, +#define X86_64_NUM_GREGS 22 + +static int x86_64_regmap[X86_64_NUM_GREGS] = { + RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, R8, R9, R10, R11, R12, R13, R14, R15, - RIP, EFLAGS + RIP, EFLAGS, + DS, ES, FS, GS }; static void @@ -41,8 +44,8 @@ x86_64_fill_gregset (void *buf) { int i; - for (i = 0; i < 18; i++) - collect_register (i, ((char *) buf) + regmap[i]); + for (i = 0; i < X86_64_NUM_GREGS; i++) + collect_register (i, ((char *) buf) + x86_64_regmap[i]); } static void @@ -50,8 +53,8 @@ x86_64_store_gregset (void *buf) { int i; - for (i = 0; i < 18; i++) - supply_register (i, ((char *) buf) + regmap[i]); + for (i = 0; i < X86_64_NUM_GREGS; i++) + supply_register (i, ((char *) buf) + x86_64_regmap[i]); } static void @@ -66,7 +69,6 @@ x86_64_store_fpregset (void *buf) i387_fxsave_to_cache (buf); } - struct regset_info target_regsets[] = { { PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t), x86_64_fill_gregset, x86_64_store_gregset }, @@ -74,3 +76,10 @@ struct regset_info target_regsets[] = { x86_64_fill_fpregset, x86_64_store_fpregset }, { 0, 0, -1, NULL, NULL } }; + +struct linux_target_ops the_low_target = { + -1, + NULL, + NULL, + NULL, +}; diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c new file mode 100644 index 0000000..91addf6 --- /dev/null +++ b/gdb/gdbserver/mem-break.c @@ -0,0 +1,280 @@ +/* Memory breakpoint operations for the remote server for GDB. + Copyright 2002 + Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + 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 "server.h" + +const char *breakpoint_data; +int breakpoint_len; + +#define MAX_BREAKPOINT_LEN 8 + +struct breakpoint +{ + struct breakpoint *next; + CORE_ADDR pc; + unsigned char old_data[MAX_BREAKPOINT_LEN]; + + /* Non-zero iff we are stepping over this breakpoint. */ + int reinserting; + + /* Non-NULL iff this breakpoint was inserted to step over + another one. Points to the other breakpoint (which is also + in the *next chain somewhere). */ + struct breakpoint *breakpoint_to_reinsert; + + /* Function to call when we hit this breakpoint. */ + void (*handler) (CORE_ADDR); +}; + +struct breakpoint *breakpoints; + +void +set_breakpoint_at (CORE_ADDR where, void (*handler) (CORE_ADDR)) +{ + struct breakpoint *bp; + + if (breakpoint_data == NULL) + error ("Target does not support breakpoints."); + + bp = malloc (sizeof (struct breakpoint)); + memset (bp, 0, sizeof (struct breakpoint)); + + (*the_target->read_memory) (where, bp->old_data, + breakpoint_len); + (*the_target->write_memory) (where, breakpoint_data, + breakpoint_len); + + bp->pc = where; + bp->handler = handler; + + bp->next = breakpoints; + breakpoints = bp; +} + +static void +delete_breakpoint (struct breakpoint *bp) +{ + struct breakpoint *cur; + + if (breakpoints == bp) + { + breakpoints = bp->next; + (*the_target->write_memory) (bp->pc, bp->old_data, + breakpoint_len); + free (bp); + return; + } + cur = breakpoints; + while (cur->next) + { + if (cur->next == bp) + { + cur->next = bp->next; + (*the_target->write_memory) (bp->pc, bp->old_data, + breakpoint_len); + free (bp); + return; + } + } + warning ("Could not find breakpoint in list."); +} + +static struct breakpoint * +find_breakpoint_at (CORE_ADDR where) +{ + struct breakpoint *bp = breakpoints; + + while (bp != NULL) + { + if (bp->pc == where) + return bp; + bp = bp->next; + } + + return NULL; +} + +static void +reinsert_breakpoint_handler (CORE_ADDR stop_pc) +{ + struct breakpoint *stop_bp, *orig_bp; + + stop_bp = find_breakpoint_at (stop_pc); + if (stop_bp == NULL) + error ("lost the stopping breakpoint."); + + orig_bp = stop_bp->breakpoint_to_reinsert; + if (orig_bp == NULL) + error ("no breakpoint to reinsert"); + + (*the_target->write_memory) (orig_bp->pc, breakpoint_data, + breakpoint_len); + orig_bp->reinserting = 0; + delete_breakpoint (stop_bp); +} + +void +reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at) +{ + struct breakpoint *bp, *orig_bp; + + set_breakpoint_at (stop_at, reinsert_breakpoint_handler); + + orig_bp = find_breakpoint_at (stop_at); + if (orig_bp == NULL) + error ("Could not find original breakpoint in list."); + + bp = find_breakpoint_at (stop_at); + if (bp == NULL) + error ("Could not find breakpoint in list (reinserting by breakpoint)."); + bp->breakpoint_to_reinsert = orig_bp; + + (*the_target->write_memory) (orig_bp->pc, orig_bp->old_data, + breakpoint_len); + orig_bp->reinserting = 1; +} + +void +uninsert_breakpoint (CORE_ADDR stopped_at) +{ + struct breakpoint *bp; + + bp = find_breakpoint_at (stopped_at); + if (bp == NULL) + error ("Could not find breakpoint in list (uninserting)."); + + (*the_target->write_memory) (bp->pc, bp->old_data, + breakpoint_len); + bp->reinserting = 1; +} + +void +reinsert_breakpoint (CORE_ADDR stopped_at) +{ + struct breakpoint *bp; + + bp = find_breakpoint_at (stopped_at); + if (bp == NULL) + error ("Could not find breakpoint in list (uninserting)."); + if (! bp->reinserting) + error ("Breakpoint already inserted at reinsert time."); + + (*the_target->write_memory) (bp->pc, breakpoint_data, + breakpoint_len); + bp->reinserting = 0; +} + +int +check_breakpoints (CORE_ADDR stop_pc) +{ + struct breakpoint *bp; + + bp = find_breakpoint_at (stop_pc); + if (bp == NULL) + return 0; + if (bp->reinserting) + { + warning ("Hit a removed breakpoint?"); + return 0; + } + + (*bp->handler) (bp->pc); + return 1; +} + +void +set_breakpoint_data (const char *bp_data, int bp_len) +{ + breakpoint_data = bp_data; + breakpoint_len = bp_len; +} + +void +check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len) +{ + struct breakpoint *bp = breakpoints; + CORE_ADDR mem_end = mem_addr + mem_len; + + for (; bp != NULL; bp = bp->next) + { + CORE_ADDR bp_end = bp->pc + breakpoint_len; + CORE_ADDR start, end; + int copy_offset, copy_len, buf_offset; + + if (mem_addr >= bp_end) + continue; + if (bp->pc >= mem_end) + continue; + + start = bp->pc; + if (mem_addr > start) + start = mem_addr; + + end = bp_end; + if (end > mem_end) + end = mem_end; + + copy_len = end - start; + copy_offset = start - bp->pc; + buf_offset = start - mem_addr; + + memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len); + } +} + +void +check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len) +{ + struct breakpoint *bp = breakpoints; + CORE_ADDR mem_end = mem_addr + mem_len; + + for (; bp != NULL; bp = bp->next) + { + CORE_ADDR bp_end = bp->pc + breakpoint_len; + CORE_ADDR start, end; + int copy_offset, copy_len, buf_offset; + + if (mem_addr >= bp_end) + continue; + if (bp->pc >= mem_end) + continue; + + start = bp->pc; + if (mem_addr > start) + start = mem_addr; + + end = bp_end; + if (end > mem_end) + end = mem_end; + + copy_len = end - start; + copy_offset = start - bp->pc; + buf_offset = start - mem_addr; + + memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len); + if (bp->reinserting == 0) + memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len); + } +} + + diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h new file mode 100644 index 0000000..356e763 --- /dev/null +++ b/gdb/gdbserver/mem-break.h @@ -0,0 +1,71 @@ +/* Memory breakpoint interfaces for the remote server for GDB. + Copyright 2002 + Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + 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 MEM_BREAK_H +#define MEM_BREAK_H + +/* Breakpoints are opaque. */ + +/* Create a new breakpoint at WHERE, and call HANDLER when + it is hit. */ + +void set_breakpoint_at (CORE_ADDR where, + void (*handler) (CORE_ADDR)); + +/* Create a reinsertion breakpoint at STOP_AT for the breakpoint + currently at STOP_PC (and temporarily remove the breakpoint at + STOP_PC). */ + +void reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at); + +/* Change the status of the breakpoint at WHERE to inserted. */ + +void reinsert_breakpoint (CORE_ADDR where); + +/* Change the status of the breakpoint at WHERE to uninserted. */ + +void uninsert_breakpoint (CORE_ADDR where); + +/* See if any breakpoint claims ownership of STOP_PC. Call the handler for + the breakpoint, if found. */ + +int check_breakpoints (CORE_ADDR stop_pc); + +/* See if any breakpoints shadow the target memory area from MEM_ADDR + to MEM_ADDR + MEM_LEN. Update the data already read from the target + (in BUF) if necessary. */ + +void check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len); + +/* See if any breakpoints shadow the target memory area from MEM_ADDR + to MEM_ADDR + MEM_LEN. Update the data to be written to the target + (in BUF) if necessary, as well as the original data for any breakpoints. */ + +void check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len); + +/* Set the byte pattern to insert for memory breakpoints. This function + must be called before any breakpoints are set. */ + +void set_breakpoint_data (const char *bp_data, int bp_len); + +#endif /* MEM_BREAK_H */ diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c index bec20bb..701d092 100644 --- a/gdb/gdbserver/regcache.c +++ b/gdb/gdbserver/regcache.c @@ -25,7 +25,11 @@ #include <stdlib.h> #include <string.h> -static char *registers; +struct inferior_regcache_data +{ + char *registers; +}; + static int register_bytes; static struct reg *reg_defs; @@ -33,6 +37,19 @@ static int num_registers; const char **gdbserver_expedite_regs; +static struct inferior_regcache_data * +get_regcache (struct inferior_info *inf) +{ + struct inferior_regcache_data *regcache; + + regcache = (struct inferior_regcache_data *) inferior_regcache_data (inf); + + if (regcache == NULL) + fatal ("no register cache"); + + return regcache; +} + int registers_length (void) { @@ -40,6 +57,28 @@ registers_length (void) } void +create_register_cache (struct inferior_info *inferior) +{ + struct inferior_regcache_data *regcache; + + regcache = malloc (sizeof (*regcache)); + + regcache->registers = malloc (register_bytes); + if (regcache->registers == NULL) + fatal ("Could not allocate register cache."); + + set_inferior_regcache_data (inferior, regcache); +} + +void +free_register_cache (struct inferior_info *inferior) +{ + free (get_regcache (current_inferior)->registers); + free (get_regcache (current_inferior)); + set_inferior_regcache_data (inferior, NULL); +} + +void set_register_cache (struct reg *regs, int n) { int offset, i; @@ -55,14 +94,13 @@ set_register_cache (struct reg *regs, int n) } register_bytes = offset / 8; - registers = malloc (offset / 8); - if (!registers) - fatal ("Could not allocate register cache."); } void registers_to_string (char *buf) { + char *registers = get_regcache (current_inferior)->registers; + convert_int_to_ascii (registers, buf, register_bytes); } @@ -70,6 +108,7 @@ void registers_from_string (char *buf) { int len = strlen (buf); + char *registers = get_regcache (current_inferior)->registers; if (len != register_bytes * 2) { @@ -119,29 +158,31 @@ register_size (int n) char * register_data (int n) { + char *registers = get_regcache (current_inferior)->registers; + return registers + (reg_defs[n].offset / 8); } void -supply_register (int n, const char *buf) +supply_register (int n, const void *buf) { memcpy (register_data (n), buf, register_size (n)); } void -supply_register_by_name (const char *name, const char *buf) +supply_register_by_name (const char *name, const void *buf) { supply_register (find_regno (name), buf); } void -collect_register (int n, char *buf) +collect_register (int n, void *buf) { memcpy (buf, register_data (n), register_size (n)); } void -collect_register_by_name (const char *name, char *buf) +collect_register_by_name (const char *name, void *buf) { collect_register (find_regno (name), buf); } diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h index 07195b3..362288e 100644 --- a/gdb/gdbserver/regcache.h +++ b/gdb/gdbserver/regcache.h @@ -21,6 +21,16 @@ #ifndef REGCACHE_H #define REGCACHE_H +struct inferior_info; + +/* Create a new register cache for INFERIOR. */ + +void create_register_cache (struct inferior_info *inferior); + +/* Release all memory associated with the register cache for INFERIOR. */ + +void free_register_cache (struct inferior_info *inferior); + /* Convert all registers to a string in the currently specified remote format. */ @@ -46,4 +56,12 @@ int find_regno (const char *name); extern const char **gdbserver_expedite_regs; +void supply_register (int n, const void *buf); + +void supply_register_by_name (const char *name, const void *buf); + +void collect_register (int n, void *buf); + +void collect_register_by_name (const char *name, void *buf); + #endif /* REGCACHE_H */ diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index ff1718f..14734f1 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -35,6 +35,7 @@ #include <fcntl.h> #include <sys/time.h> #include <unistd.h> +#include <arpa/inet.h> int remote_debug = 0; struct ui_file *gdb_stdlog; @@ -48,7 +49,7 @@ void remote_open (char *name) { int save_fcntl_flags; - + if (!strchr (name, ':')) { remote_desc = open (name, O_RDWR); @@ -99,7 +100,7 @@ remote_open (char *name) } #endif - + fprintf (stderr, "Remote debugging using %s\n", name); } else { @@ -107,7 +108,6 @@ remote_open (char *name) int port; struct sockaddr_in sockaddr; int tmp; - struct protoent *protoent; int tmp_desc; port_str = strchr (name, ':'); @@ -136,10 +136,6 @@ remote_open (char *name) if (remote_desc == -1) perror_with_name ("Accept failed"); - protoent = getprotobyname ("tcp"); - if (!protoent) - perror_with_name ("getprotobyname"); - /* Enable TCP keep alive process. */ tmp = 1; setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp)); @@ -147,13 +143,17 @@ remote_open (char *name) /* Tell TCP not to delay small packets. This greatly speeds up interactive response. */ tmp = 1; - setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY, + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, (char *) &tmp, sizeof (tmp)); close (tmp_desc); /* No longer need this */ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply exits when the remote side dies. */ + + /* Convert IP address to string. */ + fprintf (stderr, "Remote debugging from host %s\n", + inet_ntoa (sockaddr.sin_addr)); } #if defined(F_SETFL) && defined (FASYNC) @@ -164,7 +164,6 @@ remote_open (char *name) #endif #endif disable_async_io (); - fprintf (stderr, "Remote debugging using %s\n", name); } void @@ -187,6 +186,42 @@ fromhex (int a) return 0; } +int +unhexify (char *bin, const char *hex, int count) +{ + int i; + + for (i = 0; i < count; i++) + { + if (hex[0] == 0 || hex[1] == 0) + { + /* Hex string is short, or of uneven length. + Return the count that has been converted so far. */ + return i; + } + *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]); + hex += 2; + } + return i; +} + +static void +decode_address (CORE_ADDR *addrp, const char *start, int len) +{ + CORE_ADDR addr; + char ch; + int i; + + addr = 0; + for (i = 0; i < len; i++) + { + ch = start[i]; + addr = addr << 4; + addr = addr | (fromhex (ch) & 0x0f); + } + *addrp = addr; +} + /* Convert number NIB to a hex digit. */ static int @@ -198,6 +233,24 @@ tohex (int nib) return 'a' + nib - 10; } +int +hexify (char *hex, const char *bin, int count) +{ + int i; + + /* May use a length, or a nul-terminated string as input. */ + if (count == 0) + count = strlen (bin); + + for (i = 0; i < count; i++) + { + *hex++ = tohex ((*bin >> 4) & 0xf); + *hex++ = tohex (*bin++ & 0xf); + } + *hex = 0; + return i; +} + /* Send a packet to the remote machine, with error checking. The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */ @@ -293,7 +346,7 @@ input_interrupt (int unused) return; } - kill (inferior_pid, SIGINT); + kill (signal_pid, SIGINT); } } @@ -465,17 +518,15 @@ outreg (int regno, char *buf) void prepare_resume_reply (char *buf, char status, unsigned char signo) { - int nib; + int nib, sig; *buf++ = status; - /* FIXME! Should be converting this signal number (numbered - according to the signal numbering of the system we are running on) - to the signal numbers used by the gdb protocol (see enum target_signal - in gdb/target.h). */ - nib = ((signo & 0xf0) >> 4); + sig = (int)target_signal_from_host (signo); + + nib = ((sig & 0xf0) >> 4); *buf++ = tohex (nib); - nib = signo & 0x0f; + nib = sig & 0x0f; *buf++ = tohex (nib); if (status == 'T') @@ -547,3 +598,42 @@ decode_M_packet (char *from, CORE_ADDR *mem_addr_ptr, unsigned int *len_ptr, convert_ascii_to_int (&from[i++], to, *len_ptr); } + +int +look_up_one_symbol (const char *name, CORE_ADDR *addrp) +{ + char own_buf[266], *p, *q; + int len; + + /* Send the request. */ + strcpy (own_buf, "qSymbol:"); + hexify (own_buf + strlen ("qSymbol:"), name, strlen (name)); + if (putpkt (own_buf) < 0) + return -1; + + /* FIXME: Eventually add buffer overflow checking (to getpkt?) */ + len = getpkt (own_buf); + if (len < 0) + return -1; + + if (strncmp (own_buf, "qSymbol:", strlen ("qSymbol:")) != 0) + { + /* Malformed response. */ + if (remote_debug) + fprintf (stderr, "Malformed response to qSymbol, ignoring.\n"); + return -1; + } + + p = own_buf + strlen ("qSymbol:"); + q = p; + while (*q && *q != ':') + q++; + + /* Make sure we found a value for the symbol. */ + if (p == q || *q == '\0') + return 0; + + decode_address (addrp, p, q - p); + return 1; +} + diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index d845422..ba85b59 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -27,13 +27,14 @@ int thread_from_wait; int old_thread_from_wait; int extended_protocol; jmp_buf toplevel; -int inferior_pid; static unsigned char start_inferior (char *argv[], char *statusptr) { - inferior_pid = create_inferior (argv[0], argv); - fprintf (stderr, "Process %s created; pid = %d\n", argv[0], inferior_pid); + /* FIXME Check error? Or turn to void. */ + create_inferior (argv[0], argv); + /* FIXME Print pid properly. */ + fprintf (stderr, "Process %s created; pid = %d\n", argv[0], signal_pid); /* Wait till we are at 1st instruction in program, return signal number. */ return mywait (statusptr); @@ -47,8 +48,6 @@ attach_inferior (int pid, char *statusptr, unsigned char *sigptr) if (myattach (pid) != 0) return -1; - inferior_pid = pid; - *sigptr = mywait (statusptr); return 0; @@ -56,6 +55,26 @@ attach_inferior (int pid, char *statusptr, unsigned char *sigptr) extern int remote_debug; +/* Handle all of the extended 'q' packets. */ +void +handle_query (char *own_buf) +{ + if (strcmp ("qSymbol::", own_buf) == 0) + { + if (the_target->look_up_symbols != NULL) + (*the_target->look_up_symbols) (); + + strcpy (own_buf, "OK"); + return; + } + + /* Otherwise we didn't know what packet it was. Say we didn't + understand it. */ + own_buf[0] = 0; +} + +static int attached; + int main (int argc, char *argv[]) { @@ -64,9 +83,8 @@ main (int argc, char *argv[]) unsigned char signal; unsigned int len; CORE_ADDR mem_addr; - int bad_attach = 0; - int pid = 0; - int attached = 0; + int bad_attach; + int pid; char *arg_end; if (setjmp (toplevel)) @@ -75,6 +93,9 @@ main (int argc, char *argv[]) exit (1); } + bad_attach = 0; + pid = 0; + attached = 0; if (argc >= 3 && strcmp (argv[2], "--attach") == 0) { if (argc == 4 @@ -129,6 +150,9 @@ main (int argc, char *argv[]) ch = own_buf[i++]; switch (ch) { + case 'q': + handle_query (own_buf); + break; case 'd': remote_debug = !remote_debug; break; @@ -190,13 +214,21 @@ main (int argc, char *argv[]) break; case 'C': convert_ascii_to_int (own_buf + 1, &sig, 1); - myresume (0, sig); + if (target_signal_to_host_p (sig)) + signal = target_signal_to_host (sig); + else + signal = 0; + myresume (0, signal); signal = mywait (&status); prepare_resume_reply (own_buf, status, signal); break; case 'S': convert_ascii_to_int (own_buf + 1, &sig, 1); - myresume (1, sig); + if (target_signal_to_host_p (sig)) + signal = target_signal_to_host (sig); + else + signal = 0; + myresume (1, signal); signal = mywait (&status); prepare_resume_reply (own_buf, status, signal); break; diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index 6202b0f..32b90b5 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -23,38 +23,65 @@ #define SERVER_H #include "config.h" + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <setjmp.h> - -/* FIXME: Both of these should be autoconf'd for. */ -#define NORETURN +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifndef ATTR_NORETURN +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) +#define ATTR_NORETURN __attribute__ ((noreturn)) +#else +#define ATTR_NORETURN /* nothing */ +#endif +#endif + +#ifndef ATTR_FORMAT +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 4)) +#define ATTR_FORMAT(type, x, y) __attribute__ ((format(type, x, y))) +#else +#define ATTR_FORMAT(type, x, y) /* nothing */ +#endif +#endif + +/* FIXME: This should probably be autoconf'd for. It's an integer type at + least the size of a (void *). */ typedef long long CORE_ADDR; +/* Opaque inferior process information. */ +struct inferior_info; + #include "regcache.h" +#include "gdb/signals.h" -#include <setjmp.h> +#include "target.h" +#include "mem-break.h" /* Target-specific functions */ -int create_inferior (char *program, char **allargs); -void kill_inferior (void); -void fetch_inferior_registers (int regno); -void store_inferior_registers (int regno); -int mythread_alive (int pid); -void myresume (int step, int signo); -unsigned char mywait (char *status); -void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len); -int write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len); -int create_inferior (); void initialize_low (); /* Target-specific variables */ extern char *registers; +/* From inferiors.c. */ + +extern struct inferior_info *current_inferior; +extern int signal_pid; +void add_inferior (int pid); +void clear_inferiors (void); +void *inferior_target_data (struct inferior_info *); +void set_inferior_target_data (struct inferior_info *, void *); +void *inferior_regcache_data (struct inferior_info *); +void set_inferior_regcache_data (struct inferior_info *, void *); + /* Public variables in server.c */ extern int cont_thread; @@ -63,7 +90,6 @@ extern int thread_from_wait; extern int old_thread_from_wait; extern jmp_buf toplevel; -extern int inferior_pid; /* Functions from remote-utils.c */ @@ -84,15 +110,26 @@ void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr, void decode_M_packet (char *from, CORE_ADDR * mem_addr_ptr, unsigned int *len_ptr, char *to); +int unhexify (char *bin, const char *hex, int count); +int hexify (char *hex, const char *bin, int count); + +int look_up_one_symbol (const char *name, CORE_ADDR *addrp); + +/* Functions from ``signals.c''. */ +enum target_signal target_signal_from_host (int hostsig); +int target_signal_to_host_p (enum target_signal oursig); +int target_signal_to_host (enum target_signal oursig); /* Functions from utils.c */ void perror_with_name (char *string); -void error (const char *string,...); -void fatal (const char *string,...); +void error (const char *string,...) ATTR_NORETURN; +void fatal (const char *string,...) ATTR_NORETURN; void warning (const char *string,...); +/* Functions from the register cache definition. */ +void init_registers (void); /* Maximum number of bytes to read/write at once. The value here is chosen to fill up a packet (the headers account for the 32). */ diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c new file mode 100644 index 0000000..53a4c1e --- /dev/null +++ b/gdb/gdbserver/target.c @@ -0,0 +1,47 @@ +/* Target operations for the remote server for GDB. + Copyright 2002 + Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + 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 "server.h" + +struct target_ops *the_target; + +void +read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) +{ + (*the_target->read_memory) (memaddr, myaddr, len); + check_mem_read (memaddr, myaddr, len); +} + +int +write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len) +{ + check_mem_write (memaddr, myaddr, len); + return (*the_target->write_memory) (memaddr, myaddr, len); +} + +void +set_target_ops (struct target_ops *target) +{ + the_target = (struct target_ops *) malloc (sizeof (*the_target)); + memcpy (the_target, target, sizeof (*the_target)); +} diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h new file mode 100644 index 0000000..6d06b9f --- /dev/null +++ b/gdb/gdbserver/target.h @@ -0,0 +1,141 @@ +/* Target operations for the remote server for GDB. + Copyright 2002 + Free Software Foundation, Inc. + + Contributed by MontaVista Software. + + 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 TARGET_H +#define TARGET_H + +struct target_ops +{ + /* Start a new process. + + PROGRAM is a path to the program to execute. + ARGS is a standard NULL-terminated array of arguments, + to be passed to the inferior as ``argv''. + + Returns 0 on success, -1 on failure. Registers the new + process with the process list. */ + + int (*create_inferior) (char *program, char **args); + + /* Attach to a running process. + + PID is the process ID to attach to, specified by the user + or a higher layer. */ + + int (*attach) (int pid); + + /* Kill all inferiors. */ + + void (*kill) (void); + + /* Return 1 iff the thread with process ID PID is alive. */ + + int (*thread_alive) (int pid); + + /* Resume the inferior process. + + If STEP is non-zero, we want to single-step. + + If SIGNAL is nonzero, send the process that signal as we resume it. + */ + + void (*resume) (int step, int signo); + + /* Wait for the inferior process to change state. + + STATUSP will be filled in with a response code to send to GDB. + + Returns the signal which caused the process to stop. */ + + unsigned char (*wait) (char *status); + + /* Fetch registers from the inferior process. + + If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO. */ + + void (*fetch_registers) (int regno); + + /* Store registers to the inferior process. + + If REGNO is -1, store all registers; otherwise, store at least REGNO. */ + + void (*store_registers) (int regno); + + /* Read memory from the inferior process. This should generally be + called through read_inferior_memory, which handles breakpoint shadowing. + + Read LEN bytes at MEMADDR into a buffer at MYADDR. */ + + void (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len); + + /* Write memory to the inferior process. This should generally be + called through write_inferior_memory, which handles breakpoint shadowing. + + Write LEN bytes from the buffer at MYADDR to MEMADDR. + + Returns 0 on success and errno on failure. */ + + int (*write_memory) (CORE_ADDR memaddr, const char *myaddr, int len); + + /* Query GDB for the values of any symbols we're interested in. + This function is called whenever we receive a "qSymbols::" + query, which corresponds to every time more symbols (might) + become available. NULL if we aren't interested in any + symbols. */ + + void (*look_up_symbols) (void); +}; + +extern struct target_ops *the_target; + +void set_target_ops (struct target_ops *); + +#define create_inferior(program, args) \ + (*the_target->create_inferior) (program, args) + +#define myattach(pid) \ + (*the_target->attach) (pid) + +#define kill_inferior() \ + (*the_target->kill) () + +#define mythread_alive(pid) \ + (*the_target->thread_alive) (pid) + +#define myresume(step,signo) \ + (*the_target->resume) (step, signo) + +#define mywait(statusp) \ + (*the_target->wait) (statusp) + +#define fetch_inferior_registers(regno) \ + (*the_target->fetch_registers) (regno) + +#define store_inferior_registers(regno) \ + (*the_target->store_registers) (regno) + +void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len); + +int write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len); + +#endif /* TARGET_H */ diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c index a8ea9a1..e13eda8 100644 --- a/gdb/gdbserver/utils.c +++ b/gdb/gdbserver/utils.c @@ -57,7 +57,7 @@ perror_with_name (char *string) STRING is the error message, used as a fprintf string, and ARG is passed as an argument to it. */ -NORETURN void +void error (const char *string,...) { extern jmp_buf toplevel; @@ -74,7 +74,7 @@ error (const char *string,...) STRING and ARG are passed to fprintf. */ /* VARARGS */ -NORETURN void +void fatal (const char *string,...) { va_list args; |