From 3ed16b22a65754c488f464cad8fc580de87b1383 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Tue, 27 Apr 1999 01:23:18 +0000 Subject: import gdb-19990422 snapshot --- gdb/MAINTAINERS | 669 +------------- gdb/config/i386/go32.mt | 3 + gdb/config/i386/nm-go32.h | 68 +- gdb/config/i386/tm-go32.h | 212 +++++ gdb/config/tic80/tic80.mt | 7 + gdb/config/tic80/tm-tic80.h | 257 ++++++ gdb/go32-nat.c | 2099 +++++++++---------------------------------- gdb/tic80-tdep.c | 483 ++++++++++ 8 files changed, 1482 insertions(+), 2316 deletions(-) create mode 100644 gdb/config/i386/go32.mt create mode 100644 gdb/config/i386/tm-go32.h create mode 100644 gdb/config/tic80/tic80.mt create mode 100644 gdb/config/tic80/tm-tic80.h create mode 100644 gdb/tic80-tdep.c diff --git a/gdb/MAINTAINERS b/gdb/MAINTAINERS index dd541f86e69..3810c96c1b8 100644 --- a/gdb/MAINTAINERS +++ b/gdb/MAINTAINERS @@ -1,636 +1,33 @@ - GDB Maintainers - =============== - - - Overview - -------- - -This file describes different groups of people who are, together, the -maintainers and developers of the GDB project. Don't worry - it sounds -more complicated than it really is. - -There are four groups of GDB developers, covering the patch development and -review process: - - - The Global Maintainers. - - These are the developers in charge of most daily development. They - have wide authority to apply and reject patches, but defer to the - Responsible Maintainers (see below) within their spheres of - responsibility. - - - The Responsible Maintainers. - - These are developers who have expertise and interest in a particular - area of GDB, who are generally available to review patches, and who - prefer to enforce a single vision within their areas. - - - The Authorized Committers. - - These are developers who are trusted to make changes within a specific - area of GDB without additional oversight. - - - The Write After Approval Maintainers. - - These are developers who have write access to the GDB source tree. They - can check in their own changes once a developer with the appropriate - authority has approved the changes; they can also apply the Obvious - Fix Rule (below). - -All maintainers are encouraged to post major patches to the gdb-patches -mailing list for comments, even if they have the authority to commit the -patch without review from another maintainer. This especially includes -patches which change internal interfaces (e.g. global functions, data -structures) or external interfaces (e.g. user, remote, MI, et cetera). - -The term "review" is used in this file to describe several kinds of feedback -from a maintainer: approval, rejection, and requests for changes or -clarification with the intention of approving a revised version. Review is -a privilege and/or responsibility of various positions among the GDB -Maintainers. Of course, anyone - whether they hold a position but not the -relevant one for a particular patch, or are just following along on the -mailing lists for fun, or anything in between - may suggest changes or -ask questions about a patch! - -There's also a couple of other people who play special roles in the GDB -community, separately from the patch process: - - - The GDB Steering Committee. - - These are the official (FSF-appointed) maintainers of GDB. They have - final and overriding authority for all GDB-related decisions, including - anything described in this file. The committee is not generally - involved in day-to-day development (although its members may be, as - individuals). - - - The Release Manager. - - This developer is in charge of making new releases of GDB. - - - The Patch Champions. - - These volunteers make sure that no contribution is overlooked or - forgotten. - -Most changes to the list of maintainers in this file are handled by -consensus among the global maintainers and any other involved parties. -In cases where consensus can not be reached, the global maintainers may -ask the Steering Committee for a final decision. - - - The Obvious Fix Rule - -------------------- - -All maintainers listed in this file, including the Write After Approval -developers, are allowed to check in obvious fixes. - -An "obvious fix" means that there is no possibility that anyone will -disagree with the change. - -A good mental test is "will the person who hates my work the most be -able to find fault with the change" - if so, then it's not obvious and -needs to be posted first. :-) - -Something like changing or bypassing an interface is _not_ an obvious -fix, since such a change without discussion will result in -instantaneous and loud complaints. - -For documentation changes, about the only kind of fix that is obvious -is correction of a typo or bad English usage. - - - GDB Steering Committee - ---------------------- - -The members of the GDB Steering Committee are the FSF-appointed -maintainers of the GDB project. - -The Steering Committee has final authority for all GDB-related topics; -they may make whatever changes that they deem necessary, or that the FSF -requests. However, they are generally not involved in day-to-day -development. - -The current members of the steering committee are listed below, in -alphabetical order. Their affiliations are provided for reference only - -their membership on the Steering Committee is individual and not through -their affiliation, and they act on behalf of the GNU project. - - Jim Blandy (Mozilla) - Andrew Cagney (Red Hat) - Robert Dewar (AdaCore, NYU) - Klee Dienes (Apple) - Paul Hilfinger (UC Berkeley) - Dan Jacobowitz (CodeSourcery) - Stan Shebs (CodeSourcery) - Richard Stallman (FSF) - Ian Lance Taylor (C2) - Todd Whitesel - - - Global Maintainers - ------------------ - -The global maintainers may review and commit any change to GDB, except in -areas with a Responsible Maintainer available. For major changes, or -changes to areas with other active developers, global maintainers are -strongly encouraged to post their own patches for feedback before -committing. - -The global maintainers are responsible for reviewing patches to any area -for which no Responsible Maintainer is listed. - -Global maintainers also have the authority to revert patches which should -not have been applied, e.g. patches which were not approved, controversial -patches committed under the Obvious Fix Rule, patches with important bugs -that can't be immediately fixed, or patches which go against an accepted and -documented roadmap for GDB development. Any global maintainer may request -the reversion of a patch. If no global maintainer, or responsible -maintainer in the affected areas, supports the patch (except for the -maintainer who originally committed it), then after 48 hours the maintainer -who called for the reversion may revert the patch. - -No one may reapply a reverted patch without the agreement of the maintainer -who reverted it, or bringing the issue to the GDB Steering Committee for -discussion. - -At the moment there are no documented roadmaps for GDB development; in the -future, if there are, a reference to the list will be included here. - -The current global maintainers are (in alphabetical order): - -Jim Blandy jimb@mozilla.com -Joel Brobecker brobecker@adacore.com -Kevin Buettner kevinb@redhat.com -Andrew Cagney cagney@gnu.org -Daniel Jacobowitz dan@debian.org -Mark Kettenis kettenis@gnu.org -Stan Shebs stan@codesourcery.com -Michael Snyder msnyder@specifix.com -Ulrich Weigand Ulrich.Weigand@de.ibm.com -Elena Zannoni ezannoni@redhat.com -Eli Zaretskii eliz@gnu.org - - - Release Manager - --------------- - -The current release manager is: Joel Brobecker - -His responsibilities are: - - * organizing, scheduling, and managing releases of GDB. - - * deciding the approval and commit policies for release branches, - and can change them as needed. - - - - Patch Champions - --------------- - -These volunteers track all patches submitted to the gdb-patches list. They -endeavor to prevent any posted patch from being overlooked; work with -contributors to meet GDB's coding style and general requirements, along with -FSF copyright assignments; remind (ping) responsible maintainers to review -patches; and ensure that contributors are given credit. - -Current patch champions (in alphabetical order): - - Randolph Chung - - - - Responsible Maintainers - ----------------------- - -These developers have agreed to review patches in specific areas of GDB, in -which they have knowledge and experience. These areas are generally broad; -the role of a responsible maintainer is to provide coherent and cohesive -structure within their area of GDB, to assure that patches from many -different contributors all work together for the best results. - -Global maintainers will defer to responsible maintainers within their areas, -as long as the responsible maintainer is active. Active means that -responsible maintainers agree to review submitted patches in their area -promptly; patches and followups should generally be answered within a week. -If a responsible maintainer is interested in reviewing a patch but will not -have time within a week of posting, the maintainer should send an -acknowledgement of the patch to the gdb-patches mailing list, and -plan to follow up with a review within a month. These deadlines are for -initial responses to a patch - if the maintainer has suggestions -or questions, it may take an extended discussion before the patch -is ready to commit. There are no written requirements for discussion, -but maintainers are asked to be responsive. - -If a responsible maintainer misses these deadlines occasionally (e.g. -vacation or unexpected workload), it's not a disaster - any global -maintainer may step in to review the patch. But sometimes life intervenes -more permanently, and a maintainer may no longer have time for these duties. -When this happens, he or she should step down (either into the Authorized -Committers section if still interested in the area, or simply removed from -the list of Responsible Maintainers if not). - -If a responsible maintainer is unresponsive for an extended period of time -without stepping down, please contact the Global Maintainers; they will try -to contact the maintainer directly and fix the problem - potentially by -removing that maintainer from their listed position. - -If there are several maintainers for a given domain then any one of them -may review a submitted patch. - -Target Instruction Set Architectures: - -The *-tdep.c files. ISA (Instruction Set Architecture) and OS-ABI -(Operating System / Application Binary Interface) issues including CPU -variants. - -The Target/Architecture maintainer works with the host maintainer when -resolving build issues. The Target/Architecture maintainer works with -the native maintainer when resolving ABI issues. - - alpha --target=alpha-elf ,-Werror - - arm --target=arm-elf ,-Werror - Richard Earnshaw rearnsha@arm.com - - avr --target=avr ,-Werror - - cris --target=cris-elf ,-Werror , - (sim does not build with -Werror) - - frv --target=frv-elf ,-Werror - - h8300 --target=h8300-elf ,-Werror - - i386 --target=i386-elf ,-Werror - Mark Kettenis kettenis@gnu.org - - ia64 --target=ia64-linux-gnu ,-Werror - (--target=ia64-elf broken) - - m32c --target=m32c-elf ,-Werror - Jim Blandy, jimb@codesourcery.com - - m32r --target=m32r-elf ,-Werror - - m68hc11 --target=m68hc11-elf ,-Werror , - Stephane Carrez stcarrez@nerim.fr - - m68k --target=m68k-elf ,-Werror - - m88k --target=m88k-openbsd ,-Werror - Mark Kettenis kettenis@gnu.org - - mcore Deleted - - mep --target=mep-elf ,-Werror - Kevin Buettner kevinb@redhat.com - - mips --target=mips-elf ,-Werror - - mn10300 --target=mn10300-elf broken - (sim/ dies with make -j) - Michael Snyder msnyder@specifix.com - - ms1 --target=ms1-elf ,-Werror - Kevin Buettner kevinb@redhat.com - - ns32k Deleted - - pa --target=hppa-elf ,-Werror - - powerpc --target=powerpc-eabi ,-Werror - - s390 --target=s390-linux-gnu ,-Werror - - score --target=score-elf - Qinwei qinwei@sunnorth.com.cn - - sh --target=sh-elf ,-Werror - --target=sh64-elf ,-Werror - - sparc --target=sparc64-solaris2.10 ,-Werror - (--target=sparc-elf broken) - - spu --target=spu-elf ,-Werror - Ulrich Weigand uweigand@de.ibm.com - - v850 --target=v850-elf ,-Werror - - vax --target=vax-netbsd ,-Werror - - x86-64 --target=x86_64-linux-gnu ,-Werror - - xstormy16 --target=xstormy16-elf - Corinna Vinschen vinschen@redhat.com - - xtensa --target=xtensa-elf - Maxim Grigoriev maxim2405@gmail.com - -All developers recognized by this file can make arbitrary changes to -OBSOLETE targets. - -The Bourne shell script gdb_mbuild.sh can be used to rebuild all the -above targets. - - -Host/Native: - -The Native maintainer is responsible for target specific native -support - typically shared libraries and quirks to procfs/ptrace/... -The Native maintainer works with the Arch and Core maintainers when -resolving more generic problems. - -The host maintainer ensures that gdb can be built as a cross debugger on -their platform. - -AIX Joel Brobecker brobecker@adacore.com - -djgpp native Eli Zaretskii eliz@gnu.org -GNU Hurd Alfred M. Szmidt ams@gnu.org -MS Windows (NT, '00, 9x, Me, XP) host & native - Chris Faylor cgf@alum.bu.edu -GNU/Linux/x86 native & host - Mark Kettenis kettenis@gnu.org -GNU/Linux MIPS native & host - Daniel Jacobowitz dan@debian.org -GNU/Linux m68k Andreas Schwab schwab@suse.de -FreeBSD native & host Mark Kettenis kettenis@gnu.org - - - -Core: Generic components used by all of GDB - -tracing Michael Snyder msnyder@specifix.com -threads Michael Snyder msnyder@specifix.com - Mark Kettenis kettenis@gnu.org -language support - Ada Joel Brobecker brobecker@adacore.com - Paul Hilfinger hilfinger@gnat.com - C++ Daniel Jacobowitz dan@debian.org - Objective C support Adam Fedor fedor@gnu.org -shared libs Kevin Buettner kevinb@redhat.com -MI interface Vladimir Prus vladimir@codesourcery.com - -documentation Eli Zaretskii eliz@gnu.org - (including NEWS) -testsuite - gdbtk (gdb.gdbtk) Keith Seitz keiths@redhat.com - threads (gdb.threads) Michael Snyder msnyder@specifix.com - trace (gdb.trace) Michael Snyder msnyder@specifix.com - - -UI: External (user) interfaces. - -gdbtk (c & tcl) Fernando Nasser fnasser@redhat.com - Keith Seitz keiths@redhat.com -libgui (w/foundry, sn) Keith Seitz keiths@redhat.com - - -Misc: - -gdb/gdbserver Daniel Jacobowitz dan@debian.org - -Makefile.in, configure* ALL - -mmalloc/ ALL Host maintainers - -sim/ See sim/MAINTAINERS - -readline/ Master version: ftp://ftp.cwru.edu/pub/bash/ - ALL - Host maintainers (host dependant parts) - (but get your changes into the master version) - -tcl/ tk/ itcl/ ALL - - - Authorized Committers - --------------------- - -These are developers working on particular areas of GDB, who are trusted to -commit their own (or other developers') patches in those areas without -further review from a Global Maintainer or Responsible Maintainer. They are -under no obligation to review posted patches - but, of course, are invited -to do so! - -PowerPC Andrew Cagney cagney@gnu.org -CRIS Hans-Peter Nilsson hp@axis.com -IA64 Jeff Johnston jjohnstn@redhat.com -MIPS Joel Brobecker brobecker@adacore.com -m32r Kei Sakamoto sakamoto.kei@renesas.com -PowerPC Kevin Buettner kevinb@redhat.com -CRIS Orjan Friberg orjanf@axis.com -HPPA Randolph Chung tausq@debian.org -S390 Ulrich Weigand uweigand@de.ibm.com -djgpp DJ Delorie dj@delorie.com - [Please use this address to contact DJ about DJGPP] -tui Stephane Carrez stcarrez@nerim.fr -ia64 Kevin Buettner kevinb@redhat.com -AIX Kevin Buettner kevinb@redhat.com -GNU/Linux PPC native Kevin Buettner kevinb@redhat.com -gdb.java tests Anthony Green green@redhat.com -FreeBSD native & host David O'Brien obrien@freebsd.org -event loop Elena Zannoni ezannoni@redhat.com -generic symtabs Elena Zannoni ezannoni@redhat.com -dwarf readers Elena Zannoni ezannoni@redhat.com -elf reader Elena Zannoni ezannoni@redhat.com -stabs reader Elena Zannoni ezannoni@redhat.com -readline/ Elena Zannoni ezannoni@redhat.com -NetBSD native & host Jason Thorpe thorpej@netbsd.org -Pascal support Pierre Muller muller@sources.redhat.com -avr Theodore A. Roth troth@openavr.org -Modula-2 support Gaius Mulley gaius@glam.ac.uk - - - Write After Approval - (alphabetic) - -To get recommended for the Write After Approval list you need a valid -FSF assignment and have submitted one good patch. - -Pedro Alves pedro_alves@portugalmail.pt -David Anderson davea@sgi.com -John David Anglin dave.anglin@nrc-cnrc.gc.ca -Shrinivas Atre shrinivasa@kpitcummins.com -Scott Bambrough scottb@netwinder.org -Thiago Jung Bauermann bauerman@br.ibm.com -Jan Beulich jbeulich@novell.com -Jim Blandy jimb@codesourcery.com -Philip Blundell philb@gnu.org -Per Bothner per@bothner.com -Joel Brobecker brobecker@adacore.com -Dave Brolley brolley@redhat.com -Paul Brook paul@codesourcery.com -Julian Brown julian@codesourcery.com -Kevin Buettner kevinb@redhat.com -Andrew Cagney cagney@gnu.org -David Carlton carlton@bactrian.org -Stephane Carrez stcarrez@nerim.fr -Michael Chastain mec.gnu@mindspring.com -Eric Christopher echristo@apple.com -Randolph Chung tausq@debian.org -Nick Clifton nickc@redhat.com -J.T. Conklin jtc@acorntoolworks.com -Brendan Conoboy blc@redhat.com -Ludovic Courtès ludo@gnu.org -DJ Delorie dj@redhat.com -Chris Demetriou cgd@google.com -Philippe De Muyter phdm@macqel.be -Dhananjay Deshpande dhananjayd@kpitcummins.com -Markus Deuling deuling@de.ibm.com -Klee Dienes kdienes@apple.com -Gabriel Dos Reis gdr@integrable-solutions.net -Richard Earnshaw rearnsha@arm.com -Steve Ellcey sje@cup.hp.com -Frank Ch. Eigler fche@redhat.com -Ben Elliston bje@gnu.org -Doug Evans dje@google.com -Adam Fedor fedor@gnu.org -Brian Ford ford@vss.fsi.com -Orjan Friberg orjanf@axis.com -Nathan Froyd froydnj@codesourcery.com -Gary Funck gary@intrepid.com -Paul Gilliam pgilliam@us.ibm.com -Raoul Gough RaoulGough@yahoo.co.uk -Anthony Green green@redhat.com -Matthew Green mrg@eterna.com.au -Maxim Grigoriev maxim2405@gmail.com -Jerome Guitton guitton@act-europe.fr -Ben Harris bjh21@netbsd.org -Richard Henderson rth@redhat.com -Aldy Hernandez aldyh@redhat.com -Paul Hilfinger hilfinger@gnat.com -Matt Hiller hiller@redhat.com -Kazu Hirata kazu@cs.umass.edu -Jeff Holcomb jeffh@redhat.com -Don Howard dhoward@redhat.com -Nick Hudson nick.hudson@dsl.pipex.com -Martin Hunt hunt@redhat.com -Jim Ingham jingham@apple.com -Baurzhan Ismagulov ibr@radix50.net -Manoj Iyer manjo@austin.ibm.com -Daniel Jacobowitz dan@debian.org -Andreas Jaeger aj@suse.de -Jeff Johnston jjohnstn@redhat.com -Geoff Keating geoffk@redhat.com -Mark Kettenis kettenis@gnu.org -Marc Khouzam marc.khouzam@ericsson.com -Jim Kingdon kingdon@panix.com -Jan Kratochvil jan.kratochvil@redhat.com -Jonathan Larmour jlarmour@redhat.co.uk -Jeff Law law@redhat.com -David Lecomber david@streamline-computing.com -Robert Lipe rjl@sco.com -H.J. Lu hjl.tools@gmail.com -Michal Ludvig mludvig@suse.cz -Luis Machado luisgpm@br.ibm.com -Glen McCready gkm@redhat.com -Greg McGary greg@mcgary.org -Roland McGrath roland@redhat.com -Bryce McKinlay mckinlay@redhat.com -Jason Merrill jason@redhat.com -David S. Miller davem@redhat.com -Mark Mitchell mark@codesourcery.com -Marko Mlinar markom@opencores.org -Alan Modra amodra@bigpond.net.au -Jason Molenda jmolenda@apple.com -Pierre Muller muller@sources.redhat.com -Gaius Mulley gaius@glam.ac.uk -Joseph Myers joseph@codesourcery.com -Fernando Nasser fnasser@redhat.com -Adam Nemet anemet@caviumnetworks.com -Nathanael Nerode neroden@gcc.gnu.org -Hans-Peter Nilsson hp@bitrange.com -David O'Brien obrien@freebsd.org -Alexandre Oliva aoliva@redhat.com -Denis Pilat denis.pilat@st.com -Vladimir Prus vladimir@codesourcery.com -Qinwei qinwei@sunnorth.com.cn -Frederic Riss frederic.riss@st.com -Aleksandar Ristovski aristovski@qnx.com -Tom Rix trix@redhat.com -Nick Roberts nickrob@snap.net.nz -Bob Rossi bob_rossi@cox.net -Theodore A. Roth troth@openavr.org -Ian Roxborough irox@redhat.com -Maciej W. Rozycki macro@linux-mips.org -Grace Sainsbury graces@redhat.com -Kei Sakamoto sakamoto.kei@renesas.com -Mark Salter msalter@redhat.com -Richard Sandiford richard@codesourcery.com -Peter Schauer Peter.Schauer@mytum.de -Andreas Schwab schwab@suse.de -Keith Seitz keiths@redhat.com -Carlos Eduardo Seo cseo@linux.vnet.ibm.com -Stan Shebs stan@codesourcery.com -Mark Shinwell shinwell@codesourcery.com -Craig Silverstein csilvers@google.com -Aidan Skinner aidan@velvet.net -Jiri Smid smid@suse.cz -David Smith dsmith@redhat.com -Stephen P. Smith ischis2@cox.net -Jackie Smith Cashion jsmith@redhat.com -Michael Snyder msnyder@specifix.com -Petr Sorfa petrs@caldera.com -Andrew Stubbs andrew.stubbs@st.com -Ian Lance Taylor ian@airs.com -Gary Thomas gthomas@redhat.com -Jason Thorpe thorpej@netbsd.org -Caroline Tice ctice@apple.com -Tom Tromey tromey@redhat.com -David Ung davidu@mips.com -D Venkatasubramanian dvenkat@noida.hcltech.com -Corinna Vinschen vinschen@redhat.com -Keith Walker keith.walker@arm.com -Kris Warkentin kewarken@qnx.com -Ulrich Weigand uweigand@de.ibm.com -Nathan Williams nathanw@wasabisystems.com -Bob Wilson bob.wilson@acm.org -Jim Wilson wilson@tuliptree.org -Elena Zannoni ezannoni@redhat.com -Eli Zaretskii eliz@gnu.org -Wu Zhou woodzltc@cn.ibm.com -Yoshinori Sato ysato@users.sourceforge.jp -Hui Zhu teawater@gmail.com - - - Past Maintainers - -Whenever removing yourself, or someone else, from this file, consider -listing their areas of development here for posterity. - -Jimmy Guo (gdb.hp, tui) guo at cup dot hp dot com -Jeff Law (hppa) law at cygnus dot com -Daniel Berlin (C++ support) dan at cgsoftware dot com -Nick Duffek (powerpc, SCO, Sol/x86) nick at duffek dot com -David Taylor (d10v, sparc, utils, defs, - expression evaluator, language support) taylor at candd dot org -J.T. Conklin (dcache, NetBSD, remote, global) jtc at acorntoolworks dot com -Frank Ch. Eigler (sim) fche at redhat dot com -Per Bothner (Java) per at bothner dot com -Anthony Green (Java) green at redhat dot com -Fernando Nasser (testsuite/, mi, cli, KOD) fnasser at redhat dot com -Mark Salter (testsuite/lib+config) msalter at redhat dot com -Jim Kingdon (web pages) kingdon at panix dot com -Jim Ingham (gdbtk, libgui) jingham at apple dot com -Mark Kettenis (hurd native) kettenis at gnu dot org -Ian Roxborough (in-tree tcl, tk, itcl) irox at redhat dot com -Robert Lipe (SCO/Unixware) rjl at sco dot com -Peter Schauer (global, AIX, xcoffsolib, - Solaris/x86) Peter.Schauer at mytum dot de -Scott Bambrough (ARM) scottb at netwinder dot org -Philippe De Muyter (coff) phdm at macqel dot be -Michael Chastain (testsuite) mec.gnu at mindspring dot com -Fred Fish (global) - - - -Folks that have been caught up in a paper trail: - -David Carlton carlton@bactrian.org -Ramana Radhakrishnan ramana.r@gmail.com - -;; Local Variables: -;; coding: utf-8 -;; End: +d10v target Andrew Cagney cagney@cygnus.com +d30v target Andrew Cagney cagney@cygnus.com +mips target Andrew Cagney cagney@cygnus.com +powerpc target Andrew Cagney cagney@cygnus.com +generic arch support Andrew Cagney cagney@cygnus.com +target vector Andrew Cagney cagney@cygnus.com +remote.c Andrew Cagney cagney@cygnus.com +djgpp native DJ Delorie dj@cygnus.com +win32 host & native Chris Faylor cgf@cygnus.com +main (main.c, top.c) Elena Zannoni ezannoni@cygnus.com +readline Elena Zannoni ezannoni@cygnus.com +arm target Elena Zannoni ezannoni@cygnus.com +command interpreter Fernando Nasser fnasser@cygnus.com +generic symtabs Jim Blandy jimb@cygnus.com +dwarf readers Jim Blandy jimb@cygnus.com +elf reader Jim Blandy jimb@cygnus.com +stabs reader Jim Blandy jimb@cygnus.com +x86 linux native Jim Blandy jimb@cygnus.com +Scheme support Jim Blandy jimb@cygnus.com +m32r target Michael Snyder msnyder@cygnus.com +tracing Michael Snyder msnyder@cygnus.com +threads Michael Snyder msnyder@cygnus.com +breakpoint.c Michael Snyder msnyder@cygnus.com +macos host & native Stan Shebs shebs@cygnus.com +sds protocol Stan Shebs shebs@cygnus.com +rdi/adp protocol Stan Shebs shebs@cygnus.com +gdbserver Stan Shebs shebs@cygnus.com +documentation Stan Shebs shebs@cygnus.com +testsuite Stan Shebs shebs@cygnus.com +language support David Taylor taylor@cygnus.com +expression eval David Taylor taylor@cygnus.com +defs.h David Taylor taylor@cygnus.com +utils.c David Taylor taylor@cygnus.com diff --git a/gdb/config/i386/go32.mt b/gdb/config/i386/go32.mt new file mode 100644 index 00000000000..9b82c6426b4 --- /dev/null +++ b/gdb/config/i386/go32.mt @@ -0,0 +1,3 @@ +# Target: Intel 386 running DJGPP +TDEPFILES= i386-tdep.o i387-tdep.o +TM_FILE= tm-go32.h diff --git a/gdb/config/i386/nm-go32.h b/gdb/config/i386/nm-go32.h index 86ed270f7d7..183b60fa181 100644 --- a/gdb/config/i386/nm-go32.h +++ b/gdb/config/i386/nm-go32.h @@ -1,35 +1,57 @@ /* Native definitions for Intel x86 running DJGPP. - Copyright 1997, 1998, 1999, 2001, 2002, 2007, 2008 - Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. - This file is part of GDB. +This file is part of GDB. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define I386_USE_GENERIC_WATCHPOINTS +#define NO_PTRACE_H -#include "i386/nm-i386.h" +#include "i386/nm-i386v.h" -/* Support for hardware-assisted breakpoints and watchpoints. */ +#define TARGET_HAS_HARDWARE_WATCHPOINTS -#define I386_DR_LOW_SET_CONTROL(VAL) go32_set_dr7 (VAL) -extern void go32_set_dr7 (unsigned); +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1 -#define I386_DR_LOW_SET_ADDR(N,ADDR) go32_set_dr (N,ADDR) -extern void go32_set_dr (int, CORE_ADDR); +/* After a watchpoint trap, the PC points to the instruction after the + one that caused the trap. Therefore we don't need to step over it. + But we do need to reset the status register to avoid another trap. */ -#define I386_DR_LOW_RESET_ADDR(N) +#define HAVE_CONTINUABLE_WATCHPOINT + +#define STOPPED_BY_WATCHPOINT(W) \ + go32_stopped_by_watchpoint (inferior_pid) + +/* Use these macros for watchpoint insertion/removal. */ + +#define target_insert_watchpoint(addr, len, type) \ + go32_insert_watchpoint (inferior_pid, addr, len, 2) + +#define target_remove_watchpoint(addr, len, type) \ + go32_remove_watchpoint (inferior_pid, addr, len) + +#define target_insert_hw_breakpoint(addr, shadow) \ + go32_insert_hw_breakpoint(addr, shadow) + +#define target_remove_hw_breakpoint(addr, shadow) \ + go32_remove_hw_breakpoint(addr, shadow) + +#define DECR_PC_AFTER_HW_BREAK 0 + +#undef FLOAT_INFO +#define FLOAT_INFO { i386_go32_float_info (); } + +extern void i386_go32_float_info (void); -#define I386_DR_LOW_GET_STATUS() go32_get_dr6 () -extern unsigned go32_get_dr6 (void); diff --git a/gdb/config/i386/tm-go32.h b/gdb/config/i386/tm-go32.h new file mode 100644 index 00000000000..84b82929ec5 --- /dev/null +++ b/gdb/config/i386/tm-go32.h @@ -0,0 +1,212 @@ +/* Target-dependent definitions for Intel x86 running DJGPP. + Copyright 1995, 1996, 1997 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 "i386/tm-i386v.h" + +/* Number of machine registers. */ + +#undef NUM_FREGS +#define NUM_FREGS 15 +#undef NUM_REGS +#define NUM_REGS (16+NUM_FREGS) + +/* Initializer for an array of names of registers. There should be + NUM_REGS strings in this initializer. */ + +/* The order of the first 8 registers must match the compiler's + numbering scheme (which is the same as the 386 scheme). */ + +#undef REGISTER_NAMES +#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \ + "esp", "ebp", "esi", "edi", \ + "eip", "eflags","cs", "ss", \ + "ds", "es", "fs", "gs", \ + "st0", "st1", "st2", "st3", \ + "st4", "st5", "st6", "st7", \ + "fctrl","fstat", "ftag", "fcs", \ + "fopsel","fip", "fopoff" } + +#undef FP_REGNUM +#define FP_REGNUM 5 /* (ebp) Contains addr of stack frame */ +#undef SP_REGNUM +#define SP_REGNUM 4 /* (usp) Contains address of top of stack */ +#undef PS_REGNUM +#define PS_REGNUM 9 /* (ps) Contains processor status */ +#undef PC_REGNUM +#define PC_REGNUM 8 /* (eip) Contains program counter */ +#undef FP0_REGNUM +#define FP0_REGNUM 16 /* Floating point register 0 */ +#undef FPC_REGNUM +#define FPC_REGNUM 24 /* 80387 control register */ +#undef FPCWD_REGNUM +#define FPCWD_REGNUM FPC_REGNUM +#undef FPSWD_REGNUM +#define FPSWD_REGNUM 25 /* 80387 status register */ +#undef FPTWD_REGNUM +#define FPTWD_REGNUM 26 /* 80387 tag register */ +#undef FPIPO_REGNUM +#define FPIPO_REGNUM 29 /* 80387 instruction pointer offset reg */ +#undef FPIPS_REGNUM +#define FPIPS_REGNUM 27 /* 80387 instruction pointer selector reg */ +#undef FPOOS_REGNUM +#define FPOOS_REGNUM 30 /* 80387 operand pointer offset reg */ +#undef FPOPS_REGNUM +#define FPOPS_REGNUM 28 /* 80387 operand pointer selector reg */ + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ + +#undef REGISTER_BYTES +#define REGISTER_BYTES (10*4 + 6*2 + 8*10 + 5*2 + 2*4) + +/* Index within `registers' of the first byte of the space for + register N. */ + +#undef REGISTER_BYTE +#define REGBYTE_0 0 +#define REGBYTE_10 (REGBYTE_0+10*4) +#define REGBYTE_16 (REGBYTE_10+6*2) +#define REGBYTE_24 (REGBYTE_16+8*10) +#define REGBYTE_29 (REGBYTE_24+5*2) +#define REGISTER_BYTE(N) (((N) < 10) ? (N) * 4 : \ + (N) < 16 ? REGBYTE_10 +((N) - 10) * 2 : \ + (N) < 24 ? REGBYTE_16 +((N) - 16) * 10 : \ + (N) < 29 ? REGBYTE_24 +((N) - 24) * 2 : \ + REGBYTE_29 + ((N) - 29) * 4) + +/* Number of bytes of storage in the actual machine representation + for register N. */ + +#undef REGISTER_RAW_SIZE +#define REGISTER_RAW_SIZE(N) ((N) < 10 ? 4 : (N) < 16 ? 2 : (N) < 24 ? 10 : \ + (N) < 29 ? 2 : 4) + +/* Number of bytes of storage in the program's representation + for register N. */ + +#undef REGISTER_VIRTUAL_SIZE +#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N) + +/* Largest value REGISTER_RAW_SIZE can have. */ + +#undef MAX_REGISTER_RAW_SIZE +#define MAX_REGISTER_RAW_SIZE 10 + +/* Largest value REGISTER_VIRTUAL_SIZE can have. */ + +#undef MAX_REGISTER_VIRTUAL_SIZE +#define MAX_REGISTER_VIRTUAL_SIZE 10 + +/* Nonzero if register N requires conversion + from raw format to virtual format. */ + +#undef REGISTER_CONVERTIBLE +#define REGISTER_CONVERTIBLE(N) ((N) < FP0_REGNUM ? 0 :\ + (N) < FPC_REGNUM ? 1 : 0) + +/* The host and target are i386 machines and the compiler supports + long doubles. Long doubles on the host therefore have the same + layout as a 387 FPU stack register. */ + +#if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386) +#undef LD_I387 +#define LD_I387 +#endif + +/* Allow floating point numbers to be specified by a raw long double + 10 hex bytes number, e.g. 1.0 can be input as + 0x3fff8000000000000000 */ + +#ifdef LD_I387 +#define HEX_LONG_DOUBLE_INPUT(base,p,len,target) \ + ((base) == 16 && (len) == 20 \ + && i387_hex_long_double_input ((p), (target))) +#endif + +extern int i387_hex_long_double_input (char *p, long double *putithere); + +#undef REGISTER_CONVERT_TO_VIRTUAL +#ifdef LD_I387 +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ +{ \ + if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \ + { \ + memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \ + } \ + else \ + { \ + long double val = *((long double *)FROM); \ + store_floating ((TO), TYPE_LENGTH (TYPE), val); \ + } \ +} +#else +/* Convert data from raw format for register REGNUM in buffer FROM to + virtual format with type TYPE in buffer TO. */ +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ +{ \ + double val; \ + i387_to_double ((FROM), (char *)&val); \ + store_floating ((TO), TYPE_LENGTH (TYPE), val); \ +} +#endif + +extern void i387_to_double PARAMS ((char *, char *)); + +#undef REGISTER_CONVERT_TO_RAW +#ifdef LD_I387 +#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ +{ \ + if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \ + { \ + memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \ + } \ + else \ + { \ + long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ + *((long double *)TO) = val; \ + } \ +} +#else +#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ +{ \ + double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ + double_to_i387((char *)&val, (TO)); \ +} +#endif + +extern void double_to_i387 PARAMS ((char *, char *)); + +/* Return the GDB type object for the "standard" data type of data in + register N. */ + +#undef REGISTER_VIRTUAL_TYPE +#ifdef LD_I387 +#define REGISTER_VIRTUAL_TYPE(N) \ + ((N < FP0_REGNUM) ? builtin_type_int : \ + (N < FPC_REGNUM) ? builtin_type_long_double : builtin_type_int) +#else +#define REGISTER_VIRTUAL_TYPE(N) \ + ((N < FP0_REGNUM) ? builtin_type_int : \ + (N < FPC_REGNUM) ? builtin_type_double : builtin_type_int) +#endif + +#undef TARGET_LONG_DOUBLE_BIT +#define TARGET_LONG_DOUBLE_BIT 96 + +#define NAMES_HAVE_UNDERSCORE diff --git a/gdb/config/tic80/tic80.mt b/gdb/config/tic80/tic80.mt new file mode 100644 index 00000000000..10be27e2633 --- /dev/null +++ b/gdb/config/tic80/tic80.mt @@ -0,0 +1,7 @@ +# Target: TI TMS320C80 (MVP) processor +TDEPFILES= tic80-tdep.o +TM_FILE= tm-tic80.h +SIM_OBS = remote-sim.o +SIM = ../sim/tic80/libsim.a +GDBSERVER_DEPFILES= low-sim.o +GDBSERVER_LIBS = ../../sim/tic80/libsim.a ../../bfd/libbfd.a ../../libiberty/libiberty.a -lm diff --git a/gdb/config/tic80/tm-tic80.h b/gdb/config/tic80/tm-tic80.h new file mode 100644 index 00000000000..e17ca95b838 --- /dev/null +++ b/gdb/config/tic80/tm-tic80.h @@ -0,0 +1,257 @@ +/* Parameters for execution on a TI TMS320C80 (MVP) processor. + Copyright 1997 + Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef TM_TIC80_H +#define TM_TIC80_H + +#ifdef __STDC__ /* Forward declare structs used in prototypes */ +struct frame_info; +struct type; +struct value; +struct symbol; +struct frame_saved_regs; +#endif + +#define TARGET_BYTE_ORDER LITTLE_ENDIAN + +/* Define this if the C compiler puts an underscore at the front + of external names before giving them to the linker. */ + +#define NAMES_HAVE_UNDERSCORE + +#define NUM_REGS 38 + +#define REGISTER_NAMES \ +{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \ + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \ + "pc", "npc", \ + "a0", "a1", "a2", "a3", \ +} + +/* Various dedicated register numbers + FIXME: Shadow updates in sim/tic80/sim-calls.c */ + +#define SP_REGNUM 1 /* Contains address of top of stack */ +#define ARG0_REGNUM 2 /* Contains argument 1 (r3 has high word) */ +#define RET_REGNUM 2 /* Contains function return value */ +#define ARGLAST_REGNUM 12 /* Contains argument 6 (r13 has high word) */ +#define FP_REGNUM 30 /* Contains address of executing stack frame */ +#define LR_REGNUM 31 /* Contains address of caller (link register) */ +#define PC_REGNUM 32 /* Contains program counter (FIXME?) */ +#define NPC_REGNUM 33 /* Contains the next program counter (FIXME?) */ +#define A0_REGNUM 34 /* Accumulator register 0 */ +#define A3_REGNUM 37 /* Accumulator register 1 */ + +#define R0_REGNUM 0 /* General Purpose Register 0 - for sim */ +#define Rn_REGNUM 31 /* Last General Purpose Register - for sim */ +#define An_REGNUM A3_REGNUM /* Last Accumulator register - for sim */ + +/* Total amount of space needed to store our copies of the machine's + register state, the array `registers'. */ + +#define REGISTER_BYTES (((NUM_REGS - 4) * 4) + (4 * 8)) + +/* Index within `registers' of the first byte of the space for + register N. */ + +#define REGISTER_BYTE(N) \ + (((N) >= A0_REGNUM) ? (((N) - A0_REGNUM) * 8 + A0_REGNUM * 4) : ((N) * 4)) + +/* Most registers are 4 bytes */ + +#define REGISTER_SIZE 4 + +/* Some registers are 8 bytes. */ + +#define REGISTER_RAW_SIZE(N) \ + (((N) >= A0_REGNUM) ? 8 : 4) + +/* Largest value REGISTER_RAW_SIZE can have. */ + +#define MAX_REGISTER_RAW_SIZE (8) + +/* All regs are 4 bytes. */ + +#define REGISTER_VIRTUAL_SIZE(N) (REGISTER_RAW_SIZE(N)) + +/* Largest value REGISTER_VIRTUAL_SIZE can have. */ + +#define MAX_REGISTER_VIRTUAL_SIZE (MAX_REGISTER_RAW_SIZE) + +/* Return the GDB type object for the "standard" data type + of data in register N. */ + +#define REGISTER_VIRTUAL_TYPE(N) /* FIXME? */ \ + (((N) >= A0_REGNUM) ? builtin_type_float : builtin_type_int) + +/* Offset from address of function to start of its code. + Zero on most machines. */ + +#define FUNCTION_START_OFFSET 0 + +/* Stack grows downward. */ + +#define INNER_THAN(lhs,rhs) ((lhs) < (rhs)) + +/* Sequence of bytes for breakpoint instruction. + This is padded out to the size of a machine word. */ + +#define BREAKPOINT {0x49, 0x80, 0x00, 0x00} /* FIXME! */ + +/* Amount PC must be decremented by after a breakpoint. + This is often the number of bytes in BREAKPOINT + but not always. */ + +#define DECR_PC_AFTER_BREAK 0 /* FIXME! */ + +/* Discard from the stack the innermost frame, restoring all registers. */ + +#define POP_FRAME tic80_pop_frame(get_current_frame ()) +extern struct frame_info *tic80_pop_frame PARAMS ((struct frame_info *frame)); + +/* Return number of bytes at start of arglist that are not really args. */ + +#define FRAME_ARGS_SKIP 0 + +/* Set VAL to the number of args passed to frame described by FI. + Can set VAL to -1, meaning no way to tell. */ +/* We can't tell how many args there are */ + +#define FRAME_NUM_ARGS(val,fi) (val = -1) + +#define FRAME_ARGS_SKIP 0 +#define FRAME_ARGS_ADDRESS(fi) (fi)->frame +#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame + +/* Define other aspects of the stack frame. + We keep the offsets of all saved registers, 'cause we need 'em a lot! + We also keep the current size of the stack frame, and the offset of + the frame pointer from the stack pointer (for frameless functions, and + when we're still in the prologue of a function with a frame) */ + +#define EXTRA_FRAME_INFO \ + struct frame_saved_regs fsr; \ + int framesize; \ + int frameoffset; \ + int framereg; + +extern void tic80_init_extra_frame_info PARAMS ((struct frame_info *fi)); +#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) tic80_init_extra_frame_info (fi) +#define INIT_FRAME_PC /* Not necessary */ + +/* Put here the code to store, into a struct frame_saved_regs, + the addresses of the saved registers of frame described by FRAME_INFO. + This includes special registers such as pc and fp saved in special + ways in the stack frame. sp is even more special: + the address we return for it IS the sp for the next frame. */ + +#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ + tic80_frame_find_saved_regs(frame_info, &(frame_saved_regs)) +extern void tic80_frame_find_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *)); + +/* Advance PC across any function entry prologue instructions + to reach some "real" code. */ + +#define SKIP_PROLOGUE(pc) { (pc) = tic80_skip_prologue (pc); } +extern CORE_ADDR tic80_skip_prologue PARAMS ((CORE_ADDR pc)); + +/* Immediately after a function call, return the saved pc. + Can't always go through the frames for this because on some machines + the new frame is not set up until the new function executes + some instructions. */ + +#define SAVED_PC_AFTER_CALL(frame) read_register (LR_REGNUM) + +/* Describe the pointer in each stack frame to the previous stack frame + (its caller). */ + +/* FRAME_CHAIN takes a frame's nominal address + and produces the frame's chain-pointer. */ + +#define FRAME_CHAIN(thisframe) (CORE_ADDR) tic80_frame_chain (thisframe) +extern CORE_ADDR tic80_frame_chain PARAMS ((struct frame_info *)); + +#define FRAME_SAVED_PC(FRAME) tic80_frame_saved_pc (FRAME) +extern CORE_ADDR tic80_frame_saved_pc PARAMS ((struct frame_info *)); + +/* Store the address of the place in which to copy the structure the + subroutine will return. This is called from call_function. + + We store structs through a pointer passed in R2 */ + +#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) \ + write_register (ARG0_REGNUM, STRUCT_ADDR) + +/* Extract from an array REGBUF containing the (raw) register state + a function return value of type TYPE, and copy that, in virtual format, + into VALBUF. */ + +#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \ + memcpy ((VALBUF), \ + (char *)(REGBUF) + REGISTER_BYTE (RET_REGNUM) + \ + ((TYPE_LENGTH (TYPE) > 4 ? 8 : 4) - TYPE_LENGTH (TYPE)), \ + TYPE_LENGTH (TYPE)) + +/* Write into appropriate registers a function return value + of type TYPE, given in virtual format. */ + +#define STORE_RETURN_VALUE(TYPE,VALBUF) \ + write_register_bytes(REGISTER_BYTE (RET_REGNUM) + \ + ((TYPE_LENGTH (TYPE) > 4 ? 8:4) - TYPE_LENGTH (TYPE)),\ + (VALBUF), TYPE_LENGTH (TYPE)); + + + +/* PUSH_ARGUMENTS */ +extern CORE_ADDR tic80_push_arguments PARAMS ((int nargs, + struct value **args, + CORE_ADDR sp, + unsigned char struct_return, + CORE_ADDR struct_addr)); + +#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \ + (SP) = tic80_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) + +/* PUSH_RETURN_ADDRESS */ +extern CORE_ADDR tic80_push_return_address PARAMS ((CORE_ADDR, CORE_ADDR)); +#define PUSH_RETURN_ADDRESS(PC, SP) tic80_push_return_address (PC, SP) + +/* override the standard get_saved_register function with + one that takes account of generic CALL_DUMMY frames */ +#define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \ + generic_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) + +#define USE_GENERIC_DUMMY_FRAMES 1 +#define CALL_DUMMY {0} +#define CALL_DUMMY_LENGTH (0) +#define CALL_DUMMY_START_OFFSET (0) +#define CALL_DUMMY_BREAKPOINT_OFFSET (0) +#define FIX_CALL_DUMMY(DUMMY1, STARTADDR, FUNADDR, NARGS, ARGS, TYPE, GCCP) +#define CALL_DUMMY_LOCATION AT_ENTRY_POINT +#define CALL_DUMMY_ADDRESS() entry_point_address () + +/* generic dummy frame stuff */ + +#define PUSH_DUMMY_FRAME generic_push_dummy_frame () +#define PC_IN_CALL_DUMMY(PC, SP, FP) generic_pc_in_call_dummy (PC, SP, FP) + +#endif /* TM_TIC80_H */ diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index d4744a8b5c4..782d240805b 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -1,302 +1,214 @@ /* Native debugging support for Intel x86 running DJGPP. - Copyright (C) 1997, 1999, 2000, 2001, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. + Copyright 1997, 1999 Free Software Foundation, Inc. Written by Robert Hoehne. - This file is part of GDB. +This file is part of GDB. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ +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 #include "defs.h" +#include "frame.h" /* required by inferior.h */ #include "inferior.h" -#include "gdb_wait.h" +#include "target.h" +#include "wait.h" #include "gdbcore.h" #include "command.h" -#include "gdbcmd.h" #include "floatformat.h" -#include "buildsym.h" -#include "i387-tdep.h" -#include "i386-tdep.h" -#include "value.h" -#include "regcache.h" -#include "gdb_string.h" -#include "top.h" - -#include /* might be required for __DJGPP_MINOR__ */ + #include -#include -#include +#include #include -#include -#include -#include -#include -#include -#include #include #include -#if __DJGPP_MINOR__ > 2 -#include -#endif -#if __DJGPP_MINOR__ < 3 -/* This code will be provided from DJGPP 2.03 on. Until then I code it - here */ -typedef struct - { - unsigned short sig0; - unsigned short sig1; - unsigned short sig2; - unsigned short sig3; - unsigned short exponent:15; - unsigned short sign:1; - } -NPXREG; +extern void _initialize_go32_nat (void); + +struct env387 +{ + unsigned short control; + unsigned short r0; + unsigned short status; + unsigned short r1; + unsigned short tag; + unsigned short r2; + unsigned long eip; + unsigned short code_seg; + unsigned short opcode; + unsigned long operand; + unsigned short operand_seg; + unsigned short r3; + unsigned char regs[8][10]; +}; -typedef struct - { - unsigned int control; - unsigned int status; - unsigned int tag; - unsigned int eip; - unsigned int cs; - unsigned int dataptr; - unsigned int datasel; - NPXREG reg[8]; - } -NPX; +extern char **environ; -static NPX npx; +#define SOME_PID 42 -static void save_npx (void); /* Save the FPU of the debugged program */ -static void load_npx (void); /* Restore the FPU of the debugged program */ +/* FIXME add decls of all static functions here */ -/* ------------------------------------------------------------------------- */ -/* Store the contents of the NPX in the global variable `npx'. */ -/* *INDENT-OFF* */ +static int prog_has_started = 0; static void -save_npx (void) +print_387_status (unsigned short status, struct env387 *ep) { - asm ("inb $0xa0, %%al \n\ - testb $0x20, %%al \n\ - jz 1f \n\ - xorb %%al, %%al \n\ - outb %%al, $0xf0 \n\ - movb $0x20, %%al \n\ - outb %%al, $0xa0 \n\ - outb %%al, $0x20 \n\ -1: \n\ - fnsave %0 \n\ - fwait " -: "=m" (npx) -: /* No input */ -: "%eax"); -} + int i; + int bothstatus; + int top; + int fpreg; -/* *INDENT-ON* */ + bothstatus = ((status != 0) && (ep->status != 0)); + if (status != 0) + { + if (bothstatus) + printf_unfiltered ("u: "); + print_387_status_word (status); + } + if (ep->status != 0) + { + if (bothstatus) + printf_unfiltered ("e: "); + print_387_status_word (ep->status); + } -/* ------------------------------------------------------------------------- */ -/* Reload the contents of the NPX from the global variable `npx'. */ + print_387_control_word (ep->control & 0xffff); + printf_unfiltered ("last exception: "); + printf_unfiltered ("opcode %s; ", local_hex_string (ep->opcode)); + printf_unfiltered ("pc %s:", local_hex_string (ep->code_seg)); + printf_unfiltered ("%s; ", local_hex_string (ep->eip)); + printf_unfiltered ("operand %s", local_hex_string (ep->operand_seg)); + printf_unfiltered (":%s\n", local_hex_string (ep->operand)); -static void -load_npx (void) -{ - asm ("frstor %0":"=m" (npx)); -} -/* ------------------------------------------------------------------------- */ -/* Stubs for the missing redirection functions. */ -typedef struct { - char *command; - int redirected; -} cmdline_t; + top = (ep->status >> 11) & 7; -void -redir_cmdline_delete (cmdline_t *ptr) -{ - ptr->redirected = 0; -} + printf_unfiltered ("regno tag msb lsb value\n"); + for (fpreg = 0; fpreg < 8; fpreg++) + { + long double val; -int -redir_cmdline_parse (const char *args, cmdline_t *ptr) -{ - return -1; -} + printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg); -int -redir_to_child (cmdline_t *ptr) -{ - return 1; -} + switch ((ep->tag >> (fpreg * 2)) & 3) + { + case 0: + printf_unfiltered ("valid "); + break; + case 1: + printf_unfiltered ("zero "); + break; + case 2: + printf_unfiltered ("trap "); + break; + case 3: + printf_unfiltered ("empty "); + break; + } + for (i = 0; i < 8; i++) + printf_unfiltered ("%02x", ep->regs[fpreg][i]); -int -redir_to_debugger (cmdline_t *ptr) -{ - return 1; + REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM + fpreg, builtin_type_long_double, + &ep->regs[fpreg], &val); + + printf_unfiltered (" %LG\n", val); + } } -int -redir_debug_init (cmdline_t *ptr) +void +i386_go32_float_info (void) { - return 0; + print_387_status (0, (struct env387 *) &npx); } -#endif /* __DJGPP_MINOR < 3 */ -typedef enum { wp_insert, wp_remove, wp_count } wp_op; - -/* This holds the current reference counts for each debug register. */ -static int dr_ref_count[4]; - -#define SOME_PID 42 - -static int prog_has_started = 0; -static void go32_open (char *name, int from_tty); -static void go32_close (int quitting); -static void go32_attach (char *args, int from_tty); -static void go32_detach (char *args, int from_tty); -static void go32_resume (ptid_t ptid, int step, - enum target_signal siggnal); -static ptid_t go32_wait (ptid_t ptid, - struct target_waitstatus *status); -static void go32_fetch_registers (struct regcache *, int regno); -static void store_register (const struct regcache *, int regno); -static void go32_store_registers (struct regcache *, int regno); -static void go32_prepare_to_store (struct regcache *); -static int go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, - int write, - struct mem_attrib *attrib, - struct target_ops *target); -static void go32_files_info (struct target_ops *target); -static void go32_stop (ptid_t); -static void go32_kill_inferior (void); -static void go32_create_inferior (char *exec_file, char *args, char **env, int from_tty); -static void go32_mourn_inferior (void); -static int go32_can_run (void); - -static struct target_ops go32_ops; -static void go32_terminal_init (void); -static void go32_terminal_inferior (void); -static void go32_terminal_ours (void); - -#define r_ofs(x) (offsetof(TSS,x)) +#define r_ofs(x) ((int)(&(((TSS *)0)->x))) static struct { - size_t tss_ofs; - size_t size; + int tss_ofs; + int size; } regno_mapping[] = { - {r_ofs (tss_eax), 4}, /* normal registers, from a_tss */ - {r_ofs (tss_ecx), 4}, - {r_ofs (tss_edx), 4}, - {r_ofs (tss_ebx), 4}, - {r_ofs (tss_esp), 4}, - {r_ofs (tss_ebp), 4}, - {r_ofs (tss_esi), 4}, - {r_ofs (tss_edi), 4}, - {r_ofs (tss_eip), 4}, - {r_ofs (tss_eflags), 4}, - {r_ofs (tss_cs), 2}, - {r_ofs (tss_ss), 2}, - {r_ofs (tss_ds), 2}, - {r_ofs (tss_es), 2}, - {r_ofs (tss_fs), 2}, - {r_ofs (tss_gs), 2}, - {0, 10}, /* 8 FP registers, from npx.reg[] */ - {1, 10}, - {2, 10}, - {3, 10}, - {4, 10}, - {5, 10}, - {6, 10}, - {7, 10}, - /* The order of the next 7 registers must be consistent - with their numbering in config/i386/tm-i386.h, which see. */ - {0, 2}, /* control word, from npx */ - {4, 2}, /* status word, from npx */ - {8, 2}, /* tag word, from npx */ - {16, 2}, /* last FP exception CS from npx */ - {12, 4}, /* last FP exception EIP from npx */ - {24, 2}, /* last FP exception operand selector from npx */ - {20, 4}, /* last FP exception operand offset from npx */ - {18, 2} /* last FP opcode from npx */ + r_ofs (tss_eax), 4, + r_ofs (tss_ecx), 4, + r_ofs (tss_edx), 4, + r_ofs (tss_ebx), 4, + r_ofs (tss_esp), 4, + r_ofs (tss_ebp), 4, + r_ofs (tss_esi), 4, + r_ofs (tss_edi), 4, + r_ofs (tss_eip), 4, + r_ofs (tss_eflags), 4, + r_ofs (tss_cs), 2, + r_ofs (tss_ss), 2, + r_ofs (tss_ds), 2, + r_ofs (tss_es), 2, + r_ofs (tss_fs), 2, + r_ofs (tss_gs), 2, + 0, 10, + 1, 10, + 2, 10, + 3, 10, + 4, 10, + 5, 10, + 6, 10, + 7, 10, + 0, 2, + 4, 2, + 8, 2, + 12, 4, + 16, 2, + 20, 4, + 24, 2 }; static struct { int go32_sig; - enum target_signal gdb_sig; + int gdb_sig; } sig_map[] = { - {0, TARGET_SIGNAL_FPE}, - {1, TARGET_SIGNAL_TRAP}, - /* Exception 2 is triggered by the NMI. DJGPP handles it as SIGILL, - but I think SIGBUS is better, since the NMI is usually activated - as a result of a memory parity check failure. */ - {2, TARGET_SIGNAL_BUS}, - {3, TARGET_SIGNAL_TRAP}, - {4, TARGET_SIGNAL_FPE}, - {5, TARGET_SIGNAL_SEGV}, - {6, TARGET_SIGNAL_ILL}, - {7, TARGET_SIGNAL_EMT}, /* no-coprocessor exception */ - {8, TARGET_SIGNAL_SEGV}, - {9, TARGET_SIGNAL_SEGV}, - {10, TARGET_SIGNAL_BUS}, - {11, TARGET_SIGNAL_SEGV}, - {12, TARGET_SIGNAL_SEGV}, - {13, TARGET_SIGNAL_SEGV}, - {14, TARGET_SIGNAL_SEGV}, - {16, TARGET_SIGNAL_FPE}, - {17, TARGET_SIGNAL_BUS}, - {31, TARGET_SIGNAL_ILL}, - {0x1b, TARGET_SIGNAL_INT}, - {0x75, TARGET_SIGNAL_FPE}, - {0x78, TARGET_SIGNAL_ALRM}, - {0x79, TARGET_SIGNAL_INT}, - {0x7a, TARGET_SIGNAL_QUIT}, - {-1, TARGET_SIGNAL_LAST} -}; - -static struct { - enum target_signal gdb_sig; - int djgpp_excepno; -} excepn_map[] = { - {TARGET_SIGNAL_0, -1}, - {TARGET_SIGNAL_ILL, 6}, /* Invalid Opcode */ - {TARGET_SIGNAL_EMT, 7}, /* triggers SIGNOFP */ - {TARGET_SIGNAL_SEGV, 13}, /* GPF */ - {TARGET_SIGNAL_BUS, 17}, /* Alignment Check */ - /* The rest are fake exceptions, see dpmiexcp.c in djlsr*.zip for - details. */ - {TARGET_SIGNAL_TERM, 0x1b}, /* triggers Ctrl-Break type of SIGINT */ - {TARGET_SIGNAL_FPE, 0x75}, - {TARGET_SIGNAL_INT, 0x79}, - {TARGET_SIGNAL_QUIT, 0x7a}, - {TARGET_SIGNAL_ALRM, 0x78}, /* triggers SIGTIMR */ - {TARGET_SIGNAL_PROF, 0x78}, - {TARGET_SIGNAL_LAST, -1} + 0, TARGET_SIGNAL_FPE, + 1, TARGET_SIGNAL_TRAP, + 2, TARGET_SIGNAL_UNKNOWN, + 3, TARGET_SIGNAL_TRAP, + 4, TARGET_SIGNAL_FPE, + 5, TARGET_SIGNAL_SEGV, + 6, TARGET_SIGNAL_ILL, + 7, TARGET_SIGNAL_FPE, + 8, TARGET_SIGNAL_SEGV, + 9, TARGET_SIGNAL_SEGV, + 10, TARGET_SIGNAL_BUS, + 11, TARGET_SIGNAL_SEGV, + 12, TARGET_SIGNAL_SEGV, + 13, TARGET_SIGNAL_ABRT, + 14, TARGET_SIGNAL_SEGV, + 16, TARGET_SIGNAL_FPE, + 31, TARGET_SIGNAL_ILL, + 0x75, TARGET_SIGNAL_FPE, + 0x79, TARGET_SIGNAL_INT, + 0x1b, TARGET_SIGNAL_INT, + -1, -1 }; static void go32_open (char *name, int from_tty) { - printf_unfiltered ("Done. Use the \"run\" command to run the program.\n"); + printf_unfiltered ("Use the `run' command to run go32 programs\n"); } static void @@ -307,9 +219,7 @@ go32_close (int quitting) static void go32_attach (char *args, int from_tty) { - error (_("\ -You cannot attach to a running program on this platform.\n\ -Use the `run' command to run DJGPP programs.")); + printf_unfiltered ("Use the `run' command to run go32 programs\n"); } static void @@ -318,122 +228,24 @@ go32_detach (char *args, int from_tty) } static int resume_is_step; -static int resume_signal = -1; static void -go32_resume (ptid_t ptid, int step, enum target_signal siggnal) -{ - int i; - - resume_is_step = step; - - if (siggnal != TARGET_SIGNAL_0 && siggnal != TARGET_SIGNAL_TRAP) +go32_resume (int pid, int step, enum target_signal siggnal) { - for (i = 0, resume_signal = -1; - excepn_map[i].gdb_sig != TARGET_SIGNAL_LAST; i++) - if (excepn_map[i].gdb_sig == siggnal) - { - resume_signal = excepn_map[i].djgpp_excepno; - break; - } - if (resume_signal == -1) - printf_unfiltered ("Cannot deliver signal %s on this platform.\n", - target_signal_to_name (siggnal)); + resume_is_step = step; } -} - -static char child_cwd[FILENAME_MAX]; -static ptid_t -go32_wait (ptid_t ptid, struct target_waitstatus *status) +static int +go32_wait (int pid, struct target_waitstatus *status) { int i; - unsigned char saved_opcode; - unsigned long INT3_addr = 0; - int stepping_over_INT = 0; - a_tss.tss_eflags &= 0xfeff; /* reset the single-step flag (TF) */ if (resume_is_step) - { - /* If the next instruction is INT xx or INTO, we need to handle - them specially. Intel manuals say that these instructions - reset the single-step flag (a.k.a. TF). However, it seems - that, at least in the DPMI environment, and at least when - stepping over the DPMI interrupt 31h, the problem is having - TF set at all when INT 31h is executed: the debuggee either - crashes (and takes the system with it) or is killed by a - SIGTRAP. - - So we need to emulate single-step mode: we put an INT3 opcode - right after the INT xx instruction, let the debuggee run - until it hits INT3 and stops, then restore the original - instruction which we overwrote with the INT3 opcode, and back - up the debuggee's EIP to that instruction. */ - read_child (a_tss.tss_eip, &saved_opcode, 1); - if (saved_opcode == 0xCD || saved_opcode == 0xCE) - { - unsigned char INT3_opcode = 0xCC; - - INT3_addr - = saved_opcode == 0xCD ? a_tss.tss_eip + 2 : a_tss.tss_eip + 1; - stepping_over_INT = 1; - read_child (INT3_addr, &saved_opcode, 1); - write_child (INT3_addr, &INT3_opcode, 1); - } - else - a_tss.tss_eflags |= 0x0100; /* normal instruction: set TF */ - } - - /* The special value FFFFh in tss_trap indicates to run_child that - tss_irqn holds a signal to be delivered to the debuggee. */ - if (resume_signal <= -1) - { - a_tss.tss_trap = 0; - a_tss.tss_irqn = 0xff; - } + a_tss.tss_eflags |= 0x0100; else - { - a_tss.tss_trap = 0xffff; /* run_child looks for this */ - a_tss.tss_irqn = resume_signal; - } + a_tss.tss_eflags &= 0xfeff; - /* The child might change working directory behind our back. The - GDB users won't like the side effects of that when they work with - relative file names, and GDB might be confused by its current - directory not being in sync with the truth. So we always make a - point of changing back to where GDB thinks is its cwd, when we - return control to the debugger, but restore child's cwd before we - run it. */ - /* Initialize child_cwd, before the first call to run_child and not - in the initialization, so the child get also the changed directory - set with the gdb-command "cd ..." */ - if (!*child_cwd) - /* Initialize child's cwd with the current one. */ - getcwd (child_cwd, sizeof (child_cwd)); - - chdir (child_cwd); - -#if __DJGPP_MINOR__ < 3 - load_npx (); -#endif run_child (); -#if __DJGPP_MINOR__ < 3 - save_npx (); -#endif - - /* Did we step over an INT xx instruction? */ - if (stepping_over_INT && a_tss.tss_eip == INT3_addr + 1) - { - /* Restore the original opcode. */ - a_tss.tss_eip--; /* EIP points *after* the INT3 instruction */ - write_child (a_tss.tss_eip, &saved_opcode, 1); - /* Simulate a TRAP exception. */ - a_tss.tss_irqn = 1; - a_tss.tss_eflags |= 0x0100; - } - - getcwd (child_cwd, sizeof (child_cwd)); /* in case it has changed */ - chdir (current_directory); if (a_tss.tss_irqn == 0x21) { @@ -448,84 +260,91 @@ go32_wait (ptid_t ptid, struct target_waitstatus *status) { if (a_tss.tss_irqn == sig_map[i].go32_sig) { -#if __DJGPP_MINOR__ < 3 if ((status->value.sig = sig_map[i].gdb_sig) != TARGET_SIGNAL_TRAP) status->kind = TARGET_WAITKIND_SIGNALLED; -#else - status->value.sig = sig_map[i].gdb_sig; -#endif break; } } } - return pid_to_ptid (SOME_PID); + return SOME_PID; } static void -fetch_register (struct regcache *regcache, int regno) +go32_fetch_registers (int regno) { - if (regno < gdbarch_fp0_regnum (get_regcache_arch (regcache))) - regcache_raw_supply (regcache, regno, - (char *) &a_tss + regno_mapping[regno].tss_ofs); - else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno)) - i387_supply_fsave (regcache, regno, &npx); - else - internal_error (__FILE__, __LINE__, - _("Invalid register no. %d in fetch_register."), regno); -} + /*JHW*/ + int end_reg = regno + 1; /* just one reg initially */ -static void -go32_fetch_registers (struct regcache *regcache, int regno) -{ - if (regno >= 0) - fetch_register (regcache, regno); - else + if (regno < 0) /* do the all registers */ { - for (regno = 0; - regno < gdbarch_fp0_regnum (get_regcache_arch (regcache)); - regno++) - fetch_register (regcache, regno); - i387_supply_fsave (regcache, -1, &npx); + regno = 0; /* start at first register */ + /* # regs in table */ + end_reg = sizeof (regno_mapping) / sizeof (regno_mapping[0]); + } + + for (; regno < end_reg; regno++) + { + if (regno < 16) + supply_register (regno, + (char *) &a_tss + regno_mapping[regno].tss_ofs); + else if (regno < 24) + supply_register (regno, + (char *) &npx.reg[regno_mapping[regno].tss_ofs]); + else if (regno < 31) + supply_register (regno, + (char *) &npx.reg + regno_mapping[regno].tss_ofs); + else + { + printf_unfiltered ("Invalid register in go32_fetch_register(%d)", + regno); + exit (1); + } } } static void -store_register (const struct regcache *regcache, int regno) +store_register (int regno) { - if (regno < gdbarch_fp0_regnum (get_regcache_arch (regcache))) - regcache_raw_collect (regcache, regno, - (char *) &a_tss + regno_mapping[regno].tss_ofs); - else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno)) - i387_collect_fsave (regcache, regno, &npx); + void *rp; + void *v = (void *) ®isters[REGISTER_BYTE (regno)]; + + if (regno < 16) + rp = (char *) &a_tss + regno_mapping[regno].tss_ofs; + else if (regno < 24) + rp = (char *) &npx.reg[regno_mapping[regno].tss_ofs]; + else if (regno > 31) + rp = (char *) &npx + regno_mapping[regno].tss_ofs; else - internal_error (__FILE__, __LINE__, - _("Invalid register no. %d in store_register."), regno); + { + printf_unfiltered ("Invalid register in store_register(%d)", regno); + exit (1); + } + memcpy (rp, v, regno_mapping[regno].size); } static void -go32_store_registers (struct regcache *regcache, int regno) +go32_store_registers (int regno) { - unsigned r; + int r; if (regno >= 0) - store_register (regcache, regno); + store_register (regno); else { - for (r = 0; r < gdbarch_fp0_regnum (get_regcache_arch (regcache)); r++) - store_register (regcache, r); - i387_collect_fsave (regcache, -1, &npx); + for (r = 0; r < sizeof (regno_mapping) / sizeof (regno_mapping[0]); r++) + store_register (r); } } static void -go32_prepare_to_store (struct regcache *regcache) +go32_prepare_to_store (void) { } static int go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, - struct mem_attrib *attrib, struct target_ops *target) + struct target_ops *target) { if (write) { @@ -551,92 +370,44 @@ go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, } } -static cmdline_t child_cmd; /* parsed child's command line kept here */ - static void go32_files_info (struct target_ops *target) { - printf_unfiltered ("You are running a DJGPP V2 program.\n"); + printf_unfiltered ("You are running a DJGPP V2 program\n"); } static void -go32_stop (ptid_t ptid) +go32_stop (void) { normal_stop (); cleanup_client (); - inferior_ptid = null_ptid; + inferior_pid = 0; prog_has_started = 0; } static void go32_kill_inferior (void) { - redir_cmdline_delete (&child_cmd); - resume_signal = -1; - resume_is_step = 0; + go32_stop (); unpush_target (&go32_ops); } static void -go32_create_inferior (char *exec_file, char *args, char **env, int from_tty) +go32_create_inferior (char *exec_file, char *args, char **env) { - extern char **environ; jmp_buf start_state; char *cmdline; char **env_save = environ; - size_t cmdlen; - - /* If no exec file handed to us, get it from the exec-file command -- with - a good, common error message if none is specified. */ - if (exec_file == 0) - exec_file = get_exec_file (1); if (prog_has_started) { - go32_stop (inferior_ptid); go32_kill_inferior (); } - resume_signal = -1; - resume_is_step = 0; - - /* Initialize child's cwd as empty to be initialized when starting - the child. */ - *child_cwd = 0; - - /* Init command line storage. */ - if (redir_debug_init (&child_cmd) == -1) - internal_error (__FILE__, __LINE__, - _("Cannot allocate redirection storage: not enough memory.\n")); - - /* Parse the command line and create redirections. */ - if (strpbrk (args, "<>")) - { - if (redir_cmdline_parse (args, &child_cmd) == 0) - args = child_cmd.command; - else - error (_("Syntax error in command line.")); - } - else - child_cmd.command = xstrdup (args); - - cmdlen = strlen (args); - /* v2loadimage passes command lines via DOS memory, so it cannot - possibly handle commands longer than 1MB. */ - if (cmdlen > 1024*1024) - error (_("Command line too long.")); - cmdline = xmalloc (cmdlen + 4); + cmdline = (char *) alloca (strlen (args) + 4); + cmdline[0] = strlen (args); strcpy (cmdline + 1, args); - /* If the command-line length fits into DOS 126-char limits, use the - DOS command tail format; otherwise, tell v2loadimage to pass it - through a buffer in conventional memory. */ - if (cmdlen < 127) - { - cmdline[0] = strlen (args); - cmdline[cmdlen + 1] = 13; - } - else - cmdline[0] = 0xff; /* signal v2loadimage it's a long command */ + cmdline[strlen (args) + 1] = 13; environ = env; @@ -647,31 +418,19 @@ go32_create_inferior (char *exec_file, char *args, char **env, int from_tty) exit (1); } environ = env_save; - xfree (cmdline); edi_init (start_state); -#if __DJGPP_MINOR__ < 3 - save_npx (); -#endif - inferior_ptid = pid_to_ptid (SOME_PID); + inferior_pid = SOME_PID; push_target (&go32_ops); clear_proceed_status (); insert_breakpoints (); - prog_has_started = 1; + proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0); } static void go32_mourn_inferior (void) { - /* We need to make sure all the breakpoint enable bits in the DR7 - register are reset when the inferior exits. Otherwise, if they - rerun the inferior, the uncleared bits may cause random SIGTRAPs, - failure to set more watchpoints, and other calamities. It would - be nice if GDB itself would take care to remove all breakpoints - at all times, but it doesn't, probably under an assumption that - the OS cleans up when the debuggee exits. */ - i386_cleanup_dregs (); go32_kill_inferior (); generic_mourn_inferior (); } @@ -682,1226 +441,309 @@ go32_can_run (void) return 1; } -/* Hardware watchpoint support. */ - -#define D_REGS edi.dr -#define CONTROL D_REGS[7] -#define STATUS D_REGS[6] - -/* Pass the address ADDR to the inferior in the I'th debug register. - Here we just store the address in D_REGS, the watchpoint will be - actually set up when go32_wait runs the debuggee. */ -void -go32_set_dr (int i, CORE_ADDR addr) -{ - if (i < 0 || i > 3) - internal_error (__FILE__, __LINE__, - _("Invalid register %d in go32_set_dr.\n"), i); - D_REGS[i] = addr; -} - -/* Pass the value VAL to the inferior in the DR7 debug control - register. Here we just store the address in D_REGS, the watchpoint - will be actually set up when go32_wait runs the debuggee. */ -void -go32_set_dr7 (unsigned val) -{ - CONTROL = val; -} - -/* Get the value of the DR6 debug status register from the inferior. - Here we just return the value stored in D_REGS, as we've got it - from the last go32_wait call. */ -unsigned -go32_get_dr6 (void) -{ - return STATUS; -} - -/* Put the device open on handle FD into either raw or cooked - mode, return 1 if it was in raw mode, zero otherwise. */ - -static int -device_mode (int fd, int raw_p) -{ - int oldmode, newmode; - __dpmi_regs regs; - - regs.x.ax = 0x4400; - regs.x.bx = fd; - __dpmi_int (0x21, ®s); - if (regs.x.flags & 1) - return -1; - newmode = oldmode = regs.x.dx; - - if (raw_p) - newmode |= 0x20; - else - newmode &= ~0x20; - - if (oldmode & 0x80) /* Only for character dev */ - { - regs.x.ax = 0x4401; - regs.x.bx = fd; - regs.x.dx = newmode & 0xff; /* Force upper byte zero, else it fails */ - __dpmi_int (0x21, ®s); - if (regs.x.flags & 1) - return -1; - } - return (oldmode & 0x20) == 0x20; -} - - -static int inf_mode_valid = 0; -static int inf_terminal_mode; - -/* This semaphore is needed because, amazingly enough, GDB calls - target.to_terminal_ours more than once after the inferior stops. - But we need the information from the first call only, since the - second call will always see GDB's own cooked terminal. */ -static int terminal_is_ours = 1; - -static void -go32_terminal_init (void) -{ - inf_mode_valid = 0; /* reinitialize, in case they are restarting child */ - terminal_is_ours = 1; -} - static void -go32_terminal_info (char *args, int from_tty) +ignore (void) { - printf_unfiltered ("Inferior's terminal is in %s mode.\n", - !inf_mode_valid - ? "default" : inf_terminal_mode ? "raw" : "cooked"); - -#if __DJGPP_MINOR__ > 2 - if (child_cmd.redirection) - { - int i; - - for (i = 0; i < DBG_HANDLES; i++) - { - if (child_cmd.redirection[i]->file_name) - printf_unfiltered ("\tFile handle %d is redirected to `%s'.\n", - i, child_cmd.redirection[i]->file_name); - else if (_get_dev_info (child_cmd.redirection[i]->inf_handle) == -1) - printf_unfiltered - ("\tFile handle %d appears to be closed by inferior.\n", i); - /* Mask off the raw/cooked bit when comparing device info words. */ - else if ((_get_dev_info (child_cmd.redirection[i]->inf_handle) & 0xdf) - != (_get_dev_info (i) & 0xdf)) - printf_unfiltered - ("\tFile handle %d appears to be redirected by inferior.\n", i); - } - } -#endif } static void -go32_terminal_inferior (void) +ignore2 (char *a, int b) { - /* Redirect standard handles as child wants them. */ - errno = 0; - if (redir_to_child (&child_cmd) == -1) - { - redir_to_debugger (&child_cmd); - error (_("Cannot redirect standard handles for program: %s."), - safe_strerror (errno)); - } - /* set the console device of the inferior to whatever mode - (raw or cooked) we found it last time */ - if (terminal_is_ours) - { - if (inf_mode_valid) - device_mode (0, inf_terminal_mode); - terminal_is_ours = 0; - } } -static void -go32_terminal_ours (void) -{ - /* Switch to cooked mode on the gdb terminal and save the inferior - terminal mode to be restored when it is resumed */ - if (!terminal_is_ours) - { - inf_terminal_mode = device_mode (0, 0); - if (inf_terminal_mode != -1) - inf_mode_valid = 1; - else - /* If device_mode returned -1, we don't know what happens with - handle 0 anymore, so make the info invalid. */ - inf_mode_valid = 0; - terminal_is_ours = 1; - - /* Restore debugger's standard handles. */ - errno = 0; - if (redir_to_debugger (&child_cmd) == -1) - { - redir_to_child (&child_cmd); - error (_("Cannot redirect standard handles for debugger: %s."), - safe_strerror (errno)); - } - } -} - -static void -init_go32_ops (void) -{ - go32_ops.to_shortname = "djgpp"; - go32_ops.to_longname = "djgpp target process"; - go32_ops.to_doc = - "Program loaded by djgpp, when gdb is used as an external debugger"; - go32_ops.to_open = go32_open; - go32_ops.to_close = go32_close; - go32_ops.to_attach = go32_attach; - go32_ops.to_detach = go32_detach; - go32_ops.to_resume = go32_resume; - go32_ops.to_wait = go32_wait; - go32_ops.to_fetch_registers = go32_fetch_registers; - go32_ops.to_store_registers = go32_store_registers; - go32_ops.to_prepare_to_store = go32_prepare_to_store; - go32_ops.deprecated_xfer_memory = go32_xfer_memory; - go32_ops.to_files_info = go32_files_info; - go32_ops.to_insert_breakpoint = memory_insert_breakpoint; - go32_ops.to_remove_breakpoint = memory_remove_breakpoint; - go32_ops.to_terminal_init = go32_terminal_init; - go32_ops.to_terminal_inferior = go32_terminal_inferior; - go32_ops.to_terminal_ours_for_output = go32_terminal_ours; - go32_ops.to_terminal_ours = go32_terminal_ours; - go32_ops.to_terminal_info = go32_terminal_info; - go32_ops.to_kill = go32_kill_inferior; - go32_ops.to_create_inferior = go32_create_inferior; - go32_ops.to_mourn_inferior = go32_mourn_inferior; - go32_ops.to_can_run = go32_can_run; - go32_ops.to_stop = go32_stop; - go32_ops.to_stratum = process_stratum; - go32_ops.to_has_all_memory = 1; - go32_ops.to_has_memory = 1; - go32_ops.to_has_stack = 1; - go32_ops.to_has_registers = 1; - go32_ops.to_has_execution = 1; - go32_ops.to_magic = OPS_MAGIC; +/* Hardware watchpoint support. */ - /* Initialize child's cwd as empty to be initialized when starting - the child. */ - *child_cwd = 0; +#define DR_STATUS 6 +#define DR_CONTROL 7 +#define DR_ENABLE_SIZE 2 +#define DR_LOCAL_ENABLE_SHIFT 0 +#define DR_GLOBAL_ENABLE_SHIFT 1 +#define DR_LOCAL_SLOWDOWN 0x100 +#define DR_GLOBAL_SLOWDOWN 0x200 +#define DR_CONTROL_SHIFT 16 +#define DR_CONTROL_SIZE 4 +#define DR_RW_READ 0x3 +#define DR_RW_WRITE 0x1 +#define DR_CONTROL_MASK 0xf +#define DR_ENABLE_MASK 0x3 +#define DR_LEN_1 0x0 +#define DR_LEN_2 0x4 +#define DR_LEN_4 0xc - /* Initialize child's command line storage. */ - if (redir_debug_init (&child_cmd) == -1) - internal_error (__FILE__, __LINE__, - _("Cannot allocate redirection storage: not enough memory.\n")); +#define D_REGS edi.dr +#define CONTROL D_REGS[DR_CONTROL] +#define STATUS D_REGS[DR_STATUS] + +#define IS_REG_FREE(index) \ + (!(CONTROL & (3 << (DR_ENABLE_SIZE * index)))) + +#define LOCAL_ENABLE_REG(index) \ + (CONTROL |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * index))) + +#define GLOBAL_ENABLE_REG(index) \ + (CONTROL |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * index))) + +#define DISABLE_REG(index) \ + (CONTROL &= ~(3 << (DR_ENABLE_SIZE * index))) + +#define SET_LOCAL_EXACT() \ + (CONTROL |= DR_LOCAL_SLOWDOWN) + +#define SET_GLOBAL_EXACT() \ + (CONTROL |= DR_GLOBAL_SLOWDOWN) + +#define SET_BREAK(index,address) \ + do {\ + CONTROL &= ~(DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index));\ + D_REGS[index] = address;\ + } while(0) + +#define SET_WATCH(index,address,rw,len) \ + do {\ + SET_BREAK(index,address);\ + CONTROL |= (len | rw) << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index);\ + } while (0) + +#define WATCH_HIT(index) \ + (\ + (STATUS & (1 << index)) && \ + (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index)))\ + ) + +#if 0 /* use debugging macro */ +#define SHOW_DR(text) \ +do { \ + fprintf(stderr,"%08x %08x ",edi.dr[7],edi.dr[6]); \ + fprintf(stderr,"%08x %08x ",edi.dr[0],edi.dr[1]); \ + fprintf(stderr,"%08x %08x ",edi.dr[2],edi.dr[3]); \ + fprintf(stderr,"(%s)\n",#text); \ +} while (0) +#else +#define SHOW_DR(text) do {} while (0) +#endif - /* We are always processing GCC-compiled programs. */ - processing_gcc_compilation = 2; +static int go32_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, + CORE_ADDR addr, int len, int rw); - /* Override the default name of the GDB init file. */ - strcpy (gdbinit, "gdb.ini"); -} +static int go32_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, + CORE_ADDR addr, int len, int rw); -unsigned short windows_major, windows_minor; +/* Insert a watchpoint. */ -/* Compute the version Windows reports via Int 2Fh/AX=1600h. */ -static void -go32_get_windows_version(void) +int +go32_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw) { - __dpmi_regs r; + int ret = go32_insert_aligned_watchpoint (pid, addr, addr, len, rw); - r.x.ax = 0x1600; - __dpmi_int(0x2f, &r); - if (r.h.al > 2 && r.h.al != 0x80 && r.h.al != 0xff - && (r.h.al > 3 || r.h.ah > 0)) - { - windows_major = r.h.al; - windows_minor = r.h.ah; - } - else - windows_major = 0xff; /* meaning no Windows */ + SHOW_DR (insert_watch); + return ret; } -/* A subroutine of go32_sysinfo to display memory info. */ -static void -print_mem (unsigned long datum, const char *header, int in_pages_p) +static int +go32_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr, + int len, int rw) { - if (datum != 0xffffffffUL) - { - if (in_pages_p) - datum <<= 12; - puts_filtered (header); - if (datum > 1024) - { - printf_filtered ("%lu KB", datum >> 10); - if (datum > 1024 * 1024) - printf_filtered (" (%lu MB)", datum >> 20); - } - else - printf_filtered ("%lu Bytes", datum); - puts_filtered ("\n"); - } -} + int i; + int read_write_bits, len_bits; -/* Display assorted information about the underlying OS. */ -static void -go32_sysinfo (char *arg, int from_tty) -{ - struct utsname u; - char cpuid_vendor[13]; - unsigned cpuid_max = 0, cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx; - unsigned true_dos_version = _get_dos_version (1); - unsigned advertized_dos_version = ((unsigned int)_osmajor << 8) | _osminor; - int dpmi_flags; - char dpmi_vendor_info[129]; - int dpmi_vendor_available = - __dpmi_get_capabilities (&dpmi_flags, dpmi_vendor_info); - __dpmi_version_ret dpmi_version_data; - long eflags; - __dpmi_free_mem_info mem_info; - __dpmi_regs regs; - - cpuid_vendor[0] = '\0'; - if (uname (&u)) - strcpy (u.machine, "Unknown x86"); - else if (u.machine[0] == 'i' && u.machine[1] > 4) + /* Look for a free debug register. */ + for (i = 0; i <= 3; i++) { - /* CPUID with EAX = 0 returns the Vendor ID. */ - __asm__ __volatile__ ("xorl %%ebx, %%ebx;" - "xorl %%ecx, %%ecx;" - "xorl %%edx, %%edx;" - "movl $0, %%eax;" - "cpuid;" - "movl %%ebx, %0;" - "movl %%edx, %1;" - "movl %%ecx, %2;" - "movl %%eax, %3;" - : "=m" (cpuid_vendor[0]), - "=m" (cpuid_vendor[4]), - "=m" (cpuid_vendor[8]), - "=m" (cpuid_max) - : - : "%eax", "%ebx", "%ecx", "%edx"); - cpuid_vendor[12] = '\0'; + if (IS_REG_FREE (i)) + break; } - printf_filtered ("CPU Type.......................%s", u.machine); - if (cpuid_vendor[0]) - printf_filtered (" (%s)", cpuid_vendor); - puts_filtered ("\n"); + /* No more debug registers! */ + if (i > 3) + return -1; - /* CPUID with EAX = 1 returns processor signature and features. */ - if (cpuid_max >= 1) - { - static char *brand_name[] = { - "", - " Celeron", - " III", - " III Xeon", - "", "", "", "", - " 4" - }; - char cpu_string[80]; - char cpu_brand[20]; - unsigned brand_idx; - int intel_p = strcmp (cpuid_vendor, "GenuineIntel") == 0; - int amd_p = strcmp (cpuid_vendor, "AuthenticAMD") == 0; - unsigned cpu_family, cpu_model; - - __asm__ __volatile__ ("movl $1, %%eax;" - "cpuid;" - : "=a" (cpuid_eax), - "=b" (cpuid_ebx), - "=d" (cpuid_edx) - : - : "%ecx"); - brand_idx = cpuid_ebx & 0xff; - cpu_family = (cpuid_eax >> 8) & 0xf; - cpu_model = (cpuid_eax >> 4) & 0xf; - cpu_brand[0] = '\0'; - if (intel_p) - { - if (brand_idx > 0 - && brand_idx < sizeof(brand_name)/sizeof(brand_name[0]) - && *brand_name[brand_idx]) - strcpy (cpu_brand, brand_name[brand_idx]); - else if (cpu_family == 5) - { - if (((cpuid_eax >> 12) & 3) == 0 && cpu_model == 4) - strcpy (cpu_brand, " MMX"); - else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 1) - strcpy (cpu_brand, " OverDrive"); - else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 2) - strcpy (cpu_brand, " Dual"); - } - else if (cpu_family == 6 && cpu_model < 8) - { - switch (cpu_model) - { - case 1: - strcpy (cpu_brand, " Pro"); - break; - case 3: - strcpy (cpu_brand, " II"); - break; - case 5: - strcpy (cpu_brand, " II Xeon"); - break; - case 6: - strcpy (cpu_brand, " Celeron"); - break; - case 7: - strcpy (cpu_brand, " III"); - break; - } - } - } - else if (amd_p) - { - switch (cpu_family) - { - case 4: - strcpy (cpu_brand, "486/5x86"); - break; - case 5: - switch (cpu_model) - { - case 0: - case 1: - case 2: - case 3: - strcpy (cpu_brand, "-K5"); - break; - case 6: - case 7: - strcpy (cpu_brand, "-K6"); - break; - case 8: - strcpy (cpu_brand, "-K6-2"); - break; - case 9: - strcpy (cpu_brand, "-K6-III"); - break; - } - break; - case 6: - switch (cpu_model) - { - case 1: - case 2: - case 4: - strcpy (cpu_brand, " Athlon"); - break; - case 3: - strcpy (cpu_brand, " Duron"); - break; - } - break; - } - } - sprintf (cpu_string, "%s%s Model %d Stepping %d", - intel_p ? "Pentium" : (amd_p ? "AMD" : "ix86"), - cpu_brand, cpu_model, cpuid_eax & 0xf); - printfi_filtered (31, "%s\n", cpu_string); - if (((cpuid_edx & (6 | (0x0d << 23))) != 0) - || ((cpuid_edx & 1) == 0) - || (amd_p && (cpuid_edx & (3 << 30)) != 0)) - { - puts_filtered ("CPU Features..................."); - /* We only list features which might be useful in the DPMI - environment. */ - if ((cpuid_edx & 1) == 0) - puts_filtered ("No FPU "); /* it's unusual to not have an FPU */ - if ((cpuid_edx & (1 << 1)) != 0) - puts_filtered ("VME "); - if ((cpuid_edx & (1 << 2)) != 0) - puts_filtered ("DE "); - if ((cpuid_edx & (1 << 4)) != 0) - puts_filtered ("TSC "); - if ((cpuid_edx & (1 << 23)) != 0) - puts_filtered ("MMX "); - if ((cpuid_edx & (1 << 25)) != 0) - puts_filtered ("SSE "); - if ((cpuid_edx & (1 << 26)) != 0) - puts_filtered ("SSE2 "); - if (amd_p) - { - if ((cpuid_edx & (1 << 31)) != 0) - puts_filtered ("3DNow! "); - if ((cpuid_edx & (1 << 30)) != 0) - puts_filtered ("3DNow!Ext"); - } - puts_filtered ("\n"); - } - } - puts_filtered ("\n"); - printf_filtered ("DOS Version....................%s %s.%s", - _os_flavor, u.release, u.version); - if (true_dos_version != advertized_dos_version) - printf_filtered (" (disguised as v%d.%d)", _osmajor, _osminor); - puts_filtered ("\n"); - if (!windows_major) - go32_get_windows_version (); - if (windows_major != 0xff) - { - const char *windows_flavor; + read_write_bits = ((rw & 1) ? DR_RW_READ : 0) | ((rw & 2) ? DR_RW_WRITE : 0); - printf_filtered ("Windows Version................%d.%02d (Windows ", - windows_major, windows_minor); - switch (windows_major) - { - case 3: - windows_flavor = "3.X"; - break; - case 4: - switch (windows_minor) - { - case 0: - windows_flavor = "95, 95A, or 95B"; - break; - case 3: - windows_flavor = "95B OSR2.1 or 95C OSR2.5"; - break; - case 10: - windows_flavor = "98 or 98 SE"; - break; - case 90: - windows_flavor = "ME"; - break; - default: - windows_flavor = "9X"; - break; - } - break; - default: - windows_flavor = "??"; - break; - } - printf_filtered ("%s)\n", windows_flavor); - } - else if (true_dos_version == 0x532 && advertized_dos_version == 0x500) - printf_filtered ("Windows Version................Windows NT or Windows 2000\n"); - puts_filtered ("\n"); - if (dpmi_vendor_available == 0) - { - /* The DPMI spec says the vendor string should be ASCIIZ, but - I don't trust the vendors to follow that... */ - if (!memchr (&dpmi_vendor_info[2], 0, 126)) - dpmi_vendor_info[128] = '\0'; - printf_filtered ("DPMI Host......................%s v%d.%d (capabilities: %#x)\n", - &dpmi_vendor_info[2], - (unsigned)dpmi_vendor_info[0], - (unsigned)dpmi_vendor_info[1], - ((unsigned)dpmi_flags & 0x7f)); - } - __dpmi_get_version (&dpmi_version_data); - printf_filtered ("DPMI Version...................%d.%02d\n", - dpmi_version_data.major, dpmi_version_data.minor); - printf_filtered ("DPMI Info......................%s-bit DPMI, with%s Virtual Memory support\n", - (dpmi_version_data.flags & 1) ? "32" : "16", - (dpmi_version_data.flags & 4) ? "" : "out"); - printfi_filtered (31, "Interrupts reflected to %s mode\n", - (dpmi_version_data.flags & 2) ? "V86" : "Real"); - printfi_filtered (31, "Processor type: i%d86\n", - dpmi_version_data.cpu); - printfi_filtered (31, "PIC base interrupt: Master: %#x Slave: %#x\n", - dpmi_version_data.master_pic, dpmi_version_data.slave_pic); - - /* a_tss is only initialized when the debuggee is first run. */ - if (prog_has_started) + if (len == 1) + len_bits = DR_LEN_1; + else if (len == 2) { - __asm__ __volatile__ ("pushfl ; popl %0" : "=g" (eflags)); - printf_filtered ("Protection.....................Ring %d (in %s), with%s I/O protection\n", - a_tss.tss_cs & 3, (a_tss.tss_cs & 4) ? "LDT" : "GDT", - (a_tss.tss_cs & 3) > ((eflags >> 12) & 3) ? "" : "out"); + if (addr % 2) + return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw); + len_bits = DR_LEN_2; } - puts_filtered ("\n"); - __dpmi_get_free_memory_information (&mem_info); - print_mem (mem_info.total_number_of_physical_pages, - "DPMI Total Physical Memory.....", 1); - print_mem (mem_info.total_number_of_free_pages, - "DPMI Free Physical Memory......", 1); - print_mem (mem_info.size_of_paging_file_partition_in_pages, - "DPMI Swap Space................", 1); - print_mem (mem_info.linear_address_space_size_in_pages, - "DPMI Total Linear Address Size.", 1); - print_mem (mem_info.free_linear_address_space_in_pages, - "DPMI Free Linear Address Size..", 1); - print_mem (mem_info.largest_available_free_block_in_bytes, - "DPMI Largest Free Memory Block.", 0); - - regs.h.ah = 0x48; - regs.x.bx = 0xffff; - __dpmi_int (0x21, ®s); - print_mem (regs.x.bx << 4, "Free DOS Memory................", 0); - regs.x.ax = 0x5800; - __dpmi_int (0x21, ®s); - if ((regs.x.flags & 1) == 0) + else if (len == 4) { - static const char *dos_hilo[] = { - "Low", "", "", "", "High", "", "", "", "High, then Low" - }; - static const char *dos_fit[] = { - "First", "Best", "Last" - }; - int hilo_idx = (regs.x.ax >> 4) & 0x0f; - int fit_idx = regs.x.ax & 0x0f; - - if (hilo_idx > 8) - hilo_idx = 0; - if (fit_idx > 2) - fit_idx = 0; - printf_filtered ("DOS Memory Allocation..........%s memory, %s fit\n", - dos_hilo[hilo_idx], dos_fit[fit_idx]); - regs.x.ax = 0x5802; - __dpmi_int (0x21, ®s); - if ((regs.x.flags & 1) != 0) - regs.h.al = 0; - printfi_filtered (31, "UMBs %sin DOS memory chain\n", - regs.h.al == 0 ? "not " : ""); + if (addr % 4) + return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw); + len_bits = DR_LEN_4; } -} - -struct seg_descr { - unsigned short limit0 __attribute__((packed)); - unsigned short base0 __attribute__((packed)); - unsigned char base1 __attribute__((packed)); - unsigned stype:5 __attribute__((packed)); - unsigned dpl:2 __attribute__((packed)); - unsigned present:1 __attribute__((packed)); - unsigned limit1:4 __attribute__((packed)); - unsigned available:1 __attribute__((packed)); - unsigned dummy:1 __attribute__((packed)); - unsigned bit32:1 __attribute__((packed)); - unsigned page_granular:1 __attribute__((packed)); - unsigned char base2 __attribute__((packed)); -}; - -struct gate_descr { - unsigned short offset0 __attribute__((packed)); - unsigned short selector __attribute__((packed)); - unsigned param_count:5 __attribute__((packed)); - unsigned dummy:3 __attribute__((packed)); - unsigned stype:5 __attribute__((packed)); - unsigned dpl:2 __attribute__((packed)); - unsigned present:1 __attribute__((packed)); - unsigned short offset1 __attribute__((packed)); -}; - -/* Read LEN bytes starting at logical address ADDR, and put the result - into DEST. Return 1 if success, zero if not. */ -static int -read_memory_region (unsigned long addr, void *dest, size_t len) -{ - unsigned long dos_ds_limit = __dpmi_get_segment_limit (_dos_ds); - int retval = 1; - - /* For the low memory, we can simply use _dos_ds. */ - if (addr <= dos_ds_limit - len) - dosmemget (addr, len, dest); else - { - /* For memory above 1MB we need to set up a special segment to - be able to access that memory. */ - int sel = __dpmi_allocate_ldt_descriptors (1); + return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw); - if (sel <= 0) - retval = 0; - else - { - int access_rights = __dpmi_get_descriptor_access_rights (sel); - size_t segment_limit = len - 1; - - /* Make sure the crucial bits in the descriptor access - rights are set correctly. Some DPMI providers might barf - if we set the segment limit to something that is not an - integral multiple of 4KB pages if the granularity bit is - not set to byte-granular, even though the DPMI spec says - it's the host's responsibility to set that bit correctly. */ - if (len > 1024 * 1024) - { - access_rights |= 0x8000; - /* Page-granular segments should have the low 12 bits of - the limit set. */ - segment_limit |= 0xfff; - } - else - access_rights &= ~0x8000; - - if (__dpmi_set_segment_base_address (sel, addr) != -1 - && __dpmi_set_descriptor_access_rights (sel, access_rights) != -1 - && __dpmi_set_segment_limit (sel, segment_limit) != -1 - /* W2K silently fails to set the segment limit, leaving - it at zero; this test avoids the resulting crash. */ - && __dpmi_get_segment_limit (sel) >= segment_limit) - movedata (sel, 0, _my_ds (), (unsigned)dest, len); - else - retval = 0; - - __dpmi_free_ldt_descriptor (sel); - } - } - return retval; + SET_WATCH (i, addr, read_write_bits, len_bits); + LOCAL_ENABLE_REG (i); + SET_LOCAL_EXACT (); } -/* Get a segment descriptor stored at index IDX in the descriptor - table whose base address is TABLE_BASE. Return the descriptor - type, or -1 if failure. */ static int -get_descriptor (unsigned long table_base, int idx, void *descr) -{ - unsigned long addr = table_base + idx * 8; /* 8 bytes per entry */ - - if (read_memory_region (addr, descr, 8)) - return (int)((struct seg_descr *)descr)->stype; - return -1; -} - -struct dtr_reg { - unsigned short limit __attribute__((packed)); - unsigned long base __attribute__((packed)); -}; - -/* Display a segment descriptor stored at index IDX in a descriptor - table whose type is TYPE and whose base address is BASE_ADDR. If - FORCE is non-zero, display even invalid descriptors. */ -static void -display_descriptor (unsigned type, unsigned long base_addr, int idx, int force) -{ - struct seg_descr descr; - struct gate_descr gate; - - /* Get the descriptor from the table. */ - if (idx == 0 && type == 0) - puts_filtered ("0x000: null descriptor\n"); - else if (get_descriptor (base_addr, idx, &descr) != -1) - { - /* For each type of descriptor table, this has a bit set if the - corresponding type of selectors is valid in that table. */ - static unsigned allowed_descriptors[] = { - 0xffffdafeL, /* GDT */ - 0x0000c0e0L, /* IDT */ - 0xffffdafaL /* LDT */ - }; - - /* If the program hasn't started yet, assume the debuggee will - have the same CPL as the debugger. */ - int cpl = prog_has_started ? (a_tss.tss_cs & 3) : _my_cs () & 3; - unsigned long limit = (descr.limit1 << 16) | descr.limit0; - - if (descr.present - && (allowed_descriptors[type] & (1 << descr.stype)) != 0) - { - printf_filtered ("0x%03x: ", - type == 1 - ? idx : (idx * 8) | (type ? (cpl | 4) : 0)); - if (descr.page_granular) - limit = (limit << 12) | 0xfff; /* big segment: low 12 bit set */ - if (descr.stype == 1 || descr.stype == 2 || descr.stype == 3 - || descr.stype == 9 || descr.stype == 11 - || (descr.stype >= 16 && descr.stype < 32)) - printf_filtered ("base=0x%02x%02x%04x limit=0x%08lx", - descr.base2, descr.base1, descr.base0, limit); - - switch (descr.stype) - { - case 1: - case 3: - printf_filtered (" 16-bit TSS (task %sactive)", - descr.stype == 3 ? "" : "in"); - break; - case 2: - puts_filtered (" LDT"); - break; - case 4: - memcpy (&gate, &descr, sizeof gate); - printf_filtered ("selector=0x%04x offs=0x%04x%04x", - gate.selector, gate.offset1, gate.offset0); - printf_filtered (" 16-bit Call Gate (params=%d)", - gate.param_count); - break; - case 5: - printf_filtered ("TSS selector=0x%04x", descr.base0); - printfi_filtered (16, "Task Gate"); - break; - case 6: - case 7: - memcpy (&gate, &descr, sizeof gate); - printf_filtered ("selector=0x%04x offs=0x%04x%04x", - gate.selector, gate.offset1, gate.offset0); - printf_filtered (" 16-bit %s Gate", - descr.stype == 6 ? "Interrupt" : "Trap"); - break; - case 9: - case 11: - printf_filtered (" 32-bit TSS (task %sactive)", - descr.stype == 3 ? "" : "in"); - break; - case 12: - memcpy (&gate, &descr, sizeof gate); - printf_filtered ("selector=0x%04x offs=0x%04x%04x", - gate.selector, gate.offset1, gate.offset0); - printf_filtered (" 32-bit Call Gate (params=%d)", - gate.param_count); - break; - case 14: - case 15: - memcpy (&gate, &descr, sizeof gate); - printf_filtered ("selector=0x%04x offs=0x%04x%04x", - gate.selector, gate.offset1, gate.offset0); - printf_filtered (" 32-bit %s Gate", - descr.stype == 14 ? "Interrupt" : "Trap"); - break; - case 16: /* data segments */ - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - printf_filtered (" %s-bit Data (%s Exp-%s%s)", - descr.bit32 ? "32" : "16", - descr.stype & 2 ? "Read/Write," : "Read-Only, ", - descr.stype & 4 ? "down" : "up", - descr.stype & 1 ? "" : ", N.Acc"); - break; - case 24: /* code segments */ - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - printf_filtered (" %s-bit Code (%s, %sConf%s)", - descr.bit32 ? "32" : "16", - descr.stype & 2 ? "Exec/Read" : "Exec-Only", - descr.stype & 4 ? "" : "N.", - descr.stype & 1 ? "" : ", N.Acc"); - break; - default: - printf_filtered ("Unknown type 0x%02x", descr.stype); - break; - } - puts_filtered ("\n"); - } - else if (force) - { - printf_filtered ("0x%03x: ", - type == 1 - ? idx : (idx * 8) | (type ? (cpl | 4) : 0)); - if (!descr.present) - puts_filtered ("Segment not present\n"); - else - printf_filtered ("Segment type 0x%02x is invalid in this table\n", - descr.stype); - } - } - else if (force) - printf_filtered ("0x%03x: Cannot read this descriptor\n", idx); -} - -static void -go32_sldt (char *arg, int from_tty) +go32_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr, + int len, int rw) { - struct dtr_reg gdtr; - unsigned short ldtr = 0; - int ldt_idx; - struct seg_descr ldt_descr; - long ldt_entry = -1L; - int cpl = (prog_has_started ? a_tss.tss_cs : _my_cs ()) & 3; - - if (arg && *arg) - { - while (*arg && isspace(*arg)) - arg++; + int align; + int size; + int rv = 0; - if (*arg) - { - ldt_entry = parse_and_eval_long (arg); - if (ldt_entry < 0 - || (ldt_entry & 4) == 0 - || (ldt_entry & 3) != (cpl & 3)) - error (_("Invalid LDT entry 0x%03lx."), (unsigned long)ldt_entry); - } - } - - __asm__ __volatile__ ("sgdt %0" : "=m" (gdtr) : /* no inputs */ ); - __asm__ __volatile__ ("sldt %0" : "=m" (ldtr) : /* no inputs */ ); - ldt_idx = ldtr / 8; - if (ldt_idx == 0) - puts_filtered ("There is no LDT.\n"); - /* LDT's entry in the GDT must have the type LDT, which is 2. */ - else if (get_descriptor (gdtr.base, ldt_idx, &ldt_descr) != 2) - printf_filtered ("LDT is present (at %#x), but unreadable by GDB.\n", - ldt_descr.base0 - | (ldt_descr.base1 << 16) - | (ldt_descr.base2 << 24)); - else - { - unsigned base = - ldt_descr.base0 - | (ldt_descr.base1 << 16) - | (ldt_descr.base2 << 24); - unsigned limit = ldt_descr.limit0 | (ldt_descr.limit1 << 16); - int max_entry; - - if (ldt_descr.page_granular) - /* Page-granular segments must have the low 12 bits of their - limit set. */ - limit = (limit << 12) | 0xfff; - /* LDT cannot have more than 8K 8-byte entries, i.e. more than - 64KB. */ - if (limit > 0xffff) - limit = 0xffff; - - max_entry = (limit + 1) / 8; - - if (ldt_entry >= 0) - { - if (ldt_entry > limit) - error (_("Invalid LDT entry %#lx: outside valid limits [0..%#x]"), - (unsigned long)ldt_entry, limit); - - display_descriptor (ldt_descr.stype, base, ldt_entry / 8, 1); - } - else + static int size_try_array[16] = + { + 1, 1, 1, 1, /* trying size one */ + 2, 1, 2, 1, /* trying size two */ + 2, 1, 2, 1, /* trying size three */ + 4, 1, 2, 1 /* trying size four */ + }; + + while (len > 0) + { + align = addr % 4; + /* Four is the maximum length for 386. */ + size = (len > 4) ? 3 : len - 1; + size = size_try_array[size * 4 + align]; + rv = go32_insert_aligned_watchpoint (pid, waddr, addr, size, rw); + if (rv) { - int i; - - for (i = 0; i < max_entry; i++) - display_descriptor (ldt_descr.stype, base, i, 0); + go32_remove_watchpoint (pid, waddr, size); + return rv; } + addr += size; + len -= size; } + return rv; } -static void -go32_sgdt (char *arg, int from_tty) -{ - struct dtr_reg gdtr; - long gdt_entry = -1L; - int max_entry; - - if (arg && *arg) - { - while (*arg && isspace(*arg)) - arg++; - - if (*arg) - { - gdt_entry = parse_and_eval_long (arg); - if (gdt_entry < 0 || (gdt_entry & 7) != 0) - error (_("Invalid GDT entry 0x%03lx: not an integral multiple of 8."), - (unsigned long)gdt_entry); - } - } - - __asm__ __volatile__ ("sgdt %0" : "=m" (gdtr) : /* no inputs */ ); - max_entry = (gdtr.limit + 1) / 8; - - if (gdt_entry >= 0) - { - if (gdt_entry > gdtr.limit) - error (_("Invalid GDT entry %#lx: outside valid limits [0..%#x]"), - (unsigned long)gdt_entry, gdtr.limit); - - display_descriptor (0, gdtr.base, gdt_entry / 8, 1); - } - else - { - int i; +/* Remove a watchpoint. */ - for (i = 0; i < max_entry; i++) - display_descriptor (0, gdtr.base, i, 0); - } -} - -static void -go32_sidt (char *arg, int from_tty) +int +go32_remove_watchpoint (int pid, CORE_ADDR addr, int len) { - struct dtr_reg idtr; - long idt_entry = -1L; - int max_entry; - - if (arg && *arg) - { - while (*arg && isspace(*arg)) - arg++; - - if (*arg) - { - idt_entry = parse_and_eval_long (arg); - if (idt_entry < 0) - error (_("Invalid (negative) IDT entry %ld."), idt_entry); - } - } - - __asm__ __volatile__ ("sidt %0" : "=m" (idtr) : /* no inputs */ ); - max_entry = (idtr.limit + 1) / 8; - if (max_entry > 0x100) /* no more than 256 entries */ - max_entry = 0x100; - - if (idt_entry >= 0) - { - if (idt_entry > idtr.limit) - error (_("Invalid IDT entry %#lx: outside valid limits [0..%#x]"), - (unsigned long)idt_entry, idtr.limit); - - display_descriptor (1, idtr.base, idt_entry, 1); - } - else - { - int i; - - for (i = 0; i < max_entry; i++) - display_descriptor (1, idtr.base, i, 0); - } -} - -/* Cached linear address of the base of the page directory. For - now, available only under CWSDPMI. Code based on ideas and - suggestions from Charles Sandmann . */ -static unsigned long pdbr; + int i; -static unsigned long -get_cr3 (void) -{ - unsigned offset; - unsigned taskreg; - unsigned long taskbase, cr3; - struct dtr_reg gdtr; - - if (pdbr > 0 && pdbr <= 0xfffff) - return pdbr; - - /* Get the linear address of GDT and the Task Register. */ - __asm__ __volatile__ ("sgdt %0" : "=m" (gdtr) : /* no inputs */ ); - __asm__ __volatile__ ("str %0" : "=m" (taskreg) : /* no inputs */ ); - - /* Task Register is a segment selector for the TSS of the current - task. Therefore, it can be used as an index into the GDT to get - at the segment descriptor for the TSS. To get the index, reset - the low 3 bits of the selector (which give the CPL). Add 2 to the - offset to point to the 3 low bytes of the base address. */ - offset = gdtr.base + (taskreg & 0xfff8) + 2; - - - /* CWSDPMI's task base is always under the 1MB mark. */ - if (offset > 0xfffff) - return 0; - - _farsetsel (_dos_ds); - taskbase = _farnspeekl (offset) & 0xffffffU; - taskbase += _farnspeekl (offset + 2) & 0xff000000U; - if (taskbase > 0xfffff) - return 0; - - /* CR3 (a.k.a. PDBR, the Page Directory Base Register) is stored at - offset 1Ch in the TSS. */ - cr3 = _farnspeekl (taskbase + 0x1c) & ~0xfff; - if (cr3 > 0xfffff) + for (i = 0; i <= 3; i++) { -#if 0 /* not fullly supported yet */ - /* The Page Directory is in UMBs. In that case, CWSDPMI puts - the first Page Table right below the Page Directory. Thus, - the first Page Table's entry for its own address and the Page - Directory entry for that Page Table will hold the same - physical address. The loop below searches the entire UMB - range of addresses for such an occurence. */ - unsigned long addr, pte_idx; - - for (addr = 0xb0000, pte_idx = 0xb0; - pte_idx < 0xff; - addr += 0x1000, pte_idx++) + if (D_REGS[i] == addr) { - if (((_farnspeekl (addr + 4 * pte_idx) & 0xfffff027) == - (_farnspeekl (addr + 0x1000) & 0xfffff027)) - && ((_farnspeekl (addr + 4 * pte_idx + 4) & 0xfffff000) == cr3)) - { - cr3 = addr + 0x1000; - break; - } + DISABLE_REG (i); } -#endif - - if (cr3 > 0xfffff) - cr3 = 0; - } - - return cr3; -} - -/* Return the N'th Page Directory entry. */ -static unsigned long -get_pde (int n) -{ - unsigned long pde = 0; - - if (pdbr && n >= 0 && n < 1024) - { - pde = _farpeekl (_dos_ds, pdbr + 4*n); } - return pde; -} - -/* Return the N'th entry of the Page Table whose Page Directory entry - is PDE. */ -static unsigned long -get_pte (unsigned long pde, int n) -{ - unsigned long pte = 0; + SHOW_DR (remove_watch); - /* pde & 0x80 tests the 4MB page bit. We don't support 4MB - page tables, for now. */ - if ((pde & 1) && !(pde & 0x80) && n >= 0 && n < 1024) - { - pde &= ~0xfff; /* clear non-address bits */ - pte = _farpeekl (_dos_ds, pde + 4*n); - } - return pte; + return 0; } -/* Display a Page Directory or Page Table entry. IS_DIR, if non-zero, - says this is a Page Directory entry. If FORCE is non-zero, display - the entry even if its Present flag is off. OFF is the offset of the - address from the page's base address. */ -static void -display_ptable_entry (unsigned long entry, int is_dir, int force, unsigned off) -{ - if ((entry & 1) != 0) - { - printf_filtered ("Base=0x%05lx000", entry >> 12); - if ((entry & 0x100) && !is_dir) - puts_filtered (" Global"); - if ((entry & 0x40) && !is_dir) - puts_filtered (" Dirty"); - printf_filtered (" %sAcc.", (entry & 0x20) ? "" : "Not-"); - printf_filtered (" %sCached", (entry & 0x10) ? "" : "Not-"); - printf_filtered (" Write-%s", (entry & 8) ? "Thru" : "Back"); - printf_filtered (" %s", (entry & 4) ? "Usr" : "Sup"); - printf_filtered (" Read-%s", (entry & 2) ? "Write" : "Only"); - if (off) - printf_filtered (" +0x%x", off); - puts_filtered ("\n"); - } - else if (force) - printf_filtered ("Page%s not present or not supported; value=0x%lx.\n", - is_dir ? " Table" : "", entry >> 1); -} +/* Check if stopped by a watchpoint. */ -static void -go32_pde (char *arg, int from_tty) +CORE_ADDR +go32_stopped_by_watchpoint (int pid) { - long pde_idx = -1, i; + int i, ret = 0; + int status; - if (arg && *arg) + status = edi.dr[DR_STATUS]; + SHOW_DR (stopped_by); + for (i = 0; i <= 3; i++) { - while (*arg && isspace(*arg)) - arg++; - - if (*arg) + if (WATCH_HIT (i)) { - pde_idx = parse_and_eval_long (arg); - if (pde_idx < 0 || pde_idx >= 1024) - error (_("Entry %ld is outside valid limits [0..1023]."), pde_idx); + SHOW_DR (HIT); + ret = D_REGS[i]; } } + /* this is a hack to GDB. If we stopped at a hardware breakpoint, + the stop_pc must incremented by DECR_PC_AFTER_BREAK. I tried everything + with the DECR_PC_AFTER_HW_BREAK, but nothing works. */ + /* This is probably fixed by jtc's recent patch -sts 2/19/99 */ + if (STATUS && !ret) + stop_pc += DECR_PC_AFTER_BREAK; + STATUS = 0; - pdbr = get_cr3 (); - if (!pdbr) - puts_filtered ("Access to Page Directories is not supported on this system.\n"); - else if (pde_idx >= 0) - display_ptable_entry (get_pde (pde_idx), 1, 1, 0); - else - for (i = 0; i < 1024; i++) - display_ptable_entry (get_pde (i), 1, 0, 0); + return ret; } -/* A helper function to display entries in a Page Table pointed to by - the N'th entry in the Page Directory. If FORCE is non-zero, say - something even if the Page Table is not accessible. */ -static void -display_page_table (long n, int force) -{ - unsigned long pde = get_pde (n); +/* Remove a breakpoint. */ - if ((pde & 1) != 0) - { - int i; - - printf_filtered ("Page Table pointed to by Page Directory entry 0x%lx:\n", n); - for (i = 0; i < 1024; i++) - display_ptable_entry (get_pte (pde, i), 0, 0, 0); - puts_filtered ("\n"); - } - else if (force) - printf_filtered ("Page Table not present; value=0x%lx.\n", pde >> 1); -} - -static void -go32_pte (char *arg, int from_tty) +int +go32_remove_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow) { - long pde_idx = -1L, i; - - if (arg && *arg) + int i; + for (i = 0; i <= 3; i++) { - while (*arg && isspace(*arg)) - arg++; - - if (*arg) + if (D_REGS[i] == addr) { - pde_idx = parse_and_eval_long (arg); - if (pde_idx < 0 || pde_idx >= 1024) - error (_("Entry %ld is outside valid limits [0..1023]."), pde_idx); + DISABLE_REG (i); } } - - pdbr = get_cr3 (); - if (!pdbr) - puts_filtered ("Access to Page Tables is not supported on this system.\n"); - else if (pde_idx >= 0) - display_page_table (pde_idx, 1); - else - for (i = 0; i < 1024; i++) - display_page_table (i, 0); + SHOW_DR (remove_hw); + return 0; } -static void -go32_pte_for_address (char *arg, int from_tty) +int +go32_insert_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow) { - CORE_ADDR addr = 0, i; + int i; + int read_write_bits, len_bits; + int free_debug_register; + int register_number; - if (arg && *arg) + /* Look for a free debug register. */ + for (i = 0; i <= 3; i++) { - while (*arg && isspace(*arg)) - arg++; - - if (*arg) - addr = parse_and_eval_address (arg); + if (IS_REG_FREE (i)) + break; } - if (!addr) - error_no_arg (_("linear address")); - pdbr = get_cr3 (); - if (!pdbr) - puts_filtered ("Access to Page Tables is not supported on this system.\n"); - else - { - int pde_idx = (addr >> 22) & 0x3ff; - int pte_idx = (addr >> 12) & 0x3ff; - unsigned offs = addr & 0xfff; + /* No more debug registers! */ + if (i > 3) + return -1; - printf_filtered ("Page Table entry for address 0x%llx:\n", - (unsigned long long)addr); - display_ptable_entry (get_pte (get_pde (pde_idx), pte_idx), 0, 1, offs); - } + SET_BREAK (i, addr); + LOCAL_ENABLE_REG (i); + SHOW_DR (insert_hw); + + return 0; } -static struct cmd_list_element *info_dos_cmdlist = NULL; +static struct target_ops go32_ops; static void -go32_info_dos_command (char *args, int from_tty) +init_go32_ops (void) { - help_list (info_dos_cmdlist, "info dos ", class_info, gdb_stdout); + go32_ops.to_shortname = "djgpp"; + go32_ops.to_longname = "djgpp target process"; + go32_ops.to_doc = + "Program loaded by djgpp, when gdb is used as an external debugger"; + go32_ops.to_open = go32_open; + go32_ops.to_close = go32_close; + go32_ops.to_detach = go32_detach; + go32_ops.to_resume = go32_resume; + go32_ops.to_wait = go32_wait; + go32_ops.to_fetch_registers = go32_fetch_registers; + go32_ops.to_store_registers = go32_store_registers; + go32_ops.to_prepare_to_store = go32_prepare_to_store; + go32_ops.to_xfer_memory = go32_xfer_memory; + go32_ops.to_files_info = go32_files_info; + go32_ops.to_insert_breakpoint = memory_insert_breakpoint; + go32_ops.to_remove_breakpoint = memory_remove_breakpoint; + go32_ops.to_terminal_init = ignore; + go32_ops.to_terminal_inferior = ignore; + go32_ops.to_terminal_ours_for_output = ignore; + go32_ops.to_terminal_ours = ignore; + go32_ops.to_terminal_info = ignore2; + go32_ops.to_kill = go32_kill_inferior; + go32_ops.to_create_inferior = go32_create_inferior; + go32_ops.to_mourn_inferior = go32_mourn_inferior; + go32_ops.to_can_run = go32_can_run; + go32_ops.to_stop = go32_stop; + go32_ops.to_stratum = process_stratum; + go32_ops.to_has_all_memory = 1; + go32_ops.to_has_memory = 1; + go32_ops.to_has_stack = 1; + go32_ops.to_has_registers = 1; + go32_ops.to_has_execution = 1; + go32_ops.to_magic = OPS_MAGIC; } void @@ -1909,61 +751,4 @@ _initialize_go32_nat (void) { init_go32_ops (); add_target (&go32_ops); - - add_prefix_cmd ("dos", class_info, go32_info_dos_command, _("\ -Print information specific to DJGPP (aka MS-DOS) debugging."), - &info_dos_cmdlist, "info dos ", 0, &infolist); - - add_cmd ("sysinfo", class_info, go32_sysinfo, _("\ -Display information about the target system, including CPU, OS, DPMI, etc."), - &info_dos_cmdlist); - add_cmd ("ldt", class_info, go32_sldt, _("\ -Display entries in the LDT (Local Descriptor Table).\n\ -Entry number (an expression) as an argument means display only that entry."), - &info_dos_cmdlist); - add_cmd ("gdt", class_info, go32_sgdt, _("\ -Display entries in the GDT (Global Descriptor Table).\n\ -Entry number (an expression) as an argument means display only that entry."), - &info_dos_cmdlist); - add_cmd ("idt", class_info, go32_sidt, _("\ -Display entries in the IDT (Interrupt Descriptor Table).\n\ -Entry number (an expression) as an argument means display only that entry."), - &info_dos_cmdlist); - add_cmd ("pde", class_info, go32_pde, _("\ -Display entries in the Page Directory.\n\ -Entry number (an expression) as an argument means display only that entry."), - &info_dos_cmdlist); - add_cmd ("pte", class_info, go32_pte, _("\ -Display entries in Page Tables.\n\ -Entry number (an expression) as an argument means display only entries\n\ -from the Page Table pointed to by the specified Page Directory entry."), - &info_dos_cmdlist); - add_cmd ("address-pte", class_info, go32_pte_for_address, _("\ -Display a Page Table entry for a linear address.\n\ -The address argument must be a linear address, after adding to\n\ -it the base address of the appropriate segment.\n\ -The base address of variables and functions in the debuggee's data\n\ -or code segment is stored in the variable __djgpp_base_address,\n\ -so use `__djgpp_base_address + (char *)&var' as the argument.\n\ -For other segments, look up their base address in the output of\n\ -the `info dos ldt' command."), - &info_dos_cmdlist); -} - -pid_t -tcgetpgrp (int fd) -{ - if (isatty (fd)) - return SOME_PID; - errno = ENOTTY; - return -1; -} - -int -tcsetpgrp (int fd, pid_t pgid) -{ - if (isatty (fd) && pgid == SOME_PID) - return 0; - errno = pgid == SOME_PID ? ENOTTY : ENOSYS; - return -1; } diff --git a/gdb/tic80-tdep.c b/gdb/tic80-tdep.c new file mode 100644 index 00000000000..0abbb80dc1a --- /dev/null +++ b/gdb/tic80-tdep.c @@ -0,0 +1,483 @@ +/* Target-dependent code for the TI TMS320C80 (MVP) for GDB, the GNU debugger. + Copyright 1996, Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "value.h" +#include "frame.h" +#include "inferior.h" +#include "obstack.h" +#include "target.h" +#include "bfd.h" +#include "gdb_string.h" +#include "gdbcore.h" +#include "symfile.h" + +/* Function: frame_find_saved_regs + Return the frame_saved_regs structure for the frame. + Doesn't really work for dummy frames, but it does pass back + an empty frame_saved_regs, so I guess that's better than total failure */ + +void +tic80_frame_find_saved_regs (fi, regaddr) + struct frame_info *fi; + struct frame_saved_regs *regaddr; +{ + memcpy (regaddr, &fi->fsr, sizeof (struct frame_saved_regs)); +} + +/* Function: skip_prologue + Find end of function prologue. */ + +CORE_ADDR +tic80_skip_prologue (pc) + CORE_ADDR pc; +{ + CORE_ADDR func_addr, func_end; + struct symtab_and_line sal; + + /* See what the symbol table says */ + + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + sal = find_pc_line (func_addr, 0); + + if (sal.line != 0 && sal.end < func_end) + return sal.end; + else + /* Either there's no line info, or the line after the prologue is after + the end of the function. In this case, there probably isn't a + prologue. */ + return pc; + } + + /* We can't find the start of this function, so there's nothing we can do. */ + return pc; +} + +/* Function: tic80_scan_prologue + This function decodes the target function prologue to determine: + 1) the size of the stack frame + 2) which registers are saved on it + 3) the offsets of saved regs + 4) the frame size + This information is stored in the "extra" fields of the frame_info. */ + +static void +tic80_scan_prologue (fi) + struct frame_info *fi; +{ + struct symtab_and_line sal; + CORE_ADDR prologue_start, prologue_end, current_pc; + + /* Assume there is no frame until proven otherwise. */ + fi->framereg = SP_REGNUM; + fi->framesize = 0; + fi->frameoffset = 0; + + /* this code essentially duplicates skip_prologue, + but we need the start address below. */ + + if (find_pc_partial_function (fi->pc, NULL, &prologue_start, &prologue_end)) + { + sal = find_pc_line (prologue_start, 0); + + if (sal.line == 0) /* no line info, use current PC */ + if (prologue_start != entry_point_address ()) + prologue_end = fi->pc; + else + return; /* _start has no frame or prologue */ + else if (sal.end < prologue_end) /* next line begins after fn end */ + prologue_end = sal.end; /* (probably means no prologue) */ + } + else +/* FIXME */ + prologue_end = prologue_start + 40; /* We're in the boondocks: allow for */ + /* 16 pushes, an add, and "mv fp,sp" */ + + prologue_end = min (prologue_end, fi->pc); + + /* Now search the prologue looking for instructions that set up the + frame pointer, adjust the stack pointer, and save registers. */ + + for (current_pc = prologue_start; current_pc < prologue_end; current_pc += 4) + { + unsigned int insn; + int regno; + int offset = 0; + + insn = read_memory_unsigned_integer (current_pc, 4); + + if ((insn & 0x301000) == 0x301000) /* Long immediate? */ +/* FIXME - set offset for long immediate instructions */ + current_pc += 4; + else + { + offset = insn & 0x7fff; /* extract 15-bit offset */ + if (offset & 0x4000) /* if negative, sign-extend */ + offset = -(0x8000 - offset); + } + + if ((insn & 0x7fd0000) == 0x590000) /* st.{w,d} reg, xx(r1) */ + { + regno = ((insn >> 27) & 0x1f); + fi->fsr.regs[regno] = offset; + if (insn & 0x8000) /* 64-bit store (st.d)? */ + fi->fsr.regs[regno+1] = offset+4; + } + else if ((insn & 0xffff8000) == 0x086c8000) /* addu xx, r1, r1 */ + fi->framesize = -offset; + else if ((insn & 0xffff8000) == 0xf06c8000) /* addu xx, r1, r30 */ + { + fi->framereg = FP_REGNUM; /* fp is now valid */ + fi->frameoffset = offset; + break; /* end of stack adjustments */ + } + else if (insn == 0xf03b2001) /* addu r1, r0, r30 */ + { + fi->framereg = FP_REGNUM; /* fp is now valid */ + fi->frameoffset = 0; + break; /* end of stack adjustments */ + } + else +/* FIXME - handle long immediate instructions */ + break; /* anything else isn't prologue */ + } +} + +/* Function: init_extra_frame_info + This function actually figures out the frame address for a given pc and + sp. This is tricky on the c80 because we sometimes don't use an explicit + frame pointer, and the previous stack pointer isn't necessarily recorded + on the stack. The only reliable way to get this info is to + examine the prologue. */ + +void +tic80_init_extra_frame_info (fi) + struct frame_info *fi; +{ + int reg; + + if (fi->next) + fi->pc = FRAME_SAVED_PC (fi->next); + + /* Because zero is a valid register offset relative to SP, we initialize + the offsets to -1 to indicate unused entries. */ + for (reg = 0; reg < NUM_REGS; reg++) + fi->fsr.regs[reg] = -1; + + if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) + { + /* We need to setup fi->frame here because run_stack_dummy gets it wrong + by assuming it's always FP. */ + fi->frame = generic_read_register_dummy (fi->pc, fi->frame, SP_REGNUM); + fi->framesize = 0; + fi->frameoffset = 0; + return; + } + else + { + tic80_scan_prologue (fi); + + if (!fi->next) /* this is the innermost frame? */ + fi->frame = read_register (fi->framereg); + else /* not the innermost frame */ + /* If this function uses FP as the frame register, and the function + it called saved the FP, get the saved FP. */ + if (fi->framereg == FP_REGNUM && + fi->next->fsr.regs[FP_REGNUM] != (unsigned) -1) + fi->frame = read_memory_integer (fi->next->fsr.regs[FP_REGNUM], 4); + + /* Convert SP-relative offsets of saved registers to real addresses. */ + for (reg = 0; reg < NUM_REGS; reg++) + if (fi->fsr.regs[reg] == (unsigned) -1) + fi->fsr.regs[reg] = 0; /* unused entry */ + else + fi->fsr.regs[reg] += fi->frame - fi->frameoffset; + } +} + +/* Function: find_callers_reg + Find REGNUM on the stack. Otherwise, it's in an active register. One thing + we might want to do here is to check REGNUM against the clobber mask, and + somehow flag it as invalid if it isn't saved on the stack somewhere. This + would provide a graceful failure mode when trying to get the value of + caller-saves registers for an inner frame. */ + +CORE_ADDR +tic80_find_callers_reg (fi, regnum) + struct frame_info *fi; + int regnum; +{ + for (; fi; fi = fi->next) + if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) + return generic_read_register_dummy (fi->pc, fi->frame, regnum); + else if (fi->fsr.regs[regnum] != 0) + return read_memory_integer (fi->fsr.regs[regnum], + REGISTER_RAW_SIZE(regnum)); + return read_register (regnum); +} + +/* Function: frame_chain + Given a GDB frame, determine the address of the calling function's frame. + This will be used to create a new GDB frame struct, and then + INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame. + For c80, we save the frame size when we initialize the frame_info. */ + +CORE_ADDR +tic80_frame_chain (fi) + struct frame_info *fi; +{ + CORE_ADDR fn_start, callers_pc, fp; + + /* is this a dummy frame? */ + if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame)) + return fi->frame; /* dummy frame same as caller's frame */ + + /* is caller-of-this a dummy frame? */ + callers_pc = FRAME_SAVED_PC(fi); /* find out who called us: */ + fp = tic80_find_callers_reg (fi, FP_REGNUM); + if (PC_IN_CALL_DUMMY(callers_pc, fp, fp)) + return fp; /* dummy frame's frame may bear no relation to ours */ + + if (find_pc_partial_function (fi->pc, 0, &fn_start, 0)) + if (fn_start == entry_point_address ()) + return 0; /* in _start fn, don't chain further */ + + if (fi->framereg == FP_REGNUM) + return tic80_find_callers_reg (fi, FP_REGNUM); + else + return fi->frame + fi->framesize; +} + +/* Function: pop_frame + Discard from the stack the innermost frame, + restoring all saved registers. */ + +struct frame_info * +tic80_pop_frame (frame) + struct frame_info *frame; +{ + int regnum; + + if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) + generic_pop_dummy_frame (); + else + { + for (regnum = 0; regnum < NUM_REGS; regnum++) + if (frame->fsr.regs[regnum] != 0) + write_register (regnum, + read_memory_integer (frame->fsr.regs[regnum], 4)); + + write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); + write_register (SP_REGNUM, read_register (FP_REGNUM)); +#if 0 + if (read_register (PSW_REGNUM) & 0x80) + write_register (SPU_REGNUM, read_register (SP_REGNUM)); + else + write_register (SPI_REGNUM, read_register (SP_REGNUM)); +#endif + } + flush_cached_frames (); + return NULL; +} + +/* Function: frame_saved_pc + Find the caller of this frame. We do this by seeing if LR_REGNUM is saved + in the stack anywhere, otherwise we get it from the registers. */ + +CORE_ADDR +tic80_frame_saved_pc (fi) + struct frame_info *fi; +{ + if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame)) + return generic_read_register_dummy (fi->pc, fi->frame, PC_REGNUM); + else + return tic80_find_callers_reg (fi, LR_REGNUM); +} + +/* Function: tic80_push_return_address (pc, sp) + Set up the return address for the inferior function call. + Necessary for targets that don't actually execute a JSR/BSR instruction + (ie. when using an empty CALL_DUMMY) */ + +CORE_ADDR +tic80_push_return_address (pc, sp) + CORE_ADDR pc; + CORE_ADDR sp; +{ + write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ()); + return sp; +} + + +/* Function: push_arguments + Setup the function arguments for calling a function in the inferior. + + On the TI C80 architecture, there are six register pairs (R2/R3 to R12/13) + which are dedicated for passing function arguments. Up to the first six + arguments (depending on size) may go into these registers. + The rest go on the stack. + + Arguments that are smaller than 4 bytes will still take up a whole + register or a whole 32-bit word on the stack, and will be + right-justified in the register or the stack word. This includes + chars, shorts, and small aggregate types. + + Arguments that are four bytes or less in size are placed in the + even-numbered register of a register pair, and the odd-numbered + register is not used. + + Arguments of 8 bytes size (such as floating point doubles) are placed + in a register pair. The least significant 32-bit word is placed in + the even-numbered register, and the most significant word in the + odd-numbered register. + + Aggregate types with sizes between 4 and 8 bytes are passed + entirely on the stack, and are left-justified within the + double-word (as opposed to aggregates smaller than 4 bytes + which are right-justified). + + Aggregates of greater than 8 bytes are first copied onto the stack, + and then a pointer to the copy is passed in the place of the normal + argument (either in a register if available, or on the stack). + + Functions that must return an aggregate type can return it in the + normal return value registers (R2 and R3) if its size is 8 bytes or + less. For larger return values, the caller must allocate space for + the callee to copy the return value to. A pointer to this space is + passed as an implicit first argument, always in R0. */ + +CORE_ADDR +tic80_push_arguments (nargs, args, sp, struct_return, struct_addr) + int nargs; + value_ptr *args; + CORE_ADDR sp; + unsigned char struct_return; + CORE_ADDR struct_addr; +{ + int stack_offset, stack_alloc; + int argreg; + int argnum; + struct type *type; + CORE_ADDR regval; + char *val; + char valbuf[4]; + int len; + int odd_sized_struct; + int is_struct; + + /* first force sp to a 4-byte alignment */ + sp = sp & ~3; + + argreg = ARG0_REGNUM; + /* The "struct return pointer" pseudo-argument goes in R0 */ + if (struct_return) + write_register (argreg++, struct_addr); + + /* Now make sure there's space on the stack */ + for (argnum = 0, stack_alloc = 0; + argnum < nargs; argnum++) + stack_alloc += ((TYPE_LENGTH(VALUE_TYPE(args[argnum])) + 3) & ~3); + sp -= stack_alloc; /* make room on stack for args */ + + + /* Now load as many as possible of the first arguments into + registers, and push the rest onto the stack. There are 16 bytes + in four registers available. Loop thru args from first to last. */ + + argreg = ARG0_REGNUM; + for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++) + { + type = VALUE_TYPE (args[argnum]); + len = TYPE_LENGTH (type); + memset (valbuf, 0, sizeof (valbuf)); + val = (char *) VALUE_CONTENTS (args[argnum]); + +/* FIXME -- tic80 can take doubleword arguments in register pairs */ + is_struct = (type->code == TYPE_CODE_STRUCT); + odd_sized_struct = 0; + + if (! is_struct) + { + if (len < 4) + { /* value gets right-justified in the register or stack word */ + memcpy (valbuf + (4 - len), val, len); + val = valbuf; + } + if (len > 4 && (len & 3) != 0) + odd_sized_struct = 1; /* such structs go entirely on stack */ + } + else + { + /* Structs are always passed by reference. */ + write_register (argreg, sp + stack_offset); + argreg ++; + } + + while (len > 0) + { + if (is_struct || argreg > ARGLAST_REGNUM || odd_sized_struct) + { /* must go on the stack */ + write_memory (sp + stack_offset, val, 4); + stack_offset += 4; + } + /* NOTE WELL!!!!! This is not an "else if" clause!!! + That's because some things get passed on the stack + AND in the registers! */ + if (!is_struct && argreg <= ARGLAST_REGNUM) + { /* there's room in a register */ + regval = extract_address (val, REGISTER_RAW_SIZE(argreg)); + write_register (argreg, regval); + argreg += 2; /* FIXME -- what about doubleword args? */ + } + /* Store the value 4 bytes at a time. This means that things + larger than 4 bytes may go partly in registers and partly + on the stack. */ + len -= REGISTER_RAW_SIZE(argreg); + val += REGISTER_RAW_SIZE(argreg); + } + } + return sp; +} + +/* Function: tic80_write_sp + Because SP is really a read-only register that mirrors either SPU or SPI, + we must actually write one of those two as well, depending on PSW. */ + +void +tic80_write_sp (val) + CORE_ADDR val; +{ +#if 0 + unsigned long psw = read_register (PSW_REGNUM); + + if (psw & 0x80) /* stack mode: user or interrupt */ + write_register (SPU_REGNUM, val); + else + write_register (SPI_REGNUM, val); +#endif + write_register (SP_REGNUM, val); +} + +void +_initialize_tic80_tdep () +{ + tm_print_insn = print_insn_tic80; +} + -- cgit v1.2.1