mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
This commit was generated by cvs2svn to compensate for changes in r130803,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
e8077c0e5b
623 changed files with 201604 additions and 34682 deletions
|
|
@ -1,6 +1,32 @@
|
|||
# Configure fragment invoked in the post-target section for subdirs
|
||||
# wanting multilib support.
|
||||
#
|
||||
# Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file 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.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
#
|
||||
# Please report bugs to <gcc-bugs@gnu.org>
|
||||
# and send patches to <gcc-patches@gnu.org>.
|
||||
|
||||
# It is advisable to support a few --enable/--disable options to let the
|
||||
# user select which libraries s/he really wants.
|
||||
#
|
||||
|
|
@ -17,8 +43,6 @@
|
|||
# . ${srcdir}/../config-ml.in
|
||||
# fi
|
||||
#
|
||||
# See librx/configure.in in the libg++ distribution for an example of how
|
||||
# to handle autoconf'd libraries.
|
||||
#
|
||||
# Things are complicated because 6 separate cases must be handled:
|
||||
# 2 (native, cross) x 3 (absolute-path, relative-not-dot, dot) = 6.
|
||||
|
|
@ -30,13 +54,10 @@
|
|||
# The build tree is layed out as
|
||||
#
|
||||
# ./
|
||||
# libg++
|
||||
# newlib
|
||||
# m68020/
|
||||
# libg++
|
||||
# newlib
|
||||
# m68881/
|
||||
# libg++
|
||||
# newlib
|
||||
#
|
||||
# The nice feature about this arrangement is that inter-library references
|
||||
|
|
@ -69,11 +90,6 @@
|
|||
# newlib. It is up to each target to turn on multilib support for the other
|
||||
# libraries as desired.
|
||||
|
||||
# We have to handle being invoked by both Cygnus configure and Autoconf.
|
||||
#
|
||||
# Cygnus configure incoming variables:
|
||||
# srcdir, subdir, host, arguments
|
||||
#
|
||||
# Autoconf incoming variables:
|
||||
# srcdir, host, ac_configure_args
|
||||
#
|
||||
|
|
@ -83,26 +99,14 @@
|
|||
# Note that `host' in this case is GCC's `target'. Target libraries are
|
||||
# configured for a particular host.
|
||||
|
||||
if [ -n "${ac_configure_args}" ]; then
|
||||
Makefile=${ac_file-Makefile}
|
||||
ml_config_shell=${CONFIG_SHELL-/bin/sh}
|
||||
ml_arguments="${ac_configure_args}"
|
||||
ml_realsrcdir=${srcdir}
|
||||
else
|
||||
Makefile=${Makefile-Makefile}
|
||||
ml_config_shell=${config_shell-/bin/sh}
|
||||
ml_arguments="${arguments}"
|
||||
if [ -n "${subdir}" -a "${subdir}" != "." ] ; then
|
||||
ml_realsrcdir=${srcdir}/${subdir}
|
||||
else
|
||||
ml_realsrcdir=${srcdir}
|
||||
fi
|
||||
fi
|
||||
Makefile=${ac_file-Makefile}
|
||||
ml_config_shell=${CONFIG_SHELL-/bin/sh}
|
||||
ml_realsrcdir=${srcdir}
|
||||
|
||||
# Scan all the arguments and set all the ones we need.
|
||||
|
||||
ml_verbose=--verbose
|
||||
for option in ${ml_arguments}
|
||||
for option in ${ac_configure_args}
|
||||
do
|
||||
case $option in
|
||||
--*) ;;
|
||||
|
|
@ -128,7 +132,7 @@ do
|
|||
enableopt=`echo ${option} | sed 's:^--::;s:=.*$::;s:-:_:g'`
|
||||
eval $enableopt="$optarg"
|
||||
;;
|
||||
--norecursion | --no*)
|
||||
--norecursion | --no-recursion)
|
||||
ml_norecursion=yes
|
||||
;;
|
||||
--silent | --sil* | --quiet | --q*)
|
||||
|
|
@ -156,7 +160,7 @@ done
|
|||
if [ "${enable_multilib}" = yes ]; then
|
||||
|
||||
# Compute whether this is the library's top level directory
|
||||
# (ie: not a multilib subdirectory, and not a subdirectory like libg++/src).
|
||||
# (ie: not a multilib subdirectory, and not a subdirectory like newlib/src).
|
||||
# ${with_multisubdir} tells us we're in the right branch, but we could be
|
||||
# in a subdir of that.
|
||||
# ??? The previous version could void this test by separating the process into
|
||||
|
|
@ -397,6 +401,28 @@ mips*-*-*)
|
|||
esac
|
||||
;;
|
||||
powerpc*-*-* | rs6000*-*-*)
|
||||
if [ x$enable_aix64 = xno ]
|
||||
then
|
||||
old_multidirs="${multidirs}"
|
||||
multidirs=""
|
||||
for x in ${old_multidirs}; do
|
||||
case "$x" in
|
||||
*ppc64* ) : ;;
|
||||
*) multidirs="${multidirs} ${x}" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ x$enable_pthread = xno ]
|
||||
then
|
||||
old_multidirs="${multidirs}"
|
||||
multidirs=""
|
||||
for x in ${old_multidirs}; do
|
||||
case "$x" in
|
||||
*pthread* ) : ;;
|
||||
*) multidirs="${multidirs} ${x}" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
if [ x$enable_softfloat = xno ]
|
||||
then
|
||||
old_multidirs="${multidirs}"
|
||||
|
|
@ -463,17 +489,6 @@ powerpc*-*-* | rs6000*-*-*)
|
|||
esac
|
||||
done
|
||||
fi
|
||||
if [ x$enable_aix = xno ]
|
||||
then
|
||||
old_multidirs="${multidirs}"
|
||||
multidirs=""
|
||||
for x in ${old_multidirs}; do
|
||||
case "$x" in
|
||||
*mcall-aix* ) : ;;
|
||||
*) multidirs="${multidirs} ${x}" ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
;;
|
||||
sparc*-*-*)
|
||||
case " $multidirs " in
|
||||
|
|
@ -510,14 +525,16 @@ multidirs=`echo "$multidirs" | sed -e 's/^[ ][ ]*//' -e 's/[ ][ ]*$//' -e 's/[ ]
|
|||
|
||||
cat > Multi.tem <<\EOF
|
||||
|
||||
PWD_COMMAND=$${PWDCMD-pwd}
|
||||
|
||||
# FIXME: There should be an @-sign in front of the `if'.
|
||||
# Leave out until this is tested a bit more.
|
||||
multi-do:
|
||||
if [ -z "$(MULTIDIRS)" ]; then \
|
||||
true; \
|
||||
else \
|
||||
rootpre=`pwd`/; export rootpre; \
|
||||
srcrootpre=`cd $(srcdir); pwd`/; export srcrootpre; \
|
||||
rootpre=`${PWD_COMMAND}`/; export rootpre; \
|
||||
srcrootpre=`cd $(srcdir); ${PWD_COMMAND}`/; export srcrootpre; \
|
||||
lib=`echo $${rootpre} | sed -e 's,^.*/\([^/][^/]*\)/$$,\1,'`; \
|
||||
compiler="$(CC)"; \
|
||||
for i in `$${compiler} --print-multi-lib 2>/dev/null`; do \
|
||||
|
|
@ -531,10 +548,17 @@ multi-do:
|
|||
CFLAGS="$(CFLAGS) $${flags}" \
|
||||
prefix="$(prefix)" \
|
||||
exec_prefix="$(exec_prefix)" \
|
||||
GCJFLAGS="$(GCJFLAGS) $${flags}" \
|
||||
CXXFLAGS="$(CXXFLAGS) $${flags}" \
|
||||
LIBCFLAGS="$(LIBCFLAGS) $${flags}" \
|
||||
LIBCXXFLAGS="$(LIBCXXFLAGS) $${flags}" \
|
||||
LDFLAGS="$(LDFLAGS) $${flags}" \
|
||||
MULTIFLAGS="$${flags}" \
|
||||
DESTDIR="$(DESTDIR)" \
|
||||
INSTALL="$(INSTALL)" \
|
||||
INSTALL_DATA="$(INSTALL_DATA)" \
|
||||
INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \
|
||||
INSTALL_SCRIPT="$(INSTALL_SCRIPT)" \
|
||||
$(DO)); then \
|
||||
true; \
|
||||
else \
|
||||
|
|
@ -552,7 +576,7 @@ multi-clean:
|
|||
if [ -z "$(MULTIDIRS)" ]; then \
|
||||
true; \
|
||||
else \
|
||||
lib=`pwd | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
|
||||
lib=`${PWD_COMMAND} | sed -e 's,^.*/\([^/][^/]*\)$$,\1,'`; \
|
||||
for dir in Makefile $(MULTIDIRS); do \
|
||||
if [ -f ../$${dir}/$${lib}/Makefile ]; then \
|
||||
if (cd ../$${dir}/$${lib}; $(MAKE) $(FLAGS_TO_PASS) $(DO)); \
|
||||
|
|
@ -659,10 +683,10 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
|
||||
if [ "${ml_verbose}" = --verbose ]; then
|
||||
echo "Running configure in multilib subdirs ${multidirs}"
|
||||
echo "pwd: `pwd`"
|
||||
echo "pwd: `${PWDCMD-pwd}`"
|
||||
fi
|
||||
|
||||
ml_origdir=`pwd`
|
||||
ml_origdir=`${PWDCMD-pwd}`
|
||||
ml_libdir=`echo $ml_origdir | sed -e 's,^.*/,,'`
|
||||
# cd to top-level-build-dir/${with_target_subdir}
|
||||
cd ..
|
||||
|
|
@ -671,7 +695,7 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
|
||||
if [ "${ml_verbose}" = --verbose ]; then
|
||||
echo "Running configure in multilib subdir ${ml_dir}"
|
||||
echo "pwd: `pwd`"
|
||||
echo "pwd: `${PWDCMD-pwd}`"
|
||||
fi
|
||||
|
||||
if [ -d ${ml_dir} ]; then true; else
|
||||
|
|
@ -699,7 +723,7 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
|
||||
case ${srcdir} in
|
||||
".")
|
||||
echo Building symlink tree in `pwd`/${ml_dir}/${ml_libdir}
|
||||
echo Building symlink tree in `${PWDCMD-pwd}`/${ml_dir}/${ml_libdir}
|
||||
if [ "${with_target_subdir}" != "." ]; then
|
||||
ml_unsubdir="../"
|
||||
else
|
||||
|
|
@ -720,7 +744,7 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
;;
|
||||
*)
|
||||
case "${srcdir}" in
|
||||
/*) # absolute path
|
||||
/* | [A-Za-z]:[\\/]* ) # absolute path
|
||||
ml_newsrcdir=${srcdir}
|
||||
;;
|
||||
*) # otherwise relative
|
||||
|
|
@ -733,31 +757,32 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
esac
|
||||
|
||||
case "${progname}" in
|
||||
/*) ml_recprog=${progname} ;;
|
||||
/* | [A-Za-z]:[\\/]* ) ml_recprog=${progname} ;;
|
||||
*) ml_recprog=${dotdot}${progname} ;;
|
||||
esac
|
||||
|
||||
# FIXME: POPDIR=${PWD=`pwd`} doesn't work here.
|
||||
ML_POPDIR=`pwd`
|
||||
ML_POPDIR=`${PWDCMD-pwd}`
|
||||
cd ${ml_dir}/${ml_libdir}
|
||||
|
||||
if [ -f ${ml_newsrcdir}/configure ]; then
|
||||
ml_recprog="${ml_newsrcdir}/configure --cache-file=../config.cache"
|
||||
ml_recprog="${ml_newsrcdir}/configure"
|
||||
fi
|
||||
|
||||
# find compiler flag corresponding to ${ml_dir}
|
||||
for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
|
||||
for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
|
||||
dir=`echo $i | sed -e 's/;.*$//'`
|
||||
if [ "${dir}" = "${ml_dir}" ]; then
|
||||
flags=`echo $i | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`
|
||||
break
|
||||
fi
|
||||
done
|
||||
ml_config_env='CC="${CC_}$flags" CXX="${CXX_}$flags"'
|
||||
ml_config_env='CC="${CC_}$flags" CXX="${CXX_}$flags" GCJ="${GCJ_}$flags"'
|
||||
|
||||
if [ "${with_target_subdir}" = "." ]; then
|
||||
CC_=$CC' '
|
||||
CXX_=$CXX' '
|
||||
GCJ_=$GCJ' '
|
||||
else
|
||||
# Create a regular expression that matches any string as long
|
||||
# as ML_POPDIR.
|
||||
|
|
@ -786,6 +811,18 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
esac
|
||||
done
|
||||
|
||||
GCJ_=
|
||||
for arg in ${GCJ}; do
|
||||
case $arg in
|
||||
-[BIL]"${ML_POPDIR}"/*)
|
||||
GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(-[BIL]${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X-[BIL]${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
|
||||
"${ML_POPDIR}"/*)
|
||||
GCJ_="${GCJ_}"`echo "X${arg}" | sed -n "s/X\\(${popdir_rx}\\).*/\\1/p"`/${ml_dir}`echo "X${arg}" | sed -n "s/X${popdir_rx}\\(.*\\)/\\1/p"`' ' ;;
|
||||
*)
|
||||
GCJ_="${GCJ_}${arg} " ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test "x${LD_LIBRARY_PATH+set}" = xset; then
|
||||
LD_LIBRARY_PATH_=
|
||||
for arg in `echo "$LD_LIBRARY_PATH" | tr ':' ' '`; do
|
||||
|
|
@ -823,7 +860,7 @@ if [ -n "${multidirs}" ] && [ -z "${ml_norecursion}" ]; then
|
|||
|
||||
if eval ${ml_config_env} ${ml_config_shell} ${ml_recprog} \
|
||||
--with-multisubdir=${ml_dir} --with-multisrctop=${multisrctop} \
|
||||
${ml_arguments} ${ml_srcdiroption} ; then
|
||||
${ac_configure_args} ${ml_srcdiroption} ; then
|
||||
true
|
||||
else
|
||||
exit 1
|
||||
|
|
|
|||
52
contrib/gdb/djunpack.bat
Normal file
52
contrib/gdb/djunpack.bat
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
@echo off
|
||||
Rem
|
||||
Rem WARNING WARNING WARNING: This file needs to have DOS CRLF end-of-line
|
||||
Rem format, or else stock DOS/Windows shells will refuse to run it.
|
||||
Rem
|
||||
Rem This batch file unpacks the GDB distribution while simultaneously
|
||||
Rem renaming some of the files whose names are invalid on DOS or conflict
|
||||
Rem with other file names after truncation to DOS 8+3 namespace.
|
||||
Rem
|
||||
Rem Invoke like this:
|
||||
Rem
|
||||
Rem djunpack gdb-XYZ.tar
|
||||
Rem
|
||||
Rem where XYZ is the version number. If the argument includes leading
|
||||
Rem directories, it MUST use backslashes, not forward slashes.
|
||||
Rem
|
||||
Rem The following 2 lines need to be changed with each new GDB release, to
|
||||
Rem be identical to the name of the top-level directory where the GDB
|
||||
Rem distribution unpacks itself.
|
||||
set GDBVER=gdb-6.1.1
|
||||
if "%GDBVER%"=="gdb-6.1.1" GoTo EnvOk
|
||||
Rem If their environment space is too small, re-exec with a larger one
|
||||
command.com /e:4096 /c %0 %1
|
||||
GoTo End
|
||||
:EnvOk
|
||||
if not exist %1 GoTo NoArchive
|
||||
djtar -x -p -o %GDBVER%/gdb/config/djgpp/fnchange.lst %1 > fnchange.tmp
|
||||
Rem The following uses a feature of COPY whereby it does not copy
|
||||
Rem empty files. We need that because the previous line will create
|
||||
Rem an empty fnchange.tmp even if the command failed for some reason.
|
||||
copy fnchange.tmp junk.tmp > nul
|
||||
if not exist junk.tmp GoTo NoDjTar
|
||||
del junk.tmp
|
||||
sed -e 's,@V@,%GDBVER%,g' < fnchange.tmp > fnchange.lst
|
||||
Rem See the comment above about the reason for using COPY.
|
||||
copy fnchange.lst junk.tmp > nul
|
||||
if not exist junk.tmp GoTo NoSed
|
||||
del junk.tmp
|
||||
djtar -x -n fnchange.lst %1
|
||||
GoTo End
|
||||
:NoSed
|
||||
echo FAIL: Sed is not available.
|
||||
GoTo End
|
||||
:NoDjTar
|
||||
echo FAIL: DJTAR is not available or no fnchange.lst file in %1.
|
||||
GoTo End
|
||||
:NoArchive
|
||||
echo FAIL: the file %1 does not seem to exist.
|
||||
echo Remember that %1 cannot use forward slashes, only backslashes.
|
||||
GoTo End
|
||||
:End
|
||||
set GDBVER=
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
GDB Maintainers
|
||||
|
||||
|
||||
Blanket Write Privs
|
||||
Global Maintainers
|
||||
(alphabetic)
|
||||
|
||||
Jim Blandy jimb@redhat.com
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
Andrew Cagney ac131313@redhat.com
|
||||
J.T. Conklin jtc@redback.com
|
||||
Andrew Cagney cagney@gnu.org
|
||||
J.T. Conklin jtc@acorntoolworks.com
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Daniel Jacobowitz dan@debian.org
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Stan Shebs shebs@apple.com
|
||||
|
|
@ -23,7 +24,7 @@ Note individuals who maintain parts of the debugger need approval to
|
|||
check in changes outside of the immediate domain that they maintain.
|
||||
|
||||
If there is no maintainer for a given domain then the responsibility
|
||||
falls to the head maintainer.
|
||||
falls to a global maintainer.
|
||||
|
||||
If there are several maintainers for a given domain then
|
||||
responsibility falls to the first maintainer. The first maintainer is
|
||||
|
|
@ -47,142 +48,110 @@ fix, since such a change without discussion will result in
|
|||
instantaneous and loud complaints.
|
||||
|
||||
|
||||
Target/Architecture:
|
||||
Target Instruction Set Architectures:
|
||||
|
||||
Generic ISA (Instruction Set Architecture) issues, API variants, CPU
|
||||
variants. *-tdep.c. The Target/Architecture maintainer works with the
|
||||
host maintainer when resolving build issues. The Target/Architecture
|
||||
maintainer works with the native maintainer when resolving API issues.
|
||||
|
||||
a29k OBSOLETE
|
||||
a29k Deleted.
|
||||
|
||||
alpha --target=alpha-dec-osf4.0a -Werror
|
||||
alpha --target=alpha-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
arc --target=arc-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
arc Deleted.
|
||||
|
||||
arm --target=arm-elf -w
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
arm --target=arm-elf ,-Werror
|
||||
Scott Bambrough scottb@netwinder.org
|
||||
Richard Earnshaw rearnsha@arm.com
|
||||
Not multi-arch
|
||||
|
||||
avr --target=avr ,-Werror
|
||||
Theodore A. Roth troth@verinet.com
|
||||
Theodore A. Roth troth@openavr.org
|
||||
|
||||
cris --target=cris-elf -w
|
||||
cris --target=cris-elf ,-Werror
|
||||
Orjan Friberg orjanf@axis.com
|
||||
|
||||
d10v --target=d10v-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
d30v --target=d30v-elf ,-Werror
|
||||
d30v Deleted.
|
||||
|
||||
fr30 Deleted.
|
||||
|
||||
frv --target=frv-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
djgpp --target=i586-pc-msdosdjgpp ,-Werror
|
||||
(See native and host)
|
||||
|
||||
fr30 --target=fr30-elf -Werror
|
||||
h8300 --target=h8300hms ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
h8300 --target=h8300hms -Werror
|
||||
Maintenance only
|
||||
Not multi-arch, work in progress
|
||||
h8500 Deleted.
|
||||
|
||||
h8500 --target=h8500hms -Werror
|
||||
Maintenance only
|
||||
Not multi-arch, work in progress
|
||||
|
||||
i386 --target=i386-elf,i386-aout ,-Werror
|
||||
i386 --target=i386-elf ,-Werror
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
|
||||
i960 --target=i960-coff ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
i960 Deleted.
|
||||
|
||||
ia64 --target=ia64-linux ,-Werror
|
||||
ia64 --target=ia64-linux-gnu ,-Werror
|
||||
(--target=ia64-elf broken)
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
m32r --target=m32r-elf -Werror
|
||||
Michael Snyder msnyder@redhat.com
|
||||
Not multi-arch
|
||||
m32r --target=m32r-elf ,-Werror
|
||||
|
||||
m68hc11 --target=m68hc11-elf ,-Werror
|
||||
Stephane Carrez Stephane.Carrez@worldnet.fr
|
||||
m68hc11 --target=m68hc11-elf ,-Werror ,
|
||||
Stephane Carrez stcarrez@nerim.fr
|
||||
|
||||
m68k --target=m68k-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
m88k --target=m88k ,-Werror
|
||||
Known problem in 5.1
|
||||
m88k Deleted.
|
||||
|
||||
mcore --target=mcore-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
mcore --target=mcore-elf,mcore-pe ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
mips --target=mips-elf,mips64-elf ,-Werror
|
||||
mips --target=mips-elf ,-Werror
|
||||
Andrew Cagney cagney@redhat.com
|
||||
|
||||
mn10200 --target=mn10200-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
mn10200 Deleted.
|
||||
|
||||
mn10300 --target=mn10300-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
ns32k --target=ns32k-netbsd ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
pa (--target=hppa1.1-hp-proelf broken)
|
||||
pa (--target=hppa-elf broken)
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
powerpc --target=powerpc-eabi ,-Werror
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
|
||||
rs6000 --target=rs6000-ibm-aix4.1 ,-Werror
|
||||
(see rs6000 native and ppc target)
|
||||
|
||||
s390 --target=s390-linux ,-Werror
|
||||
s390 --target=s390-linux-gnu ,-Werror
|
||||
(contact DJ Barrow djbarrow@de.ibm.com)
|
||||
|
||||
sh --target=sh-hms,sh-elf ,-Werror
|
||||
sh --target=sh-elf ,-Werror
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
|
||||
sparc --target=sparc-elf,sparc64-elf ,-Werror
|
||||
sparc --target=sparc-elf ,-Werror
|
||||
Maintenance only
|
||||
|
||||
tic80 Deleted.
|
||||
|
||||
v850 --target=v850-elf ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
vax --target=vax-dec-vms5.5 ,-Werror
|
||||
vax --target=vax-netbsd ,-Werror
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
|
||||
w65 Deleted.
|
||||
|
||||
x86-64 (--target=x86_64-linux-gnu broken)
|
||||
x86-64 --target=x86_64-linux-gnu ,-Werror
|
||||
Maintenance only
|
||||
|
||||
xstormy16 --target=xstormy16-elf ,-Werror
|
||||
Corinna Vinschen vinschen@redhat.com
|
||||
|
||||
z8k --target=z8k-coff ,-Werror
|
||||
Known problem in 5.1
|
||||
Maintenance only
|
||||
OBSOLETE candidate, not multi-arch
|
||||
z8k Deleted.
|
||||
|
||||
All developers recognized by this file can make arbitrary changes to
|
||||
OBSOLETE targets.
|
||||
|
|
@ -194,21 +163,8 @@ All recognized developers can make mechanical changes (by virtue of
|
|||
the obvious fix rule) to ``maintenance only'' targets. The change
|
||||
shall be sanity checked by compiling with one of the listed targets.
|
||||
|
||||
The GAWK segment:
|
||||
|
||||
awk < "${maintainers}" '
|
||||
$2 ~ /--target=.*/ {
|
||||
targets = gensub (/^.*--target=/, "", 1, $2)
|
||||
warnings = gensub (/[)]*$/, "", 1, $3)
|
||||
split (targets, targ, /,/)
|
||||
for (i in targ) {
|
||||
print targ[i], warnings
|
||||
}
|
||||
}'
|
||||
|
||||
can be used to generate a full list of --target=
|
||||
--enable-gdb-build-warning= pairs.
|
||||
|
||||
The Bourne shell script gdb_mbuild.sh can be used to rebuild all the
|
||||
above targets.
|
||||
|
||||
|
||||
Host/Native:
|
||||
|
|
@ -218,19 +174,19 @@ 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 (including mmalloc) can be built
|
||||
as a cross debugger on their platform.
|
||||
The host maintainer ensures that gdb can be built as a cross debugger on
|
||||
their platform.
|
||||
|
||||
AIX Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
Joel Brobecker brobecker@gnat.com
|
||||
|
||||
djgpp native Eli Zaretskii eliz@gnu.org
|
||||
DJ Delorie dj@redhat.com
|
||||
MS Windows (NT, CE, '00, 9x, Me) host & native
|
||||
Chris Faylor cgf@redhat.com
|
||||
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
|
||||
Jim Blandy jimb@redhat.com
|
||||
GNU/Linux PPC native Kevin Buettner kevinb@redhat.com
|
||||
GNU/Linux MIPS native & host
|
||||
Daniel Jacobowitz dan@debian.org
|
||||
|
|
@ -238,12 +194,13 @@ GNU/Linux m68k Andreas Schwab schwab@suse.de
|
|||
FreeBSD native & host Mark Kettenis kettenis@gnu.org
|
||||
David O'Brien obrien@freebsd.org
|
||||
hurd native Mark Kettenis kettenis@gnu.org
|
||||
NetBSD native & host Jason Thorpe thorpej@wasabisystems.com
|
||||
SCO/Unixware Robert Lipe rjl@sco.com
|
||||
GNU/Linux ARM native Scott Bambrough scottb@netwinder.org
|
||||
Solaris/x86 native & host (devolved)
|
||||
Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
Solaris/SPARC native & host (devolved)
|
||||
Michael Snyder msnyder@redhat.com
|
||||
(Global Maintainers)
|
||||
|
||||
|
||||
|
||||
|
|
@ -253,8 +210,10 @@ generic arch support Andrew Cagney cagney@redhat.com
|
|||
Any host/target maintainer can add to
|
||||
gdbarch.{c,h,sh}. Send tricky ones to cagney.
|
||||
target vector Andrew Cagney cagney@redhat.com
|
||||
main (main.c, top.c) Elena Zannoni ezannoni@redhat.com
|
||||
|
||||
event loop Elena Zannoni ezannoni@redhat.com
|
||||
For the part of top.c related to the event loop,
|
||||
send questions to ezannoni@redhat.com
|
||||
|
||||
generic symtabs Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
|
|
@ -267,42 +226,39 @@ generic symtabs Jim Blandy jimb@redhat.com
|
|||
coff reader Philippe De Muyter phdm@macqel.be
|
||||
xcoff reader Any maintainer can modify this; please send tricky
|
||||
ones to Kevin Buettner <kevinb@redhat.com>
|
||||
linespec Jim Blandy jimb@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
HP/UX readers Any [past] maintainer can modify this.
|
||||
Please send tricky ones to the symtabs maintainers.
|
||||
|
||||
tracing bytecode stuff Jim Blandy jimb@redhat.com
|
||||
(Global Maintainers)
|
||||
tracing Michael Snyder msnyder@redhat.com
|
||||
threads Michael Snyder msnyder@redhat.com
|
||||
Mark Kettenis kettenis@gnu.org
|
||||
breakpoints Michael Snyder msnyder@redhat.com
|
||||
Jim Blandy jimb@redhat.com
|
||||
breakpoints (Global Maintainers)
|
||||
language support (Blanket Write Privs Maintainers)
|
||||
C++ Daniel Jacobowitz dan@debian.org
|
||||
Java support (devolved)
|
||||
Per Bothner per@bothner.com
|
||||
Anthony Green green@redhat.com
|
||||
Java support (Global Maintainers)
|
||||
Pascal support Pierre Muller muller@sources.redhat.com
|
||||
Scheme support Jim Blandy jimb@redhat.com
|
||||
|
||||
shared libs (devolved) Jim Blandy jimb@redhat.com
|
||||
Kevin Buettner kevinb@redhat.com
|
||||
Objective C support Adam Fedor fedor@gnu.org
|
||||
shared libs (devolved) Kevin Buettner kevinb@redhat.com
|
||||
xcoffsolib Peter Schauer Peter.Schauer@regent.e-technik.tu-muenchen.de
|
||||
|
||||
remote.c Andrew Cagney cagney@redhat.com
|
||||
include/remote-sim.h, remote-sim.c
|
||||
Andrew Cagney cagney@redhat.com
|
||||
sds protocol Fernando Nasser fnasser@redhat.com
|
||||
rdi/adp protocol Fernando Nasser fnasser@redhat.com
|
||||
sds protocol (vacant)
|
||||
rdi/adp protocol (vacant)
|
||||
documentation Eli Zaretskii eliz@gnu.org
|
||||
testsuite Fernando Nasser fnasser@redhat.com
|
||||
config Mark Salter msalter@redhat.com
|
||||
lib Mark Salter msalter@redhat.com
|
||||
testsuite Michael Chastain mec.gnu@mindspring.com
|
||||
(Global Maintainers)
|
||||
lib/, config/, gdb.base/, ...
|
||||
Michael Chastain mec.gnu@mindspring.com
|
||||
(Global Maintainers)
|
||||
gdbtk (gdb.gdbtk) Keith Seitz keiths@redhat.com
|
||||
c++ (gdb.c++) Michael Chastain mec@shout.net
|
||||
c++ (gdb.cp) Michael Chastain mec.gnu@mindspring.com
|
||||
David Carlton carlton@bactrian.org
|
||||
mi tests (gdb.mi) Elena Zannoni ezannoni@redhat.com
|
||||
Andrew Cagney cagney@redhat.com
|
||||
stabs (gdb.stabs) Elena Zannoni ezannoni@redhat.com
|
||||
threads (gdb.threads) Michael Snyder msnyder@redhat.com
|
||||
trace (gdb.trace) Michael Snyder msnyder@redhat.com
|
||||
hp tests (gdb.hp) (vacant)
|
||||
|
|
@ -312,7 +268,7 @@ Kernel Object Display Fernando Nasser fnasser@redhat.com
|
|||
|
||||
UI: External (user) interfaces.
|
||||
|
||||
command interpreter Fernando Nasser fnasser@redhat.com
|
||||
command interpreter (Global Maintainers)
|
||||
gdbtk (c & tcl) Jim Ingham jingham@apple.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
Keith Seitz keiths@redhat.com
|
||||
|
|
@ -321,8 +277,8 @@ libgui (w/foundry, sn) Jim Ingham jingham@apple.com
|
|||
mi (gdb/mi) Andrew Cagney cagney@redhat.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
tui (vacant)
|
||||
Technical Contact Point wdb@cup.hp.com
|
||||
tui Stephane Carrez stcarrez@nerim.fr
|
||||
(Global Maintainers)
|
||||
|
||||
|
||||
Misc:
|
||||
|
|
@ -336,6 +292,8 @@ Makefile.in, configure* ALL
|
|||
|
||||
mmalloc/ ALL Host maintainers
|
||||
|
||||
NEWS ALL
|
||||
|
||||
sim/ See sim/MAINTAINERS
|
||||
|
||||
readline/ Master version: ftp://ftp.cwru.edu/pub/bash/
|
||||
|
|
@ -352,49 +310,109 @@ To get recommended for the Write After Approval list you need a valid
|
|||
FSF assignment and have submitted one good patch.
|
||||
|
||||
David Anderson davea@sgi.com
|
||||
Shrinivas Atre shrinivasa@kpitcummins.com
|
||||
Scott Bambrough scottb@netwinder.org
|
||||
Jim Blandy jimb@redhat.com
|
||||
Philip Blundell philb@gnu.org
|
||||
Joel Brobecker brobecker@act-europe.fr
|
||||
Per Bothner per@bothner.com
|
||||
Joel Brobecker brobecker@gnat.com
|
||||
Dave Brolley brolley@redhat.com
|
||||
Paul Brook paul@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@redhat.com
|
||||
Randolph Chung tausq@debian.org
|
||||
Nick Clifton nickc@redhat.com
|
||||
Brendan Conoboy blc@redhat.com
|
||||
DJ Delorie dj@redhat.com
|
||||
Chris G. Demetriou cgd@broadcom.com
|
||||
Philippe De Muyter phdm@macqel.be
|
||||
Dhananjay Deshpande dhananjayd@kpitcummins.com
|
||||
Klee Dienes kdienes@apple.com
|
||||
Richard Earnshaw rearnsha@arm.com
|
||||
Frank Ch. Eigler fche@redhat.com
|
||||
Ben Elliston bje@gnu.org
|
||||
Brian Ford ford@vss.fsi.com
|
||||
Raoul Gough RaoulGough@yahoo.co.uk
|
||||
Anthony Green green@redhat.com
|
||||
Matthew Green mrg@eterna.com.au
|
||||
Jerome Guitton guitton@act-europe.fr
|
||||
Adam Fedor fedor@gnu.org
|
||||
Fred Fish fnf@ninemoons.com
|
||||
Orjan Friberg orjanf@axis.com
|
||||
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@hxi.com
|
||||
Kazu Hirata kazu@cs.umass.edu
|
||||
Jeff Holcomb jeffh@redhat.com
|
||||
Don Howard dhoward@redhat.com
|
||||
Martin Hunt hunt@redhat.com
|
||||
Jim Ingham jingham@apple.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
|
||||
Jim Kingdon jkingdon@engr.sgi.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@lucon.org
|
||||
Michal Ludvig mludvig@suse.cz
|
||||
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
|
||||
Fernando Nasser fnasser@redhat.com
|
||||
Hans-Peter Nilsson hp@bitrange.com
|
||||
David O'Brien obrien@freebsd.org
|
||||
Alexandre Oliva aoliva@redhat.com
|
||||
Tom Rix trix@redhat.com
|
||||
Theodore A. Roth troth@verinet.com
|
||||
Nick Roberts nick@nick.uklinux.net
|
||||
Bob Rossi bob_rossi@cox.net
|
||||
Theodore A. Roth troth@openavr.org
|
||||
Ian Roxborough irox@redhat.com
|
||||
Grace Sainsbury graces@redhat.com
|
||||
Kei Sakamoto sakamoto.kei@renesas.com
|
||||
Mark Salter msalter@redhat.com
|
||||
Richard Sandiford rsandifo@redhat.com
|
||||
Peter Schauer Peter.Schauer@regent
|
||||
Andreas Schwab schwab@suse.de
|
||||
Keith Seitz keiths@redhat.com
|
||||
Stan Shebs shebs@apple.com
|
||||
Aidan Skinner aidan@velvet.net
|
||||
Jiri Smid smid@suse.cz
|
||||
David Smith dsmith@redhat.com
|
||||
Stephen P. Smith ischis2@home.com
|
||||
Stephen P. Smith ischis2@cox.net
|
||||
Jackie Smith Cashion jsmith@redhat.com
|
||||
Michael Snyder msnyder@redhat.com
|
||||
Petr Sorfa petrs@caldera.com
|
||||
Ian Lance Taylor ian@wasabisystems.com
|
||||
Gary Thomas gthomas@redhat.com
|
||||
Jason Thorpe thorpej@wasabisystems.com
|
||||
Tom Tromey tromey@redhat.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
|
||||
Jim Wilson wilson@specifixinc.com
|
||||
Elena Zannoni ezannoni@redhat.com
|
||||
Eli Zaretskii eliz@gnu.org
|
||||
|
||||
|
||||
|
||||
|
|
@ -408,12 +426,18 @@ David Taylor (d10v, sparc, utils, defs,
|
|||
expression evaluator, language support) taylor at candd dot org
|
||||
J.T. Conklin (dcache, NetBSD, remote) jtc at redback 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) fnasser at redhat dot com
|
||||
Mark Salter (testsuite/lib+config) msalter at redhat dot com
|
||||
|
||||
|
||||
|
||||
Folks that have been caught up in a paper trail:
|
||||
|
||||
Chris Faylor cgf@alum.bu.edu
|
||||
Jim Kingdon jkingdon@engr.sgi.com
|
||||
David Carlton carlton@bactrian.org
|
||||
|
||||
--
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,439 @@
|
|||
What has changed in GDB?
|
||||
(Organized release by release)
|
||||
|
||||
*** Changes in GDB 6.1.1:
|
||||
|
||||
* TUI (Text-mode User Interface) built-in (also included in GDB 6.1)
|
||||
|
||||
The TUI (Text-mode User Interface) is now built as part of a default
|
||||
GDB configuration. It is enabled by either selecting the TUI with the
|
||||
command line option "-i=tui" or by running the separate "gdbtui"
|
||||
program. For more information on the TUI, see the manual "Debugging
|
||||
with GDB".
|
||||
|
||||
* Pending breakpoint support (also included in GDB 6.1)
|
||||
|
||||
Support has been added to allow you to specify breakpoints in shared
|
||||
libraries that have not yet been loaded. If a breakpoint location
|
||||
cannot be found, and the "breakpoint pending" option is set to auto,
|
||||
GDB queries you if you wish to make the breakpoint pending on a future
|
||||
shared-library load. If and when GDB resolves the breakpoint symbol,
|
||||
the pending breakpoint is removed as one or more regular breakpoints
|
||||
are created.
|
||||
|
||||
Pending breakpoints are very useful for GCJ Java debugging.
|
||||
|
||||
* Fixed ISO-C build problems
|
||||
|
||||
The files bfd/elf-bfd.h, gdb/dictionary.c and gdb/types.c contained
|
||||
non ISO-C code that stopped them being built using a more strict ISO-C
|
||||
compiler (e.g., IBM's C compiler).
|
||||
|
||||
* Fixed build problem on IRIX 5
|
||||
|
||||
Due to header problems with <sys/proc.h>, the file gdb/proc-api.c
|
||||
wasn't able to compile compile on an IRIX 5 system.
|
||||
|
||||
* Added execute permission to gdb/gdbserver/configure
|
||||
|
||||
The shell script gdb/testsuite/gdb.stabs/configure lacked execute
|
||||
permission. This bug would cause configure to fail on a number of
|
||||
systems (Solaris, IRIX). Ref: server/519.
|
||||
|
||||
* Fixed build problem on hpux2.0w-hp-hpux11.00 using the HP ANSI C compiler
|
||||
|
||||
Older HPUX ANSI C compilers did not accept variable array sizes. somsolib.c
|
||||
has been updated to use constant array sizes.
|
||||
|
||||
* Fixed a panic in the DWARF Call Frame Info code on Solaris 2.7
|
||||
|
||||
GCC 3.3.2, on Solaris 2.7, includes the DW_EH_PE_funcrel encoding in
|
||||
its generated DWARF Call Frame Info. This encoding was causing GDB to
|
||||
panic, that panic has been fixed. Ref: gdb/1628.
|
||||
|
||||
* Fixed a problem when examining parameters in shared library code.
|
||||
|
||||
When examining parameters in optimized shared library code generated
|
||||
by a mainline GCC, GDB would incorrectly report ``Variable "..." is
|
||||
not available''. GDB now correctly displays the variable's value.
|
||||
|
||||
*** Changes in GDB 6.1:
|
||||
|
||||
* Removed --with-mmalloc
|
||||
|
||||
Support for the mmalloc memory manager has been removed, as it
|
||||
conflicted with the internal gdb byte cache.
|
||||
|
||||
* Changes in AMD64 configurations
|
||||
|
||||
The AMD64 target now includes the %cs and %ss registers. As a result
|
||||
the AMD64 remote protocol has changed; this affects the floating-point
|
||||
and SSE registers. If you rely on those registers for your debugging,
|
||||
you should upgrade gdbserver on the remote side.
|
||||
|
||||
* Revised SPARC target
|
||||
|
||||
The SPARC target has been completely revised, incorporating the
|
||||
FreeBSD/sparc64 support that was added for GDB 6.0. As a result
|
||||
support for LynxOS and SunOS 4 has been dropped. Calling functions
|
||||
from within GDB on operating systems with a non-executable stack
|
||||
(Solaris, OpenBSD) now works.
|
||||
|
||||
* New C++ demangler
|
||||
|
||||
GDB has a new C++ demangler which does a better job on the mangled
|
||||
names generated by current versions of g++. It also runs faster, so
|
||||
with this and other changes gdb should now start faster on large C++
|
||||
programs.
|
||||
|
||||
* DWARF 2 Location Expressions
|
||||
|
||||
GDB support for location expressions has been extended to support function
|
||||
arguments and frame bases. Older versions of GDB could crash when they
|
||||
encountered these.
|
||||
|
||||
* C++ nested types and namespaces
|
||||
|
||||
GDB's support for nested types and namespaces in C++ has been
|
||||
improved, especially if you use the DWARF 2 debugging format. (This
|
||||
is the default for recent versions of GCC on most platforms.)
|
||||
Specifically, if you have a class "Inner" defined within a class or
|
||||
namespace "Outer", then GDB realizes that the class's name is
|
||||
"Outer::Inner", not simply "Inner". This should greatly reduce the
|
||||
frequency of complaints about not finding RTTI symbols. In addition,
|
||||
if you are stopped at inside of a function defined within a namespace,
|
||||
GDB modifies its name lookup accordingly.
|
||||
|
||||
* New native configurations
|
||||
|
||||
NetBSD/amd64 x86_64-*-netbsd*
|
||||
OpenBSD/amd64 x86_64-*-openbsd*
|
||||
OpenBSD/alpha alpha*-*-openbsd*
|
||||
OpenBSD/sparc sparc-*-openbsd*
|
||||
OpenBSD/sparc64 sparc64-*-openbsd*
|
||||
|
||||
* New debugging protocols
|
||||
|
||||
M32R with SDI protocol m32r-*-elf*
|
||||
|
||||
* "set prompt-escape-char" command deleted.
|
||||
|
||||
The command "set prompt-escape-char" has been deleted. This command,
|
||||
and its very obscure effet on GDB's prompt, was never documented,
|
||||
tested, nor mentioned in the NEWS file.
|
||||
|
||||
* OBSOLETE configurations and files
|
||||
|
||||
Configurations that have been declared obsolete in this release have
|
||||
been commented out. Unless there is activity to revive these
|
||||
configurations, the next release of GDB will have their sources
|
||||
permanently REMOVED.
|
||||
|
||||
Sun 3, running SunOS 3 m68*-*-sunos3*
|
||||
Sun 3, running SunOS 4 m68*-*-sunos4*
|
||||
Sun 2, running SunOS 3 m68000-*-sunos3*
|
||||
Sun 2, running SunOS 4 m68000-*-sunos4*
|
||||
Motorola 680x0 running LynxOS m68*-*-lynxos*
|
||||
AT&T 3b1/Unix pc m68*-att-*
|
||||
Bull DPX2 (68k, System V release 3) m68*-bull-sysv*
|
||||
decstation mips-dec-* mips-little-*
|
||||
riscos mips-*-riscos* mips-*-sysv*
|
||||
sonymips mips-sony-*
|
||||
sysv mips*-*-sysv4* (IRIX 5/6 not included)
|
||||
|
||||
* REMOVED configurations and files
|
||||
|
||||
SGI Irix-4.x mips-sgi-irix4 or iris4
|
||||
SGI Iris (MIPS) running Irix V3: mips-sgi-irix or iris
|
||||
Z8000 simulator z8k-zilog-none or z8ksim
|
||||
Matsushita MN10200 w/simulator mn10200-*-*
|
||||
H8/500 simulator h8500-hitachi-hms or h8500hms
|
||||
HP/PA running BSD hppa*-*-bsd*
|
||||
HP/PA running OSF/1 hppa*-*-osf*
|
||||
HP/PA Pro target hppa*-*-pro*
|
||||
PMAX (MIPS) running Mach 3.0 mips*-*-mach3*
|
||||
386BSD i[3456]86-*-bsd*
|
||||
Sequent family i[3456]86-sequent-sysv4*
|
||||
i[3456]86-sequent-sysv*
|
||||
i[3456]86-sequent-bsd*
|
||||
SPARC running LynxOS sparc-*-lynxos*
|
||||
SPARC running SunOS 4 sparc-*-sunos4*
|
||||
Tsqware Sparclet sparclet-*-*
|
||||
Fujitsu SPARClite sparclite-fujitsu-none or sparclite
|
||||
|
||||
*** Changes in GDB 6.0:
|
||||
|
||||
* Objective-C
|
||||
|
||||
Support for debugging the Objective-C programming language has been
|
||||
integrated into GDB.
|
||||
|
||||
* New backtrace mechanism (includes DWARF 2 Call Frame Information).
|
||||
|
||||
DWARF 2's Call Frame Information makes available compiler generated
|
||||
information that more exactly describes the program's run-time stack.
|
||||
By using this information, GDB is able to provide more robust stack
|
||||
backtraces.
|
||||
|
||||
The i386, amd64 (nee, x86-64), Alpha, m68hc11, ia64, and m32r targets
|
||||
have been updated to use a new backtrace mechanism which includes
|
||||
DWARF 2 CFI support.
|
||||
|
||||
* Hosted file I/O.
|
||||
|
||||
GDB's remote protocol has been extended to include support for hosted
|
||||
file I/O (where the remote target uses GDB's file system). See GDB's
|
||||
remote protocol documentation for details.
|
||||
|
||||
* All targets using the new architecture framework.
|
||||
|
||||
All of GDB's targets have been updated to use the new internal
|
||||
architecture framework. The way is now open for future GDB releases
|
||||
to include cross-architecture native debugging support (i386 on amd64,
|
||||
ppc32 on ppc64).
|
||||
|
||||
* GNU/Linux's Thread Local Storage (TLS)
|
||||
|
||||
GDB now includes support for for the GNU/Linux implementation of
|
||||
per-thread variables.
|
||||
|
||||
* GNU/Linux's Native POSIX Thread Library (NPTL)
|
||||
|
||||
GDB's thread code has been updated to work with either the new
|
||||
GNU/Linux NPTL thread library or the older "LinuxThreads" library.
|
||||
|
||||
* Separate debug info.
|
||||
|
||||
GDB, in conjunction with BINUTILS, now supports a mechanism for
|
||||
automatically loading debug information from a separate file. Instead
|
||||
of shipping full debug and non-debug versions of system libraries,
|
||||
system integrators can now instead ship just the stripped libraries
|
||||
and optional debug files.
|
||||
|
||||
* DWARF 2 Location Expressions
|
||||
|
||||
DWARF 2 Location Expressions allow the compiler to more completely
|
||||
describe the location of variables (even in optimized code) to the
|
||||
debugger.
|
||||
|
||||
GDB now includes preliminary support for location expressions (support
|
||||
for DW_OP_piece is still missing).
|
||||
|
||||
* Java
|
||||
|
||||
A number of long standing bugs that caused GDB to die while starting a
|
||||
Java application have been fixed. GDB's Java support is now
|
||||
considered "useable".
|
||||
|
||||
* GNU/Linux support for fork, vfork, and exec.
|
||||
|
||||
The "catch fork", "catch exec", "catch vfork", and "set follow-fork-mode"
|
||||
commands are now implemented for GNU/Linux. They require a 2.5.x or later
|
||||
kernel.
|
||||
|
||||
* GDB supports logging output to a file
|
||||
|
||||
There are two new commands, "set logging" and "show logging", which can be
|
||||
used to capture GDB's output to a file.
|
||||
|
||||
* The meaning of "detach" has changed for gdbserver
|
||||
|
||||
The "detach" command will now resume the application, as documented. To
|
||||
disconnect from gdbserver and leave it stopped, use the new "disconnect"
|
||||
command.
|
||||
|
||||
* d10v, m68hc11 `regs' command deprecated
|
||||
|
||||
The `info registers' command has been updated so that it displays the
|
||||
registers using a format identical to the old `regs' command.
|
||||
|
||||
* Profiling support
|
||||
|
||||
A new command, "maint set profile on/off", has been added. This command can
|
||||
be used to enable or disable profiling while running GDB, to profile a
|
||||
session or a set of commands. In addition there is a new configure switch,
|
||||
"--enable-profiling", which will cause GDB to be compiled with profiling
|
||||
data, for more informative profiling results.
|
||||
|
||||
* Default MI syntax changed to "mi2".
|
||||
|
||||
The default MI (machine interface) syntax, enabled by the command line
|
||||
option "-i=mi", has been changed to "mi2". The previous MI syntax,
|
||||
"mi1", can be enabled by specifying the option "-i=mi1".
|
||||
|
||||
Support for the original "mi0" syntax (included in GDB 5.0) has been
|
||||
removed.
|
||||
|
||||
Fix for gdb/192: removed extraneous space when displaying frame level.
|
||||
Fix for gdb/672: update changelist is now output in mi list format.
|
||||
Fix for gdb/702: a -var-assign that updates the value now shows up
|
||||
in a subsequent -var-update.
|
||||
|
||||
* New native configurations.
|
||||
|
||||
FreeBSD/amd64 x86_64-*-freebsd*
|
||||
|
||||
* Multi-arched targets.
|
||||
|
||||
HP/PA HPUX11 hppa*-*-hpux*
|
||||
Renesas M32R/D w/simulator m32r-*-elf*
|
||||
|
||||
* OBSOLETE configurations and files
|
||||
|
||||
Configurations that have been declared obsolete in this release have
|
||||
been commented out. Unless there is activity to revive these
|
||||
configurations, the next release of GDB will have their sources
|
||||
permanently REMOVED.
|
||||
|
||||
Z8000 simulator z8k-zilog-none or z8ksim
|
||||
Matsushita MN10200 w/simulator mn10200-*-*
|
||||
H8/500 simulator h8500-hitachi-hms or h8500hms
|
||||
HP/PA running BSD hppa*-*-bsd*
|
||||
HP/PA running OSF/1 hppa*-*-osf*
|
||||
HP/PA Pro target hppa*-*-pro*
|
||||
PMAX (MIPS) running Mach 3.0 mips*-*-mach3*
|
||||
Sequent family i[3456]86-sequent-sysv4*
|
||||
i[3456]86-sequent-sysv*
|
||||
i[3456]86-sequent-bsd*
|
||||
Tsqware Sparclet sparclet-*-*
|
||||
Fujitsu SPARClite sparclite-fujitsu-none or sparclite
|
||||
|
||||
* REMOVED configurations and files
|
||||
|
||||
V850EA ISA
|
||||
Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
|
||||
IBM AIX PS/2 i[3456]86-*-aix
|
||||
i386 running Mach 3.0 i[3456]86-*-mach3*
|
||||
i386 running Mach i[3456]86-*-mach*
|
||||
i386 running OSF/1 i[3456]86-*osf1mk*
|
||||
HP/Apollo 68k Family m68*-apollo*-sysv*,
|
||||
m68*-apollo*-bsd*,
|
||||
m68*-hp-bsd*, m68*-hp-hpux*
|
||||
Argonaut Risc Chip (ARC) arc-*-*
|
||||
Mitsubishi D30V d30v-*-*
|
||||
Fujitsu FR30 fr30-*-elf*
|
||||
OS/9000 i[34]86-*-os9k
|
||||
I960 with MON960 i960-*-coff
|
||||
|
||||
* MIPS $fp behavior changed
|
||||
|
||||
The convenience variable $fp, for the MIPS, now consistently returns
|
||||
the address of the current frame's base. Previously, depending on the
|
||||
context, $fp could refer to either $sp or the current frame's base
|
||||
address. See ``8.10 Registers'' in the manual ``Debugging with GDB:
|
||||
The GNU Source-Level Debugger''.
|
||||
|
||||
*** Changes in GDB 5.3:
|
||||
|
||||
* GNU/Linux shared library multi-threaded performance improved.
|
||||
|
||||
When debugging a multi-threaded application on GNU/Linux, GDB now uses
|
||||
`/proc', in preference to `ptrace' for memory reads. This may result
|
||||
in an improvement in the start-up time of multi-threaded, shared
|
||||
library applications when run under GDB. One GDB user writes: ``loads
|
||||
shared libs like mad''.
|
||||
|
||||
* ``gdbserver'' now supports multi-threaded applications on some targets
|
||||
|
||||
Support for debugging multi-threaded applications which use
|
||||
the GNU/Linux LinuxThreads package has been added for
|
||||
arm*-*-linux*-gnu*, i[3456]86-*-linux*-gnu*, mips*-*-linux*-gnu*,
|
||||
powerpc*-*-linux*-gnu*, and sh*-*-linux*-gnu*.
|
||||
|
||||
* GDB now supports C/C++ preprocessor macros.
|
||||
|
||||
GDB now expands preprocessor macro invocations in C/C++ expressions,
|
||||
and provides various commands for showing macro definitions and how
|
||||
they expand.
|
||||
|
||||
The new command `macro expand EXPRESSION' expands any macro
|
||||
invocations in expression, and shows the result.
|
||||
|
||||
The new command `show macro MACRO-NAME' shows the definition of the
|
||||
macro named MACRO-NAME, and where it was defined.
|
||||
|
||||
Most compilers don't include information about macros in the debugging
|
||||
information by default. In GCC 3.1, for example, you need to compile
|
||||
your program with the options `-gdwarf-2 -g3'. If the macro
|
||||
information is present in the executable, GDB will read it.
|
||||
|
||||
* Multi-arched targets.
|
||||
|
||||
DEC Alpha (partial) alpha*-*-*
|
||||
DEC VAX (partial) vax-*-*
|
||||
NEC V850 v850-*-*
|
||||
National Semiconductor NS32000 (partial) ns32k-*-*
|
||||
Motorola 68000 (partial) m68k-*-*
|
||||
Motorola MCORE mcore-*-*
|
||||
|
||||
* New targets.
|
||||
|
||||
Fujitsu FRV architecture added by Red Hat frv*-*-*
|
||||
|
||||
|
||||
* New native configurations
|
||||
|
||||
Alpha NetBSD alpha*-*-netbsd*
|
||||
SH NetBSD sh*-*-netbsdelf*
|
||||
MIPS NetBSD mips*-*-netbsd*
|
||||
UltraSPARC NetBSD sparc64-*-netbsd*
|
||||
|
||||
* OBSOLETE configurations and files
|
||||
|
||||
Configurations that have been declared obsolete in this release have
|
||||
been commented out. Unless there is activity to revive these
|
||||
configurations, the next release of GDB will have their sources
|
||||
permanently REMOVED.
|
||||
|
||||
Mitsubishi D30V d30v-*-*
|
||||
OS/9000 i[34]86-*-os9k
|
||||
IBM AIX PS/2 i[3456]86-*-aix
|
||||
Fujitsu FR30 fr30-*-elf*
|
||||
Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
|
||||
Argonaut Risc Chip (ARC) arc-*-*
|
||||
i386 running Mach 3.0 i[3456]86-*-mach3*
|
||||
i386 running Mach i[3456]86-*-mach*
|
||||
i386 running OSF/1 i[3456]86-*osf1mk*
|
||||
HP/Apollo 68k Family m68*-apollo*-sysv*,
|
||||
m68*-apollo*-bsd*,
|
||||
m68*-hp-bsd*, m68*-hp-hpux*
|
||||
I960 with MON960 i960-*-coff
|
||||
|
||||
* OBSOLETE languages
|
||||
|
||||
CHILL, a Pascal like language used by telecommunications companies.
|
||||
|
||||
* REMOVED configurations and files
|
||||
|
||||
AMD 29k family via UDI a29k-amd-udi, udi29k
|
||||
A29K VxWorks a29k-*-vxworks
|
||||
AMD 29000 embedded, using EBMON a29k-none-none
|
||||
AMD 29000 embedded with COFF a29k-none-coff
|
||||
AMD 29000 embedded with a.out a29k-none-aout
|
||||
|
||||
testsuite/gdb.hp/gdb.threads-hp/ directory
|
||||
|
||||
* New command "set max-user-call-depth <nnn>"
|
||||
|
||||
This command allows the user to limit the call depth of user-defined
|
||||
commands. The default is 1024.
|
||||
|
||||
* Changes in FreeBSD/i386 native debugging.
|
||||
|
||||
Support for the "generate-core-file" has been added.
|
||||
|
||||
* New commands "dump", "append", and "restore".
|
||||
|
||||
These commands allow data to be copied from target memory
|
||||
to a bfd-format or binary file (dump and append), and back
|
||||
from a file into memory (restore).
|
||||
|
||||
* Improved "next/step" support on multi-processor Alpha Tru64.
|
||||
|
||||
The previous single-step mechanism could cause unpredictable problems,
|
||||
including the random appearance of SIGSEGV or SIGTRAP signals. The use
|
||||
of a software single-step mechanism prevents this.
|
||||
|
||||
*** Changes in GDB 5.2.1:
|
||||
|
||||
* New targets.
|
||||
|
|
|
|||
|
|
@ -1,32 +1,113 @@
|
|||
|
||||
Known problems in GDB 5.2
|
||||
Known problems in GDB 6.1
|
||||
|
||||
See also: http://www.gnu.org/software/gdb/bugs/
|
||||
|
||||
|
||||
hppa2.0-hp-hpux10.20
|
||||
--------------------
|
||||
*** Build problems
|
||||
|
||||
gdb/487: The top level make files used to build GDB are not compatible
|
||||
with HP/UX make. As a workaround, use GNU make.
|
||||
build/1458: comple failed on hpux11
|
||||
|
||||
gdb/486: The HP/UX C compiler defaults to K&R mode but GDB only builds
|
||||
with an ISO C compiler. The top level configuration incorrectly sets
|
||||
CC to `cc' instead of `cc -Ae'. As a workaround, the correct compiler
|
||||
can be specified as part of the configuration vis:
|
||||
GDB 6.1 is known to have build problems on HP/UX 11.00 using the
|
||||
vendor supplied compilers (GDB does build on HP/UX 11.11, and using
|
||||
GCC).
|
||||
|
||||
$ 'CC=cc -Ae' ./configure
|
||||
*** Misc
|
||||
|
||||
gdb/1560: Control-C does not always interrupt GDB.
|
||||
|
||||
s390*-*-*
|
||||
---------
|
||||
When GDB is busy processing a command which takes a long time to
|
||||
complete, hitting Control-C does not have the expected effect.
|
||||
The command execution is not aborted, and the "QUIT" message confirming
|
||||
the abortion is displayed only after the command has been completed.
|
||||
|
||||
gdb/513: GDB does not build on s390 GNU/Linux. The problem should be
|
||||
fixed in more recent sources.
|
||||
*** C++ support
|
||||
|
||||
gdb/931: GDB could be more generous when reading types C++ templates on input
|
||||
|
||||
i386-*-freebsd4.4*
|
||||
------------------
|
||||
When the user types a template, GDB frequently requires the type to be
|
||||
typed in a certain way (e.g. "const char*" as opposed to "const char *"
|
||||
or "char const *" or "char const*").
|
||||
|
||||
gdb/455: GDB doesn't build on a FreeBSD 4.4-STABLE system. The
|
||||
problem is still being investigated.
|
||||
gdb/1512: no canonical way to output names of C++ types
|
||||
|
||||
We currently don't have any canonical way to output names of C++ types.
|
||||
E.g. "const char *" versus "char const *"; more subtleties arise when
|
||||
dealing with templates.
|
||||
|
||||
gdb/1516: [regression] local classes, gcc 2.95.3, dwarf-2
|
||||
|
||||
With gcc 2.95.3 and the dwarf-2 debugging format, classes which are
|
||||
defined locally to a function include the demangled name of the function
|
||||
as part of their name. For example, if a function "foobar" contains a
|
||||
local class definition "Local", gdb will say that the name of the class
|
||||
type is "foobar__Fi.0:Local".
|
||||
|
||||
This applies only to classes where the class type is defined inside a
|
||||
function, not to variables defined with types that are defined somewhere
|
||||
outside any function (which most types are).
|
||||
|
||||
gdb/1588: names of c++ nested types in casts must be enclosed in quotes
|
||||
|
||||
You must type
|
||||
(gdb) print ('Foo::Bar') x
|
||||
or
|
||||
(gdb) print ('Foo::Bar' *) y
|
||||
instead of
|
||||
(gdb) print (Foo::Bar) x
|
||||
or
|
||||
(gdb) print (Foo::Bar *) y
|
||||
respectively.
|
||||
|
||||
gdb/1091: Constructor breakpoints ignored
|
||||
gdb/1193: g++ 3.3 creates multiple constructors: gdb 5.3 can't set breakpoints
|
||||
|
||||
When gcc 3.x compiles a C++ constructor or C++ destructor, it generates
|
||||
2 or 3 different versions of the object code. These versions have
|
||||
unique mangled names (they have to, in order for linking to work), but
|
||||
they have identical source code names, which leads to a great deal of
|
||||
confusion. Specifically, if you set a breakpoint in a constructor or a
|
||||
destructor, gdb will put a breakpoint in one of the versions, but your
|
||||
program may execute the other version. This makes it impossible to set
|
||||
breakpoints reliably in constructors or destructors.
|
||||
|
||||
gcc 3.x generates these multiple object code functions in order to
|
||||
implement virtual base classes. gcc 2.x generated just one object code
|
||||
function with a hidden parameter, but gcc 3.x conforms to a multi-vendor
|
||||
ABI for C++ which requires multiple object code functions.
|
||||
|
||||
*** Stack backtraces
|
||||
|
||||
GDB's core code base has been updated to use a new backtrace
|
||||
mechanism. This mechanism makes it possible to support new features
|
||||
such DWARF 2 Call Frame Information (which in turn makes possible
|
||||
backtraces through optimized code).
|
||||
|
||||
Since this code is new, it is known to still have a few problems:
|
||||
|
||||
gdb/1505: [regression] gdb prints a bad backtrace for a thread
|
||||
|
||||
When backtracing a thread, gdb does not stop when it reaches the
|
||||
outermost frame, instead continuing until it hits garbage. This is
|
||||
sensitive to the operating system and thread library.
|
||||
|
||||
hppa*-*-*
|
||||
mips*-*-*
|
||||
|
||||
The MIPS and HPPA backtrace code has only very recently been updated
|
||||
to use GDB's new frame mechanism. At present there are still a few
|
||||
problems, in particular backtraces through signal handlers do not
|
||||
work.
|
||||
|
||||
People encountering problems with these architectures should consult
|
||||
GDB's web pages and mailing lists (http://www.gnu.org/software/gdb/)
|
||||
to see if there are updates.
|
||||
|
||||
powerpc*-*-*
|
||||
|
||||
PowerPC architecture support, in 6.1, does not use the new frame code.
|
||||
|
||||
Fortunately, PowerPC architecture support, in GDB's mainline sources,
|
||||
have been updated. People encountering problems should consider
|
||||
downloading a more current snapshot of GDB
|
||||
(http://www.gnu.org/software/gdb/current/).
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
README for gdb-5.2.1 release
|
||||
Updated 19 July, 2002 by Andrew Cagney
|
||||
README for gdb-6.1 release
|
||||
Updated 29 February, 2004 by Andrew Cagney
|
||||
|
||||
This is GDB, the GNU source-level debugger.
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ Unpacking and Installation -- quick overview
|
|||
In this release, the GDB debugger sources, the generic GNU include
|
||||
files, the BFD ("binary file description") library, the readline
|
||||
library, and other libraries all have directories of their own
|
||||
underneath the gdb-5.2.1 directory. The idea is that a variety of GNU
|
||||
underneath the gdb-6.1 directory. The idea is that a variety of GNU
|
||||
tools can share a common copy of these things. Be aware of variation
|
||||
over time--for example don't try to build gdb with a copy of bfd from
|
||||
a release other than the gdb release (such as a binutils release),
|
||||
|
|
@ -29,8 +29,8 @@ Configuration scripts and makefiles exist to cruise up and down this
|
|||
directory tree and automatically build all the pieces in the right
|
||||
order.
|
||||
|
||||
When you unpack the gdb-5.2.1.tar.gz file, you'll find a directory
|
||||
called `gdb-5.2.1', which contains:
|
||||
When you unpack the gdb-6.1.tar.gz file, you'll find a directory
|
||||
called `gdb-6.1', which contains:
|
||||
|
||||
COPYING config.sub intl missing opcodes
|
||||
COPYING.LIB configure libiberty mkinstalldirs readline
|
||||
|
|
@ -44,7 +44,7 @@ called `gdb-5.2.1', which contains:
|
|||
|
||||
You can build GDB right in the source directory:
|
||||
|
||||
cd gdb-5.2.1
|
||||
cd gdb-6.1
|
||||
./configure
|
||||
make
|
||||
cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
|
||||
|
|
@ -58,18 +58,31 @@ You can build GDB in any empty build directory:
|
|||
|
||||
mkdir build
|
||||
cd build
|
||||
<full path to your sources>/gdb-5.2.1/configure
|
||||
<full path to your sources>/gdb-6.1/configure
|
||||
make
|
||||
cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
|
||||
|
||||
(Building GDB with DJGPP tools for MS-DOS/MS-Windows is slightly
|
||||
different; see the file gdb-5.2.1/gdb/config/djgpp/README for details.)
|
||||
different; see the file gdb-6.1/gdb/config/djgpp/README for details.)
|
||||
|
||||
This will configure and build all the libraries as well as GDB. If
|
||||
`configure' can't determine your system type, specify one as its
|
||||
argument, e.g., `./configure sun4' or `./configure decstation'.
|
||||
|
||||
If you get compiler errors during this stage, see the `Reporting
|
||||
Make sure that your 'configure' line ends in 'gdb-6.1/configure':
|
||||
|
||||
/berman/migchain/source/gdb-6.1/configure # RIGHT
|
||||
/berman/migchain/source/gdb-6.1/gdb/configure # WRONG
|
||||
|
||||
The gdb package contains several subdirectories, such as 'gdb',
|
||||
'bfd', and 'readline'. If your 'configure' line ends in
|
||||
'gdb-6.1/gdb/configure', then you are configuring only the gdb
|
||||
subdirectory, not the whole gdb package. This leads to build errors
|
||||
such as:
|
||||
|
||||
make: *** No rule to make target `../bfd/bfd.h', needed by `gdb.o'. Stop.
|
||||
|
||||
If you get other compiler errors during this stage, see the `Reporting
|
||||
Bugs' section below; there are a few known problems.
|
||||
|
||||
GDB requires an ISO C (ANSI C) compiler. If you do not have an ISO
|
||||
|
|
@ -94,7 +107,7 @@ documentation and TeX (or `texi2roff') to typeset the printed version.
|
|||
|
||||
GDB includes an already formatted copy of the on-line Info version
|
||||
of this manual in the `gdb/doc' subdirectory. The main Info file is
|
||||
`gdb-5.2.1/gdb/doc/gdb.info', and it refers to subordinate files
|
||||
`gdb-6.1/gdb/doc/gdb.info', and it refers to subordinate files
|
||||
matching `gdb.info*' in the same directory. If necessary, you can
|
||||
print out these files, or read them with any editor; but they are
|
||||
easier to read using the `info' subsystem in GNU Emacs or the
|
||||
|
|
@ -106,7 +119,7 @@ Info formatting programs, such as `texinfo-format-buffer' or
|
|||
`makeinfo'.
|
||||
|
||||
If you have `makeinfo' installed, and are in the top level GDB
|
||||
source directory (`gdb-5.2.1', in the case of version 5.2.1), you can make
|
||||
source directory (`gdb-6.1', in the case of version 6.1), you can make
|
||||
the Info file by typing:
|
||||
|
||||
cd gdb/doc
|
||||
|
|
@ -115,7 +128,7 @@ the Info file by typing:
|
|||
If you want to typeset and print copies of this manual, you need
|
||||
TeX, a program to print its DVI output files, and `texinfo.tex', the
|
||||
Texinfo definitions file. This file is included in the GDB
|
||||
distribution, in the directory `gdb-5.2.1/texinfo'.
|
||||
distribution, in the directory `gdb-6.1/texinfo'.
|
||||
|
||||
TeX is a typesetting program; it does not print files directly, but
|
||||
produces output files called DVI files. To print a typeset document,
|
||||
|
|
@ -129,11 +142,11 @@ without any extension or a `.dvi' extension.
|
|||
This file tells TeX how to typeset a document written in Texinfo
|
||||
format. On its own, TeX cannot read, much less typeset a Texinfo file.
|
||||
`texinfo.tex' is distributed with GDB and is located in the
|
||||
`gdb-5.2.1/texinfo' directory.
|
||||
`gdb-6.1/texinfo' directory.
|
||||
|
||||
If you have TeX and a DVI printer program installed, you can typeset
|
||||
and print this manual. First switch to the the `gdb' subdirectory of
|
||||
the main source directory (for example, to `gdb-5.2.1/gdb') and then type:
|
||||
the main source directory (for example, to `gdb-6.1/gdb') and then type:
|
||||
|
||||
make doc/gdb.dvi
|
||||
|
||||
|
|
@ -156,55 +169,55 @@ preparing GDB for installation; you can then use `make' to build the
|
|||
a single directory, whose name is usually composed by appending the
|
||||
version number to `gdb'.
|
||||
|
||||
For example, the GDB version 5.2.1 distribution is in the `gdb-5.2.1'
|
||||
For example, the GDB version 6.1 distribution is in the `gdb-6.1'
|
||||
directory. That directory contains:
|
||||
|
||||
`gdb-5.2.1/{COPYING,COPYING.LIB}'
|
||||
`gdb-6.1/{COPYING,COPYING.LIB}'
|
||||
Standard GNU license files. Please read them.
|
||||
|
||||
`gdb-5.2.1/bfd'
|
||||
`gdb-6.1/bfd'
|
||||
source for the Binary File Descriptor library
|
||||
|
||||
`gdb-5.2.1/config*'
|
||||
`gdb-6.1/config*'
|
||||
script for configuring GDB, along with other support files
|
||||
|
||||
`gdb-5.2.1/gdb'
|
||||
`gdb-6.1/gdb'
|
||||
the source specific to GDB itself
|
||||
|
||||
`gdb-5.2.1/include'
|
||||
`gdb-6.1/include'
|
||||
GNU include files
|
||||
|
||||
`gdb-5.2.1/libiberty'
|
||||
`gdb-6.1/libiberty'
|
||||
source for the `-liberty' free software library
|
||||
|
||||
`gdb-5.2.1/mmalloc'
|
||||
`gdb-6.1/mmalloc'
|
||||
source for the GNU memory-mapped malloc package
|
||||
|
||||
`gdb-5.2.1/opcodes'
|
||||
`gdb-6.1/opcodes'
|
||||
source for the library of opcode tables and disassemblers
|
||||
|
||||
`gdb-5.2.1/readline'
|
||||
`gdb-6.1/readline'
|
||||
source for the GNU command-line interface
|
||||
NOTE: The readline library is compiled for use by GDB, but will
|
||||
not be installed on your system when "make install" is issued.
|
||||
|
||||
`gdb-5.2.1/sim'
|
||||
`gdb-6.1/sim'
|
||||
source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc)
|
||||
|
||||
`gdb-5.2.1/intl'
|
||||
`gdb-6.1/intl'
|
||||
source for the GNU gettext library, for internationalization.
|
||||
This is slightly modified from the standalone gettext
|
||||
distribution you can get from GNU.
|
||||
|
||||
`gdb-5.2.1/texinfo'
|
||||
`gdb-6.1/texinfo'
|
||||
The `texinfo.tex' file, which you need in order to make a printed
|
||||
manual using TeX.
|
||||
|
||||
`gdb-5.2.1/etc'
|
||||
`gdb-6.1/etc'
|
||||
Coding standards, useful files for editing GDB, and other
|
||||
miscellanea.
|
||||
|
||||
`gdb-5.2.1/utils'
|
||||
`gdb-6.1/utils'
|
||||
A grab bag of random utilities.
|
||||
|
||||
Note: the following instructions are for building GDB on Unix or
|
||||
|
|
@ -213,14 +226,14 @@ MS-DOS/MS-Windows are in the file gdb/config/djgpp/README.
|
|||
|
||||
The simplest way to configure and build GDB is to run `configure'
|
||||
from the `gdb-VERSION-NUMBER' source directory, which in this example
|
||||
is the `gdb-5.2.1' directory.
|
||||
is the `gdb-6.1' directory.
|
||||
|
||||
First switch to the `gdb-VERSION-NUMBER' source directory if you are
|
||||
not already in it; then run `configure'.
|
||||
|
||||
For example:
|
||||
|
||||
cd gdb-5.2.1
|
||||
cd gdb-6.1
|
||||
./configure
|
||||
make
|
||||
|
||||
|
|
@ -236,8 +249,8 @@ you may need to run `sh' on it explicitly:
|
|||
sh configure
|
||||
|
||||
If you run `configure' from a directory that contains source
|
||||
directories for multiple libraries or programs, such as the `gdb-5.2.1'
|
||||
source directory for version 5.2.1, `configure' creates configuration
|
||||
directories for multiple libraries or programs, such as the `gdb-6.1'
|
||||
source directory for version 6.1, `configure' creates configuration
|
||||
files for every directory level underneath (unless you tell it not to,
|
||||
with the `--norecursion' option).
|
||||
|
||||
|
|
@ -245,10 +258,10 @@ with the `--norecursion' option).
|
|||
directories in the GDB distribution, if you only want to configure that
|
||||
subdirectory; but be sure to specify a path to it.
|
||||
|
||||
For example, with version 5.2.1, type the following to configure only
|
||||
For example, with version 6.1, type the following to configure only
|
||||
the `bfd' subdirectory:
|
||||
|
||||
cd gdb-5.2.1/bfd
|
||||
cd gdb-6.1/bfd
|
||||
../configure
|
||||
|
||||
You can install `gdb' anywhere; it has no hardwired paths. However,
|
||||
|
|
@ -277,13 +290,13 @@ directory. If the path to `configure' would be the same as the
|
|||
argument to `--srcdir', you can leave out the `--srcdir' option; it
|
||||
will be assumed.)
|
||||
|
||||
For example, with version 5.2.1, you can build GDB in a separate
|
||||
For example, with version 6.1, you can build GDB in a separate
|
||||
directory for a Sun 4 like this:
|
||||
|
||||
cd gdb-5.2.1
|
||||
cd gdb-6.1
|
||||
mkdir ../gdb-sun4
|
||||
cd ../gdb-sun4
|
||||
../gdb-5.2.1/configure
|
||||
../gdb-6.1/configure
|
||||
make
|
||||
|
||||
When `configure' builds a configuration using a remote source
|
||||
|
|
@ -304,8 +317,8 @@ called `configure' (or one of its subdirectories).
|
|||
|
||||
The `Makefile' that `configure' generates in each source directory
|
||||
also runs recursively. If you type `make' in a source directory such
|
||||
as `gdb-5.2.1' (or in a separate configured directory configured with
|
||||
`--srcdir=PATH/gdb-5.2.1'), you will build all the required libraries,
|
||||
as `gdb-6.1' (or in a separate configured directory configured with
|
||||
`--srcdir=PATH/gdb-6.1'), you will build all the required libraries,
|
||||
and then build GDB.
|
||||
|
||||
When you have multiple hosts or targets configured in separate
|
||||
|
|
@ -348,7 +361,7 @@ you can use it to test your guesses on abbreviations--for example:
|
|||
Invalid configuration `i786v': machine `i786v' not recognized
|
||||
|
||||
`config.sub' is also distributed in the GDB source directory
|
||||
(`gdb-5.2.1', for version 5.2.1).
|
||||
(`gdb-6.1', for version 6.1).
|
||||
|
||||
|
||||
`configure' options
|
||||
|
|
@ -449,25 +462,15 @@ Linux.
|
|||
There are a number of remote interfaces for talking to existing ROM
|
||||
monitors and other hardware:
|
||||
|
||||
remote-adapt.c AMD 29000 "Adapt"
|
||||
remote-array.c Array Tech RAID controller
|
||||
remote-bug.c Motorola BUG monitor
|
||||
remote-e7000.c Hitachi E7000 ICE
|
||||
remote-eb.c AMD 29000 "EBMON"
|
||||
remote-es.c Ericsson 1800 monitor
|
||||
remote-e7000.c Renesas E7000 ICE
|
||||
remote-est.c EST emulator
|
||||
remote-hms.c Hitachi Micro Systems H8/300 monitor
|
||||
remote-hms.c Renesas Micro Systems H8/300 monitor
|
||||
remote-mips.c MIPS remote debugging protocol
|
||||
remote-mm.c AMD 29000 "minimon"
|
||||
remote-nindy.c Intel 960 "Nindy"
|
||||
remote-nrom.c NetROM ROM emulator
|
||||
remote-os9k.c PC running OS/9000
|
||||
remote-rdi.c ARM with Angel monitor
|
||||
remote-rdp.c ARM with Demon monitor
|
||||
remote-sds.c PowerPC SDS monitor
|
||||
remote-sim.c Generalized simulator protocol
|
||||
remote-st.c Tandem ST-2000 monitor
|
||||
remote-udi.c AMD 29000 using the AMD "Universal Debug Interface"
|
||||
remote-vx.c VxWorks realtime kernel
|
||||
|
||||
Remote-vx.c and the vx-share subdirectory contain a remote
|
||||
|
|
@ -475,14 +478,6 @@ interface for the VxWorks realtime kernel, which communicates over TCP
|
|||
using the Sun RPC library. This would be a useful starting point for
|
||||
other remote- via-ethernet back ends.
|
||||
|
||||
Remote-udi.c and the 29k-share subdirectory contain a remote
|
||||
interface for AMD 29000 programs, which uses the AMD "Universal Debug
|
||||
Interface". This allows GDB to talk to software simulators,
|
||||
emulators, and/or bare hardware boards, via network or serial
|
||||
interfaces. Note that GDB only provides an interface that speaks UDI,
|
||||
not a complete solution. You will need something on the other end
|
||||
that also speaks UDI.
|
||||
|
||||
|
||||
Reporting Bugs in GDB
|
||||
=====================
|
||||
|
|
@ -496,7 +491,7 @@ As an alternative, the bug report can be submitted, via e-mail, to the
|
|||
address "bug-gdb@gnu.org".
|
||||
|
||||
When submitting a bug, please include the GDB version number (e.g.,
|
||||
gdb-5.2.1), and how you configured it (e.g., "sun4" or "mach386 host,
|
||||
gdb-6.1), and how you configured it (e.g., "sun4" or "mach386 host,
|
||||
i586-intel-synopsys target"). Since GDB now supports so many
|
||||
different configurations, it is important that you be precise about
|
||||
this. If at all possible, you should include the actual banner that
|
||||
|
|
@ -513,7 +508,7 @@ Graphical interface to GDB -- X Windows, MS Windows
|
|||
Several graphical interfaces to GDB are available. You should
|
||||
check:
|
||||
|
||||
http://www.gnu.org/software/gdb/gui/
|
||||
http://www.gnu.org/software/gdb/links/
|
||||
|
||||
for an up-to-date list.
|
||||
|
||||
|
|
@ -551,17 +546,17 @@ ftp://sources.redhat.com/pub/dejagnu/ will contain a recent snapshot.
|
|||
Once DejaGNU is installed, you can run the tests in one of the
|
||||
following ways:
|
||||
|
||||
(1) cd gdb-5.2.1
|
||||
(1) cd gdb-6.1
|
||||
make check-gdb
|
||||
|
||||
or
|
||||
|
||||
(2) cd gdb-5.2.1/gdb
|
||||
(2) cd gdb-6.1/gdb
|
||||
make check
|
||||
|
||||
or
|
||||
|
||||
(3) cd gdb-5.2.1/gdb/testsuite
|
||||
(3) cd gdb-6.1/gdb/testsuite
|
||||
make site.exp (builds the site specific file)
|
||||
runtest -tool gdb GDB=../gdb (or GDB=<somepath> as appropriate)
|
||||
|
||||
|
|
|
|||
|
|
@ -114,12 +114,6 @@ The following cleanups have been identified as part of GDB 5.2.
|
|||
|
||||
--
|
||||
|
||||
Remove old code that does not use ui_out functions and all the related
|
||||
"ifdef"s. This also allows the elimination of -DUI_OUT from
|
||||
Makefile.in and configure.in.
|
||||
|
||||
--
|
||||
|
||||
Compiler warnings.
|
||||
|
||||
Eliminate warnings for all targets on at least one host for one of the
|
||||
|
|
@ -177,14 +171,6 @@ Deprecate, if not delete, the following:
|
|||
how it relates to rawreg and the
|
||||
regnum is clear.
|
||||
|
||||
REGISTER_BYTES
|
||||
The size of the cache can be computed
|
||||
on the fly.
|
||||
|
||||
IS_TRAPPED_INTERNALVAR
|
||||
The pseudo registers should eventually make
|
||||
this redundant.
|
||||
|
||||
--
|
||||
|
||||
Obsolete the targets:
|
||||
|
|
@ -247,10 +233,6 @@ New languages come onto the scene all the time.
|
|||
|
||||
Re: Various C++ things
|
||||
|
||||
value_headof/value_from_vtable_info are worthless, and should be
|
||||
removed. The one place in printcmd.c that uses it should use the RTTI
|
||||
functions.
|
||||
|
||||
RTTI for g++ should be using the typeinfo functions rather than the
|
||||
vtables. The typeinfo functions are always at offset 4 from the
|
||||
beginning of the vtable, and are always right. The vtables will have
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ dnl not used, don't export to save symbols
|
|||
AC_SUBST(TCL_LD_FLAGS)
|
||||
dnl don't export, not used outside of configure
|
||||
AC_SUBST(TCL_LD_SEARCH_FLAGS)
|
||||
AC_SUBST(TCL_CC_SEARCH_FLAGS)
|
||||
AC_SUBST(TCL_COMPAT_OBJS)
|
||||
AC_SUBST(TCL_RANLIB)
|
||||
AC_SUBST(TCL_BUILD_LIB_SPEC)
|
||||
|
|
@ -733,132 +734,6 @@ AC_SUBST(ITKHDIR)
|
|||
#AC_SUBST(ITKLIB)
|
||||
])
|
||||
|
||||
# check for Tix headers.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXH, [
|
||||
AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
|
||||
if test -f $i/generic/tix.h ; then
|
||||
ac_cv_c_tixh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
TIXHDIR="# no Tix private headers found"
|
||||
AC_MSG_ERROR([Can't find Tix private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" != x ; then
|
||||
TIXHDIR="-I${ac_cv_c_tixh}"
|
||||
fi
|
||||
AC_SUBST(TIXHDIR)
|
||||
])
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
|
||||
#
|
||||
# Ok, lets find the tix configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-itkconfig
|
||||
#
|
||||
|
||||
if test x"${no_tix}" = x ; then
|
||||
# we reset no_tix in case something fails here
|
||||
no_tix=true
|
||||
AC_ARG_WITH(tixconfig, [ --with-tixconfig Directory containing tix configuration (tixConfig.sh)],
|
||||
with_tixconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tix configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tixconfig,[
|
||||
|
||||
# First check to see if --with-tixconfig was specified.
|
||||
if test x"${with_tixconfig}" != x ; then
|
||||
if test -f "${with_tixconfig}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tix library
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
../tix \
|
||||
`ls -dr ../tix 2>/dev/null` \
|
||||
../../tix \
|
||||
`ls -dr ../../tix 2>/dev/null` \
|
||||
../../../tix \
|
||||
`ls -dr ../../../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
echo "**** Looking at $i"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
echo "**** Other private locations"
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tix \
|
||||
`ls -dr ${srcdir}/../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/${configdir}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
TIXCONFIG="# no Tix configs found"
|
||||
AC_MSG_WARN(Can't find Tix configuration definitions)
|
||||
else
|
||||
no_tix=
|
||||
TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
|
||||
AC_MSG_RESULT(found $TIXCONFIG)
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_TIXCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
|
||||
if test -f "$TIXCONFIG" ; then
|
||||
. $TIXCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(TIX_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_MAJOR_VERSION)
|
||||
dnl AC_SUBST(TIX_MINOR_VERSION)
|
||||
dnl AC_SUBST(TIX_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl dnl AC_SUBST(TIX_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(TIX_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_EXEC_PREFIX)
|
||||
|
||||
dnl AC_SUBST(TIX_BUILD_INCLUDES)
|
||||
AC_SUBST(TIX_BUILD_LIB_SPEC)
|
||||
dnl AC_SUBST(TIX_LIB_SPEC)
|
||||
])
|
||||
|
||||
dnl sinclude(../gettext.m4) already included by bfd/acinclude.m4
|
||||
dnl The lines below arrange for aclocal not to bring gettext.m4's
|
||||
|
|
@ -976,3 +851,148 @@ case "x$am_cv_prog_cc_stdc" in
|
|||
*) CC="$CC $am_cv_prog_cc_stdc" ;;
|
||||
esac
|
||||
])
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
|
||||
done
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_func_iconv=yes)
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_lib_iconv=yes
|
||||
am_cv_func_iconv=yes)
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
fi
|
||||
LIBICONV=
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
LIBICONV="-liconv"
|
||||
fi
|
||||
AC_SUBST(LIBICONV)
|
||||
])
|
||||
|
||||
# AC_GNU_SOURCE
|
||||
# -------------
|
||||
# FIXME: Remove thise once we start using Autoconf 2.5x (x>=4).
|
||||
AC_DEFUN([AC_GNU_SOURCE],
|
||||
[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl
|
||||
AC_BEFORE([$0], [AC_TRY_RUN])dnl
|
||||
AC_DEFINE([_GNU_SOURCE])
|
||||
])
|
||||
|
||||
dnl written by Guido Draheim <guidod@gmx.de>, original by Alexandre Oliva
|
||||
dnl Version 1.3 (2001/03/02)
|
||||
dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html
|
||||
|
||||
AC_DEFUN([AC_DEFINE_DIR], [
|
||||
test "x$prefix" = xNONE && prefix="$ac_default_prefix"
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
ac_define_dir=`eval echo [$]$2`
|
||||
ac_define_dir=`eval echo [$]ac_define_dir`
|
||||
ifelse($3, ,
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir"),
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3))
|
||||
])
|
||||
|
||||
dnl See whether we need a declaration for a function.
|
||||
dnl The result is highly dependent on the INCLUDES passed in, so make sure
|
||||
dnl to use a different cache variable name in this macro if it is invoked
|
||||
dnl in a different context somewhere else.
|
||||
dnl gcc_AC_CHECK_DECL(SYMBOL,
|
||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
|
||||
AC_DEFUN(gcc_AC_CHECK_DECL,
|
||||
[AC_MSG_CHECKING([whether $1 is declared])
|
||||
AC_CACHE_VAL(gcc_cv_have_decl_$1,
|
||||
[AC_TRY_COMPILE([$4],
|
||||
[#ifndef $1
|
||||
char *(*pfn) = (char *(*)) $1 ;
|
||||
#endif], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")])
|
||||
if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then
|
||||
AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Check multiple functions to see whether each needs a declaration.
|
||||
dnl Arrange to define HAVE_DECL_<FUNCTION> to 0 or 1 as appropriate.
|
||||
dnl gcc_AC_CHECK_DECLS(SYMBOLS,
|
||||
dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]])
|
||||
AC_DEFUN(gcc_AC_CHECK_DECLS,
|
||||
[for ac_func in $1
|
||||
do
|
||||
changequote(, )dnl
|
||||
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
|
||||
changequote([, ])dnl
|
||||
gcc_AC_CHECK_DECL($ac_func,
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2],
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3],
|
||||
dnl It is possible that the include files passed in here are local headers
|
||||
dnl which supply a backup declaration for the relevant prototype based on
|
||||
dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test
|
||||
dnl will always return success. E.g. see libiberty.h's handling of
|
||||
dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to
|
||||
dnl 1 so that any local headers used do not provide their own prototype
|
||||
dnl during this test.
|
||||
#undef $ac_tr_decl
|
||||
#define $ac_tr_decl 1
|
||||
$4
|
||||
)
|
||||
done
|
||||
dnl Automatically generate config.h entries via autoheader.
|
||||
if test x = y ; then
|
||||
patsubst(translit([$1], [a-z], [A-Z]), [\w+],
|
||||
[AC_DEFINE([HAVE_DECL_\&], 1,
|
||||
[Define to 1 if we found this declaration otherwise define to 0.])])dnl
|
||||
fi
|
||||
])
|
||||
|
||||
|
|
|
|||
272
contrib/gdb/gdb/aclocal.m4
vendored
272
contrib/gdb/gdb/aclocal.m4
vendored
|
|
@ -271,6 +271,7 @@ dnl not used, don't export to save symbols
|
|||
AC_SUBST(TCL_LD_FLAGS)
|
||||
dnl don't export, not used outside of configure
|
||||
AC_SUBST(TCL_LD_SEARCH_FLAGS)
|
||||
AC_SUBST(TCL_CC_SEARCH_FLAGS)
|
||||
AC_SUBST(TCL_COMPAT_OBJS)
|
||||
AC_SUBST(TCL_RANLIB)
|
||||
AC_SUBST(TCL_BUILD_LIB_SPEC)
|
||||
|
|
@ -745,132 +746,6 @@ AC_SUBST(ITKHDIR)
|
|||
#AC_SUBST(ITKLIB)
|
||||
])
|
||||
|
||||
# check for Tix headers.
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXH, [
|
||||
AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
|
||||
if test -f $i/generic/tix.h ; then
|
||||
ac_cv_c_tixh=`(cd $i/generic; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" = x ; then
|
||||
TIXHDIR="# no Tix private headers found"
|
||||
AC_MSG_ERROR([Can't find Tix private headers])
|
||||
fi
|
||||
if test x"${ac_cv_c_tixh}" != x ; then
|
||||
TIXHDIR="-I${ac_cv_c_tixh}"
|
||||
fi
|
||||
AC_SUBST(TIXHDIR)
|
||||
])
|
||||
|
||||
AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
|
||||
#
|
||||
# Ok, lets find the tix configuration
|
||||
# First, look for one uninstalled.
|
||||
# the alternative search directory is invoked by --with-itkconfig
|
||||
#
|
||||
|
||||
if test x"${no_tix}" = x ; then
|
||||
# we reset no_tix in case something fails here
|
||||
no_tix=true
|
||||
AC_ARG_WITH(tixconfig, [ --with-tixconfig Directory containing tix configuration (tixConfig.sh)],
|
||||
with_tixconfig=${withval})
|
||||
AC_MSG_CHECKING([for Tix configuration])
|
||||
AC_CACHE_VAL(ac_cv_c_tixconfig,[
|
||||
|
||||
# First check to see if --with-tixconfig was specified.
|
||||
if test x"${with_tixconfig}" != x ; then
|
||||
if test -f "${with_tixconfig}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
|
||||
else
|
||||
AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
|
||||
fi
|
||||
fi
|
||||
|
||||
# then check for a private Tix library
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
../tix \
|
||||
`ls -dr ../tix 2>/dev/null` \
|
||||
../../tix \
|
||||
`ls -dr ../../tix 2>/dev/null` \
|
||||
../../../tix \
|
||||
`ls -dr ../../../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few common install locations
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
|
||||
echo "**** Looking at $i"
|
||||
if test -f "$i/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# check in a few other private locations
|
||||
echo "**** Other private locations"
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
for i in \
|
||||
${srcdir}/../tix \
|
||||
`ls -dr ${srcdir}/../tix 2>/dev/null` ; do
|
||||
echo "**** Looking at $i - with ${configdir}"
|
||||
if test -f "$i/${configdir}/tixConfig.sh" ; then
|
||||
ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
if test x"${ac_cv_c_tixconfig}" = x ; then
|
||||
TIXCONFIG="# no Tix configs found"
|
||||
AC_MSG_WARN(Can't find Tix configuration definitions)
|
||||
else
|
||||
no_tix=
|
||||
TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
|
||||
AC_MSG_RESULT(found $TIXCONFIG)
|
||||
fi
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
# Defined as a separate macro so we don't have to cache the values
|
||||
# from PATH_TIXCONFIG (because this can also be cached).
|
||||
AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
|
||||
if test -f "$TIXCONFIG" ; then
|
||||
. $TIXCONFIG
|
||||
fi
|
||||
|
||||
AC_SUBST(TIX_VERSION)
|
||||
dnl not actually used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_MAJOR_VERSION)
|
||||
dnl AC_SUBST(TIX_MINOR_VERSION)
|
||||
dnl AC_SUBST(TIX_DEFS)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl dnl AC_SUBST(TIX_LIB_FILE)
|
||||
|
||||
dnl not used outside of configure
|
||||
dnl AC_SUBST(TIX_LIBS)
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_PREFIX)
|
||||
|
||||
dnl not used, don't export to save symbols
|
||||
dnl AC_SUBST(TIX_EXEC_PREFIX)
|
||||
|
||||
dnl AC_SUBST(TIX_BUILD_INCLUDES)
|
||||
AC_SUBST(TIX_BUILD_LIB_SPEC)
|
||||
dnl AC_SUBST(TIX_LIB_SPEC)
|
||||
])
|
||||
|
||||
dnl sinclude(../gettext.m4) already included by bfd/acinclude.m4
|
||||
dnl The lines below arrange for aclocal not to bring gettext.m4's
|
||||
|
|
@ -985,6 +860,151 @@ case "x$am_cv_prog_cc_stdc" in
|
|||
esac
|
||||
])
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
|
||||
done
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_func_iconv=yes)
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_lib_iconv=yes
|
||||
am_cv_func_iconv=yes)
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
fi
|
||||
LIBICONV=
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
LIBICONV="-liconv"
|
||||
fi
|
||||
AC_SUBST(LIBICONV)
|
||||
])
|
||||
|
||||
# AC_GNU_SOURCE
|
||||
# -------------
|
||||
# FIXME: Remove thise once we start using Autoconf 2.5x (x>=4).
|
||||
AC_DEFUN([AC_GNU_SOURCE],
|
||||
[AC_BEFORE([$0], [AC_TRY_COMPILE])dnl
|
||||
AC_BEFORE([$0], [AC_TRY_RUN])dnl
|
||||
AC_DEFINE([_GNU_SOURCE])
|
||||
])
|
||||
|
||||
dnl written by Guido Draheim <guidod@gmx.de>, original by Alexandre Oliva
|
||||
dnl Version 1.3 (2001/03/02)
|
||||
dnl source http://www.gnu.org/software/ac-archive/Miscellaneous/ac_define_dir.html
|
||||
|
||||
AC_DEFUN([AC_DEFINE_DIR], [
|
||||
test "x$prefix" = xNONE && prefix="$ac_default_prefix"
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
ac_define_dir=`eval echo [$]$2`
|
||||
ac_define_dir=`eval echo [$]ac_define_dir`
|
||||
ifelse($3, ,
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir"),
|
||||
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", $3))
|
||||
])
|
||||
|
||||
dnl See whether we need a declaration for a function.
|
||||
dnl The result is highly dependent on the INCLUDES passed in, so make sure
|
||||
dnl to use a different cache variable name in this macro if it is invoked
|
||||
dnl in a different context somewhere else.
|
||||
dnl gcc_AC_CHECK_DECL(SYMBOL,
|
||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
|
||||
AC_DEFUN(gcc_AC_CHECK_DECL,
|
||||
[AC_MSG_CHECKING([whether $1 is declared])
|
||||
AC_CACHE_VAL(gcc_cv_have_decl_$1,
|
||||
[AC_TRY_COMPILE([$4],
|
||||
[#ifndef $1
|
||||
char *(*pfn) = (char *(*)) $1 ;
|
||||
#endif], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")])
|
||||
if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then
|
||||
AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Check multiple functions to see whether each needs a declaration.
|
||||
dnl Arrange to define HAVE_DECL_<FUNCTION> to 0 or 1 as appropriate.
|
||||
dnl gcc_AC_CHECK_DECLS(SYMBOLS,
|
||||
dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]])
|
||||
AC_DEFUN(gcc_AC_CHECK_DECLS,
|
||||
[for ac_func in $1
|
||||
do
|
||||
changequote(, )dnl
|
||||
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
|
||||
changequote([, ])dnl
|
||||
gcc_AC_CHECK_DECL($ac_func,
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2],
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3],
|
||||
dnl It is possible that the include files passed in here are local headers
|
||||
dnl which supply a backup declaration for the relevant prototype based on
|
||||
dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test
|
||||
dnl will always return success. E.g. see libiberty.h's handling of
|
||||
dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to
|
||||
dnl 1 so that any local headers used do not provide their own prototype
|
||||
dnl during this test.
|
||||
#undef $ac_tr_decl
|
||||
#define $ac_tr_decl 1
|
||||
$4
|
||||
)
|
||||
done
|
||||
dnl Automatically generate config.h entries via autoheader.
|
||||
if test x = y ; then
|
||||
patsubst(translit([$1], [a-z], [A-Z]), [\w+],
|
||||
[AC_DEFINE([HAVE_DECL_\&], 1,
|
||||
[Define to 1 if we found this declaration otherwise define to 0.])])dnl
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# Add --enable-maintainer-mode option to configure.
|
||||
# From Jim Meyering
|
||||
|
||||
|
|
|
|||
2642
contrib/gdb/gdb/ada-exp.c
Normal file
2642
contrib/gdb/gdb/ada-exp.c
Normal file
File diff suppressed because it is too large
Load diff
969
contrib/gdb/gdb/ada-exp.y
Normal file
969
contrib/gdb/gdb/ada-exp.y
Normal file
|
|
@ -0,0 +1,969 @@
|
|||
/* YACC parser for Ada expressions, for GDB.
|
||||
Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Parse an Ada expression from text in a string,
|
||||
and return the result as a struct expression pointer.
|
||||
That structure contains arithmetic operations in reverse polish,
|
||||
with constants represented by operations that are followed by special data.
|
||||
See expression.h for the details of the format.
|
||||
What is important here is that it can be built up sequentially
|
||||
during the process of parsing; the lower levels of the tree always
|
||||
come first in the result.
|
||||
|
||||
malloc's and realloc's in this file are transformed to
|
||||
xmalloc and xrealloc respectively by the same sed command in the
|
||||
makefile that remaps any other malloc/realloc inserted by the parser
|
||||
generator. Doing this with #defines and trying to control the interaction
|
||||
with include files (<malloc.h> and <stdlib.h> for example) just became
|
||||
too messy, particularly when such includes can be inserted at random
|
||||
times by the parser generator. */
|
||||
|
||||
%{
|
||||
|
||||
#include "defs.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "ada-lang.h"
|
||||
#include "bfd.h" /* Required by objfiles.h. */
|
||||
#include "symfile.h" /* Required by objfiles.h. */
|
||||
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
|
||||
#include "frame.h"
|
||||
#include "block.h"
|
||||
|
||||
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
|
||||
as well as gratuitiously global symbol names, so we can have multiple
|
||||
yacc generated parsers in gdb. These are only the variables
|
||||
produced by yacc. If other parser generators (bison, byacc, etc) produce
|
||||
additional global names that conflict at link time, then those parser
|
||||
generators need to be fixed instead of adding those names to this list. */
|
||||
|
||||
/* NOTE: This is clumsy, especially since BISON and FLEX provide --prefix
|
||||
options. I presume we are maintaining it to accommodate systems
|
||||
without BISON? (PNH) */
|
||||
|
||||
#define yymaxdepth ada_maxdepth
|
||||
#define yyparse _ada_parse /* ada_parse calls this after initialization */
|
||||
#define yylex ada_lex
|
||||
#define yyerror ada_error
|
||||
#define yylval ada_lval
|
||||
#define yychar ada_char
|
||||
#define yydebug ada_debug
|
||||
#define yypact ada_pact
|
||||
#define yyr1 ada_r1
|
||||
#define yyr2 ada_r2
|
||||
#define yydef ada_def
|
||||
#define yychk ada_chk
|
||||
#define yypgo ada_pgo
|
||||
#define yyact ada_act
|
||||
#define yyexca ada_exca
|
||||
#define yyerrflag ada_errflag
|
||||
#define yynerrs ada_nerrs
|
||||
#define yyps ada_ps
|
||||
#define yypv ada_pv
|
||||
#define yys ada_s
|
||||
#define yy_yys ada_yys
|
||||
#define yystate ada_state
|
||||
#define yytmp ada_tmp
|
||||
#define yyv ada_v
|
||||
#define yy_yyv ada_yyv
|
||||
#define yyval ada_val
|
||||
#define yylloc ada_lloc
|
||||
#define yyreds ada_reds /* With YYDEBUG defined */
|
||||
#define yytoks ada_toks /* With YYDEBUG defined */
|
||||
#define yyname ada_name /* With YYDEBUG defined */
|
||||
#define yyrule ada_rule /* With YYDEBUG defined */
|
||||
|
||||
#ifndef YYDEBUG
|
||||
#define YYDEBUG 1 /* Default to yydebug support */
|
||||
#endif
|
||||
|
||||
#define YYFPRINTF parser_fprintf
|
||||
|
||||
struct name_info {
|
||||
struct symbol* sym;
|
||||
struct minimal_symbol* msym;
|
||||
struct block* block;
|
||||
struct stoken stoken;
|
||||
};
|
||||
|
||||
/* If expression is in the context of TYPE'(...), then TYPE, else
|
||||
* NULL. */
|
||||
static struct type* type_qualifier;
|
||||
|
||||
int yyparse (void);
|
||||
|
||||
static int yylex (void);
|
||||
|
||||
void yyerror (char *);
|
||||
|
||||
static struct stoken string_to_operator (struct stoken);
|
||||
|
||||
static void write_attribute_call0 (enum ada_attribute);
|
||||
|
||||
static void write_attribute_call1 (enum ada_attribute, LONGEST);
|
||||
|
||||
static void write_attribute_calln (enum ada_attribute, int);
|
||||
|
||||
static void write_object_renaming (struct block*, struct symbol*);
|
||||
|
||||
static void write_var_from_name (struct block*, struct name_info);
|
||||
|
||||
static LONGEST
|
||||
convert_char_literal (struct type*, LONGEST);
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
LONGEST lval;
|
||||
struct {
|
||||
LONGEST val;
|
||||
struct type *type;
|
||||
} typed_val;
|
||||
struct {
|
||||
DOUBLEST dval;
|
||||
struct type *type;
|
||||
} typed_val_float;
|
||||
struct type *tval;
|
||||
struct stoken sval;
|
||||
struct name_info ssym;
|
||||
int voidval;
|
||||
struct block *bval;
|
||||
struct internalvar *ivar;
|
||||
|
||||
}
|
||||
|
||||
%type <voidval> exp exp1 simple_exp start variable
|
||||
%type <tval> type
|
||||
|
||||
%token <typed_val> INT NULL_PTR CHARLIT
|
||||
%token <typed_val_float> FLOAT
|
||||
%token <tval> TYPENAME
|
||||
%token <bval> BLOCKNAME
|
||||
|
||||
/* Both NAME and TYPENAME tokens represent symbols in the input,
|
||||
and both convey their data as strings.
|
||||
But a TYPENAME is a string that happens to be defined as a typedef
|
||||
or builtin type name (such as int or char)
|
||||
and a NAME is any other symbol.
|
||||
Contexts where this distinction is not important can use the
|
||||
nonterminal "name", which matches either NAME or TYPENAME. */
|
||||
|
||||
%token <sval> STRING
|
||||
%token <ssym> NAME DOT_ID OBJECT_RENAMING
|
||||
%type <bval> block
|
||||
%type <lval> arglist tick_arglist
|
||||
|
||||
%type <tval> save_qualifier
|
||||
|
||||
%token DOT_ALL
|
||||
|
||||
/* Special type cases, put in to allow the parser to distinguish different
|
||||
legal basetypes. */
|
||||
%token <lval> LAST REGNAME
|
||||
|
||||
%token <ivar> INTERNAL_VARIABLE
|
||||
|
||||
%nonassoc ASSIGN
|
||||
%left _AND_ OR XOR THEN ELSE
|
||||
%left '=' NOTEQUAL '<' '>' LEQ GEQ IN DOTDOT
|
||||
%left '@'
|
||||
%left '+' '-' '&'
|
||||
%left UNARY
|
||||
%left '*' '/' MOD REM
|
||||
%right STARSTAR ABS NOT
|
||||
/* The following are right-associative only so that reductions at this
|
||||
precedence have lower precedence than '.' and '('. The syntax still
|
||||
forces a.b.c, e.g., to be LEFT-associated. */
|
||||
%right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
|
||||
%right TICK_MAX TICK_MIN TICK_MODULUS
|
||||
%right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
|
||||
%right '.' '(' '[' DOT_ID DOT_ALL
|
||||
|
||||
%token ARROW NEW
|
||||
|
||||
|
||||
%%
|
||||
|
||||
start : exp1
|
||||
| type { write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
/* Expressions, including the sequencing operator. */
|
||||
exp1 : exp
|
||||
| exp1 ';' exp
|
||||
{ write_exp_elt_opcode (BINOP_COMMA); }
|
||||
;
|
||||
|
||||
/* Expressions, not including the sequencing operator. */
|
||||
simple_exp : simple_exp DOT_ALL
|
||||
{ write_exp_elt_opcode (UNOP_IND); }
|
||||
;
|
||||
|
||||
simple_exp : simple_exp DOT_ID
|
||||
{ write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
write_exp_string ($2.stoken);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : simple_exp '(' arglist ')'
|
||||
{
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
write_exp_elt_longcst ($3);
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : type '(' exp ')'
|
||||
{
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp : type '\'' save_qualifier { type_qualifier = $1; } '(' exp ')'
|
||||
{
|
||||
/* write_exp_elt_opcode (UNOP_QUAL); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
write_exp_elt_type ($1);
|
||||
/* write_exp_elt_opcode (UNOP_QUAL); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
type_qualifier = $3;
|
||||
}
|
||||
;
|
||||
|
||||
save_qualifier : { $$ = type_qualifier; }
|
||||
;
|
||||
|
||||
simple_exp :
|
||||
simple_exp '(' exp DOTDOT exp ')'
|
||||
{ write_exp_elt_opcode (TERNOP_SLICE); }
|
||||
;
|
||||
|
||||
simple_exp : '(' exp1 ')' { }
|
||||
;
|
||||
|
||||
simple_exp : variable
|
||||
;
|
||||
|
||||
simple_exp: REGNAME /* GDB extension */
|
||||
{ write_exp_elt_opcode (OP_REGISTER);
|
||||
write_exp_elt_longcst ((LONGEST) $1);
|
||||
write_exp_elt_opcode (OP_REGISTER);
|
||||
}
|
||||
;
|
||||
|
||||
simple_exp: INTERNAL_VARIABLE /* GDB extension */
|
||||
{ write_exp_elt_opcode (OP_INTERNALVAR);
|
||||
write_exp_elt_intern ($1);
|
||||
write_exp_elt_opcode (OP_INTERNALVAR);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
exp : simple_exp
|
||||
;
|
||||
|
||||
simple_exp: LAST
|
||||
{ write_exp_elt_opcode (OP_LAST);
|
||||
write_exp_elt_longcst ((LONGEST) $1);
|
||||
write_exp_elt_opcode (OP_LAST);
|
||||
}
|
||||
;
|
||||
|
||||
exp : exp ASSIGN exp /* Extension for convenience */
|
||||
{ write_exp_elt_opcode (BINOP_ASSIGN); }
|
||||
;
|
||||
|
||||
exp : '-' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_NEG); }
|
||||
;
|
||||
|
||||
exp : '+' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_PLUS); }
|
||||
;
|
||||
|
||||
exp : NOT exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
|
||||
;
|
||||
|
||||
exp : ABS exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_ABS); }
|
||||
;
|
||||
|
||||
arglist : { $$ = 0; }
|
||||
;
|
||||
|
||||
arglist : exp
|
||||
{ $$ = 1; }
|
||||
| any_name ARROW exp
|
||||
{ $$ = 1; }
|
||||
| arglist ',' exp
|
||||
{ $$ = $1 + 1; }
|
||||
| arglist ',' any_name ARROW exp
|
||||
{ $$ = $1 + 1; }
|
||||
;
|
||||
|
||||
exp : '{' type '}' exp %prec '.'
|
||||
/* GDB extension */
|
||||
{ write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
write_exp_elt_type ($2);
|
||||
write_exp_elt_opcode (UNOP_MEMVAL);
|
||||
}
|
||||
;
|
||||
|
||||
/* Binary operators in order of decreasing precedence. */
|
||||
|
||||
exp : exp STARSTAR exp
|
||||
{ write_exp_elt_opcode (BINOP_EXP); }
|
||||
;
|
||||
|
||||
exp : exp '*' exp
|
||||
{ write_exp_elt_opcode (BINOP_MUL); }
|
||||
;
|
||||
|
||||
exp : exp '/' exp
|
||||
{ write_exp_elt_opcode (BINOP_DIV); }
|
||||
;
|
||||
|
||||
exp : exp REM exp /* May need to be fixed to give correct Ada REM */
|
||||
{ write_exp_elt_opcode (BINOP_REM); }
|
||||
;
|
||||
|
||||
exp : exp MOD exp
|
||||
{ write_exp_elt_opcode (BINOP_MOD); }
|
||||
;
|
||||
|
||||
exp : exp '@' exp /* GDB extension */
|
||||
{ write_exp_elt_opcode (BINOP_REPEAT); }
|
||||
;
|
||||
|
||||
exp : exp '+' exp
|
||||
{ write_exp_elt_opcode (BINOP_ADD); }
|
||||
;
|
||||
|
||||
exp : exp '&' exp
|
||||
{ write_exp_elt_opcode (BINOP_CONCAT); }
|
||||
;
|
||||
|
||||
exp : exp '-' exp
|
||||
{ write_exp_elt_opcode (BINOP_SUB); }
|
||||
;
|
||||
|
||||
exp : exp '=' exp
|
||||
{ write_exp_elt_opcode (BINOP_EQUAL); }
|
||||
;
|
||||
|
||||
exp : exp NOTEQUAL exp
|
||||
{ write_exp_elt_opcode (BINOP_NOTEQUAL); }
|
||||
;
|
||||
|
||||
exp : exp LEQ exp
|
||||
{ write_exp_elt_opcode (BINOP_LEQ); }
|
||||
;
|
||||
|
||||
exp : exp IN exp DOTDOT exp
|
||||
{ /*write_exp_elt_opcode (TERNOP_MBR); */ }
|
||||
/* FIXME: TERNOP_MBR should be defined in
|
||||
expression.h */
|
||||
| exp IN exp TICK_RANGE tick_arglist
|
||||
{ /*write_exp_elt_opcode (BINOP_MBR); */
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) $5);
|
||||
/*write_exp_elt_opcode (BINOP_MBR); */
|
||||
}
|
||||
| exp IN TYPENAME %prec TICK_ACCESS
|
||||
{ /*write_exp_elt_opcode (UNOP_MBR); */
|
||||
/* FIXME: UNOP_QUAL should be defined in expression.h */
|
||||
write_exp_elt_type ($3);
|
||||
/* write_exp_elt_opcode (UNOP_MBR); */
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
}
|
||||
| exp NOT IN exp DOTDOT exp
|
||||
{ /*write_exp_elt_opcode (TERNOP_MBR); */
|
||||
/* FIXME: TERNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
| exp NOT IN exp TICK_RANGE tick_arglist
|
||||
{ /* write_exp_elt_opcode (BINOP_MBR); */
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) $6);
|
||||
/*write_exp_elt_opcode (BINOP_MBR);*/
|
||||
/* FIXME: BINOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
| exp NOT IN TYPENAME %prec TICK_ACCESS
|
||||
{ /*write_exp_elt_opcode (UNOP_MBR);*/
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_type ($4);
|
||||
/* write_exp_elt_opcode (UNOP_MBR);*/
|
||||
/* FIXME: UNOP_MBR should be defined in expression.h */
|
||||
write_exp_elt_opcode (UNOP_LOGICAL_NOT);
|
||||
}
|
||||
;
|
||||
|
||||
exp : exp GEQ exp
|
||||
{ write_exp_elt_opcode (BINOP_GEQ); }
|
||||
;
|
||||
|
||||
exp : exp '<' exp
|
||||
{ write_exp_elt_opcode (BINOP_LESS); }
|
||||
;
|
||||
|
||||
exp : exp '>' exp
|
||||
{ write_exp_elt_opcode (BINOP_GTR); }
|
||||
;
|
||||
|
||||
exp : exp _AND_ exp /* Fix for Ada elementwise AND. */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_AND); }
|
||||
;
|
||||
|
||||
exp : exp _AND_ THEN exp %prec _AND_
|
||||
{ write_exp_elt_opcode (BINOP_LOGICAL_AND); }
|
||||
;
|
||||
|
||||
exp : exp OR exp /* Fix for Ada elementwise OR */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_IOR); }
|
||||
;
|
||||
|
||||
exp : exp OR ELSE exp
|
||||
{ write_exp_elt_opcode (BINOP_LOGICAL_OR); }
|
||||
;
|
||||
|
||||
exp : exp XOR exp /* Fix for Ada elementwise XOR */
|
||||
{ write_exp_elt_opcode (BINOP_BITWISE_XOR); }
|
||||
;
|
||||
|
||||
simple_exp : simple_exp TICK_ACCESS
|
||||
{ write_exp_elt_opcode (UNOP_ADDR); }
|
||||
| simple_exp TICK_ADDRESS
|
||||
{ write_exp_elt_opcode (UNOP_ADDR);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
write_exp_elt_type (builtin_type_ada_system_address);
|
||||
write_exp_elt_opcode (UNOP_CAST);
|
||||
}
|
||||
| simple_exp TICK_FIRST tick_arglist
|
||||
{ write_attribute_call1 (ATR_FIRST, $3); }
|
||||
| simple_exp TICK_LAST tick_arglist
|
||||
{ write_attribute_call1 (ATR_LAST, $3); }
|
||||
| simple_exp TICK_LENGTH tick_arglist
|
||||
{ write_attribute_call1 (ATR_LENGTH, $3); }
|
||||
| simple_exp TICK_SIZE
|
||||
{ write_attribute_call0 (ATR_SIZE); }
|
||||
| simple_exp TICK_TAG
|
||||
{ write_attribute_call0 (ATR_TAG); }
|
||||
| opt_type_prefix TICK_MIN '(' exp ',' exp ')'
|
||||
{ write_attribute_calln (ATR_MIN, 2); }
|
||||
| opt_type_prefix TICK_MAX '(' exp ',' exp ')'
|
||||
{ write_attribute_calln (ATR_MAX, 2); }
|
||||
| opt_type_prefix TICK_POS '(' exp ')'
|
||||
{ write_attribute_calln (ATR_POS, 1); }
|
||||
| type_prefix TICK_FIRST tick_arglist
|
||||
{ write_attribute_call1 (ATR_FIRST, $3); }
|
||||
| type_prefix TICK_LAST tick_arglist
|
||||
{ write_attribute_call1 (ATR_LAST, $3); }
|
||||
| type_prefix TICK_LENGTH tick_arglist
|
||||
{ write_attribute_call1 (ATR_LENGTH, $3); }
|
||||
| type_prefix TICK_VAL '(' exp ')'
|
||||
{ write_attribute_calln (ATR_VAL, 1); }
|
||||
| type_prefix TICK_MODULUS
|
||||
{ write_attribute_call0 (ATR_MODULUS); }
|
||||
;
|
||||
|
||||
tick_arglist : %prec '('
|
||||
{ $$ = 1; }
|
||||
| '(' INT ')'
|
||||
{ $$ = $2.val; }
|
||||
;
|
||||
|
||||
type_prefix :
|
||||
TYPENAME
|
||||
{ write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type ($1);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
opt_type_prefix :
|
||||
type_prefix
|
||||
| /* EMPTY */
|
||||
{ write_exp_elt_opcode (OP_TYPE);
|
||||
write_exp_elt_type (builtin_type_void);
|
||||
write_exp_elt_opcode (OP_TYPE); }
|
||||
;
|
||||
|
||||
|
||||
exp : INT
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type ($1.type);
|
||||
write_exp_elt_longcst ((LONGEST)($1.val));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
;
|
||||
|
||||
exp : CHARLIT
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
if (type_qualifier == NULL)
|
||||
write_exp_elt_type ($1.type);
|
||||
else
|
||||
write_exp_elt_type (type_qualifier);
|
||||
write_exp_elt_longcst
|
||||
(convert_char_literal (type_qualifier, $1.val));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
;
|
||||
|
||||
exp : FLOAT
|
||||
{ write_exp_elt_opcode (OP_DOUBLE);
|
||||
write_exp_elt_type ($1.type);
|
||||
write_exp_elt_dblcst ($1.dval);
|
||||
write_exp_elt_opcode (OP_DOUBLE);
|
||||
}
|
||||
;
|
||||
|
||||
exp : NULL_PTR
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst ((LONGEST)(0));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
;
|
||||
|
||||
exp : STRING
|
||||
{ /* Ada strings are converted into array constants
|
||||
a lower bound of 1. Thus, the array upper bound
|
||||
is the string length. */
|
||||
char *sp = $1.ptr; int count;
|
||||
if ($1.length == 0)
|
||||
{ /* One dummy character for the type */
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_char);
|
||||
write_exp_elt_longcst ((LONGEST)(0));
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
for (count = $1.length; count > 0; count -= 1)
|
||||
{
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_char);
|
||||
write_exp_elt_longcst ((LONGEST)(*sp));
|
||||
sp += 1;
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
write_exp_elt_opcode (OP_ARRAY);
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_longcst ((LONGEST) ($1.length));
|
||||
write_exp_elt_opcode (OP_ARRAY);
|
||||
}
|
||||
;
|
||||
|
||||
exp : NEW TYPENAME
|
||||
{ error ("NEW not implemented."); }
|
||||
;
|
||||
|
||||
variable: NAME { write_var_from_name (NULL, $1); }
|
||||
| block NAME /* GDB extension */
|
||||
{ write_var_from_name ($1, $2); }
|
||||
| OBJECT_RENAMING { write_object_renaming (NULL, $1.sym); }
|
||||
| block OBJECT_RENAMING
|
||||
{ write_object_renaming ($1, $2.sym); }
|
||||
;
|
||||
|
||||
any_name : NAME { }
|
||||
| TYPENAME { }
|
||||
| OBJECT_RENAMING { }
|
||||
;
|
||||
|
||||
block : BLOCKNAME /* GDB extension */
|
||||
{ $$ = $1; }
|
||||
| block BLOCKNAME /* GDB extension */
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
|
||||
type : TYPENAME { $$ = $1; }
|
||||
| block TYPENAME { $$ = $2; }
|
||||
| TYPENAME TICK_ACCESS
|
||||
{ $$ = lookup_pointer_type ($1); }
|
||||
| block TYPENAME TICK_ACCESS
|
||||
{ $$ = lookup_pointer_type ($2); }
|
||||
;
|
||||
|
||||
/* Some extensions borrowed from C, for the benefit of those who find they
|
||||
can't get used to Ada notation in GDB. */
|
||||
|
||||
exp : '*' exp %prec '.'
|
||||
{ write_exp_elt_opcode (UNOP_IND); }
|
||||
| '&' exp %prec '.'
|
||||
{ write_exp_elt_opcode (UNOP_ADDR); }
|
||||
| exp '[' exp ']'
|
||||
{ write_exp_elt_opcode (BINOP_SUBSCRIPT); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* yylex defined in ada-lex.c: Reads one token, getting characters */
|
||||
/* through lexptr. */
|
||||
|
||||
/* Remap normal flex interface names (yylex) as well as gratuitiously */
|
||||
/* global symbol names, so we can have multiple flex-generated parsers */
|
||||
/* in gdb. */
|
||||
|
||||
/* (See note above on previous definitions for YACC.) */
|
||||
|
||||
#define yy_create_buffer ada_yy_create_buffer
|
||||
#define yy_delete_buffer ada_yy_delete_buffer
|
||||
#define yy_init_buffer ada_yy_init_buffer
|
||||
#define yy_load_buffer_state ada_yy_load_buffer_state
|
||||
#define yy_switch_to_buffer ada_yy_switch_to_buffer
|
||||
#define yyrestart ada_yyrestart
|
||||
#define yytext ada_yytext
|
||||
#define yywrap ada_yywrap
|
||||
|
||||
/* The following kludge was found necessary to prevent conflicts between */
|
||||
/* defs.h and non-standard stdlib.h files. */
|
||||
#define qsort __qsort__dummy
|
||||
#include "ada-lex.c"
|
||||
|
||||
int
|
||||
ada_parse ()
|
||||
{
|
||||
lexer_init (yyin); /* (Re-)initialize lexer. */
|
||||
left_block_context = NULL;
|
||||
type_qualifier = NULL;
|
||||
|
||||
return _ada_parse ();
|
||||
}
|
||||
|
||||
void
|
||||
yyerror (msg)
|
||||
char *msg;
|
||||
{
|
||||
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
|
||||
}
|
||||
|
||||
/* The operator name corresponding to operator symbol STRING (adds
|
||||
quotes and maps to lower-case). Destroys the previous contents of
|
||||
the array pointed to by STRING.ptr. Error if STRING does not match
|
||||
a valid Ada operator. Assumes that STRING.ptr points to a
|
||||
null-terminated string and that, if STRING is a valid operator
|
||||
symbol, the array pointed to by STRING.ptr contains at least
|
||||
STRING.length+3 characters. */
|
||||
|
||||
static struct stoken
|
||||
string_to_operator (string)
|
||||
struct stoken string;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
|
||||
{
|
||||
if (string.length == strlen (ada_opname_table[i].demangled)-2
|
||||
&& strncasecmp (string.ptr, ada_opname_table[i].demangled+1,
|
||||
string.length) == 0)
|
||||
{
|
||||
strncpy (string.ptr, ada_opname_table[i].demangled,
|
||||
string.length+2);
|
||||
string.length += 2;
|
||||
return string;
|
||||
}
|
||||
}
|
||||
error ("Invalid operator symbol `%s'", string.ptr);
|
||||
}
|
||||
|
||||
/* Emit expression to access an instance of SYM, in block BLOCK (if
|
||||
* non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
|
||||
static void
|
||||
write_var_from_sym (orig_left_context, block, sym)
|
||||
struct block* orig_left_context;
|
||||
struct block* block;
|
||||
struct symbol* sym;
|
||||
{
|
||||
if (orig_left_context == NULL && symbol_read_needs_frame (sym))
|
||||
{
|
||||
if (innermost_block == 0 ||
|
||||
contained_in (block, innermost_block))
|
||||
innermost_block = block;
|
||||
}
|
||||
|
||||
write_exp_elt_opcode (OP_VAR_VALUE);
|
||||
/* We want to use the selected frame, not another more inner frame
|
||||
which happens to be in the same block */
|
||||
write_exp_elt_block (NULL);
|
||||
write_exp_elt_sym (sym);
|
||||
write_exp_elt_opcode (OP_VAR_VALUE);
|
||||
}
|
||||
|
||||
/* Emit expression to access an instance of NAME. */
|
||||
static void
|
||||
write_var_from_name (orig_left_context, name)
|
||||
struct block* orig_left_context;
|
||||
struct name_info name;
|
||||
{
|
||||
if (name.msym != NULL)
|
||||
{
|
||||
write_exp_msymbol (name.msym,
|
||||
lookup_function_type (builtin_type_int),
|
||||
builtin_type_int);
|
||||
}
|
||||
else if (name.sym == NULL)
|
||||
{
|
||||
/* Multiple matches: record name and starting block for later
|
||||
resolution by ada_resolve. */
|
||||
/* write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
|
||||
/* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */
|
||||
write_exp_elt_block (name.block);
|
||||
/* write_exp_elt_name (name.stoken.ptr); */
|
||||
/* FIXME: write_exp_elt_name should be defined in defs.h, located in parse.c */
|
||||
/* write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
|
||||
/* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */
|
||||
}
|
||||
else
|
||||
write_var_from_sym (orig_left_context, name.block, name.sym);
|
||||
}
|
||||
|
||||
/* Write a call on parameterless attribute ATR. */
|
||||
|
||||
static void
|
||||
write_attribute_call0 (atr)
|
||||
enum ada_attribute atr;
|
||||
{
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE); */
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) 0);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE); */
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Write a call on an attribute ATR with one constant integer
|
||||
* parameter. */
|
||||
|
||||
static void
|
||||
write_attribute_call1 (atr, arg)
|
||||
enum ada_attribute atr;
|
||||
LONGEST arg;
|
||||
{
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_int);
|
||||
write_exp_elt_longcst (arg);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Write a call on an attribute ATR with N parameters, whose code must have
|
||||
* been generated previously. */
|
||||
|
||||
static void
|
||||
write_attribute_calln (atr, n)
|
||||
enum ada_attribute atr;
|
||||
int n;
|
||||
{
|
||||
/*write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
write_exp_elt_longcst ((LONGEST) n);
|
||||
write_exp_elt_longcst ((LONGEST) atr);
|
||||
/* write_exp_elt_opcode (OP_ATTRIBUTE);*/
|
||||
/* FIXME: OP_ATTRIBUTE should be defined in expression.h */
|
||||
}
|
||||
|
||||
/* Emit expression corresponding to the renamed object designated by
|
||||
* the type RENAMING, which must be the referent of an object renaming
|
||||
* type, in the context of ORIG_LEFT_CONTEXT (?). */
|
||||
static void
|
||||
write_object_renaming (orig_left_context, renaming)
|
||||
struct block* orig_left_context;
|
||||
struct symbol* renaming;
|
||||
{
|
||||
const char* qualification = DEPRECATED_SYMBOL_NAME (renaming);
|
||||
const char* simple_tail;
|
||||
const char* expr = TYPE_FIELD_NAME (SYMBOL_TYPE (renaming), 0);
|
||||
const char* suffix;
|
||||
char* name;
|
||||
struct symbol* sym;
|
||||
enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
|
||||
|
||||
/* if orig_left_context is null, then use the currently selected
|
||||
block, otherwise we might fail our symbol lookup below */
|
||||
if (orig_left_context == NULL)
|
||||
orig_left_context = get_selected_block (NULL);
|
||||
|
||||
for (simple_tail = qualification + strlen (qualification);
|
||||
simple_tail != qualification; simple_tail -= 1)
|
||||
{
|
||||
if (*simple_tail == '.')
|
||||
{
|
||||
simple_tail += 1;
|
||||
break;
|
||||
}
|
||||
else if (DEPRECATED_STREQN (simple_tail, "__", 2))
|
||||
{
|
||||
simple_tail += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
suffix = strstr (expr, "___XE");
|
||||
if (suffix == NULL)
|
||||
goto BadEncoding;
|
||||
|
||||
name = (char*) malloc (suffix - expr + 1);
|
||||
/* add_name_string_cleanup (name); */
|
||||
/* FIXME: add_name_string_cleanup should be defined in
|
||||
parser-defs.h, implemented in parse.c */
|
||||
strncpy (name, expr, suffix-expr);
|
||||
name[suffix-expr] = '\000';
|
||||
sym = lookup_symbol (name, orig_left_context, VAR_DOMAIN, 0, NULL);
|
||||
/* if (sym == NULL)
|
||||
error ("Could not find renamed variable: %s", ada_demangle (name));
|
||||
*/
|
||||
/* FIXME: ada_demangle should be defined in defs.h, implemented in ada-lang.c */
|
||||
write_var_from_sym (orig_left_context, block_found, sym);
|
||||
|
||||
suffix += 5;
|
||||
slice_state = SIMPLE_INDEX;
|
||||
while (*suffix == 'X')
|
||||
{
|
||||
suffix += 1;
|
||||
|
||||
switch (*suffix) {
|
||||
case 'L':
|
||||
slice_state = LOWER_BOUND;
|
||||
case 'S':
|
||||
suffix += 1;
|
||||
if (isdigit (*suffix))
|
||||
{
|
||||
char* next;
|
||||
long val = strtol (suffix, &next, 10);
|
||||
if (next == suffix)
|
||||
goto BadEncoding;
|
||||
suffix = next;
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_ada_int);
|
||||
write_exp_elt_longcst ((LONGEST) val);
|
||||
write_exp_elt_opcode (OP_LONG);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* end;
|
||||
char* index_name;
|
||||
int index_len;
|
||||
struct symbol* index_sym;
|
||||
|
||||
end = strchr (suffix, 'X');
|
||||
if (end == NULL)
|
||||
end = suffix + strlen (suffix);
|
||||
|
||||
index_len = simple_tail - qualification + 2 + (suffix - end) + 1;
|
||||
index_name = (char*) malloc (index_len);
|
||||
memset (index_name, '\000', index_len);
|
||||
/* add_name_string_cleanup (index_name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in
|
||||
parser-defs.h, implemented in parse.c */
|
||||
strncpy (index_name, qualification, simple_tail - qualification);
|
||||
index_name[simple_tail - qualification] = '\000';
|
||||
strncat (index_name, suffix, suffix-end);
|
||||
suffix = end;
|
||||
|
||||
index_sym =
|
||||
lookup_symbol (index_name, NULL, VAR_DOMAIN, 0, NULL);
|
||||
if (index_sym == NULL)
|
||||
error ("Could not find %s", index_name);
|
||||
write_var_from_sym (NULL, block_found, sym);
|
||||
}
|
||||
if (slice_state == SIMPLE_INDEX)
|
||||
{
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
write_exp_elt_longcst ((LONGEST) 1);
|
||||
write_exp_elt_opcode (OP_FUNCALL);
|
||||
}
|
||||
else if (slice_state == LOWER_BOUND)
|
||||
slice_state = UPPER_BOUND;
|
||||
else if (slice_state == UPPER_BOUND)
|
||||
{
|
||||
write_exp_elt_opcode (TERNOP_SLICE);
|
||||
slice_state = SIMPLE_INDEX;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
{
|
||||
struct stoken field_name;
|
||||
const char* end;
|
||||
suffix += 1;
|
||||
|
||||
if (slice_state != SIMPLE_INDEX)
|
||||
goto BadEncoding;
|
||||
end = strchr (suffix, 'X');
|
||||
if (end == NULL)
|
||||
end = suffix + strlen (suffix);
|
||||
field_name.length = end - suffix;
|
||||
field_name.ptr = (char*) malloc (end - suffix + 1);
|
||||
strncpy (field_name.ptr, suffix, end - suffix);
|
||||
field_name.ptr[end - suffix] = '\000';
|
||||
suffix = end;
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
write_exp_string (field_name);
|
||||
write_exp_elt_opcode (STRUCTOP_STRUCT);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
goto BadEncoding;
|
||||
}
|
||||
}
|
||||
if (slice_state == SIMPLE_INDEX)
|
||||
return;
|
||||
|
||||
BadEncoding:
|
||||
error ("Internal error in encoding of renaming declaration: %s",
|
||||
DEPRECATED_SYMBOL_NAME (renaming));
|
||||
}
|
||||
|
||||
/* Convert the character literal whose ASCII value would be VAL to the
|
||||
appropriate value of type TYPE, if there is a translation.
|
||||
Otherwise return VAL. Hence, in an enumeration type ('A', 'B'),
|
||||
the literal 'A' (VAL == 65), returns 0. */
|
||||
static LONGEST
|
||||
convert_char_literal (struct type* type, LONGEST val)
|
||||
{
|
||||
char name[7];
|
||||
int f;
|
||||
|
||||
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
|
||||
return val;
|
||||
sprintf (name, "QU%02x", (int) val);
|
||||
for (f = 0; f < TYPE_NFIELDS (type); f += 1)
|
||||
{
|
||||
if (DEPRECATED_STREQ (name, TYPE_FIELD_NAME (type, f)))
|
||||
return TYPE_FIELD_BITPOS (type, f);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
8254
contrib/gdb/gdb/ada-lang.c
Normal file
8254
contrib/gdb/gdb/ada-lang.c
Normal file
File diff suppressed because it is too large
Load diff
392
contrib/gdb/gdb/ada-lang.h
Normal file
392
contrib/gdb/gdb/ada-lang.h
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
/* Ada language support definitions for GDB, the GNU debugger.
|
||||
Copyright 1992, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#if !defined (ADA_LANG_H)
|
||||
#define ADA_LANG_H 1
|
||||
|
||||
struct partial_symbol;
|
||||
|
||||
#include "value.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
struct block;
|
||||
|
||||
/* A macro to reorder the bytes of an address depending on the
|
||||
endiannes of the target. */
|
||||
#define EXTRACT_ADDRESS(x) ((void *) extract_unsigned_integer (&(x), sizeof (x)))
|
||||
/* A macro to reorder the bytes of an int depending on the endiannes
|
||||
of the target */
|
||||
#define EXTRACT_INT(x) ((int) extract_signed_integer (&(x), sizeof (x)))
|
||||
|
||||
/* Chain of cleanups for arguments of OP_UNRESOLVED_VALUE names. Created in
|
||||
yyparse and freed in ada_resolve. */
|
||||
extern struct cleanup *unresolved_names;
|
||||
|
||||
/* Corresponding mangled/demangled names and opcodes for Ada user-definable
|
||||
operators. */
|
||||
struct ada_opname_map
|
||||
{
|
||||
const char *mangled;
|
||||
const char *demangled;
|
||||
enum exp_opcode op;
|
||||
};
|
||||
|
||||
/* Table of Ada operators in mangled and demangled forms. */
|
||||
/* Defined in ada-lang.c */
|
||||
extern const struct ada_opname_map ada_opname_table[];
|
||||
|
||||
/* The maximum number of tasks known to the Ada runtime */
|
||||
extern const int MAX_NUMBER_OF_KNOWN_TASKS;
|
||||
|
||||
/* Identifiers for Ada attributes that need special processing. Be sure
|
||||
to update the table attribute_names in ada-lang.c whenever you change this.
|
||||
*/
|
||||
|
||||
enum ada_attribute
|
||||
{
|
||||
/* Invalid attribute for error checking. */
|
||||
ATR_INVALID,
|
||||
|
||||
ATR_FIRST,
|
||||
ATR_LAST,
|
||||
ATR_LENGTH,
|
||||
ATR_IMAGE,
|
||||
ATR_IMG,
|
||||
ATR_MAX,
|
||||
ATR_MIN,
|
||||
ATR_MODULUS,
|
||||
ATR_POS,
|
||||
ATR_SIZE,
|
||||
ATR_TAG,
|
||||
ATR_VAL,
|
||||
|
||||
/* Dummy last attribute. */
|
||||
ATR_END
|
||||
};
|
||||
|
||||
enum task_states
|
||||
{
|
||||
Unactivated,
|
||||
Runnable,
|
||||
Terminated,
|
||||
Activator_Sleep,
|
||||
Acceptor_Sleep,
|
||||
Entry_Caller_Sleep,
|
||||
Async_Select_Sleep,
|
||||
Delay_Sleep,
|
||||
Master_Completion_Sleep,
|
||||
Master_Phase_2_Sleep
|
||||
};
|
||||
|
||||
extern char *ada_task_states[];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *P_ARRAY;
|
||||
int *P_BOUNDS;
|
||||
}
|
||||
fat_string;
|
||||
|
||||
typedef struct entry_call
|
||||
{
|
||||
void *self;
|
||||
}
|
||||
*entry_call_link;
|
||||
|
||||
struct task_fields
|
||||
{
|
||||
int entry_num;
|
||||
#if (defined (VXWORKS_TARGET) || !defined (i386)) \
|
||||
&& !(defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
int pad1;
|
||||
#endif
|
||||
char state;
|
||||
#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
char pad_8bits;
|
||||
#endif
|
||||
void *parent;
|
||||
int priority;
|
||||
int current_priority;
|
||||
fat_string image;
|
||||
entry_call_link call;
|
||||
#if (defined (sun) && defined (__SVR4)) && !defined (VXWORKS_TARGET)
|
||||
int pad2;
|
||||
unsigned thread;
|
||||
unsigned lwp;
|
||||
#else
|
||||
void *thread;
|
||||
void *lwp;
|
||||
#endif
|
||||
}
|
||||
#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
|
||||
__attribute__ ((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct task_entry
|
||||
{
|
||||
void *task_id;
|
||||
int task_num;
|
||||
int known_tasks_index;
|
||||
struct task_entry *next_task;
|
||||
void *thread;
|
||||
void *lwp;
|
||||
int stack_per;
|
||||
};
|
||||
|
||||
extern struct type *builtin_type_ada_int;
|
||||
extern struct type *builtin_type_ada_short;
|
||||
extern struct type *builtin_type_ada_long;
|
||||
extern struct type *builtin_type_ada_long_long;
|
||||
extern struct type *builtin_type_ada_char;
|
||||
extern struct type *builtin_type_ada_float;
|
||||
extern struct type *builtin_type_ada_double;
|
||||
extern struct type *builtin_type_ada_long_double;
|
||||
extern struct type *builtin_type_ada_natural;
|
||||
extern struct type *builtin_type_ada_positive;
|
||||
extern struct type *builtin_type_ada_system_address;
|
||||
|
||||
/* Assuming V points to an array of S objects, make sure that it contains at
|
||||
least M objects, updating V and S as necessary. */
|
||||
|
||||
#define GROW_VECT(v, s, m) \
|
||||
if ((s) < (m)) grow_vect ((void**) &(v), &(s), (m), sizeof(*(v)));
|
||||
|
||||
extern void grow_vect (void **, size_t *, size_t, int);
|
||||
|
||||
extern int ada_parse (void); /* Defined in ada-exp.y */
|
||||
|
||||
extern void ada_error (char *); /* Defined in ada-exp.y */
|
||||
|
||||
/* Defined in ada-typeprint.c */
|
||||
extern void ada_print_type (struct type *, char *, struct ui_file *, int,
|
||||
int);
|
||||
|
||||
extern int ada_val_print (struct type *, char *, int, CORE_ADDR,
|
||||
struct ui_file *, int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
extern int ada_value_print (struct value *, struct ui_file *, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
/* Defined in ada-lang.c */
|
||||
|
||||
extern struct value *value_from_contents_and_address (struct type *, char *,
|
||||
CORE_ADDR);
|
||||
|
||||
extern void ada_emit_char (int, struct ui_file *, int, int);
|
||||
|
||||
extern void ada_printchar (int, struct ui_file *);
|
||||
|
||||
extern void ada_printstr (struct ui_file *, char *, unsigned int, int, int);
|
||||
|
||||
extern void ada_convert_actuals (struct value *, int, struct value **,
|
||||
CORE_ADDR *);
|
||||
|
||||
extern struct value *ada_value_subscript (struct value *, int,
|
||||
struct value **);
|
||||
|
||||
extern struct type *ada_array_element_type (struct type *, int);
|
||||
|
||||
extern int ada_array_arity (struct type *);
|
||||
|
||||
struct type *ada_type_of_array (struct value *, int);
|
||||
|
||||
extern struct value *ada_coerce_to_simple_array (struct value *);
|
||||
|
||||
extern struct value *ada_coerce_to_simple_array_ptr (struct value *);
|
||||
|
||||
extern int ada_is_simple_array (struct type *);
|
||||
|
||||
extern int ada_is_array_descriptor (struct type *);
|
||||
|
||||
extern int ada_is_bogus_array_descriptor (struct type *);
|
||||
|
||||
extern struct type *ada_index_type (struct type *, int);
|
||||
|
||||
extern struct value *ada_array_bound (struct value *, int, int);
|
||||
|
||||
extern int ada_lookup_symbol_list (const char *, struct block *,
|
||||
domain_enum, struct symbol ***,
|
||||
struct block ***);
|
||||
|
||||
extern char *ada_fold_name (const char *);
|
||||
|
||||
extern struct symbol *ada_lookup_symbol (const char *, struct block *,
|
||||
domain_enum);
|
||||
|
||||
extern struct minimal_symbol *ada_lookup_minimal_symbol (const char *);
|
||||
|
||||
extern void ada_resolve (struct expression **, struct type *);
|
||||
|
||||
extern int ada_resolve_function (struct symbol **, struct block **, int,
|
||||
struct value **, int, const char *,
|
||||
struct type *);
|
||||
|
||||
extern void ada_fill_in_ada_prototype (struct symbol *);
|
||||
|
||||
extern int user_select_syms (struct symbol **, struct block **, int, int);
|
||||
|
||||
extern int get_selections (int *, int, int, int, char *);
|
||||
|
||||
extern char *ada_start_decode_line_1 (char *);
|
||||
|
||||
extern struct symtabs_and_lines ada_finish_decode_line_1 (char **,
|
||||
struct symtab *,
|
||||
int, char ***);
|
||||
|
||||
extern int ada_scan_number (const char *, int, LONGEST *, int *);
|
||||
|
||||
extern struct type *ada_parent_type (struct type *);
|
||||
|
||||
extern int ada_is_ignored_field (struct type *, int);
|
||||
|
||||
extern int ada_is_packed_array_type (struct type *);
|
||||
|
||||
extern struct value *ada_value_primitive_packed_val (struct value *, char *,
|
||||
long, int, int,
|
||||
struct type *);
|
||||
|
||||
extern struct type *ada_coerce_to_simple_array_type (struct type *);
|
||||
|
||||
extern int ada_is_character_type (struct type *);
|
||||
|
||||
extern int ada_is_string_type (struct type *);
|
||||
|
||||
extern int ada_is_tagged_type (struct type *);
|
||||
|
||||
extern struct type *ada_tag_type (struct value *);
|
||||
|
||||
extern struct value *ada_value_tag (struct value *);
|
||||
|
||||
extern int ada_is_parent_field (struct type *, int);
|
||||
|
||||
extern int ada_is_wrapper_field (struct type *, int);
|
||||
|
||||
extern int ada_is_variant_part (struct type *, int);
|
||||
|
||||
extern struct type *ada_variant_discrim_type (struct type *, struct type *);
|
||||
|
||||
extern int ada_is_others_clause (struct type *, int);
|
||||
|
||||
extern int ada_in_variant (LONGEST, struct type *, int);
|
||||
|
||||
extern char *ada_variant_discrim_name (struct type *);
|
||||
|
||||
extern struct type *ada_lookup_struct_elt_type (struct type *, char *, int,
|
||||
int *);
|
||||
|
||||
extern struct value *ada_value_struct_elt (struct value *, char *, char *);
|
||||
|
||||
extern struct value *ada_search_struct_field (char *, struct value *, int,
|
||||
struct type *);
|
||||
|
||||
extern int ada_is_aligner_type (struct type *);
|
||||
|
||||
extern struct type *ada_aligned_type (struct type *);
|
||||
|
||||
extern char *ada_aligned_value_addr (struct type *, char *);
|
||||
|
||||
extern const char *ada_attribute_name (int);
|
||||
|
||||
extern int ada_is_fixed_point_type (struct type *);
|
||||
|
||||
extern DOUBLEST ada_delta (struct type *);
|
||||
|
||||
extern DOUBLEST ada_fixed_to_float (struct type *, LONGEST);
|
||||
|
||||
extern LONGEST ada_float_to_fixed (struct type *, DOUBLEST);
|
||||
|
||||
extern int ada_is_vax_floating_type (struct type *);
|
||||
|
||||
extern int ada_vax_float_type_suffix (struct type *);
|
||||
|
||||
extern struct value *ada_vax_float_print_function (struct type *);
|
||||
|
||||
extern struct type *ada_system_address_type (void);
|
||||
|
||||
extern int ada_which_variant_applies (struct type *, struct type *, char *);
|
||||
|
||||
extern struct value *ada_to_fixed_value (struct type *, char *, CORE_ADDR,
|
||||
struct value *);
|
||||
|
||||
extern struct type *ada_to_fixed_type (struct type *, char *, CORE_ADDR,
|
||||
struct value *);
|
||||
|
||||
extern int ada_name_prefix_len (const char *);
|
||||
|
||||
extern char *ada_type_name (struct type *);
|
||||
|
||||
extern struct type *ada_find_parallel_type (struct type *,
|
||||
const char *suffix);
|
||||
|
||||
extern LONGEST get_int_var_value (char *, char *, int *);
|
||||
|
||||
extern struct type *ada_find_any_type (const char *name);
|
||||
|
||||
extern int ada_prefer_type (struct type *, struct type *);
|
||||
|
||||
extern struct type *ada_get_base_type (struct type *);
|
||||
|
||||
extern struct type *ada_completed_type (struct type *);
|
||||
|
||||
extern char *ada_mangle (const char *);
|
||||
|
||||
extern const char *ada_enum_name (const char *);
|
||||
|
||||
extern int ada_is_modular_type (struct type *);
|
||||
|
||||
extern LONGEST ada_modulus (struct type *);
|
||||
|
||||
extern struct value *ada_value_ind (struct value *);
|
||||
|
||||
extern void ada_print_scalar (struct type *, LONGEST, struct ui_file *);
|
||||
|
||||
extern int ada_is_range_type_name (const char *);
|
||||
|
||||
extern const char *ada_renaming_type (struct type *);
|
||||
|
||||
extern int ada_is_object_renaming (struct symbol *);
|
||||
|
||||
extern const char *ada_simple_renamed_entity (struct symbol *);
|
||||
|
||||
extern char *ada_breakpoint_rewrite (char *, int *);
|
||||
|
||||
/* Tasking-related: ada-tasks.c */
|
||||
|
||||
extern int valid_task_id (int);
|
||||
|
||||
extern int get_current_task (void);
|
||||
|
||||
extern void init_task_list (void);
|
||||
|
||||
extern void *get_self_id (void);
|
||||
|
||||
extern int get_current_task (void);
|
||||
|
||||
extern int get_entry_number (void *);
|
||||
|
||||
extern void ada_report_exception_break (struct breakpoint *);
|
||||
|
||||
extern int ada_maybe_exception_partial_symbol (struct partial_symbol *sym);
|
||||
|
||||
extern int ada_is_exception_sym (struct symbol *sym);
|
||||
|
||||
|
||||
#endif
|
||||
928
contrib/gdb/gdb/ada-lex.l
Normal file
928
contrib/gdb/gdb/ada-lex.l
Normal file
|
|
@ -0,0 +1,928 @@
|
|||
/* FLEX lexer for Ada expressions, for GDB.
|
||||
Copyright (C) 1994, 1997, 2000
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/* The converted version of this file is to be included in ada-exp.y, */
|
||||
/* the Ada parser for gdb. The function yylex obtains characters from */
|
||||
/* the global pointer lexptr. It returns a syntactic category for */
|
||||
/* each successive token and places a semantic value into yylval */
|
||||
/* (ada-lval), defined by the parser. */
|
||||
|
||||
/* Run flex with (at least) the -i option (case-insensitive), and the -I */
|
||||
/* option (interactive---no unnecessary lookahead). */
|
||||
|
||||
DIG [0-9]
|
||||
NUM10 ({DIG}({DIG}|_)*)
|
||||
HEXDIG [0-9a-f]
|
||||
NUM16 ({HEXDIG}({HEXDIG}|_)*)
|
||||
OCTDIG [0-7]
|
||||
LETTER [a-z_]
|
||||
ID ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
|
||||
WHITE [ \t\n]
|
||||
TICK ("'"{WHITE}*)
|
||||
GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
|
||||
OPER ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
|
||||
|
||||
EXP (e[+-]{NUM10})
|
||||
POSEXP (e"+"?{NUM10})
|
||||
|
||||
%{
|
||||
#define NUMERAL_WIDTH 256
|
||||
#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
|
||||
|
||||
/* Temporary staging for numeric literals. */
|
||||
static char numbuf[NUMERAL_WIDTH];
|
||||
static void canonicalizeNumeral (char* s1, const char*);
|
||||
static int processInt (const char*, const char*, const char*);
|
||||
static int processReal (const char*);
|
||||
static int processId (const char*, int);
|
||||
static int processAttribute (const char*);
|
||||
static int find_dot_all (const char*);
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL static int yylex ( void )
|
||||
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
|
||||
if ( *lexptr == '\000' ) \
|
||||
(RESULT) = YY_NULL; \
|
||||
else \
|
||||
{ \
|
||||
*(BUF) = *lexptr; \
|
||||
(RESULT) = 1; \
|
||||
lexptr += 1; \
|
||||
}
|
||||
|
||||
static char *tempbuf = NULL;
|
||||
static int tempbufsize = 0;
|
||||
static int tempbuf_len;
|
||||
static struct block* left_block_context;
|
||||
|
||||
static void resize_tempbuf (unsigned int);
|
||||
|
||||
static void block_lookup (char*, char*);
|
||||
|
||||
static int name_lookup (char*, char*, int*);
|
||||
|
||||
static int find_dot_all (const char*);
|
||||
|
||||
%}
|
||||
|
||||
%s IN_STRING BEFORE_QUAL_QUOTE
|
||||
|
||||
%%
|
||||
|
||||
{WHITE} { }
|
||||
|
||||
"--".* { yyterminate(); }
|
||||
|
||||
{NUM10}{POSEXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1);
|
||||
}
|
||||
|
||||
{NUM10} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (NULL, numbuf, NULL);
|
||||
}
|
||||
|
||||
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (numbuf,
|
||||
strchr (numbuf, '#') + 1,
|
||||
strrchr(numbuf, '#') + 1);
|
||||
}
|
||||
|
||||
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processInt (numbuf, strchr (numbuf, '#') + 1, NULL);
|
||||
}
|
||||
|
||||
"0x"{HEXDIG}+ {
|
||||
canonicalizeNumeral (numbuf, yytext+2);
|
||||
return processInt ("16#", numbuf, NULL);
|
||||
}
|
||||
|
||||
|
||||
{NUM10}"."{NUM10}{EXP} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processReal (numbuf);
|
||||
}
|
||||
|
||||
{NUM10}"."{NUM10} {
|
||||
canonicalizeNumeral (numbuf, yytext);
|
||||
return processReal (numbuf);
|
||||
}
|
||||
|
||||
{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
|
||||
error ("Based real literals not implemented yet.");
|
||||
}
|
||||
|
||||
{NUM10}"#"{NUM16}"."{NUM16}"#" {
|
||||
error ("Based real literals not implemented yet.");
|
||||
}
|
||||
|
||||
<INITIAL>"'"({GRAPHIC}|\")"'" {
|
||||
yylval.typed_val.type = builtin_type_ada_char;
|
||||
yylval.typed_val.val = yytext[1];
|
||||
return CHARLIT;
|
||||
}
|
||||
|
||||
<INITIAL>"'[\""{HEXDIG}{2}"\"]'" {
|
||||
int v;
|
||||
yylval.typed_val.type = builtin_type_ada_char;
|
||||
sscanf (yytext+3, "%2x", &v);
|
||||
yylval.typed_val.val = v;
|
||||
return CHARLIT;
|
||||
}
|
||||
|
||||
\"{OPER}\"/{WHITE}*"(" { return processId (yytext, yyleng); }
|
||||
|
||||
<INITIAL>\" {
|
||||
tempbuf_len = 0;
|
||||
BEGIN IN_STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*\" {
|
||||
resize_tempbuf (yyleng+tempbuf_len);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-1);
|
||||
tempbuf_len += yyleng-1;
|
||||
yylval.sval.ptr = tempbuf;
|
||||
yylval.sval.length = tempbuf_len;
|
||||
BEGIN INITIAL;
|
||||
return STRING;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-5+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
sscanf(yytext+yyleng-4, "%2x", &n);
|
||||
tempbuf[yyleng-6+tempbuf_len] = (char) n;
|
||||
tempbuf_len += yyleng-5;
|
||||
}
|
||||
|
||||
<IN_STRING>{GRAPHIC}*"[\"\"\"]" {
|
||||
int n;
|
||||
resize_tempbuf (yyleng-4+tempbuf_len+1);
|
||||
strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
|
||||
tempbuf[yyleng-5+tempbuf_len] = '"';
|
||||
tempbuf_len += yyleng-4;
|
||||
}
|
||||
|
||||
if {
|
||||
while (*lexptr != 'i' && *lexptr != 'I')
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ADA KEYWORDS */
|
||||
|
||||
abs { return ABS; }
|
||||
and { return _AND_; }
|
||||
else { return ELSE; }
|
||||
in { return IN; }
|
||||
mod { return MOD; }
|
||||
new { return NEW; }
|
||||
not { return NOT; }
|
||||
null { return NULL_PTR; }
|
||||
or { return OR; }
|
||||
rem { return REM; }
|
||||
then { return THEN; }
|
||||
xor { return XOR; }
|
||||
|
||||
/* ATTRIBUTES */
|
||||
|
||||
{TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); }
|
||||
|
||||
/* PUNCTUATION */
|
||||
|
||||
"=>" { return ARROW; }
|
||||
".." { return DOTDOT; }
|
||||
"**" { return STARSTAR; }
|
||||
":=" { return ASSIGN; }
|
||||
"/=" { return NOTEQUAL; }
|
||||
"<=" { return LEQ; }
|
||||
">=" { return GEQ; }
|
||||
|
||||
<BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
|
||||
|
||||
[-&*+./:<>=|;\[\]] { return yytext[0]; }
|
||||
|
||||
"," { if (paren_depth == 0 && comma_terminates)
|
||||
{
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return ',';
|
||||
}
|
||||
|
||||
"(" { paren_depth += 1; return '('; }
|
||||
")" { if (paren_depth == 0)
|
||||
{
|
||||
lexptr -= 1;
|
||||
yyrestart(NULL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
paren_depth -= 1;
|
||||
return ')';
|
||||
}
|
||||
}
|
||||
|
||||
"."{WHITE}*all { return DOT_ALL; }
|
||||
|
||||
"."{WHITE}*{ID} {
|
||||
processId (yytext+1, yyleng-1);
|
||||
return DOT_ID;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
|
||||
int all_posn = find_dot_all (yytext);
|
||||
int token_type, segments, k;
|
||||
int quote_follows;
|
||||
|
||||
if (all_posn == -1 && yytext[yyleng-1] == '\'')
|
||||
{
|
||||
quote_follows = 1;
|
||||
do {
|
||||
yyless (yyleng-1);
|
||||
} while (yytext[yyleng-1] == ' ');
|
||||
}
|
||||
else
|
||||
quote_follows = 0;
|
||||
|
||||
if (all_posn >= 0)
|
||||
yyless (all_posn);
|
||||
processId(yytext, yyleng);
|
||||
segments = name_lookup (ada_mangle (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr, &token_type);
|
||||
left_block_context = NULL;
|
||||
for (k = yyleng; segments > 0 && k > 0; k -= 1)
|
||||
{
|
||||
if (yytext[k-1] == '.')
|
||||
segments -= 1;
|
||||
quote_follows = 0;
|
||||
}
|
||||
if (k <= 0)
|
||||
error ("confused by name %s", yytext);
|
||||
yyless (k);
|
||||
if (quote_follows)
|
||||
BEGIN BEFORE_QUAL_QUOTE;
|
||||
return token_type;
|
||||
}
|
||||
|
||||
/* GDB EXPRESSION CONSTRUCTS */
|
||||
|
||||
|
||||
"'"[^']+"'"{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
}
|
||||
|
||||
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: {
|
||||
processId(yytext, yyleng-2);
|
||||
block_lookup (ada_mangle (yylval.ssym.stoken.ptr),
|
||||
yylval.ssym.stoken.ptr);
|
||||
return BLOCKNAME;
|
||||
}
|
||||
|
||||
[{}@] { return yytext[0]; }
|
||||
|
||||
"$$" { yylval.lval = -1; return LAST; }
|
||||
"$$"{DIG}+ { yylval.lval = -atoi(yytext+2); return LAST; }
|
||||
"$" { yylval.lval = 0; return LAST; }
|
||||
"$"{DIG}+ { yylval.lval = atoi(yytext+1); return LAST; }
|
||||
|
||||
|
||||
/* REGISTERS AND GDB CONVENIENCE VARIABLES */
|
||||
|
||||
"$"({LETTER}|{DIG}|"$")+ {
|
||||
int c;
|
||||
for (c = 0; c < NUM_REGS; c++)
|
||||
if (REGISTER_NAME (c) &&
|
||||
strcmp (yytext + 1, REGISTER_NAME (c)) == 0)
|
||||
{
|
||||
yylval.lval = c;
|
||||
return REGNAME;
|
||||
}
|
||||
yylval.sval.ptr = yytext;
|
||||
yylval.sval.length = yyleng;
|
||||
yylval.ivar =
|
||||
lookup_internalvar (copy_name (yylval.sval) + 1);
|
||||
return INTERNAL_VARIABLE;
|
||||
}
|
||||
|
||||
/* CATCH-ALL ERROR CASE */
|
||||
|
||||
. { error ("Invalid character '%s' in expression.", yytext); }
|
||||
%%
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Initialize the lexer for processing new expression */
|
||||
void
|
||||
lexer_init (FILE* inp)
|
||||
{
|
||||
BEGIN INITIAL;
|
||||
yyrestart (inp);
|
||||
}
|
||||
|
||||
|
||||
/* Make sure that tempbuf points at an array at least N characters long. */
|
||||
|
||||
static void
|
||||
resize_tempbuf (n)
|
||||
unsigned int n;
|
||||
{
|
||||
if (tempbufsize < n)
|
||||
{
|
||||
tempbufsize = (n+63) & ~63;
|
||||
tempbuf = (char*) xrealloc (tempbuf, tempbufsize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
|
||||
|
||||
static void
|
||||
canonicalizeNumeral (s1,s2)
|
||||
char* s1;
|
||||
const char* s2;
|
||||
{
|
||||
for (; *s2 != '\000'; s2 += 1)
|
||||
{
|
||||
if (*s2 != '_')
|
||||
{
|
||||
*s1 = tolower(*s2);
|
||||
s1 += 1;
|
||||
}
|
||||
}
|
||||
s1[0] = '\000';
|
||||
}
|
||||
|
||||
#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
|
||||
|
||||
/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
|
||||
where 2 <= BASE <= 16. */
|
||||
|
||||
static int
|
||||
is_digit_in_base (digit, base)
|
||||
unsigned char digit;
|
||||
int base;
|
||||
{
|
||||
if (!isxdigit (digit))
|
||||
return 0;
|
||||
if (base <= 10)
|
||||
return (isdigit (digit) && digit < base + '0');
|
||||
else
|
||||
return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
|
||||
}
|
||||
|
||||
static int
|
||||
digit_to_int (c)
|
||||
unsigned char c;
|
||||
{
|
||||
if (isdigit (c))
|
||||
return c - '0';
|
||||
else
|
||||
return tolower (c) - 'a' + 10;
|
||||
}
|
||||
|
||||
/* As for strtoul, but for ULONGEST results. */
|
||||
ULONGEST
|
||||
strtoulst (num, trailer, base)
|
||||
const char *num;
|
||||
const char **trailer;
|
||||
int base;
|
||||
{
|
||||
unsigned int high_part;
|
||||
ULONGEST result;
|
||||
int i;
|
||||
unsigned char lim;
|
||||
|
||||
if (base < 2 || base > 16)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
lim = base - 1 + '0';
|
||||
|
||||
result = high_part = 0;
|
||||
for (i = 0; is_digit_in_base (num[i], base); i += 1)
|
||||
{
|
||||
result = result*base + digit_to_int (num[i]);
|
||||
high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN);
|
||||
result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
|
||||
if (high_part > 0xff)
|
||||
{
|
||||
errno = ERANGE;
|
||||
result = high_part = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trailer != NULL)
|
||||
*trailer = &num[i];
|
||||
|
||||
return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Interprets the prefix of NUM that consists of digits of the given BASE
|
||||
as an integer of that BASE, with the string EXP as an exponent.
|
||||
Puts value in yylval, and returns INT, if the string is valid. Causes
|
||||
an error if the number is improperly formated. BASE, if NULL, defaults
|
||||
to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */
|
||||
|
||||
static int
|
||||
processInt (base0, num0, exp0)
|
||||
const char* num0;
|
||||
const char* base0;
|
||||
const char* exp0;
|
||||
{
|
||||
ULONGEST result;
|
||||
long exp;
|
||||
int base;
|
||||
|
||||
char* trailer;
|
||||
|
||||
if (base0 == NULL)
|
||||
base = 10;
|
||||
else
|
||||
{
|
||||
base = strtol (base0, (char**) NULL, 10);
|
||||
if (base < 2 || base > 16)
|
||||
error ("Invalid base: %d.", base);
|
||||
}
|
||||
|
||||
if (exp0 == NULL)
|
||||
exp = 0;
|
||||
else
|
||||
exp = strtol(exp0, (char**) NULL, 10);
|
||||
|
||||
errno = 0;
|
||||
result = strtoulst (num0, &trailer, base);
|
||||
if (errno == ERANGE)
|
||||
error ("Integer literal out of range");
|
||||
if (isxdigit(*trailer))
|
||||
error ("Invalid digit `%c' in based literal", *trailer);
|
||||
|
||||
while (exp > 0)
|
||||
{
|
||||
if (result > (ULONG_MAX / base))
|
||||
error ("Integer literal out of range");
|
||||
result *= base;
|
||||
exp -= 1;
|
||||
}
|
||||
|
||||
if ((result >> (TARGET_INT_BIT-1)) == 0)
|
||||
yylval.typed_val.type = builtin_type_ada_int;
|
||||
else if ((result >> (TARGET_LONG_BIT-1)) == 0)
|
||||
yylval.typed_val.type = builtin_type_ada_long;
|
||||
else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0)
|
||||
{
|
||||
/* We have a number representable as an unsigned integer quantity.
|
||||
For consistency with the C treatment, we will treat it as an
|
||||
anonymous modular (unsigned) quantity. Alas, the types are such
|
||||
that we need to store .val as a signed quantity. Sorry
|
||||
for the mess, but C doesn't officially guarantee that a simple
|
||||
assignment does the trick (no, it doesn't; read the reference manual).
|
||||
*/
|
||||
yylval.typed_val.type = builtin_type_unsigned_long;
|
||||
if (result & LONGEST_SIGN)
|
||||
yylval.typed_val.val =
|
||||
(LONGEST) (result & ~LONGEST_SIGN)
|
||||
- (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
|
||||
else
|
||||
yylval.typed_val.val = (LONGEST) result;
|
||||
return INT;
|
||||
}
|
||||
else
|
||||
yylval.typed_val.type = builtin_type_ada_long_long;
|
||||
|
||||
yylval.typed_val.val = (LONGEST) result;
|
||||
return INT;
|
||||
}
|
||||
|
||||
static int
|
||||
processReal (num0)
|
||||
const char* num0;
|
||||
{
|
||||
if (sizeof (DOUBLEST) <= sizeof (float))
|
||||
sscanf (num0, "%g", &yylval.typed_val_float.dval);
|
||||
else if (sizeof (DOUBLEST) <= sizeof (double))
|
||||
sscanf (num0, "%lg", &yylval.typed_val_float.dval);
|
||||
else
|
||||
{
|
||||
#ifdef PRINTF_HAS_LONG_DOUBLE
|
||||
sscanf (num0, "%Lg", &yylval.typed_val_float.dval);
|
||||
#else
|
||||
/* Scan it into a double, then convert and assign it to the
|
||||
long double. This at least wins with values representable
|
||||
in the range of doubles. */
|
||||
double temp;
|
||||
sscanf (num0, "%lg", &temp);
|
||||
yylval.typed_val_float.dval = temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
yylval.typed_val_float.type = builtin_type_ada_float;
|
||||
if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT)
|
||||
yylval.typed_val_float.type = builtin_type_ada_double;
|
||||
if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)
|
||||
yylval.typed_val_float.type = builtin_type_ada_long_double;
|
||||
|
||||
return FLOAT;
|
||||
}
|
||||
|
||||
static int
|
||||
processId (name0, len)
|
||||
const char *name0;
|
||||
int len;
|
||||
{
|
||||
char* name = xmalloc (len + 11);
|
||||
int i0, i;
|
||||
|
||||
/* add_name_string_cleanup (name); */
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
while (len > 0 && isspace (name0[len-1]))
|
||||
len -= 1;
|
||||
i = i0 = 0;
|
||||
while (i0 < len)
|
||||
{
|
||||
if (isalnum (name0[i0]))
|
||||
{
|
||||
name[i] = tolower (name0[i0]);
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
else switch (name0[i0])
|
||||
{
|
||||
default:
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
break;
|
||||
case ' ': case '\t':
|
||||
i0 += 1;
|
||||
break;
|
||||
case '\'':
|
||||
i0 += 1;
|
||||
while (i0 < len && name0[i0] != '\'')
|
||||
{
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
i0 += 1;
|
||||
break;
|
||||
case '<':
|
||||
i0 += 1;
|
||||
while (i0 < len && name0[i0] != '>')
|
||||
{
|
||||
name[i] = name0[i0];
|
||||
i += 1; i0 += 1;
|
||||
}
|
||||
i0 += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
name[i] = '\000';
|
||||
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = i;
|
||||
return NAME;
|
||||
}
|
||||
|
||||
static void
|
||||
block_lookup (name, err_name)
|
||||
char* name;
|
||||
char* err_name;
|
||||
{
|
||||
struct symbol** syms;
|
||||
struct block** blocks;
|
||||
int nsyms;
|
||||
struct symtab *symtab;
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_DOMAIN, &syms, &blocks);
|
||||
if (left_block_context == NULL &&
|
||||
(nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK))
|
||||
symtab = lookup_symtab (name);
|
||||
else
|
||||
symtab = NULL;
|
||||
|
||||
if (symtab != NULL)
|
||||
left_block_context = yylval.bval =
|
||||
BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
else if (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK)
|
||||
{
|
||||
if (left_block_context == NULL)
|
||||
error ("No file or function \"%s\".", err_name);
|
||||
else
|
||||
error ("No function \"%s\" in specified context.", err_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0]);
|
||||
if (nsyms > 1)
|
||||
warning ("Function name \"%s\" ambiguous here", err_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up NAME0 (assumed to be mangled) as a name in VAR_DOMAIN,
|
||||
setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is
|
||||
found. Try first the entire name, then the name without the last
|
||||
segment (i.e., after the last .id), etc., and return the number of
|
||||
segments that had to be removed to get a match. Calls error if no
|
||||
matches are found, using ERR_NAME in any error message. When
|
||||
exactly one symbol match is found, it is placed in yylval. */
|
||||
|
||||
static int
|
||||
name_lookup (name0, err_name, token_type)
|
||||
char* name0;
|
||||
char* err_name;
|
||||
int* token_type;
|
||||
{
|
||||
struct symbol** syms;
|
||||
struct block** blocks;
|
||||
struct type* type;
|
||||
int len0 = strlen (name0);
|
||||
char* name = savestring (name0, len0);
|
||||
int nsyms;
|
||||
int segments;
|
||||
|
||||
/* add_name_string_cleanup (name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
yylval.ssym.stoken.ptr = name;
|
||||
yylval.ssym.stoken.length = strlen (name);
|
||||
for (segments = 0; ; segments += 1)
|
||||
{
|
||||
struct type* preferred_type;
|
||||
int i, preferred_index;
|
||||
|
||||
if (left_block_context == NULL)
|
||||
nsyms = ada_lookup_symbol_list (name, expression_context_block,
|
||||
VAR_DOMAIN, &syms, &blocks);
|
||||
else
|
||||
nsyms = ada_lookup_symbol_list (name, left_block_context,
|
||||
VAR_DOMAIN, &syms, &blocks);
|
||||
|
||||
/* Check for a type definition. */
|
||||
|
||||
/* Look for a symbol that doesn't denote void. This is (I think) a */
|
||||
/* temporary kludge to get around problems in GNAT output. */
|
||||
preferred_index = -1; preferred_type = NULL;
|
||||
for (i = 0; i < nsyms; i += 1)
|
||||
switch (SYMBOL_CLASS (syms[i]))
|
||||
{
|
||||
case LOC_TYPEDEF:
|
||||
if (ada_prefer_type (SYMBOL_TYPE (syms[i]), preferred_type))
|
||||
{
|
||||
preferred_index = i;
|
||||
preferred_type = SYMBOL_TYPE (syms[i]);
|
||||
}
|
||||
break;
|
||||
case LOC_REGISTER:
|
||||
case LOC_ARG:
|
||||
case LOC_REF_ARG:
|
||||
case LOC_REGPARM:
|
||||
case LOC_REGPARM_ADDR:
|
||||
case LOC_LOCAL:
|
||||
case LOC_LOCAL_ARG:
|
||||
case LOC_BASEREG:
|
||||
case LOC_BASEREG_ARG:
|
||||
goto NotType;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (preferred_type != NULL)
|
||||
{
|
||||
/* if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID)
|
||||
error ("`%s' matches only void type name(s)",
|
||||
ada_demangle (name));
|
||||
*/
|
||||
/* FIXME: ada_demangle should be defined in defs.h, and is located in ada-lang.c */
|
||||
/* else*/ if (ada_is_object_renaming (syms[preferred_index]))
|
||||
{
|
||||
yylval.ssym.sym = syms[preferred_index];
|
||||
*token_type = OBJECT_RENAMING;
|
||||
return segments;
|
||||
}
|
||||
else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index]))
|
||||
!= NULL)
|
||||
{
|
||||
int result;
|
||||
const char* renaming =
|
||||
ada_simple_renamed_entity (syms[preferred_index]);
|
||||
char* new_name = xmalloc (strlen (renaming) + len0
|
||||
- yylval.ssym.stoken.length + 1);
|
||||
/* add_name_string_cleanup (new_name);*/
|
||||
/* FIXME: add_name_string_cleanup should be defined in parse.c */
|
||||
strcpy (new_name, renaming);
|
||||
strcat (new_name, name0 + yylval.ssym.stoken.length);
|
||||
result = name_lookup (new_name, err_name, token_type);
|
||||
if (result > segments)
|
||||
error ("Confused by renamed symbol.");
|
||||
return result;
|
||||
}
|
||||
else if (segments == 0)
|
||||
{
|
||||
yylval.tval = preferred_type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (segments == 0)
|
||||
{
|
||||
type = lookup_primitive_typename (name);
|
||||
if (type == NULL && DEPRECATED_STREQ ("system__address", name))
|
||||
type = builtin_type_ada_system_address;
|
||||
if (type != NULL)
|
||||
{
|
||||
yylval.tval = type;
|
||||
*token_type = TYPENAME;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NotType:
|
||||
if (nsyms == 1)
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = syms[0];
|
||||
yylval.ssym.msym = NULL;
|
||||
yylval.ssym.block = blocks[0];
|
||||
return segments;
|
||||
}
|
||||
else if (nsyms == 0) {
|
||||
int i;
|
||||
yylval.ssym.msym = ada_lookup_minimal_symbol (name);
|
||||
if (yylval.ssym.msym != NULL)
|
||||
{
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.block = NULL;
|
||||
*token_type = NAME;
|
||||
return segments;
|
||||
}
|
||||
|
||||
for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1)
|
||||
{
|
||||
if (name[i] == '.')
|
||||
{
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
else if (name[i] == '_' && name[i-1] == '_')
|
||||
{
|
||||
i -= 1;
|
||||
name[i] = '\0';
|
||||
yylval.ssym.stoken.length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i <= 0)
|
||||
{
|
||||
if (!have_full_symbols () && !have_partial_symbols ()
|
||||
&& left_block_context == NULL)
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
if (left_block_context == NULL)
|
||||
error ("No definition of \"%s\" in current context.",
|
||||
err_name);
|
||||
else
|
||||
error ("No definition of \"%s\" in specified context.",
|
||||
err_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*token_type = NAME;
|
||||
yylval.ssym.sym = NULL;
|
||||
yylval.ssym.msym = NULL;
|
||||
if (left_block_context == NULL)
|
||||
yylval.ssym.block = expression_context_block;
|
||||
else
|
||||
yylval.ssym.block = left_block_context;
|
||||
return segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the position within STR of the '.' in a
|
||||
'.{WHITE}*all' component of a dotted name, or -1 if there is none. */
|
||||
static int
|
||||
find_dot_all (str)
|
||||
const char* str;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; str[i] != '\000'; i += 1)
|
||||
{
|
||||
if (str[i] == '.')
|
||||
{
|
||||
int i0 = i;
|
||||
do
|
||||
i += 1;
|
||||
while (isspace (str[i]));
|
||||
if (strcmp (str+i, "all") == 0
|
||||
&& ! isalnum (str[i+3]) && str[i+3] != '_')
|
||||
return i0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
|
||||
case. */
|
||||
|
||||
static int
|
||||
subseqMatch (subseq, str)
|
||||
const char* subseq;
|
||||
const char* str;
|
||||
{
|
||||
if (subseq[0] == '\0')
|
||||
return 1;
|
||||
else if (str[0] == '\0')
|
||||
return 0;
|
||||
else if (tolower (subseq[0]) == tolower (str[0]))
|
||||
return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
|
||||
else
|
||||
return subseqMatch (subseq, str+1);
|
||||
}
|
||||
|
||||
|
||||
static struct { const char* name; int code; }
|
||||
attributes[] = {
|
||||
{ "address", TICK_ADDRESS },
|
||||
{ "unchecked_access", TICK_ACCESS },
|
||||
{ "unrestricted_access", TICK_ACCESS },
|
||||
{ "access", TICK_ACCESS },
|
||||
{ "first", TICK_FIRST },
|
||||
{ "last", TICK_LAST },
|
||||
{ "length", TICK_LENGTH },
|
||||
{ "max", TICK_MAX },
|
||||
{ "min", TICK_MIN },
|
||||
{ "modulus", TICK_MODULUS },
|
||||
{ "pos", TICK_POS },
|
||||
{ "range", TICK_RANGE },
|
||||
{ "size", TICK_SIZE },
|
||||
{ "tag", TICK_TAG },
|
||||
{ "val", TICK_VAL },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
/* Return the syntactic code corresponding to the attribute name or
|
||||
abbreviation STR. */
|
||||
|
||||
static int
|
||||
processAttribute (str)
|
||||
const char* str;
|
||||
{
|
||||
int i, k;
|
||||
|
||||
for (i = 0; attributes[i].code != -1; i += 1)
|
||||
if (strcasecmp (str, attributes[i].name) == 0)
|
||||
return attributes[i].code;
|
||||
|
||||
for (i = 0, k = -1; attributes[i].code != -1; i += 1)
|
||||
if (subseqMatch (str, attributes[i].name))
|
||||
{
|
||||
if (k == -1)
|
||||
k = i;
|
||||
else
|
||||
error ("ambiguous attribute name: `%s'", str);
|
||||
}
|
||||
if (k == -1)
|
||||
error ("unrecognized attribute: `%s'", str);
|
||||
|
||||
return attributes[k].code;
|
||||
}
|
||||
|
||||
int
|
||||
yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
819
contrib/gdb/gdb/ada-tasks.c
Normal file
819
contrib/gdb/gdb/ada-tasks.c
Normal file
|
|
@ -0,0 +1,819 @@
|
|||
/* file ada-tasks.c: Ada tasking control for GDB
|
||||
Copyright 1997 Free Software Foundation, Inc.
|
||||
Contributed by Ada Core Technologies, Inc
|
||||
.
|
||||
This file is part of GDB.
|
||||
|
||||
[$Id: ada-tasks.c,v 1.7 2003/06/17 20:58:32 ciceron Exp $]
|
||||
Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "defs.h"
|
||||
#include "command.h"
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "inferior.h"
|
||||
#include "symtab.h"
|
||||
#include "target.h"
|
||||
#include "regcache.h"
|
||||
#include "gdbcore.h"
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
#include "gregset.h"
|
||||
#endif
|
||||
|
||||
#include "ada-lang.h"
|
||||
|
||||
/* FIXME: move all this conditional compilation in description
|
||||
files or in configure.in */
|
||||
|
||||
#if defined (VXWORKS_TARGET)
|
||||
#define THREAD_TO_PID(tid,lwpid) (tid)
|
||||
|
||||
#elif defined (linux)
|
||||
#define THREAD_TO_PID(tid,lwpid) (0)
|
||||
|
||||
#elif (defined (sun) && defined (__SVR4))
|
||||
#define THREAD_TO_PID thread_to_pid
|
||||
|
||||
#elif defined (sgi) || defined (__WIN32__) || defined (hpux)
|
||||
#define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
|
||||
|
||||
#else
|
||||
#define THREAD_TO_PID(tid,lwpid) (0)
|
||||
#endif
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
#define THREAD_FETCH_REGISTERS dec_thread_fetch_registers
|
||||
#define GET_CURRENT_THREAD dec_thread_get_current_thread
|
||||
extern int dec_thread_get_registers (gdb_gregset_t *, gdb_fpregset_t *);
|
||||
#endif
|
||||
|
||||
#if defined (_AIX)
|
||||
#define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
|
||||
#define GET_CURRENT_THREAD aix_thread_get_current_thread
|
||||
#endif
|
||||
|
||||
#if defined(VXWORKS_TARGET)
|
||||
#define GET_CURRENT_THREAD() ((void*)inferior_pid)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
|
||||
#elif defined (sun) && defined (__SVR4)
|
||||
#define GET_CURRENT_THREAD solaris_thread_get_current_thread
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
extern void *GET_CURRENT_THREAD ();
|
||||
|
||||
#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
|
||||
extern void *GET_CURRENT_THREAD ();
|
||||
|
||||
#elif defined (__WIN32__) || defined (hpux)
|
||||
#define GET_CURRENT_THREAD() (inferior_pid)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
|
||||
#else
|
||||
#define GET_CURRENT_THREAD() (NULL)
|
||||
#define THREAD_FETCH_REGISTERS() (-1)
|
||||
#endif
|
||||
|
||||
#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
|
||||
|
||||
#define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
|
||||
/* external declarations */
|
||||
|
||||
/* Global visible variables */
|
||||
|
||||
struct task_entry *task_list = NULL;
|
||||
int ada__tasks_check_symbol_table = 1;
|
||||
void *pthread_kern_addr = NULL;
|
||||
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
gdb_gregset_t gregset_saved;
|
||||
gdb_fpregset_t fpregset_saved;
|
||||
#endif
|
||||
|
||||
/* The maximum number of tasks known to the Ada runtime */
|
||||
const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
|
||||
|
||||
/* the current task */
|
||||
int current_task = -1, current_task_id = -1, current_task_index;
|
||||
void *current_thread, *current_lwp;
|
||||
|
||||
char *ada_task_states[] = {
|
||||
"Unactivated",
|
||||
"Runnable",
|
||||
"Terminated",
|
||||
"Child Activation Wait",
|
||||
"Accept Statement",
|
||||
"Waiting on entry call",
|
||||
"Async Select Wait",
|
||||
"Delay Sleep",
|
||||
"Child Termination Wait",
|
||||
"Wait Child in Term Alt",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Asynchronous Hold"
|
||||
};
|
||||
|
||||
/* Global internal types */
|
||||
|
||||
static char *ada_long_task_states[] = {
|
||||
"Unactivated",
|
||||
"Runnable",
|
||||
"Terminated",
|
||||
"Waiting for child activation",
|
||||
"Blocked in accept statement",
|
||||
"Waiting on entry call",
|
||||
"Asynchronous Selective Wait",
|
||||
"Delay Sleep",
|
||||
"Waiting for children termination",
|
||||
"Waiting for children in terminate alternative",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"Asynchronous Hold"
|
||||
};
|
||||
|
||||
/* Global internal variables */
|
||||
|
||||
static int highest_task_num = 0;
|
||||
int thread_support = 0; /* 1 if the thread library in use is supported */
|
||||
static int gdbtk_task_initialization = 0;
|
||||
|
||||
static int
|
||||
add_task_entry (void *p_task_id, int index)
|
||||
{
|
||||
struct task_entry *new_task_entry = NULL;
|
||||
struct task_entry *pt;
|
||||
|
||||
highest_task_num++;
|
||||
new_task_entry = xmalloc (sizeof (struct task_entry));
|
||||
new_task_entry->task_num = highest_task_num;
|
||||
new_task_entry->task_id = p_task_id;
|
||||
new_task_entry->known_tasks_index = index;
|
||||
new_task_entry->next_task = NULL;
|
||||
pt = task_list;
|
||||
if (pt)
|
||||
{
|
||||
while (pt->next_task)
|
||||
pt = pt->next_task;
|
||||
pt->next_task = new_task_entry;
|
||||
pt->stack_per = 0;
|
||||
}
|
||||
else
|
||||
task_list = new_task_entry;
|
||||
return new_task_entry->task_num;
|
||||
}
|
||||
|
||||
int
|
||||
get_entry_number (void *p_task_id)
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt != NULL)
|
||||
{
|
||||
if (pt->task_id == p_task_id)
|
||||
return pt->task_num;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct task_entry *
|
||||
get_thread_entry_vptr (void *thread)
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt != NULL)
|
||||
{
|
||||
if (pt->thread == thread)
|
||||
return pt;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct task_entry *
|
||||
get_entry_vptr (int p_task_num)
|
||||
{
|
||||
struct task_entry *pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
if (pt->task_num == p_task_num)
|
||||
return pt;
|
||||
pt = pt->next_task;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
init_task_list (void)
|
||||
{
|
||||
struct task_entry *pt, *old_pt;
|
||||
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
old_pt = pt;
|
||||
pt = pt->next_task;
|
||||
xfree (old_pt);
|
||||
};
|
||||
task_list = NULL;
|
||||
highest_task_num = 0;
|
||||
}
|
||||
|
||||
int
|
||||
valid_task_id (int task)
|
||||
{
|
||||
return get_entry_vptr (task) != NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
get_self_id (void)
|
||||
{
|
||||
struct value *val;
|
||||
void *self_id;
|
||||
int result;
|
||||
struct task_entry *ent;
|
||||
extern int do_not_insert_breakpoints;
|
||||
|
||||
#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
|
||||
if (thread_support)
|
||||
#endif
|
||||
{
|
||||
ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
|
||||
return ent ? ent->task_id : 0;
|
||||
}
|
||||
|
||||
/* FIXME: calling a function in the inferior with a multithreaded application
|
||||
is not reliable, so return NULL if there is no safe way to get the current
|
||||
task */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
get_current_task (void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* FIXME: language_ada should be defined in defs.h */
|
||||
/* if (current_language->la_language != language_ada) return -1; */
|
||||
|
||||
result = get_entry_number (get_self_id ());
|
||||
|
||||
/* return -1 if not found */
|
||||
return result == 0 ? -1 : result;
|
||||
}
|
||||
|
||||
/* Print detailed information about specified task */
|
||||
|
||||
static void
|
||||
info_task (char *arg, int from_tty)
|
||||
{
|
||||
void *temp_task;
|
||||
struct task_entry *pt, *pt2;
|
||||
void *self_id, *caller;
|
||||
struct task_fields atcb, atcb2;
|
||||
struct entry_call call;
|
||||
int bounds[2];
|
||||
char image[256];
|
||||
int num;
|
||||
|
||||
/* FIXME: language_ada should be defined in defs.h */
|
||||
/* if (current_language->la_language != language_ada)
|
||||
{
|
||||
printf_filtered ("The current language does not support tasks.\n");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
pt = get_entry_vptr (atoi (arg));
|
||||
if (pt == NULL)
|
||||
{
|
||||
printf_filtered ("Task %s not found.\n", arg);
|
||||
return;
|
||||
}
|
||||
|
||||
temp_task = pt->task_id;
|
||||
|
||||
/* read the atcb in the inferior */
|
||||
READ_MEMORY ((CORE_ADDR) temp_task, atcb);
|
||||
|
||||
/* print the Ada task id */
|
||||
printf_filtered ("Ada Task: %p\n", temp_task);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb.image.P_ARRAY != NULL)
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
|
||||
bounds[1] = EXTRACT_INT (bounds[1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
|
||||
(char *) &image, bounds[1]);
|
||||
printf_filtered ("Name: %.*s\n", bounds[1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered ("<no name>\n");
|
||||
|
||||
/* print the thread id */
|
||||
|
||||
if ((long) pt->thread < 65536)
|
||||
printf_filtered ("Thread: %ld\n", (long int) pt->thread);
|
||||
else
|
||||
printf_filtered ("Thread: %p\n", pt->thread);
|
||||
|
||||
if ((long) pt->lwp != 0)
|
||||
{
|
||||
if ((long) pt->lwp < 65536)
|
||||
printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
|
||||
else
|
||||
printf_filtered ("LWP: %p\n", pt->lwp);
|
||||
}
|
||||
|
||||
/* print the parent gdb task id */
|
||||
num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
|
||||
if (num != 0)
|
||||
{
|
||||
printf_filtered ("Parent: %d", num);
|
||||
pt2 = get_entry_vptr (num);
|
||||
READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb2.image.P_ARRAY != NULL)
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
|
||||
bounds);
|
||||
bounds[1] = EXTRACT_INT (bounds[1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
|
||||
(char *) &image, bounds[1]);
|
||||
printf_filtered (" (%.*s)\n", bounds[1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("No parent\n");
|
||||
|
||||
/* print the base priority of the task */
|
||||
printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
|
||||
|
||||
/* print the current state of the task */
|
||||
|
||||
/* check if this task is accepting a rendezvous */
|
||||
if (atcb.call == NULL)
|
||||
caller = NULL;
|
||||
else
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
|
||||
caller = EXTRACT_ADDRESS (call.self);
|
||||
}
|
||||
|
||||
if (caller != NULL)
|
||||
{
|
||||
num = get_entry_number (caller);
|
||||
printf_filtered ("Accepting rendezvous with %d", num);
|
||||
|
||||
if (num != 0)
|
||||
{
|
||||
pt2 = get_entry_vptr (num);
|
||||
READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
|
||||
|
||||
/* print the name of the task */
|
||||
if (atcb2.image.P_ARRAY != NULL)
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
|
||||
bounds);
|
||||
bounds[1] = EXTRACT_INT (bounds[1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
|
||||
(char *) &image, bounds[1]);
|
||||
printf_filtered (" (%.*s)\n", bounds[1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
else
|
||||
printf_filtered ("State: %s\n", ada_long_task_states[atcb.state]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* A useful function that shows the alignment of all the fields in the
|
||||
tasks_fields structure
|
||||
*/
|
||||
|
||||
print_align (void)
|
||||
{
|
||||
struct task_fields tf;
|
||||
void *tf_base = &(tf);
|
||||
void *tf_state = &(tf.state);
|
||||
void *tf_entry_num = &(tf.entry_num);
|
||||
void *tf_parent = &(tf.parent);
|
||||
void *tf_priority = &(tf.priority);
|
||||
void *tf_current_priority = &(tf.current_priority);
|
||||
void *tf_image = &(tf.image);
|
||||
void *tf_call = &(tf.call);
|
||||
void *tf_thread = &(tf.thread);
|
||||
void *tf_lwp = &(tf.lwp);
|
||||
printf_filtered ("\n");
|
||||
printf_filtered ("(tf_base = 0x%x)\n", tf_base);
|
||||
printf_filtered ("task_fields.entry_num at %3d (0x%x)\n",
|
||||
tf_entry_num - tf_base, tf_entry_num);
|
||||
printf_filtered ("task_fields.state at %3d (0x%x)\n",
|
||||
tf_state - tf_base, tf_state);
|
||||
printf_filtered ("task_fields.parent at %3d (0x%x)\n",
|
||||
tf_parent - tf_base, tf_parent);
|
||||
printf_filtered ("task_fields.priority at %3d (0x%x)\n",
|
||||
tf_priority - tf_base, tf_priority);
|
||||
printf_filtered ("task_fields.current_priority at %3d (0x%x)\n",
|
||||
tf_current_priority - tf_base, tf_current_priority);
|
||||
printf_filtered ("task_fields.image at %3d (0x%x)\n",
|
||||
tf_image - tf_base, tf_image);
|
||||
printf_filtered ("task_fields.call at %3d (0x%x)\n",
|
||||
tf_call - tf_base, tf_call);
|
||||
printf_filtered ("task_fields.thread at %3d (0x%x)\n",
|
||||
tf_thread - tf_base, tf_thread);
|
||||
printf_filtered ("task_fields.lwp at %3d (0x%x)\n",
|
||||
tf_lwp - tf_base, tf_lwp);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print information about currently known tasks */
|
||||
|
||||
static void
|
||||
info_tasks (char *arg, int from_tty)
|
||||
{
|
||||
struct value *val;
|
||||
int i, task_number, state;
|
||||
void *temp_task, *temp_tasks[MAX_NUMBER_OF_KNOWN_TASKS];
|
||||
struct task_entry *pt;
|
||||
void *self_id, *caller, *thread_id = NULL;
|
||||
struct task_fields atcb;
|
||||
struct entry_call call;
|
||||
int bounds[2];
|
||||
char image[256];
|
||||
int size;
|
||||
char car;
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
pthreadTeb_t thr;
|
||||
gdb_gregset_t regs;
|
||||
#endif
|
||||
|
||||
static struct symbol *sym;
|
||||
static struct minimal_symbol *msym;
|
||||
static void *known_tasks_addr = NULL;
|
||||
|
||||
int init_only = gdbtk_task_initialization;
|
||||
gdbtk_task_initialization = 0;
|
||||
|
||||
task_number = 0;
|
||||
|
||||
if (PIDGET (inferior_ptid) == 0)
|
||||
{
|
||||
printf_filtered ("The program is not being run under gdb. ");
|
||||
printf_filtered ("Use 'run' or 'attach' first.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ada__tasks_check_symbol_table)
|
||||
{
|
||||
thread_support = 0;
|
||||
#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
|
||||
defined (_AIX)
|
||||
thread_support = 1;
|
||||
#endif
|
||||
|
||||
msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
|
||||
if (msym != NULL)
|
||||
known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
|
||||
else
|
||||
#ifndef VXWORKS_TARGET
|
||||
return;
|
||||
#else
|
||||
{
|
||||
if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ada__tasks_check_symbol_table = 0;
|
||||
}
|
||||
|
||||
if (known_tasks_addr == NULL)
|
||||
return;
|
||||
|
||||
#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
|
||||
if (thread_support)
|
||||
#endif
|
||||
thread_id = GET_CURRENT_THREAD ();
|
||||
|
||||
/* then we get a list of tasks created */
|
||||
|
||||
init_task_list ();
|
||||
|
||||
READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
|
||||
|
||||
for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
|
||||
{
|
||||
temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
|
||||
|
||||
if (temp_task != NULL)
|
||||
{
|
||||
task_number = get_entry_number (temp_task);
|
||||
if (task_number == 0)
|
||||
task_number = add_task_entry (temp_task, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return without printing anything if this function was called in
|
||||
order to init GDBTK tasking. */
|
||||
|
||||
if (init_only)
|
||||
return;
|
||||
|
||||
/* print the header */
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
printf_filtered
|
||||
(" ID TID P-ID Pri Stack %% State Name\n");
|
||||
#else
|
||||
printf_filtered (" ID TID P-ID Pri State Name\n");
|
||||
#endif
|
||||
|
||||
/* Now that we have a list of task id's, we can print them */
|
||||
pt = task_list;
|
||||
while (pt)
|
||||
{
|
||||
temp_task = pt->task_id;
|
||||
|
||||
/* read the atcb in the inferior */
|
||||
READ_MEMORY ((CORE_ADDR) temp_task, atcb);
|
||||
|
||||
/* store the thread id for future use */
|
||||
pt->thread = EXTRACT_ADDRESS (atcb.thread);
|
||||
|
||||
#if defined (linux)
|
||||
pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
|
||||
#else
|
||||
pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
|
||||
#endif
|
||||
|
||||
/* print a star if this task is the current one */
|
||||
if (thread_id)
|
||||
#if defined (__WIN32__) || defined (SGI) || defined (hpux)
|
||||
printf_filtered (pt->lwp == thread_id ? "*" : " ");
|
||||
#else
|
||||
printf_filtered (pt->thread == thread_id ? "*" : " ");
|
||||
#endif
|
||||
|
||||
/* print the gdb task id */
|
||||
printf_filtered ("%3d", pt->task_num);
|
||||
|
||||
/* print the Ada task id */
|
||||
#ifndef VXWORKS_TARGET
|
||||
printf_filtered (" %9lx", (long) temp_task);
|
||||
#else
|
||||
#ifdef TARGET_64
|
||||
printf_filtered (" %#9lx", (unsigned long) pt->thread & 0x3ffffffffff);
|
||||
#else
|
||||
printf_filtered (" %#9lx", (long) pt->thread);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* print the parent gdb task id */
|
||||
printf_filtered
|
||||
(" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
|
||||
|
||||
/* print the base priority of the task */
|
||||
printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
|
||||
|
||||
#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
|
||||
if (pt->task_num == 1 || atcb.state == Terminated)
|
||||
{
|
||||
printf_filtered (" Unknown");
|
||||
goto next;
|
||||
}
|
||||
|
||||
read_memory ((CORE_ADDR) atcb.thread, &thr, sizeof (thr));
|
||||
current_thread = atcb.thread;
|
||||
regs.regs[SP_REGNUM] = 0;
|
||||
if (dec_thread_get_registers (®s, NULL) == 0)
|
||||
{
|
||||
pt->stack_per = (100 * ((long) thr.__stack_base -
|
||||
regs.regs[SP_REGNUM])) / thr.__stack_size;
|
||||
/* if the thread is terminated but still there, the
|
||||
stack_base/size values are erroneous. Try to patch it */
|
||||
if (pt->stack_per < 0 || pt->stack_per > 100)
|
||||
pt->stack_per = 0;
|
||||
}
|
||||
|
||||
/* print information about stack space used in the thread */
|
||||
if (thr.__stack_size < 1024 * 1024)
|
||||
{
|
||||
size = thr.__stack_size / 1024;
|
||||
car = 'K';
|
||||
}
|
||||
else if (thr.__stack_size < 1024 * 1024 * 1024)
|
||||
{
|
||||
size = thr.__stack_size / 1024 / 1024;
|
||||
car = 'M';
|
||||
}
|
||||
else /* Who knows... */
|
||||
{
|
||||
size = thr.__stack_size / 1024 / 1024 / 1024;
|
||||
car = 'G';
|
||||
}
|
||||
printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
|
||||
next:
|
||||
#endif
|
||||
|
||||
/* print the current state of the task */
|
||||
|
||||
/* check if this task is accepting a rendezvous */
|
||||
if (atcb.call == NULL)
|
||||
caller = NULL;
|
||||
else
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
|
||||
caller = EXTRACT_ADDRESS (call.self);
|
||||
}
|
||||
|
||||
if (caller != NULL)
|
||||
printf_filtered (" Accepting RV with %-4d",
|
||||
get_entry_number (caller));
|
||||
else
|
||||
{
|
||||
state = atcb.state;
|
||||
#if defined (__WIN32__) || defined (SGI) || defined (hpux)
|
||||
if (state == Runnable && (thread_id && pt->lwp == thread_id))
|
||||
#else
|
||||
if (state == Runnable && (thread_id && pt->thread == thread_id))
|
||||
#endif
|
||||
/* Replace "Runnable" by "Running" if this is the current task */
|
||||
printf_filtered (" %-22s", "Running");
|
||||
else
|
||||
printf_filtered (" %-22s", ada_task_states[state]);
|
||||
}
|
||||
|
||||
/* finally, print the name of the task */
|
||||
if (atcb.image.P_ARRAY != NULL)
|
||||
{
|
||||
READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS),
|
||||
bounds);
|
||||
bounds[1] = EXTRACT_INT (bounds[1]);
|
||||
read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
|
||||
(char *) &image, bounds[1]);
|
||||
printf_filtered (" %.*s\n", bounds[1], image);
|
||||
}
|
||||
else
|
||||
printf_filtered (" <no name>\n");
|
||||
|
||||
pt = pt->next_task;
|
||||
}
|
||||
}
|
||||
|
||||
/* Task list initialization for GDB-Tk. We basically use info_tasks()
|
||||
to initialize our variables, but abort that function before we
|
||||
actually print anything. */
|
||||
|
||||
int
|
||||
gdbtk_tcl_tasks_initialize (void)
|
||||
{
|
||||
gdbtk_task_initialization = 1;
|
||||
info_tasks ("", gdb_stdout);
|
||||
|
||||
return (task_list != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
info_tasks_command (char *arg, int from_tty)
|
||||
{
|
||||
if (arg == NULL || *arg == '\000')
|
||||
info_tasks (arg, from_tty);
|
||||
else
|
||||
info_task (arg, from_tty);
|
||||
}
|
||||
|
||||
/* Switch from one thread to another. */
|
||||
|
||||
static void
|
||||
switch_to_thread (ptid_t ptid)
|
||||
{
|
||||
if (ptid_equal (ptid, inferior_ptid))
|
||||
return;
|
||||
|
||||
inferior_ptid = ptid;
|
||||
flush_cached_frames ();
|
||||
registers_changed ();
|
||||
stop_pc = read_pc ();
|
||||
select_frame (get_current_frame ());
|
||||
}
|
||||
|
||||
/* Switch to a specified task. */
|
||||
|
||||
static int
|
||||
task_switch (void *tid, void *lwpid)
|
||||
{
|
||||
int res = 0, pid;
|
||||
|
||||
if (thread_support)
|
||||
{
|
||||
flush_cached_frames ();
|
||||
|
||||
if (current_task != current_task_id)
|
||||
{
|
||||
res = THREAD_FETCH_REGISTERS ();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
supply_gregset (&gregset_saved);
|
||||
supply_fpregset (&fpregset_saved);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
stop_pc = read_pc ();
|
||||
select_frame (get_current_frame ());
|
||||
return res;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
task_command (char *tidstr, int from_tty)
|
||||
{
|
||||
int num;
|
||||
struct task_entry *e;
|
||||
|
||||
if (!tidstr)
|
||||
error ("Please specify a task ID. Use the \"info tasks\" command to\n"
|
||||
"see the IDs of currently known tasks.");
|
||||
|
||||
num = atoi (tidstr);
|
||||
e = get_entry_vptr (num);
|
||||
|
||||
if (e == NULL)
|
||||
error ("Task ID %d not known. Use the \"info tasks\" command to\n"
|
||||
"see the IDs of currently known tasks.", num);
|
||||
|
||||
if (current_task_id == -1)
|
||||
{
|
||||
#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
|
||||
fill_gregset (&gregset_saved, -1);
|
||||
fill_fpregset (&fpregset_saved, -1);
|
||||
#endif
|
||||
current_task_id = get_current_task ();
|
||||
}
|
||||
|
||||
current_task = num;
|
||||
current_task_index = e->known_tasks_index;
|
||||
current_thread = e->thread;
|
||||
current_lwp = e->lwp;
|
||||
if (task_switch (e->thread, e->lwp) == 0)
|
||||
{
|
||||
/* FIXME: find_printable_frame should be defined in frame.h, and
|
||||
implemented in ada-lang.c */
|
||||
/* find_printable_frame (deprecated_selected_frame, frame_relative_level (deprecated_selected_frame)); */
|
||||
printf_filtered ("[Switching to task %d]\n", num);
|
||||
print_stack_frame (deprecated_selected_frame,
|
||||
frame_relative_level (deprecated_selected_frame), 1);
|
||||
}
|
||||
else
|
||||
printf_filtered ("Unable to switch to task %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_tasks (void)
|
||||
{
|
||||
static struct cmd_list_element *task_cmd_list = NULL;
|
||||
extern struct cmd_list_element *cmdlist;
|
||||
|
||||
add_info ("tasks", info_tasks_command,
|
||||
"Without argument: list all known Ada tasks, with status information.\n"
|
||||
"info tasks n: print detailed information of task n.\n");
|
||||
|
||||
add_prefix_cmd ("task", class_run, task_command,
|
||||
"Use this command to switch between tasks.\n\
|
||||
The new task ID must be currently known.", &task_cmd_list, "task ", 1, &cmdlist);
|
||||
}
|
||||
852
contrib/gdb/gdb/ada-typeprint.c
Normal file
852
contrib/gdb/gdb/ada-typeprint.c
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
/* Support for printing Ada types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1997, 2003 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "bfd.h" /* Binary File Description */
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "gdbcore.h"
|
||||
#include "target.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "language.h"
|
||||
#include "demangle.h"
|
||||
#include "c-lang.h"
|
||||
#include "typeprint.h"
|
||||
#include "ada-lang.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include "gdb_string.h"
|
||||
#include <errno.h>
|
||||
|
||||
static int print_record_field_types (struct type *, struct type *,
|
||||
struct ui_file *, int, int);
|
||||
|
||||
static void print_array_type (struct type *, struct ui_file *, int, int);
|
||||
|
||||
static void print_choices (struct type *, int, struct ui_file *,
|
||||
struct type *);
|
||||
|
||||
static void print_range (struct type *, struct ui_file *);
|
||||
|
||||
static void print_range_bound (struct type *, char *, int *,
|
||||
struct ui_file *);
|
||||
|
||||
static void
|
||||
print_dynamic_range_bound (struct type *, const char *, int,
|
||||
const char *, struct ui_file *);
|
||||
|
||||
static void print_range_type_named (char *, struct ui_file *);
|
||||
|
||||
|
||||
|
||||
static char *name_buffer;
|
||||
static int name_buffer_len;
|
||||
|
||||
/* The (demangled) Ada name of TYPE. This value persists until the
|
||||
next call. */
|
||||
|
||||
static char *
|
||||
demangled_type_name (struct type *type)
|
||||
{
|
||||
if (ada_type_name (type) == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
char *raw_name = ada_type_name (type);
|
||||
char *s, *q;
|
||||
|
||||
if (name_buffer == NULL || name_buffer_len <= strlen (raw_name))
|
||||
{
|
||||
name_buffer_len = 16 + 2 * strlen (raw_name);
|
||||
name_buffer = xrealloc (name_buffer, name_buffer_len);
|
||||
}
|
||||
strcpy (name_buffer, raw_name);
|
||||
|
||||
s = (char *) strstr (name_buffer, "___");
|
||||
if (s != NULL)
|
||||
*s = '\0';
|
||||
|
||||
s = name_buffer + strlen (name_buffer) - 1;
|
||||
while (s > name_buffer && (s[0] != '_' || s[-1] != '_'))
|
||||
s -= 1;
|
||||
|
||||
if (s == name_buffer)
|
||||
return name_buffer;
|
||||
|
||||
if (!islower (s[1]))
|
||||
return NULL;
|
||||
|
||||
for (s = q = name_buffer; *s != '\0'; q += 1)
|
||||
{
|
||||
if (s[0] == '_' && s[1] == '_')
|
||||
{
|
||||
*q = '.';
|
||||
s += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*q = *s;
|
||||
s += 1;
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
return name_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print a description of a type in the format of a
|
||||
typedef for the current language.
|
||||
NEW is the new name for a type TYPE. */
|
||||
|
||||
void
|
||||
ada_typedef_print (struct type *type, struct symbol *new,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
fprintf_filtered (stream, "type %.*s is ",
|
||||
ada_name_prefix_len (SYMBOL_PRINT_NAME (new)),
|
||||
SYMBOL_PRINT_NAME (new));
|
||||
type_print (type, "", stream, 1);
|
||||
}
|
||||
|
||||
/* Print range type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_range (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
struct type *target_type;
|
||||
target_type = TYPE_TARGET_TYPE (type);
|
||||
if (target_type == NULL)
|
||||
target_type = type;
|
||||
|
||||
switch (TYPE_CODE (target_type))
|
||||
{
|
||||
case TYPE_CODE_RANGE:
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_BOOL:
|
||||
case TYPE_CODE_CHAR:
|
||||
case TYPE_CODE_ENUM:
|
||||
break;
|
||||
default:
|
||||
target_type = builtin_type_ada_int;
|
||||
break;
|
||||
}
|
||||
|
||||
if (TYPE_NFIELDS (type) < 2)
|
||||
{
|
||||
/* A range needs at least 2 bounds to be printed. If there are less
|
||||
than 2, just print the type name instead of the range itself.
|
||||
This check handles cases such as characters, for example.
|
||||
|
||||
Note that if the name is not defined, then we don't print anything.
|
||||
*/
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (TYPE_NAME (type)),
|
||||
TYPE_NAME (type));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We extract the range type bounds respectively from the first element
|
||||
and the last element of the type->fields array */
|
||||
const LONGEST lower_bound = (LONGEST) TYPE_LOW_BOUND (type);
|
||||
const LONGEST upper_bound =
|
||||
(LONGEST) TYPE_FIELD_BITPOS (type, TYPE_NFIELDS (type) - 1);
|
||||
|
||||
ada_print_scalar (target_type, lower_bound, stream);
|
||||
fprintf_filtered (stream, " .. ");
|
||||
ada_print_scalar (target_type, upper_bound, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the number or discriminant bound at BOUNDS+*N on STREAM, and
|
||||
set *N past the bound and its delimiter, if any. */
|
||||
|
||||
static void
|
||||
print_range_bound (struct type *type, char *bounds, int *n,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
LONGEST B;
|
||||
if (ada_scan_number (bounds, *n, &B, n))
|
||||
{
|
||||
ada_print_scalar (type, B, stream);
|
||||
if (bounds[*n] == '_')
|
||||
*n += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bound_len;
|
||||
char *bound = bounds + *n;
|
||||
char *pend;
|
||||
|
||||
pend = strstr (bound, "__");
|
||||
if (pend == NULL)
|
||||
*n += bound_len = strlen (bound);
|
||||
else
|
||||
{
|
||||
bound_len = pend - bound;
|
||||
*n += bound_len + 2;
|
||||
}
|
||||
fprintf_filtered (stream, "%.*s", bound_len, bound);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming NAME[0 .. NAME_LEN-1] is the name of a range type, print
|
||||
the value (if found) of the bound indicated by SUFFIX ("___L" or
|
||||
"___U") according to the ___XD conventions. */
|
||||
|
||||
static void
|
||||
print_dynamic_range_bound (struct type *type, const char *name, int name_len,
|
||||
const char *suffix, struct ui_file *stream)
|
||||
{
|
||||
static char *name_buf = NULL;
|
||||
static size_t name_buf_len = 0;
|
||||
LONGEST B;
|
||||
int OK;
|
||||
|
||||
GROW_VECT (name_buf, name_buf_len, name_len + strlen (suffix) + 1);
|
||||
strncpy (name_buf, name, name_len);
|
||||
strcpy (name_buf + name_len, suffix);
|
||||
|
||||
B = get_int_var_value (name_buf, 0, &OK);
|
||||
if (OK)
|
||||
ada_print_scalar (type, B, stream);
|
||||
else
|
||||
fprintf_filtered (stream, "?");
|
||||
}
|
||||
|
||||
/* Print the range type named NAME. */
|
||||
|
||||
static void
|
||||
print_range_type_named (char *name, struct ui_file *stream)
|
||||
{
|
||||
struct type *raw_type = ada_find_any_type (name);
|
||||
struct type *base_type;
|
||||
LONGEST low, high;
|
||||
char *subtype_info;
|
||||
|
||||
if (raw_type == NULL)
|
||||
base_type = builtin_type_int;
|
||||
else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
|
||||
base_type = TYPE_TARGET_TYPE (raw_type);
|
||||
else
|
||||
base_type = raw_type;
|
||||
|
||||
subtype_info = strstr (name, "___XD");
|
||||
if (subtype_info == NULL && raw_type == NULL)
|
||||
fprintf_filtered (stream, "? .. ?");
|
||||
else if (subtype_info == NULL)
|
||||
print_range (raw_type, stream);
|
||||
else
|
||||
{
|
||||
int prefix_len = subtype_info - name;
|
||||
char *bounds_str;
|
||||
int n;
|
||||
|
||||
subtype_info += 5;
|
||||
bounds_str = strchr (subtype_info, '_');
|
||||
n = 1;
|
||||
|
||||
if (*subtype_info == 'L')
|
||||
{
|
||||
print_range_bound (raw_type, bounds_str, &n, stream);
|
||||
subtype_info += 1;
|
||||
}
|
||||
else
|
||||
print_dynamic_range_bound (raw_type, name, prefix_len, "___L",
|
||||
stream);
|
||||
|
||||
fprintf_filtered (stream, " .. ");
|
||||
|
||||
if (*subtype_info == 'U')
|
||||
print_range_bound (raw_type, bounds_str, &n, stream);
|
||||
else
|
||||
print_dynamic_range_bound (raw_type, name, prefix_len, "___U",
|
||||
stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print enumerated type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_enum_type (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
int len = TYPE_NFIELDS (type);
|
||||
int i, lastval;
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
wrap_here (" ");
|
||||
|
||||
lastval = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (i)
|
||||
fprintf_filtered (stream, ", ");
|
||||
wrap_here (" ");
|
||||
fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
|
||||
if (lastval != TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
fprintf_filtered (stream, " => %d", TYPE_FIELD_BITPOS (type, i));
|
||||
lastval = TYPE_FIELD_BITPOS (type, i);
|
||||
}
|
||||
lastval += 1;
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
/* Print representation of Ada fixed-point type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_fixed_point_type (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
DOUBLEST delta = ada_delta (type);
|
||||
DOUBLEST small = ada_fixed_to_float (type, 1.0);
|
||||
|
||||
if (delta < 0.0)
|
||||
fprintf_filtered (stream, "delta ??");
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "delta %g", (double) delta);
|
||||
if (delta != small)
|
||||
fprintf_filtered (stream, " <'small = %g>", (double) small);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print representation of special VAX floating-point type TYPE on STREAM. */
|
||||
|
||||
static void
|
||||
print_vax_floating_point_type (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
fprintf_filtered (stream, "<float format %c>",
|
||||
ada_vax_float_type_suffix (type));
|
||||
}
|
||||
|
||||
/* Print simple (constrained) array type TYPE on STREAM. LEVEL is the
|
||||
recursion (indentation) level, in case the element type itself has
|
||||
nested structure, and SHOW is the number of levels of internal
|
||||
structure to show (see ada_print_type). */
|
||||
|
||||
static void
|
||||
print_array_type (struct type *type, struct ui_file *stream, int show,
|
||||
int level)
|
||||
{
|
||||
int bitsize;
|
||||
int n_indices;
|
||||
|
||||
bitsize = 0;
|
||||
fprintf_filtered (stream, "array (");
|
||||
|
||||
n_indices = -1;
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, "...");
|
||||
else
|
||||
{
|
||||
if (ada_is_packed_array_type (type))
|
||||
type = ada_coerce_to_simple_array_type (type);
|
||||
if (ada_is_simple_array (type))
|
||||
{
|
||||
struct type *range_desc_type =
|
||||
ada_find_parallel_type (type, "___XA");
|
||||
struct type *arr_type;
|
||||
|
||||
bitsize = 0;
|
||||
if (range_desc_type == NULL)
|
||||
{
|
||||
for (arr_type = type; TYPE_CODE (arr_type) == TYPE_CODE_ARRAY;
|
||||
arr_type = TYPE_TARGET_TYPE (arr_type))
|
||||
{
|
||||
if (arr_type != type)
|
||||
fprintf_filtered (stream, ", ");
|
||||
print_range (TYPE_INDEX_TYPE (arr_type), stream);
|
||||
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
|
||||
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
n_indices = TYPE_NFIELDS (range_desc_type);
|
||||
for (k = 0, arr_type = type;
|
||||
k < n_indices;
|
||||
k += 1, arr_type = TYPE_TARGET_TYPE (arr_type))
|
||||
{
|
||||
if (k > 0)
|
||||
fprintf_filtered (stream, ", ");
|
||||
print_range_type_named (TYPE_FIELD_NAME
|
||||
(range_desc_type, k), stream);
|
||||
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
|
||||
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, i0;
|
||||
for (i = i0 = ada_array_arity (type); i > 0; i -= 1)
|
||||
fprintf_filtered (stream, "%s<>", i == i0 ? "" : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, ") of ");
|
||||
wrap_here ("");
|
||||
ada_print_type (ada_array_element_type (type, n_indices), "", stream,
|
||||
show == 0 ? 0 : show - 1, level + 1);
|
||||
if (bitsize > 0)
|
||||
fprintf_filtered (stream, " <packed: %d-bit elements>", bitsize);
|
||||
}
|
||||
|
||||
/* Print the choices encoded by field FIELD_NUM of variant-part TYPE on
|
||||
STREAM, assuming the VAL_TYPE is the type of the values. */
|
||||
|
||||
static void
|
||||
print_choices (struct type *type, int field_num, struct ui_file *stream,
|
||||
struct type *val_type)
|
||||
{
|
||||
int have_output;
|
||||
int p;
|
||||
const char *name = TYPE_FIELD_NAME (type, field_num);
|
||||
|
||||
have_output = 0;
|
||||
|
||||
/* Skip over leading 'V': NOTE soon to be obsolete. */
|
||||
if (name[0] == 'V')
|
||||
{
|
||||
if (!ada_scan_number (name, 1, NULL, &p))
|
||||
goto Huh;
|
||||
}
|
||||
else
|
||||
p = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (name[p])
|
||||
{
|
||||
default:
|
||||
return;
|
||||
case 'S':
|
||||
case 'R':
|
||||
case 'O':
|
||||
if (have_output)
|
||||
fprintf_filtered (stream, " | ");
|
||||
have_output = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (name[p])
|
||||
{
|
||||
case 'S':
|
||||
{
|
||||
LONGEST W;
|
||||
if (!ada_scan_number (name, p + 1, &W, &p))
|
||||
goto Huh;
|
||||
ada_print_scalar (val_type, W, stream);
|
||||
break;
|
||||
}
|
||||
case 'R':
|
||||
{
|
||||
LONGEST L, U;
|
||||
if (!ada_scan_number (name, p + 1, &L, &p)
|
||||
|| name[p] != 'T' || !ada_scan_number (name, p + 1, &U, &p))
|
||||
goto Huh;
|
||||
ada_print_scalar (val_type, L, stream);
|
||||
fprintf_filtered (stream, " .. ");
|
||||
ada_print_scalar (val_type, U, stream);
|
||||
break;
|
||||
}
|
||||
case 'O':
|
||||
fprintf_filtered (stream, "others");
|
||||
p += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Huh:
|
||||
fprintf_filtered (stream, "??");
|
||||
|
||||
}
|
||||
|
||||
/* Assuming that field FIELD_NUM of TYPE is a VARIANTS field whose
|
||||
discriminant is contained in OUTER_TYPE, print its variants on STREAM.
|
||||
LEVEL is the recursion
|
||||
(indentation) level, in case any of the fields themselves have
|
||||
nested structure, and SHOW is the number of levels of internal structure
|
||||
to show (see ada_print_type). For this purpose, fields nested in a
|
||||
variant part are taken to be at the same level as the fields
|
||||
immediately outside the variant part. */
|
||||
|
||||
static void
|
||||
print_variant_clauses (struct type *type, int field_num,
|
||||
struct type *outer_type, struct ui_file *stream,
|
||||
int show, int level)
|
||||
{
|
||||
int i;
|
||||
struct type *var_type;
|
||||
struct type *discr_type;
|
||||
|
||||
var_type = TYPE_FIELD_TYPE (type, field_num);
|
||||
discr_type = ada_variant_discrim_type (var_type, outer_type);
|
||||
|
||||
if (TYPE_CODE (var_type) == TYPE_CODE_PTR)
|
||||
{
|
||||
var_type = TYPE_TARGET_TYPE (var_type);
|
||||
if (TYPE_FLAGS (var_type) & TYPE_FLAG_STUB)
|
||||
{
|
||||
var_type = ada_find_parallel_type (var_type, "___XVU");
|
||||
if (var_type == NULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (var_type); i += 1)
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*swhen ", level + 4, "");
|
||||
print_choices (var_type, i, stream, discr_type);
|
||||
fprintf_filtered (stream, " =>");
|
||||
if (print_record_field_types (TYPE_FIELD_TYPE (var_type, i),
|
||||
outer_type, stream, show, level + 4) <= 0)
|
||||
fprintf_filtered (stream, " null;");
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming that field FIELD_NUM of TYPE is a variant part whose
|
||||
discriminants are contained in OUTER_TYPE, print a description of it
|
||||
on STREAM. LEVEL is the recursion (indentation) level, in case any of
|
||||
the fields themselves have nested structure, and SHOW is the number of
|
||||
levels of internal structure to show (see ada_print_type). For this
|
||||
purpose, fields nested in a variant part are taken to be at the same
|
||||
level as the fields immediately outside the variant part. */
|
||||
|
||||
static void
|
||||
print_variant_part (struct type *type, int field_num, struct type *outer_type,
|
||||
struct ui_file *stream, int show, int level)
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*scase %s is", level + 4, "",
|
||||
ada_variant_discrim_name
|
||||
(TYPE_FIELD_TYPE (type, field_num)));
|
||||
print_variant_clauses (type, field_num, outer_type, stream, show,
|
||||
level + 4);
|
||||
fprintf_filtered (stream, "\n%*send case;", level + 4, "");
|
||||
}
|
||||
|
||||
/* Print a description on STREAM of the fields in record type TYPE, whose
|
||||
discriminants are in OUTER_TYPE. LEVEL is the recursion (indentation)
|
||||
level, in case any of the fields themselves have nested structure,
|
||||
and SHOW is the number of levels of internal structure to show
|
||||
(see ada_print_type). Does not print parent type information of TYPE.
|
||||
Returns 0 if no fields printed, -1 for an incomplete type, else > 0.
|
||||
Prints each field beginning on a new line, but does not put a new line at
|
||||
end. */
|
||||
|
||||
static int
|
||||
print_record_field_types (struct type *type, struct type *outer_type,
|
||||
struct ui_file *stream, int show, int level)
|
||||
{
|
||||
int len, i, flds;
|
||||
|
||||
flds = 0;
|
||||
len = TYPE_NFIELDS (type);
|
||||
|
||||
if (len == 0 && (TYPE_FLAGS (type) & TYPE_FLAG_STUB) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
QUIT;
|
||||
|
||||
if (ada_is_parent_field (type, i) || ada_is_ignored_field (type, i))
|
||||
;
|
||||
else if (ada_is_wrapper_field (type, i))
|
||||
flds += print_record_field_types (TYPE_FIELD_TYPE (type, i), type,
|
||||
stream, show, level);
|
||||
else if (ada_is_variant_part (type, i))
|
||||
{
|
||||
print_variant_part (type, i, outer_type, stream, show, level);
|
||||
flds = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
flds += 1;
|
||||
fprintf_filtered (stream, "\n%*s", level + 4, "");
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
fprintf_filtered (stream, ";");
|
||||
}
|
||||
}
|
||||
|
||||
return flds;
|
||||
}
|
||||
|
||||
/* Print record type TYPE on STREAM. LEVEL is the recursion (indentation)
|
||||
level, in case the element type itself has nested structure, and SHOW is
|
||||
the number of levels of internal structure to show (see ada_print_type). */
|
||||
|
||||
static void
|
||||
print_record_type (struct type *type0, struct ui_file *stream, int show,
|
||||
int level)
|
||||
{
|
||||
struct type *parent_type;
|
||||
struct type *type;
|
||||
|
||||
type = type0;
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
|
||||
{
|
||||
struct type *type1 = ada_find_parallel_type (type, "___XVE");
|
||||
if (type1 != NULL)
|
||||
type = type1;
|
||||
}
|
||||
|
||||
parent_type = ada_parent_type (type);
|
||||
if (ada_type_name (parent_type) != NULL)
|
||||
fprintf_filtered (stream, "new %s with ",
|
||||
demangled_type_name (parent_type));
|
||||
else if (parent_type == NULL && ada_is_tagged_type (type))
|
||||
fprintf_filtered (stream, "tagged ");
|
||||
|
||||
fprintf_filtered (stream, "record");
|
||||
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, " ... end record");
|
||||
else
|
||||
{
|
||||
int flds;
|
||||
|
||||
flds = 0;
|
||||
if (parent_type != NULL && ada_type_name (parent_type) == NULL)
|
||||
flds += print_record_field_types (parent_type, parent_type,
|
||||
stream, show, level);
|
||||
flds += print_record_field_types (type, type, stream, show, level);
|
||||
|
||||
if (flds > 0)
|
||||
fprintf_filtered (stream, "\n%*send record", level, "");
|
||||
else if (flds < 0)
|
||||
fprintf_filtered (stream, " <incomplete type> end record");
|
||||
else
|
||||
fprintf_filtered (stream, " null; end record");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the unchecked union type TYPE in something resembling Ada
|
||||
format on STREAM. LEVEL is the recursion (indentation) level
|
||||
in case the element type itself has nested structure, and SHOW is the
|
||||
number of levels of internal structure to show (see ada_print_type). */
|
||||
static void
|
||||
print_unchecked_union_type (struct type *type, struct ui_file *stream,
|
||||
int show, int level)
|
||||
{
|
||||
fprintf_filtered (stream, "record (?) is");
|
||||
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, " ... end record");
|
||||
else if (TYPE_NFIELDS (type) == 0)
|
||||
fprintf_filtered (stream, " null; end record");
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf_filtered (stream, "\n%*scase ? is", level + 4, "");
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (type); i += 1)
|
||||
{
|
||||
fprintf_filtered (stream, "\n%*swhen ? =>\n%*s", level + 8, "",
|
||||
level + 12, "");
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 12);
|
||||
fprintf_filtered (stream, ";");
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, "\n%*send case;\n%*send record",
|
||||
level + 4, "", level, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Print function or procedure type TYPE on STREAM. Make it a header
|
||||
for function or procedure NAME if NAME is not null. */
|
||||
|
||||
static void
|
||||
print_func_type (struct type *type, struct ui_file *stream, char *name)
|
||||
{
|
||||
int i, len = TYPE_NFIELDS (type);
|
||||
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
|
||||
fprintf_filtered (stream, "procedure");
|
||||
else
|
||||
fprintf_filtered (stream, "function");
|
||||
|
||||
if (name != NULL && name[0] != '\0')
|
||||
fprintf_filtered (stream, " %s", name);
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
fprintf_filtered (stream, " (");
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
fputs_filtered ("; ", stream);
|
||||
wrap_here (" ");
|
||||
}
|
||||
fprintf_filtered (stream, "a%d: ", i + 1);
|
||||
ada_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
|
||||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, " return ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print a description of a type TYPE0.
|
||||
Output goes to STREAM (via stdio).
|
||||
If VARSTRING is a non-empty string, print as an Ada variable/field
|
||||
declaration.
|
||||
SHOW+1 is the maximum number of levels of internal type structure
|
||||
to show (this applies to record types, enumerated types, and
|
||||
array types).
|
||||
SHOW is the number of levels of internal type structure to show
|
||||
when there is a type name for the SHOWth deepest level (0th is
|
||||
outer level).
|
||||
When SHOW<0, no inner structure is shown.
|
||||
LEVEL indicates level of recursion (for nested definitions). */
|
||||
|
||||
void
|
||||
ada_print_type (struct type *type0, char *varstring, struct ui_file *stream,
|
||||
int show, int level)
|
||||
{
|
||||
enum type_code code;
|
||||
int demangled_args;
|
||||
struct type *type = ada_completed_type (ada_get_base_type (type0));
|
||||
char *type_name = demangled_type_name (type);
|
||||
int is_var_decl = (varstring != NULL && varstring[0] != '\0');
|
||||
|
||||
if (type == NULL)
|
||||
{
|
||||
if (is_var_decl)
|
||||
fprintf_filtered (stream, "%.*s: ",
|
||||
ada_name_prefix_len (varstring), varstring);
|
||||
fprintf_filtered (stream, "<null type?>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (show > 0)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (is_var_decl && TYPE_CODE (type) != TYPE_CODE_FUNC)
|
||||
fprintf_filtered (stream, "%.*s: ",
|
||||
ada_name_prefix_len (varstring), varstring);
|
||||
|
||||
if (type_name != NULL && show <= 0)
|
||||
{
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (type_name), type_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ada_is_aligner_type (type))
|
||||
ada_print_type (ada_aligned_type (type), "", stream, show, level);
|
||||
else if (ada_is_packed_array_type (type))
|
||||
print_array_type (type, stream, show, level);
|
||||
else
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
default:
|
||||
fprintf_filtered (stream, "<");
|
||||
c_print_type (type, "", stream, show, level);
|
||||
fprintf_filtered (stream, ">");
|
||||
break;
|
||||
case TYPE_CODE_PTR:
|
||||
fprintf_filtered (stream, "access ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_REF:
|
||||
fprintf_filtered (stream, "<ref> ");
|
||||
ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_ARRAY:
|
||||
print_array_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_INT:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
print_fixed_point_type (type, stream);
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
print_vax_floating_point_type (type, stream);
|
||||
else
|
||||
{
|
||||
char *name = ada_type_name (type);
|
||||
if (!ada_is_range_type_name (name))
|
||||
fprintf_filtered (stream, "<%d-byte integer>",
|
||||
TYPE_LENGTH (type));
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "range ");
|
||||
print_range_type_named (name, stream);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_RANGE:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
print_fixed_point_type (type, stream);
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
print_vax_floating_point_type (type, stream);
|
||||
else if (ada_is_modular_type (type))
|
||||
fprintf_filtered (stream, "mod %ld", (long) ada_modulus (type));
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "range ");
|
||||
print_range (type, stream);
|
||||
}
|
||||
break;
|
||||
case TYPE_CODE_FLT:
|
||||
fprintf_filtered (stream, "<%d-byte float>", TYPE_LENGTH (type));
|
||||
break;
|
||||
case TYPE_CODE_ENUM:
|
||||
if (show < 0)
|
||||
fprintf_filtered (stream, "(...)");
|
||||
else
|
||||
print_enum_type (type, stream);
|
||||
break;
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (ada_is_array_descriptor (type))
|
||||
print_array_type (type, stream, show, level);
|
||||
else if (ada_is_bogus_array_descriptor (type))
|
||||
fprintf_filtered (stream,
|
||||
"array (?) of ? (<mal-formed descriptor>)");
|
||||
else
|
||||
print_record_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_UNION:
|
||||
print_unchecked_union_type (type, stream, show, level);
|
||||
break;
|
||||
case TYPE_CODE_FUNC:
|
||||
print_func_type (type, stream, varstring);
|
||||
break;
|
||||
}
|
||||
}
|
||||
987
contrib/gdb/gdb/ada-valprint.c
Normal file
987
contrib/gdb/gdb/ada-valprint.c
Normal file
|
|
@ -0,0 +1,987 @@
|
|||
/* Support for printing Ada values for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1997, 2001
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "value.h"
|
||||
#include "demangle.h"
|
||||
#include "valprint.h"
|
||||
#include "language.h"
|
||||
#include "annotate.h"
|
||||
#include "ada-lang.h"
|
||||
#include "c-lang.h"
|
||||
#include "infcall.h"
|
||||
|
||||
/* Encapsulates arguments to ada_val_print. */
|
||||
struct ada_val_print_args
|
||||
{
|
||||
struct type *type;
|
||||
char *valaddr0;
|
||||
int embedded_offset;
|
||||
CORE_ADDR address;
|
||||
struct ui_file *stream;
|
||||
int format;
|
||||
int deref_ref;
|
||||
int recurse;
|
||||
enum val_prettyprint pretty;
|
||||
};
|
||||
|
||||
static void print_record (struct type *, char *, struct ui_file *, int,
|
||||
int, enum val_prettyprint);
|
||||
|
||||
static int print_field_values (struct type *, char *, struct ui_file *,
|
||||
int, int, enum val_prettyprint,
|
||||
int, struct type *, char *);
|
||||
|
||||
static int print_variant_part (struct type *, int, char *,
|
||||
struct ui_file *, int, int,
|
||||
enum val_prettyprint, int, struct type *,
|
||||
char *);
|
||||
|
||||
static void val_print_packed_array_elements (struct type *, char *valaddr,
|
||||
int, struct ui_file *, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
static void adjust_type_signedness (struct type *);
|
||||
|
||||
static int ada_val_print_stub (void *args0);
|
||||
|
||||
static int ada_val_print_1 (struct type *, char *, int, CORE_ADDR,
|
||||
struct ui_file *, int, int, int,
|
||||
enum val_prettyprint);
|
||||
|
||||
|
||||
/* Make TYPE unsigned if its range of values includes no negatives. */
|
||||
static void
|
||||
adjust_type_signedness (struct type *type)
|
||||
{
|
||||
if (type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE
|
||||
&& TYPE_LOW_BOUND (type) >= 0)
|
||||
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
|
||||
}
|
||||
|
||||
/* Assuming TYPE is a simple array type, prints its lower bound on STREAM,
|
||||
if non-standard (i.e., other than 1 for numbers, other than lower bound
|
||||
of index type for enumerated type). Returns 1 if something printed,
|
||||
otherwise 0. */
|
||||
|
||||
static int
|
||||
print_optional_low_bound (struct ui_file *stream, struct type *type)
|
||||
{
|
||||
struct type *index_type;
|
||||
long low_bound;
|
||||
|
||||
index_type = TYPE_INDEX_TYPE (type);
|
||||
low_bound = 0;
|
||||
|
||||
if (index_type == NULL)
|
||||
return 0;
|
||||
if (TYPE_CODE (index_type) == TYPE_CODE_RANGE)
|
||||
{
|
||||
low_bound = TYPE_LOW_BOUND (index_type);
|
||||
index_type = TYPE_TARGET_TYPE (index_type);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
switch (TYPE_CODE (index_type))
|
||||
{
|
||||
case TYPE_CODE_ENUM:
|
||||
if (low_bound == TYPE_FIELD_BITPOS (index_type, 0))
|
||||
return 0;
|
||||
break;
|
||||
case TYPE_CODE_UNDEF:
|
||||
index_type = builtin_type_long;
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
if (low_bound == 1)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ada_print_scalar (index_type, (LONGEST) low_bound, stream);
|
||||
fprintf_filtered (stream, " => ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Version of val_print_array_elements for GNAT-style packed arrays.
|
||||
Prints elements of packed array of type TYPE at bit offset
|
||||
BITOFFSET from VALADDR on STREAM. Formats according to FORMAT and
|
||||
separates with commas. RECURSE is the recursion (nesting) level.
|
||||
If PRETTY, uses "prettier" format. TYPE must have been decoded (as
|
||||
by ada_coerce_to_simple_array). */
|
||||
|
||||
static void
|
||||
val_print_packed_array_elements (struct type *type, char *valaddr,
|
||||
int bitoffset, struct ui_file *stream,
|
||||
int format, int recurse,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
unsigned eltlen;
|
||||
/* Position of the array element we are examining to see
|
||||
whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
|
||||
struct value *mark = value_mark ();
|
||||
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
eltlen = TYPE_LENGTH (check_typedef (elttype));
|
||||
|
||||
{
|
||||
LONGEST low, high;
|
||||
if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), &low, &high) < 0)
|
||||
len = 1;
|
||||
else
|
||||
len = high - low + 1;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
annotate_array_section_begin (i, elttype);
|
||||
|
||||
while (i < len && things_printed < print_max)
|
||||
{
|
||||
struct value *v0, *v1;
|
||||
int i0;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
fprintf_filtered (stream, ",\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
}
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
|
||||
i0 = i;
|
||||
v0 = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
(i0 * bitsize) / HOST_CHAR_BIT,
|
||||
(i0 * bitsize) % HOST_CHAR_BIT,
|
||||
bitsize, elttype);
|
||||
while (1)
|
||||
{
|
||||
i += 1;
|
||||
if (i >= len)
|
||||
break;
|
||||
v1 = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
(i * bitsize) / HOST_CHAR_BIT,
|
||||
(i * bitsize) % HOST_CHAR_BIT,
|
||||
bitsize, elttype);
|
||||
if (memcmp (VALUE_CONTENTS (v0), VALUE_CONTENTS (v1), eltlen) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i - i0 > repeat_count_threshold)
|
||||
{
|
||||
val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
|
||||
0, recurse + 1, pretty);
|
||||
annotate_elt_rep (i - i0);
|
||||
fprintf_filtered (stream, " <repeats %u times>", i - i0);
|
||||
annotate_elt_rep_end ();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int j;
|
||||
for (j = i0; j < i; j += 1)
|
||||
{
|
||||
if (j > i0)
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
fprintf_filtered (stream, ",\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
}
|
||||
val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
|
||||
0, recurse + 1, pretty);
|
||||
annotate_elt ();
|
||||
}
|
||||
}
|
||||
things_printed += i - i0;
|
||||
}
|
||||
annotate_array_section_end ();
|
||||
if (i < len)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
|
||||
value_free_to_mark (mark);
|
||||
}
|
||||
|
||||
static struct type *
|
||||
printable_val_type (struct type *type, char *valaddr)
|
||||
{
|
||||
return ada_to_fixed_type (ada_aligned_type (type), valaddr, 0, NULL);
|
||||
}
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string whose delimiter is QUOTER. TYPE_LEN is the length in bytes
|
||||
(1 or 2) of the character. */
|
||||
|
||||
void
|
||||
ada_emit_char (int c, struct ui_file *stream, int quoter, int type_len)
|
||||
{
|
||||
if (type_len != 2)
|
||||
type_len = 1;
|
||||
|
||||
c &= (1 << (type_len * TARGET_CHAR_BIT)) - 1;
|
||||
|
||||
if (isascii (c) && isprint (c))
|
||||
{
|
||||
if (c == quoter && c == '"')
|
||||
fprintf_filtered (stream, "[\"%c\"]", quoter);
|
||||
else
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "[\"%0*x\"]", type_len * 2, c);
|
||||
}
|
||||
|
||||
/* Character #I of STRING, given that TYPE_LEN is the size in bytes (1
|
||||
or 2) of a character. */
|
||||
|
||||
static int
|
||||
char_at (char *string, int i, int type_len)
|
||||
{
|
||||
if (type_len == 1)
|
||||
return string[i];
|
||||
else
|
||||
return (int) extract_unsigned_integer (string + 2 * i, 2);
|
||||
}
|
||||
|
||||
void
|
||||
ada_printchar (int c, struct ui_file *stream)
|
||||
{
|
||||
fputs_filtered ("'", stream);
|
||||
ada_emit_char (c, stream, '\'', 1);
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
/* [From print_type_scalar in typeprint.c]. Print VAL on STREAM in a
|
||||
form appropriate for TYPE. */
|
||||
|
||||
void
|
||||
ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned len;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (TYPE_FIELD_BITPOS (type, i) == val)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
LA_PRINT_CHAR ((unsigned char) val, stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_BOOL:
|
||||
fprintf_filtered (stream, val ? "true" : "false");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_RANGE:
|
||||
ada_print_scalar (TYPE_TARGET_TYPE (type), val, stream);
|
||||
return;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_FLT:
|
||||
case TYPE_CODE_VOID:
|
||||
case TYPE_CODE_SET:
|
||||
case TYPE_CODE_STRING:
|
||||
case TYPE_CODE_ERROR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_METHOD:
|
||||
case TYPE_CODE_REF:
|
||||
warning ("internal error: unhandled type in ada_print_scalar");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid type code in symbol table.");
|
||||
}
|
||||
gdb_flush (stream);
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH characters.
|
||||
Printing stops early if the number hits print_max; repeat counts
|
||||
are printed as appropriate. Print ellipses at the end if we
|
||||
had to stop before printing LENGTH characters, or if
|
||||
FORCE_ELLIPSES. TYPE_LEN is the length (1 or 2) of the character type.
|
||||
*/
|
||||
|
||||
static void
|
||||
printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int force_ellipses, int type_len)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length && things_printed < print_max; i += 1)
|
||||
{
|
||||
/* Position of the character we are examining
|
||||
to see whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length &&
|
||||
char_at (string, rep1, type_len) == char_at (string, i,
|
||||
type_len))
|
||||
{
|
||||
rep1 += 1;
|
||||
reps += 1;
|
||||
}
|
||||
|
||||
if (reps > repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\", ", stream);
|
||||
else
|
||||
fputs_filtered ("\", ", stream);
|
||||
in_quotes = 0;
|
||||
}
|
||||
fputs_filtered ("'", stream);
|
||||
ada_emit_char (char_at (string, i, type_len), stream, '\'',
|
||||
type_len);
|
||||
fputs_filtered ("'", stream);
|
||||
fprintf_filtered (stream, " <repeats %u times>", reps);
|
||||
i = rep1 - 1;
|
||||
things_printed += repeat_count_threshold;
|
||||
need_comma = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\"", stream);
|
||||
else
|
||||
fputs_filtered ("\"", stream);
|
||||
in_quotes = 1;
|
||||
}
|
||||
ada_emit_char (char_at (string, i, type_len), stream, '"',
|
||||
type_len);
|
||||
things_printed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\\"", stream);
|
||||
else
|
||||
fputs_filtered ("\"", stream);
|
||||
}
|
||||
|
||||
if (force_ellipses || i < length)
|
||||
fputs_filtered ("...", stream);
|
||||
}
|
||||
|
||||
void
|
||||
ada_printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int force_ellipses, int width)
|
||||
{
|
||||
printstr (stream, string, length, force_ellipses, width);
|
||||
}
|
||||
|
||||
|
||||
/* Print data of type TYPE located at VALADDR (within GDB), which came from
|
||||
the inferior at address ADDRESS, onto stdio stream STREAM according to
|
||||
FORMAT (a letter as for the printf % codes or 0 for natural format).
|
||||
The data at VALADDR is in target byte order.
|
||||
|
||||
If the data is printed as a string, returns the number of string characters
|
||||
printed.
|
||||
|
||||
If DEREF_REF is nonzero, then dereference references, otherwise just print
|
||||
them like pointers.
|
||||
|
||||
RECURSE indicates the amount of indentation to supply before
|
||||
continuation lines; this amount is roughly twice the value of RECURSE.
|
||||
|
||||
When PRETTY is non-zero, prints record fields on separate lines.
|
||||
(For some reason, the current version of gdb instead uses a global
|
||||
variable---prettyprint_arrays--- to causes a similar effect on
|
||||
arrays.) */
|
||||
|
||||
int
|
||||
ada_val_print (struct type *type, char *valaddr0, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
struct ada_val_print_args args;
|
||||
args.type = type;
|
||||
args.valaddr0 = valaddr0;
|
||||
args.embedded_offset = embedded_offset;
|
||||
args.address = address;
|
||||
args.stream = stream;
|
||||
args.format = format;
|
||||
args.deref_ref = deref_ref;
|
||||
args.recurse = recurse;
|
||||
args.pretty = pretty;
|
||||
|
||||
return catch_errors (ada_val_print_stub, &args, NULL, RETURN_MASK_ALL);
|
||||
}
|
||||
|
||||
/* Helper for ada_val_print; used as argument to catch_errors to
|
||||
unmarshal the arguments to ada_val_print_1, which does the work. */
|
||||
static int
|
||||
ada_val_print_stub (void * args0)
|
||||
{
|
||||
struct ada_val_print_args *argsp = (struct ada_val_print_args *) args0;
|
||||
return ada_val_print_1 (argsp->type, argsp->valaddr0,
|
||||
argsp->embedded_offset, argsp->address,
|
||||
argsp->stream, argsp->format, argsp->deref_ref,
|
||||
argsp->recurse, argsp->pretty);
|
||||
}
|
||||
|
||||
/* See the comment on ada_val_print. This function differs in that it
|
||||
* does not catch evaluation errors (leaving that to ada_val_print). */
|
||||
|
||||
static int
|
||||
ada_val_print_1 (struct type *type, char *valaddr0, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
unsigned int len;
|
||||
int i;
|
||||
struct type *elttype;
|
||||
unsigned int eltlen;
|
||||
LONGEST val;
|
||||
CORE_ADDR addr;
|
||||
char *valaddr = valaddr0 + embedded_offset;
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if (ada_is_array_descriptor (type) || ada_is_packed_array_type (type))
|
||||
{
|
||||
int retn;
|
||||
struct value *mark = value_mark ();
|
||||
struct value *val;
|
||||
val = value_from_contents_and_address (type, valaddr, address);
|
||||
val = ada_coerce_to_simple_array_ptr (val);
|
||||
if (val == NULL)
|
||||
{
|
||||
fprintf_filtered (stream, "(null)");
|
||||
retn = 0;
|
||||
}
|
||||
else
|
||||
retn = ada_val_print_1 (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
|
||||
VALUE_ADDRESS (val), stream, format,
|
||||
deref_ref, recurse, pretty);
|
||||
value_free_to_mark (mark);
|
||||
return retn;
|
||||
}
|
||||
|
||||
valaddr = ada_aligned_value_addr (type, valaddr);
|
||||
embedded_offset -= valaddr - valaddr0 - embedded_offset;
|
||||
type = printable_val_type (type, valaddr);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
default:
|
||||
return c_val_print (type, valaddr0, embedded_offset, address, stream,
|
||||
format, deref_ref, recurse, pretty);
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_RANGE:
|
||||
if (ada_is_fixed_point_type (type))
|
||||
{
|
||||
LONGEST v = unpack_long (type, valaddr);
|
||||
int len = TYPE_LENGTH (type);
|
||||
|
||||
fprintf_filtered (stream, len < 4 ? "%.11g" : "%.17g",
|
||||
(double) ada_fixed_to_float (type, v));
|
||||
return 0;
|
||||
}
|
||||
else if (ada_is_vax_floating_type (type))
|
||||
{
|
||||
struct value *val =
|
||||
value_from_contents_and_address (type, valaddr, address);
|
||||
struct value *func = ada_vax_float_print_function (type);
|
||||
if (func != 0)
|
||||
{
|
||||
static struct type *parray_of_char = NULL;
|
||||
struct value *printable_val;
|
||||
|
||||
if (parray_of_char == NULL)
|
||||
parray_of_char =
|
||||
make_pointer_type
|
||||
(create_array_type
|
||||
(NULL, builtin_type_char,
|
||||
create_range_type (NULL, builtin_type_int, 0, 32)), NULL);
|
||||
|
||||
printable_val =
|
||||
value_ind (value_cast (parray_of_char,
|
||||
call_function_by_hand (func, 1,
|
||||
&val)));
|
||||
|
||||
fprintf_filtered (stream, "%s", VALUE_CONTENTS (printable_val));
|
||||
return 0;
|
||||
}
|
||||
/* No special printing function. Do as best we can. */
|
||||
}
|
||||
else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
|
||||
{
|
||||
struct type *target_type = TYPE_TARGET_TYPE (type);
|
||||
if (TYPE_LENGTH (type) != TYPE_LENGTH (target_type))
|
||||
{
|
||||
/* Obscure case of range type that has different length from
|
||||
its base type. Perform a conversion, or we will get a
|
||||
nonsense value. Actually, we could use the same
|
||||
code regardless of lengths; I'm just avoiding a cast. */
|
||||
struct value *v = value_cast (target_type,
|
||||
value_from_contents_and_address
|
||||
(type, valaddr, 0));
|
||||
return ada_val_print_1 (target_type, VALUE_CONTENTS (v), 0, 0,
|
||||
stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
else
|
||||
return ada_val_print_1 (TYPE_TARGET_TYPE (type),
|
||||
valaddr0, embedded_offset,
|
||||
address, stream, format, deref_ref,
|
||||
recurse, pretty);
|
||||
}
|
||||
else
|
||||
{
|
||||
format = format ? format : output_format;
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
val_print_type_code_int (type, valaddr, stream);
|
||||
if (ada_is_character_type (type))
|
||||
{
|
||||
fputs_filtered (" ", stream);
|
||||
ada_printchar ((unsigned char) unpack_long (type, valaddr),
|
||||
stream);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
if (format)
|
||||
{
|
||||
print_scalar_formatted (valaddr, type, format, 0, stream);
|
||||
break;
|
||||
}
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (type, valaddr);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (val == TYPE_FIELD_BITPOS (type, i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < len)
|
||||
{
|
||||
const char *name = ada_enum_name (TYPE_FIELD_NAME (type, i));
|
||||
if (name[0] == '\'')
|
||||
fprintf_filtered (stream, "%ld %s", (long) val, name);
|
||||
else
|
||||
fputs_filtered (name, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_longest (stream, 'd', 0, val);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNION:
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (ada_is_bogus_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(...?)");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_record (type, valaddr, stream, format, recurse, pretty);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
|
||||
{
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
eltlen = TYPE_LENGTH (elttype);
|
||||
len = TYPE_LENGTH (type) / eltlen;
|
||||
|
||||
/* For an array of chars, print with string syntax. */
|
||||
if (ada_is_string_type (type) && (format == 0 || format == 's'))
|
||||
{
|
||||
if (prettyprint_arrays)
|
||||
{
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
/* If requested, look for the first null char and only print
|
||||
elements up to it. */
|
||||
if (stop_print_at_null)
|
||||
{
|
||||
int temp_len;
|
||||
|
||||
/* Look for a NULL char. */
|
||||
for (temp_len = 0;
|
||||
temp_len < len && temp_len < print_max
|
||||
&& char_at (valaddr, temp_len, eltlen) != 0;
|
||||
temp_len += 1);
|
||||
len = temp_len;
|
||||
}
|
||||
|
||||
printstr (stream, valaddr, len, 0, eltlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
fprintf_filtered (stream, "(");
|
||||
print_optional_low_bound (stream, type);
|
||||
if (TYPE_FIELD_BITSIZE (type, 0) > 0)
|
||||
val_print_packed_array_elements (type, valaddr, 0, stream,
|
||||
format, recurse, pretty);
|
||||
else
|
||||
val_print_array_elements (type, valaddr, address, stream,
|
||||
format, deref_ref, recurse,
|
||||
pretty, 0);
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
gdb_flush (stream);
|
||||
return len;
|
||||
}
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
if (addressprint)
|
||||
{
|
||||
fprintf_filtered (stream, "@");
|
||||
/* Extract an address, assume that the address is unsigned. */
|
||||
print_address_numeric
|
||||
(extract_unsigned_integer (valaddr,
|
||||
TARGET_PTR_BIT / HOST_CHAR_BIT),
|
||||
1, stream);
|
||||
if (deref_ref)
|
||||
fputs_filtered (": ", stream);
|
||||
}
|
||||
/* De-reference the reference */
|
||||
if (deref_ref)
|
||||
{
|
||||
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
|
||||
{
|
||||
LONGEST deref_val_int = (LONGEST)
|
||||
unpack_pointer (lookup_pointer_type (builtin_type_void),
|
||||
valaddr);
|
||||
if (deref_val_int != 0)
|
||||
{
|
||||
struct value *deref_val =
|
||||
ada_value_ind (value_from_longest
|
||||
(lookup_pointer_type (elttype),
|
||||
deref_val_int));
|
||||
val_print (VALUE_TYPE (deref_val),
|
||||
VALUE_CONTENTS (deref_val), 0,
|
||||
VALUE_ADDRESS (deref_val), stream, format,
|
||||
deref_ref, recurse + 1, pretty);
|
||||
}
|
||||
else
|
||||
fputs_filtered ("(null)", stream);
|
||||
}
|
||||
else
|
||||
fputs_filtered ("???", stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
print_variant_part (struct type *type, int field_num, char *valaddr,
|
||||
struct ui_file *stream, int format, int recurse,
|
||||
enum val_prettyprint pretty, int comma_needed,
|
||||
struct type *outer_type, char *outer_valaddr)
|
||||
{
|
||||
struct type *var_type = TYPE_FIELD_TYPE (type, field_num);
|
||||
int which = ada_which_variant_applies (var_type, outer_type, outer_valaddr);
|
||||
|
||||
if (which < 0)
|
||||
return 0;
|
||||
else
|
||||
return print_field_values
|
||||
(TYPE_FIELD_TYPE (var_type, which),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT
|
||||
+ TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT,
|
||||
stream, format, recurse, pretty,
|
||||
comma_needed, outer_type, outer_valaddr);
|
||||
}
|
||||
|
||||
int
|
||||
ada_value_print (struct value *val0, struct ui_file *stream, int format,
|
||||
enum val_prettyprint pretty)
|
||||
{
|
||||
char *valaddr = VALUE_CONTENTS (val0);
|
||||
CORE_ADDR address = VALUE_ADDRESS (val0) + VALUE_OFFSET (val0);
|
||||
struct type *type =
|
||||
ada_to_fixed_type (VALUE_TYPE (val0), valaddr, address, NULL);
|
||||
struct value *val =
|
||||
value_from_contents_and_address (type, valaddr, address);
|
||||
|
||||
/* If it is a pointer, indicate what it points to. */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
{
|
||||
/* Hack: remove (char *) for char strings. Their
|
||||
type is indicated by the quoted string anyway. */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR &&
|
||||
TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof (char) &&
|
||||
TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT &&
|
||||
!TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)))
|
||||
{
|
||||
/* Print nothing */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
}
|
||||
else if (ada_is_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") ");
|
||||
}
|
||||
else if (ada_is_bogus_array_descriptor (type))
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf_filtered (stream, ") (...?)");
|
||||
return 0;
|
||||
}
|
||||
return (val_print (type, VALUE_CONTENTS (val), 0, address,
|
||||
stream, format, 1, 0, pretty));
|
||||
}
|
||||
|
||||
static void
|
||||
print_record (struct type *type, char *valaddr, struct ui_file *stream,
|
||||
int format, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
|
||||
if (print_field_values (type, valaddr, stream, format, recurse, pretty,
|
||||
0, type, valaddr) != 0 && pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 * recurse, stream);
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
||||
/* Print out fields of value at VALADDR having structure type TYPE.
|
||||
|
||||
TYPE, VALADDR, STREAM, FORMAT, RECURSE, and PRETTY have the
|
||||
same meanings as in ada_print_value and ada_val_print.
|
||||
|
||||
OUTER_TYPE and OUTER_VALADDR give type and address of enclosing record
|
||||
(used to get discriminant values when printing variant parts).
|
||||
|
||||
COMMA_NEEDED is 1 if fields have been printed at the current recursion
|
||||
level, so that a comma is needed before any field printed by this
|
||||
call.
|
||||
|
||||
Returns 1 if COMMA_NEEDED or any fields were printed. */
|
||||
|
||||
static int
|
||||
print_field_values (struct type *type, char *valaddr, struct ui_file *stream,
|
||||
int format, int recurse, enum val_prettyprint pretty,
|
||||
int comma_needed, struct type *outer_type,
|
||||
char *outer_valaddr)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
len = TYPE_NFIELDS (type);
|
||||
|
||||
for (i = 0; i < len; i += 1)
|
||||
{
|
||||
if (ada_is_ignored_field (type, i))
|
||||
continue;
|
||||
|
||||
if (ada_is_wrapper_field (type, i))
|
||||
{
|
||||
comma_needed =
|
||||
print_field_values (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr
|
||||
+ TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
|
||||
stream, format, recurse, pretty,
|
||||
comma_needed, type, valaddr);
|
||||
continue;
|
||||
}
|
||||
else if (ada_is_variant_part (type, i))
|
||||
{
|
||||
comma_needed =
|
||||
print_variant_part (type, i, valaddr,
|
||||
stream, format, recurse, pretty, comma_needed,
|
||||
outer_type, outer_valaddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comma_needed)
|
||||
fprintf_filtered (stream, ", ");
|
||||
comma_needed = 1;
|
||||
|
||||
if (pretty)
|
||||
{
|
||||
fprintf_filtered (stream, "\n");
|
||||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
wrap_here (n_spaces (2 + 2 * recurse));
|
||||
}
|
||||
if (inspect_it)
|
||||
{
|
||||
if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
|
||||
fputs_filtered ("\"( ptr \"", stream);
|
||||
else
|
||||
fputs_filtered ("\"( nodef \"", stream);
|
||||
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
|
||||
language_cplus, DMGL_NO_OPTS);
|
||||
fputs_filtered ("\" \"", stream);
|
||||
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
|
||||
language_cplus, DMGL_NO_OPTS);
|
||||
fputs_filtered ("\") \"", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
annotate_field_begin (TYPE_FIELD_TYPE (type, i));
|
||||
fprintf_filtered (stream, "%.*s",
|
||||
ada_name_prefix_len (TYPE_FIELD_NAME (type, i)),
|
||||
TYPE_FIELD_NAME (type, i));
|
||||
annotate_field_name_end ();
|
||||
fputs_filtered (" => ", stream);
|
||||
annotate_field_value ();
|
||||
}
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
struct value *v;
|
||||
|
||||
/* Bitfields require special handling, especially due to byte
|
||||
order problems. */
|
||||
if (TYPE_CPLUS_SPECIFIC (type) != NULL
|
||||
&& TYPE_FIELD_IGNORE (type, i))
|
||||
{
|
||||
fputs_filtered ("<optimized out or zero length>", stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
int bit_pos = TYPE_FIELD_BITPOS (type, i);
|
||||
int bit_size = TYPE_FIELD_BITSIZE (type, i);
|
||||
|
||||
adjust_type_signedness (TYPE_FIELD_TYPE (type, i));
|
||||
v = ada_value_primitive_packed_val (NULL, valaddr,
|
||||
bit_pos / HOST_CHAR_BIT,
|
||||
bit_pos % HOST_CHAR_BIT,
|
||||
bit_size,
|
||||
TYPE_FIELD_TYPE (type, i));
|
||||
val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, 0,
|
||||
stream, format, 0, recurse + 1, pretty);
|
||||
}
|
||||
}
|
||||
else
|
||||
ada_val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
|
||||
0, 0, stream, format, 0, recurse + 1, pretty);
|
||||
annotate_field_end ();
|
||||
}
|
||||
|
||||
return comma_needed;
|
||||
}
|
||||
386
contrib/gdb/gdb/alpha-mdebug-tdep.c
Normal file
386
contrib/gdb/gdb/alpha-mdebug-tdep.c
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
/* Target-dependent mdebug code for the ALPHA architecture.
|
||||
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "frame-unwind.h"
|
||||
#include "frame-base.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbcore.h"
|
||||
#include "block.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
/* FIXME: Some of this code should perhaps be merged with mips. */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
/* Layout of a stack frame on the alpha:
|
||||
|
||||
| |
|
||||
pdr members: | 7th ... nth arg, |
|
||||
| `pushed' by caller. |
|
||||
| |
|
||||
----------------|-------------------------------|<-- old_sp == vfp
|
||||
^ ^ ^ ^ | |
|
||||
| | | | | |
|
||||
| |localoff | Copies of 1st .. 6th |
|
||||
| | | | | argument if necessary. |
|
||||
| | | v | |
|
||||
| | | --- |-------------------------------|<-- LOCALS_ADDRESS
|
||||
| | | | |
|
||||
| | | | Locals and temporaries. |
|
||||
| | | | |
|
||||
| | | |-------------------------------|
|
||||
| | | | |
|
||||
|-fregoffset | Saved float registers. |
|
||||
| | | | F9 |
|
||||
| | | | . |
|
||||
| | | | . |
|
||||
| | | | F2 |
|
||||
| | v | |
|
||||
| | -------|-------------------------------|
|
||||
| | | |
|
||||
| | | Saved registers. |
|
||||
| | | S6 |
|
||||
|-regoffset | . |
|
||||
| | | . |
|
||||
| | | S0 |
|
||||
| | | pdr.pcreg |
|
||||
| v | |
|
||||
| ----------|-------------------------------|
|
||||
| | |
|
||||
frameoffset | Argument build area, gets |
|
||||
| | 7th ... nth arg for any |
|
||||
| | called procedure. |
|
||||
v | |
|
||||
-------------|-------------------------------|<-- sp
|
||||
| |
|
||||
*/
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
|
||||
#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
|
||||
#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
|
||||
#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
|
||||
#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
|
||||
#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
|
||||
#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
|
||||
#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
|
||||
#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
|
||||
|
||||
/* Locate the mdebug PDR for the given PC. Return null if one can't
|
||||
be found; you'll have to fall back to other methods in that case. */
|
||||
|
||||
static alpha_extra_func_info_t
|
||||
find_proc_desc (CORE_ADDR pc)
|
||||
{
|
||||
struct block *b = block_for_pc (pc);
|
||||
alpha_extra_func_info_t proc_desc = NULL;
|
||||
struct symbol *sym = NULL;
|
||||
|
||||
if (b)
|
||||
{
|
||||
CORE_ADDR startaddr;
|
||||
find_pc_partial_function (pc, NULL, &startaddr, NULL);
|
||||
|
||||
if (startaddr > BLOCK_START (b))
|
||||
/* This is the "pathological" case referred to in a comment in
|
||||
print_frame_info. It might be better to move this check into
|
||||
symbol reading. */
|
||||
sym = NULL;
|
||||
else
|
||||
sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
|
||||
}
|
||||
|
||||
if (sym)
|
||||
{
|
||||
proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym);
|
||||
|
||||
/* If we never found a PDR for this function in symbol reading,
|
||||
then examine prologues to find the information. */
|
||||
if (proc_desc->pdr.framereg == -1)
|
||||
proc_desc = NULL;
|
||||
}
|
||||
|
||||
return proc_desc;
|
||||
}
|
||||
|
||||
/* This returns the PC of the first inst after the prologue. If we can't
|
||||
find the prologue, then return 0. */
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_mdebug_after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
|
||||
{
|
||||
if (proc_desc)
|
||||
{
|
||||
/* If function is frameless, then we need to do it the hard way. I
|
||||
strongly suspect that frameless always means prologueless... */
|
||||
if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
|
||||
&& PROC_FRAME_OFFSET (proc_desc) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return alpha_after_prologue (pc);
|
||||
}
|
||||
|
||||
/* Return non-zero if we *might* be in a function prologue. Return zero
|
||||
if we are definitively *not* in a function prologue. */
|
||||
|
||||
static int
|
||||
alpha_mdebug_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
|
||||
{
|
||||
CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc);
|
||||
return (after_prologue_pc == 0 || pc < after_prologue_pc);
|
||||
}
|
||||
|
||||
|
||||
/* Frame unwinder that reads mdebug PDRs. */
|
||||
|
||||
struct alpha_mdebug_unwind_cache
|
||||
{
|
||||
alpha_extra_func_info_t proc_desc;
|
||||
CORE_ADDR vfp;
|
||||
CORE_ADDR *saved_regs;
|
||||
};
|
||||
|
||||
/* Extract all of the information about the frame from PROC_DESC
|
||||
and store the resulting register save locations in the structure. */
|
||||
|
||||
static struct alpha_mdebug_unwind_cache *
|
||||
alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info;
|
||||
alpha_extra_func_info_t proc_desc;
|
||||
ULONGEST vfp;
|
||||
CORE_ADDR pc, reg_position;
|
||||
unsigned long mask;
|
||||
int ireg, returnreg;
|
||||
|
||||
if (*this_prologue_cache)
|
||||
return *this_prologue_cache;
|
||||
|
||||
info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
|
||||
*this_prologue_cache = info;
|
||||
pc = frame_pc_unwind (next_frame);
|
||||
|
||||
/* ??? We don't seem to be able to cache the lookup of the PDR
|
||||
from alpha_mdebug_frame_p. It'd be nice if we could change
|
||||
the arguments to that function. Oh well. */
|
||||
proc_desc = find_proc_desc (pc);
|
||||
info->proc_desc = proc_desc;
|
||||
gdb_assert (proc_desc != NULL);
|
||||
|
||||
info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
|
||||
|
||||
/* The VFP of the frame is at FRAME_REG+FRAME_OFFSET. */
|
||||
frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp);
|
||||
vfp += PROC_FRAME_OFFSET (info->proc_desc);
|
||||
info->vfp = vfp;
|
||||
|
||||
/* Fill in the offsets for the registers which gen_mask says were saved. */
|
||||
|
||||
reg_position = vfp + PROC_REG_OFFSET (proc_desc);
|
||||
mask = PROC_REG_MASK (proc_desc);
|
||||
returnreg = PROC_PC_REG (proc_desc);
|
||||
|
||||
/* Note that RA is always saved first, regardless of its actual
|
||||
register number. */
|
||||
if (mask & (1 << returnreg))
|
||||
{
|
||||
/* Clear bit for RA so we don't save it again later. */
|
||||
mask &= ~(1 << returnreg);
|
||||
|
||||
info->saved_regs[returnreg] = reg_position;
|
||||
reg_position += 8;
|
||||
}
|
||||
|
||||
for (ireg = 0; ireg <= 31; ++ireg)
|
||||
if (mask & (1 << ireg))
|
||||
{
|
||||
info->saved_regs[ireg] = reg_position;
|
||||
reg_position += 8;
|
||||
}
|
||||
|
||||
reg_position = vfp + PROC_FREG_OFFSET (proc_desc);
|
||||
mask = PROC_FREG_MASK (proc_desc);
|
||||
|
||||
for (ireg = 0; ireg <= 31; ++ireg)
|
||||
if (mask & (1 << ireg))
|
||||
{
|
||||
info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
|
||||
reg_position += 8;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/* Given a GDB frame, determine the address of the calling function's
|
||||
frame. This will be used to create a new GDB frame struct. */
|
||||
|
||||
static void
|
||||
alpha_mdebug_frame_this_id (struct frame_info *next_frame,
|
||||
void **this_prologue_cache,
|
||||
struct frame_id *this_id)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info
|
||||
= alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||
|
||||
*this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame));
|
||||
}
|
||||
|
||||
/* Retrieve the value of REGNUM in FRAME. Don't give up! */
|
||||
|
||||
static void
|
||||
alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
|
||||
void **this_prologue_cache,
|
||||
int regnum, int *optimizedp,
|
||||
enum lval_type *lvalp, CORE_ADDR *addrp,
|
||||
int *realnump, void *bufferp)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info
|
||||
= alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||
|
||||
/* The PC of the previous frame is stored in the link register of
|
||||
the current frame. Frob regnum so that we pull the value from
|
||||
the correct place. */
|
||||
if (regnum == ALPHA_PC_REGNUM)
|
||||
regnum = PROC_PC_REG (info->proc_desc);
|
||||
|
||||
/* For all registers known to be saved in the current frame,
|
||||
do the obvious and pull the value out. */
|
||||
if (info->saved_regs[regnum])
|
||||
{
|
||||
*optimizedp = 0;
|
||||
*lvalp = lval_memory;
|
||||
*addrp = info->saved_regs[regnum];
|
||||
*realnump = -1;
|
||||
if (bufferp != NULL)
|
||||
get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The stack pointer of the previous frame is computed by popping
|
||||
the current stack frame. */
|
||||
if (regnum == ALPHA_SP_REGNUM)
|
||||
{
|
||||
*optimizedp = 0;
|
||||
*lvalp = not_lval;
|
||||
*addrp = 0;
|
||||
*realnump = -1;
|
||||
if (bufferp != NULL)
|
||||
store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise assume the next frame has the same register value. */
|
||||
frame_register (next_frame, regnum, optimizedp, lvalp, addrp,
|
||||
realnump, bufferp);
|
||||
}
|
||||
|
||||
static const struct frame_unwind alpha_mdebug_frame_unwind = {
|
||||
NORMAL_FRAME,
|
||||
alpha_mdebug_frame_this_id,
|
||||
alpha_mdebug_frame_prev_register
|
||||
};
|
||||
|
||||
const struct frame_unwind *
|
||||
alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
alpha_extra_func_info_t proc_desc;
|
||||
|
||||
/* If this PC does not map to a PDR, then clearly this isn't an
|
||||
mdebug frame. */
|
||||
proc_desc = find_proc_desc (pc);
|
||||
if (proc_desc == NULL)
|
||||
return NULL;
|
||||
|
||||
/* If we're in the prologue, the PDR for this frame is not yet valid.
|
||||
Say no here and we'll fall back on the heuristic unwinder. */
|
||||
if (alpha_mdebug_in_prologue (pc, proc_desc))
|
||||
return NULL;
|
||||
|
||||
return &alpha_mdebug_frame_unwind;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_mdebug_frame_base_address (struct frame_info *next_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info
|
||||
= alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||
|
||||
return info->vfp;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info
|
||||
= alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||
|
||||
return info->vfp - PROC_LOCALOFF (info->proc_desc);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alpha_mdebug_frame_args_address (struct frame_info *next_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
struct alpha_mdebug_unwind_cache *info
|
||||
= alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||
|
||||
return info->vfp - ALPHA_NUM_ARG_REGS * 8;
|
||||
}
|
||||
|
||||
static const struct frame_base alpha_mdebug_frame_base = {
|
||||
&alpha_mdebug_frame_unwind,
|
||||
alpha_mdebug_frame_base_address,
|
||||
alpha_mdebug_frame_locals_address,
|
||||
alpha_mdebug_frame_args_address
|
||||
};
|
||||
|
||||
static const struct frame_base *
|
||||
alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
alpha_extra_func_info_t proc_desc;
|
||||
|
||||
/* If this PC does not map to a PDR, then clearly this isn't an
|
||||
mdebug frame. */
|
||||
proc_desc = find_proc_desc (pc);
|
||||
if (proc_desc == NULL)
|
||||
return NULL;
|
||||
|
||||
return &alpha_mdebug_frame_base;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer);
|
||||
frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
|
||||
}
|
||||
110
contrib/gdb/gdb/alpha-tdep.h
Normal file
110
contrib/gdb/gdb/alpha-tdep.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* Common target dependent code for GDB on Alpha systems.
|
||||
Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003 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 ALPHA_TDEP_H
|
||||
#define ALPHA_TDEP_H
|
||||
|
||||
/* Say how long (ordinary) registers are. This is a piece of bogosity
|
||||
used in push_word and a few other places;
|
||||
DEPRECATED_REGISTER_RAW_SIZE is the real way to know how big a
|
||||
register is. */
|
||||
#define ALPHA_REGISTER_SIZE 8
|
||||
|
||||
/* Number of machine registers. */
|
||||
#define ALPHA_NUM_REGS 67
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state. */
|
||||
#define ALPHA_REGISTER_BYTES (ALPHA_NUM_REGS * 8)
|
||||
|
||||
/* Register numbers of various important registers. Note that most of
|
||||
these values are "real" register numbers, and correspond to the
|
||||
general registers of the machine. */
|
||||
|
||||
#define ALPHA_V0_REGNUM 0 /* Function integer return value */
|
||||
#define ALPHA_T7_REGNUM 8 /* Return address register for OSF/1 __add* */
|
||||
#define ALPHA_GCC_FP_REGNUM 15 /* Used by gcc as frame register */
|
||||
#define ALPHA_A0_REGNUM 16 /* Loc of first arg during a subr call */
|
||||
#define ALPHA_T9_REGNUM 23 /* Return address register for OSF/1 __div* */
|
||||
#define ALPHA_RA_REGNUM 26 /* Contains return address value */
|
||||
#define ALPHA_T12_REGNUM 27 /* Contains start addr of current proc */
|
||||
#define ALPHA_GP_REGNUM 29 /* Contains the global pointer */
|
||||
#define ALPHA_SP_REGNUM 30 /* Contains address of top of stack */
|
||||
#define ALPHA_ZERO_REGNUM 31 /* Read-only register, always 0 */
|
||||
#define ALPHA_FP0_REGNUM 32 /* Floating point register 0 */
|
||||
#define ALPHA_FPA0_REGNUM 48 /* First float arg during a subr call */
|
||||
#define ALPHA_FPCR_REGNUM 63 /* Floating point control register */
|
||||
#define ALPHA_PC_REGNUM 64 /* Contains program counter */
|
||||
#define ALPHA_UNIQUE_REGNUM 66 /* PAL_rduniq value */
|
||||
|
||||
/* The alpha has two different virtual pointers for arguments and locals.
|
||||
|
||||
The virtual argument pointer is pointing to the bottom of the argument
|
||||
transfer area, which is located immediately below the virtual frame
|
||||
pointer. Its size is fixed for the native compiler, it is either zero
|
||||
(for the no arguments case) or large enough to hold all argument registers.
|
||||
gcc uses a variable sized argument transfer area. As it has
|
||||
to stay compatible with the native debugging tools it has to use the same
|
||||
virtual argument pointer and adjust the argument offsets accordingly.
|
||||
|
||||
The virtual local pointer is localoff bytes below the virtual frame
|
||||
pointer, the value of localoff is obtained from the PDR. */
|
||||
#define ALPHA_NUM_ARG_REGS 6
|
||||
|
||||
/* Target-dependent structure in gdbarch. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
CORE_ADDR vm_min_address; /* Used by alpha_heuristic_proc_start. */
|
||||
|
||||
/* If PC is inside a dynamically-generated signal trampoline function
|
||||
(i.e. one copied onto the user stack at run-time), return how many
|
||||
bytes PC is beyond the start of that function. Otherwise, return -1. */
|
||||
LONGEST (*dynamic_sigtramp_offset) (CORE_ADDR);
|
||||
|
||||
/* Translate a signal handler stack base address into the address of
|
||||
the sigcontext structure for that signal handler. */
|
||||
CORE_ADDR (*sigcontext_addr) (struct frame_info *);
|
||||
|
||||
/* Offset of registers in `struct sigcontext'. */
|
||||
int sc_pc_offset;
|
||||
int sc_regs_offset;
|
||||
int sc_fpregs_offset;
|
||||
|
||||
int jb_pc; /* Offset to PC value in jump buffer.
|
||||
If htis is negative, longjmp support
|
||||
will be disabled. */
|
||||
size_t jb_elt_size; /* And the size of each entry in the buf. */
|
||||
};
|
||||
|
||||
extern unsigned int alpha_read_insn (CORE_ADDR pc);
|
||||
extern void alpha_software_single_step (enum target_signal, int);
|
||||
extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc);
|
||||
|
||||
extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *);
|
||||
extern void alpha_dwarf2_init_abi (struct gdbarch_info, struct gdbarch *);
|
||||
|
||||
extern void alpha_supply_int_regs (int, const void *, const void *,
|
||||
const void *);
|
||||
extern void alpha_fill_int_regs (int, void *, void *, void *);
|
||||
extern void alpha_supply_fp_regs (int, const void *, const void *);
|
||||
extern void alpha_fill_fp_regs (int, void *, void *);
|
||||
|
||||
#endif /* ALPHA_TDEP_H */
|
||||
|
|
@ -22,6 +22,9 @@
|
|||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
|
|
@ -34,103 +37,45 @@
|
|||
typedef struct reg gregset_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FPREGSET_T
|
||||
typedef struct fpreg fpregset_t;
|
||||
#endif
|
||||
#ifndef HAVE_FPREGSET_T
|
||||
typedef struct fpreg fpregset_t;
|
||||
#endif
|
||||
|
||||
#include "gregset.h"
|
||||
|
||||
/* Number of general-purpose registers. */
|
||||
#define NUM_GREGS 32
|
||||
|
||||
/* Number of floating point registers. */
|
||||
#define NUM_FPREGS 31
|
||||
|
||||
|
||||
/* Transfering the registers between GDB, inferiors and core files. */
|
||||
|
||||
/* Fill GDB's register array with the general-purpose register values
|
||||
in *GREGSETP. */
|
||||
/* Provide *regset() wrappers around the generic Alpha BSD register
|
||||
supply/fill routines. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
{
|
||||
if (CANNOT_FETCH_REGISTER (i))
|
||||
supply_register (i, NULL);
|
||||
else
|
||||
supply_register (i, (char *) &gregsetp->r_regs[i]);
|
||||
}
|
||||
|
||||
/* The PC travels in the R_ZERO slot. */
|
||||
supply_register (PC_REGNUM, (char *) &gregsetp->r_regs[R_ZERO]);
|
||||
alphabsd_supply_reg ((char *) gregsetp, -1);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a general-purpose register) in
|
||||
*GREGSETPS with the value in GDB's register array. If REGNO is -1,
|
||||
do this for all registers. */
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GREGS; i++)
|
||||
if ((regno == -1 || regno == i) && ! CANNOT_STORE_REGISTER (i))
|
||||
regcache_collect (i, (char *) &gregsetp->r_regs[i]);
|
||||
|
||||
/* The PC travels in the R_ZERO slot. */
|
||||
if (regno == -1 || regno == PC_REGNUM)
|
||||
regcache_collect (PC_REGNUM, (char *) &gregsetp->r_regs[R_ZERO]);
|
||||
alphabsd_fill_reg ((char *) gregsetp, regno);
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the floating-point register values
|
||||
in *FPREGSETP. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + NUM_FPREGS; i++)
|
||||
{
|
||||
if (CANNOT_FETCH_REGISTER (i))
|
||||
supply_register (i, NULL);
|
||||
else
|
||||
supply_register (i, (char *) &fpregsetp->fpr_regs[i - FP0_REGNUM]);
|
||||
}
|
||||
|
||||
supply_register (FPCR_REGNUM, (char *) &fpregsetp->fpr_cr);
|
||||
alphabsd_supply_fpreg ((char *) fpregsetp, -1);
|
||||
}
|
||||
|
||||
/* Fill register REGNO (if it is a floating-point register) in
|
||||
*FPREGSETP with the value in GDB's register array. If REGNO is -1,
|
||||
do this for all registers. */
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regno)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = FP0_REGNUM; i < FP0_REGNUM + NUM_FPREGS; i++)
|
||||
if ((regno == -1 || regno == i) && ! CANNOT_STORE_REGISTER (i))
|
||||
regcache_collect (i, (char *) &fpregsetp->fpr_regs[i - FP0_REGNUM]);
|
||||
|
||||
if (regno == -1 || regno == FPCR_REGNUM)
|
||||
regcache_collect (FPCR_REGNUM, (char *) &fpregsetp->fpr_cr);
|
||||
alphabsd_fill_fpreg ((char *) fpregsetp, regno);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Determine if PT_GETREGS fetches this register. */
|
||||
|
||||
static int
|
||||
getregs_supplies (int regno)
|
||||
{
|
||||
|
||||
return ((regno >= V0_REGNUM && regno <= ZERO_REGNUM)
|
||||
return ((regno >= ALPHA_V0_REGNUM && regno <= ALPHA_ZERO_REGNUM)
|
||||
|| regno >= PC_REGNUM);
|
||||
}
|
||||
|
||||
|
|
@ -141,33 +86,29 @@ getregs_supplies (int regno)
|
|||
void
|
||||
fetch_inferior_registers (int regno)
|
||||
{
|
||||
|
||||
if (regno == -1 || getregs_supplies (regno))
|
||||
{
|
||||
gregset_t gregs;
|
||||
struct reg gregs;
|
||||
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
supply_gregset (&gregs);
|
||||
alphabsd_supply_reg ((char *) &gregs, regno);
|
||||
if (regno != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (regno == -1 || regno >= FP0_REGNUM)
|
||||
{
|
||||
fpregset_t fpregs;
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
supply_fpregset (&fpregs);
|
||||
alphabsd_supply_fpreg ((char *) &fpregs, regno);
|
||||
}
|
||||
|
||||
/* Reset virtual frame pointer. */
|
||||
supply_register (FP_REGNUM, NULL);
|
||||
}
|
||||
|
||||
/* Store register REGNO back into the inferior. If REGNO is -1, do
|
||||
|
|
@ -176,15 +117,14 @@ fetch_inferior_registers (int regno)
|
|||
void
|
||||
store_inferior_registers (int regno)
|
||||
{
|
||||
|
||||
if (regno == -1 || getregs_supplies (regno))
|
||||
{
|
||||
gregset_t gregs;
|
||||
struct reg gregs;
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
fill_gregset (&gregs, regno);
|
||||
alphabsd_fill_reg ((char *) &gregs, regno);
|
||||
|
||||
if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &gregs, 0) == -1)
|
||||
|
|
@ -196,13 +136,13 @@ store_inferior_registers (int regno)
|
|||
|
||||
if (regno == -1 || regno >= FP0_REGNUM)
|
||||
{
|
||||
fpregset_t fpregs;
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
fill_fpregset (&fpregs, regno);
|
||||
alphabsd_fill_fpreg ((char *) &fpregs, regno);
|
||||
|
||||
if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
|
|
|
|||
55
contrib/gdb/gdb/alphabsd-tdep.c
Normal file
55
contrib/gdb/gdb/alphabsd-tdep.c
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* Common target dependent code for GDB on Alpha systems running BSD.
|
||||
Copyright 2000, 2001, 2002 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 "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
|
||||
/* Conviently, GDB uses the same register numbering as the
|
||||
ptrace register structure used by BSD on Alpha. */
|
||||
|
||||
void
|
||||
alphabsd_supply_reg (char *regs, int regno)
|
||||
{
|
||||
/* PC is at slot 32; UNIQUE not present. */
|
||||
alpha_supply_int_regs (regno, regs, regs + 31*8, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_fill_reg (char *regs, int regno)
|
||||
{
|
||||
/* PC is at slot 32; UNIQUE not present. */
|
||||
alpha_fill_int_regs (regno, regs, regs + 31*8, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_supply_fpreg (char *fpregs, int regno)
|
||||
{
|
||||
/* FPCR is at slot 33; slot 32 unused. */
|
||||
alpha_supply_fp_regs (regno, fpregs, fpregs + 32*8);
|
||||
}
|
||||
|
||||
void
|
||||
alphabsd_fill_fpreg (char *fpregs, int regno)
|
||||
{
|
||||
/* FPCR is at slot 33; slot 32 unused. */
|
||||
alpha_fill_fp_regs (regno, fpregs, fpregs + 32*8);
|
||||
}
|
||||
33
contrib/gdb/gdb/alphabsd-tdep.h
Normal file
33
contrib/gdb/gdb/alphabsd-tdep.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* Common target dependent code for GDB on Alpha systems running BSD.
|
||||
Copyright 2002 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 ALPHABSD_TDEP_H
|
||||
#define ALPHABSD_TDEP_H
|
||||
|
||||
void alphabsd_supply_reg (char *, int);
|
||||
void alphabsd_fill_reg (char *, int);
|
||||
|
||||
void alphabsd_supply_fpreg (char *, int);
|
||||
void alphabsd_fill_fpreg (char *, int);
|
||||
|
||||
#define SIZEOF_STRUCT_REG (32 * 8)
|
||||
#define SIZEOF_STRUCT_FPREG (33 * 8)
|
||||
|
||||
#endif /* ALPHABSD_TDEP_H */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* Target-dependent code for FreeBSD/Alpha.
|
||||
Copyright 2001 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -20,8 +20,11 @@
|
|||
|
||||
#include "defs.h"
|
||||
#include "value.h"
|
||||
#include "osabi.h"
|
||||
|
||||
int
|
||||
#include "alpha-tdep.h"
|
||||
|
||||
static int
|
||||
alphafbsd_use_struct_convention (int gcc_p, struct type *type)
|
||||
{
|
||||
enum type_code code;
|
||||
|
|
@ -29,7 +32,7 @@ alphafbsd_use_struct_convention (int gcc_p, struct type *type)
|
|||
|
||||
/* All aggregate types that won't fit in a register must be returned
|
||||
in memory. */
|
||||
if (TYPE_LENGTH (type) > REGISTER_SIZE)
|
||||
if (TYPE_LENGTH (type) > ALPHA_REGISTER_SIZE)
|
||||
return 1;
|
||||
|
||||
/* The only aggregate types that can be returned in a register are
|
||||
|
|
@ -51,3 +54,71 @@ alphafbsd_use_struct_convention (int gcc_p, struct type *type)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
/* Return whether PC is in a BSD sigtramp routine. */
|
||||
|
||||
CORE_ADDR alphafbsd_sigtramp_start = 0x11ffff68;
|
||||
CORE_ADDR alphafbsd_sigtramp_end = 0x11ffffe0;
|
||||
|
||||
static int
|
||||
alphafbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
return (pc >= alphafbsd_sigtramp_start && pc < alphafbsd_sigtramp_end);
|
||||
}
|
||||
|
||||
static LONGEST
|
||||
alphafbsd_sigtramp_offset (CORE_ADDR pc)
|
||||
{
|
||||
return pc - alphafbsd_sigtramp_start;
|
||||
}
|
||||
|
||||
/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
|
||||
routine, return the address of the associated sigcontext structure. */
|
||||
|
||||
static CORE_ADDR
|
||||
alphafbsd_sigcontext_addr (struct frame_info *next_frame)
|
||||
{
|
||||
return frame_unwind_register_unsigned (next_frame, ALPHA_SP_REGNUM) + 24;
|
||||
}
|
||||
|
||||
/* FreeBSD 5.0-RELEASE or later. */
|
||||
|
||||
static void
|
||||
alphafbsd_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* Hook into the DWARF CFI frame unwinder. */
|
||||
alpha_dwarf2_init_abi (info, gdbarch);
|
||||
|
||||
/* Hook into the MDEBUG frame unwinder. */
|
||||
alpha_mdebug_init_abi (info, gdbarch);
|
||||
|
||||
set_gdbarch_use_struct_convention (gdbarch, alphafbsd_use_struct_convention);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alphafbsd_pc_in_sigtramp);
|
||||
|
||||
tdep->dynamic_sigtramp_offset = alphafbsd_sigtramp_offset;
|
||||
tdep->sigcontext_addr = alphafbsd_sigcontext_addr;
|
||||
tdep->sc_pc_offset = 288;
|
||||
tdep->sc_regs_offset = 24;
|
||||
tdep->sc_fpregs_offset = 320;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_alphafbsd_tdep (void);
|
||||
|
||||
void
|
||||
_initialize_alphafbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_FREEBSD_ELF,
|
||||
alphafbsd_init_abi);
|
||||
}
|
||||
|
|
|
|||
234
contrib/gdb/gdb/alphanbsd-tdep.c
Normal file
234
contrib/gdb/gdb/alphanbsd-tdep.c
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/* Target-dependent code for NetBSD/Alpha.
|
||||
|
||||
Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Wasabi Systems, 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 "gdbcore.h"
|
||||
#include "frame.h"
|
||||
#include "regcache.h"
|
||||
#include "value.h"
|
||||
#include "osabi.h"
|
||||
|
||||
#include "solib-svr4.h"
|
||||
|
||||
#include "alpha-tdep.h"
|
||||
#include "alphabsd-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
|
||||
static void
|
||||
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR ignore)
|
||||
{
|
||||
char *regs, *fpregs;
|
||||
int regno;
|
||||
|
||||
/* Table to map a gdb register number to a trapframe register index. */
|
||||
static const int regmap[] =
|
||||
{
|
||||
0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15,
|
||||
30, 31, 32, 16,
|
||||
17, 18, 19, 20,
|
||||
21, 22, 23, 24,
|
||||
25, 29, 26
|
||||
};
|
||||
#define SIZEOF_TRAPFRAME (33 * 8)
|
||||
|
||||
/* We get everything from one section. */
|
||||
if (which != 0)
|
||||
return;
|
||||
|
||||
regs = core_reg_sect;
|
||||
fpregs = core_reg_sect + SIZEOF_TRAPFRAME;
|
||||
|
||||
if (core_reg_size < (SIZEOF_TRAPFRAME + SIZEOF_STRUCT_FPREG))
|
||||
{
|
||||
warning ("Wrong size register set in core file.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer registers. */
|
||||
for (regno = 0; regno < ALPHA_ZERO_REGNUM; regno++)
|
||||
supply_register (regno, regs + (regmap[regno] * 8));
|
||||
supply_register (ALPHA_ZERO_REGNUM, NULL);
|
||||
supply_register (PC_REGNUM, regs + (28 * 8));
|
||||
|
||||
/* Floating point registers. */
|
||||
alphabsd_supply_fpreg (fpregs, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
|
||||
CORE_ADDR ignore)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0: /* Integer registers. */
|
||||
if (core_reg_size != SIZEOF_STRUCT_REG)
|
||||
warning ("Wrong size register set in core file.");
|
||||
else
|
||||
alphabsd_supply_reg (core_reg_sect, -1);
|
||||
break;
|
||||
|
||||
case 2: /* Floating point registers. */
|
||||
if (core_reg_size != SIZEOF_STRUCT_FPREG)
|
||||
warning ("Wrong size FP register set in core file.");
|
||||
else
|
||||
alphabsd_supply_fpreg (core_reg_sect, -1);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Don't know what kind of register request this is; just ignore it. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct core_fns alphanbsd_core_fns =
|
||||
{
|
||||
bfd_target_unknown_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_core_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
static struct core_fns alphanbsd_elfcore_fns =
|
||||
{
|
||||
bfd_target_elf_flavour, /* core_flavour */
|
||||
default_check_format, /* check_format */
|
||||
default_core_sniffer, /* core_sniffer */
|
||||
fetch_elfcore_registers, /* core_read_registers */
|
||||
NULL /* next */
|
||||
};
|
||||
|
||||
/* Under NetBSD/alpha, signal handler invocations can be identified by the
|
||||
designated code sequence that is used to return from a signal handler.
|
||||
In particular, the return address of a signal handler points to the
|
||||
following code sequence:
|
||||
|
||||
ldq a0, 0(sp)
|
||||
lda sp, 16(sp)
|
||||
lda v0, 295(zero) # __sigreturn14
|
||||
call_pal callsys
|
||||
|
||||
Each instruction has a unique encoding, so we simply attempt to match
|
||||
the instruction the PC is pointing to with any of the above instructions.
|
||||
If there is a hit, we know the offset to the start of the designated
|
||||
sequence and can then check whether we really are executing in the
|
||||
signal trampoline. If not, -1 is returned, otherwise the offset from the
|
||||
start of the return sequence is returned. */
|
||||
static const unsigned char sigtramp_retcode[] =
|
||||
{
|
||||
0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */
|
||||
0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */
|
||||
0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */
|
||||
0x83, 0x00, 0x00, 0x00, /* call_pal callsys */
|
||||
};
|
||||
#define RETCODE_NWORDS 4
|
||||
#define RETCODE_SIZE (RETCODE_NWORDS * 4)
|
||||
|
||||
LONGEST
|
||||
alphanbsd_sigtramp_offset (CORE_ADDR pc)
|
||||
{
|
||||
unsigned char ret[RETCODE_SIZE], w[4];
|
||||
LONGEST off;
|
||||
int i;
|
||||
|
||||
if (read_memory_nobpt (pc, (char *) w, 4) != 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < RETCODE_NWORDS; i++)
|
||||
{
|
||||
if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == RETCODE_NWORDS)
|
||||
return (-1);
|
||||
|
||||
off = i * 4;
|
||||
pc -= off;
|
||||
|
||||
if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0)
|
||||
return -1;
|
||||
|
||||
if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0)
|
||||
return off;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
alphanbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
|
||||
{
|
||||
return (nbsd_pc_in_sigtramp (pc, func_name)
|
||||
|| alphanbsd_sigtramp_offset (pc) >= 0);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
alphanbsd_sigcontext_addr (struct frame_info *frame)
|
||||
{
|
||||
/* FIXME: This is not correct for all versions of NetBSD/alpha.
|
||||
We will probably need to disassemble the trampoline to figure
|
||||
out which trampoline frame type we have. */
|
||||
return get_frame_base (frame);
|
||||
}
|
||||
|
||||
static void
|
||||
alphanbsd_init_abi (struct gdbarch_info info,
|
||||
struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* Hook into the DWARF CFI frame unwinder. */
|
||||
alpha_dwarf2_init_abi (info, gdbarch);
|
||||
|
||||
/* Hook into the MDEBUG frame unwinder. */
|
||||
alpha_mdebug_init_abi (info, gdbarch);
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, alphanbsd_pc_in_sigtramp);
|
||||
|
||||
/* NetBSD/alpha does not provide single step support via ptrace(2); we
|
||||
must use software single-stepping. */
|
||||
set_gdbarch_software_single_step (gdbarch, alpha_software_single_step);
|
||||
|
||||
set_solib_svr4_fetch_link_map_offsets (gdbarch,
|
||||
nbsd_lp64_solib_svr4_fetch_link_map_offsets);
|
||||
|
||||
tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset;
|
||||
tdep->sigcontext_addr = alphanbsd_sigcontext_addr;
|
||||
|
||||
tdep->jb_pc = 2;
|
||||
tdep->jb_elt_size = 8;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_alphanbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF,
|
||||
alphanbsd_init_abi);
|
||||
gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_OPENBSD_ELF,
|
||||
alphanbsd_init_abi);
|
||||
|
||||
add_core_fns (&alphanbsd_core_fns);
|
||||
add_core_fns (&alphanbsd_elfcore_fns);
|
||||
}
|
||||
163
contrib/gdb/gdb/amd64-nat.c
Normal file
163
contrib/gdb/gdb/amd64-nat.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* Native-dependent code for AMD64.
|
||||
|
||||
Copyright 2003, 2004 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 "gdbarch.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "i386-tdep.h"
|
||||
#include "amd64-tdep.h"
|
||||
|
||||
/* The following bits of code help with implementing debugging 32-bit
|
||||
code natively on AMD64. The idea is to define two mappings between
|
||||
the register number as used by GDB and the register set used by the
|
||||
host to represent the general-purpose registers; one for 32-bit
|
||||
code and one for 64-bit code. The mappings are specified by the
|
||||
follwing variables and consist of an array of offsets within the
|
||||
register set indexed by register number, and the number of
|
||||
registers supported by the mapping. We don't need mappings for the
|
||||
floating-point and SSE registers, since the difference between
|
||||
64-bit and 32-bit variants are negligable. The difference in the
|
||||
number of SSE registers is already handled by the target code. */
|
||||
|
||||
/* General-purpose register mapping for native 32-bit code. */
|
||||
int *amd64_native_gregset32_reg_offset;
|
||||
int amd64_native_gregset32_num_regs = I386_NUM_GREGS;
|
||||
|
||||
/* General-purpose register mapping for native 64-bit code. */
|
||||
int *amd64_native_gregset64_reg_offset;
|
||||
int amd64_native_gregset64_num_regs = AMD64_NUM_GREGS;
|
||||
|
||||
/* Return the offset of REGNUM within the appropriate native
|
||||
general-purpose register set. */
|
||||
|
||||
static int
|
||||
amd64_native_gregset_reg_offset (int regnum)
|
||||
{
|
||||
int *reg_offset = amd64_native_gregset64_reg_offset;
|
||||
int num_regs = amd64_native_gregset64_num_regs;
|
||||
|
||||
gdb_assert (regnum >= 0);
|
||||
|
||||
if (gdbarch_ptr_bit (current_gdbarch) == 32)
|
||||
{
|
||||
reg_offset = amd64_native_gregset32_reg_offset;
|
||||
num_regs = amd64_native_gregset32_num_regs;
|
||||
}
|
||||
|
||||
if (num_regs > NUM_REGS)
|
||||
num_regs = NUM_REGS;
|
||||
|
||||
if (regnum < num_regs && regnum < NUM_REGS)
|
||||
return reg_offset[regnum];
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return whether the native general-purpose register set supplies
|
||||
register REGNUM. */
|
||||
|
||||
int
|
||||
amd64_native_gregset_supplies_p (int regnum)
|
||||
{
|
||||
return (amd64_native_gregset_reg_offset (regnum) != -1);
|
||||
}
|
||||
|
||||
|
||||
/* Supply register REGNUM, whose contents are store in BUF, to
|
||||
REGCACHE. If REGNUM is -1, supply all appropriate registers. */
|
||||
|
||||
void
|
||||
amd64_supply_native_gregset (struct regcache *regcache,
|
||||
const void *gregs, int regnum)
|
||||
{
|
||||
const char *regs = gregs;
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
int num_regs = amd64_native_gregset64_num_regs;
|
||||
int i;
|
||||
|
||||
if (gdbarch_ptr_bit (gdbarch) == 32)
|
||||
num_regs = amd64_native_gregset32_num_regs;
|
||||
|
||||
if (num_regs > NUM_REGS)
|
||||
num_regs = NUM_REGS;
|
||||
|
||||
for (i = 0; i < num_regs; i++)
|
||||
{
|
||||
if (regnum == -1 || regnum == i)
|
||||
{
|
||||
int offset = amd64_native_gregset_reg_offset (i);
|
||||
|
||||
if (offset != -1)
|
||||
regcache_raw_supply (regcache, i, regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect register REGNUM from REGCACHE and store its contents in
|
||||
GREGS. If REGNUM is -1, collect and store all appropriate
|
||||
registers. */
|
||||
|
||||
void
|
||||
amd64_collect_native_gregset (const struct regcache *regcache,
|
||||
void *gregs, int regnum)
|
||||
{
|
||||
char *regs = gregs;
|
||||
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||
int num_regs = amd64_native_gregset64_num_regs;
|
||||
int i;
|
||||
|
||||
if (gdbarch_ptr_bit (gdbarch) == 32)
|
||||
{
|
||||
num_regs = amd64_native_gregset32_num_regs;
|
||||
|
||||
/* Make sure %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and
|
||||
%eip get zero-extended to 64 bits. */
|
||||
for (i = 0; i <= I386_EIP_REGNUM; i++)
|
||||
{
|
||||
if (regnum == -1 || regnum == i)
|
||||
memset (regs + amd64_native_gregset_reg_offset (i), 0, 8);
|
||||
}
|
||||
/* Ditto for %cs, %ss, %ds, %es, %fs, and %gs. */
|
||||
for (i = I386_CS_REGNUM; i <= I386_GS_REGNUM; i++)
|
||||
{
|
||||
if (regnum == -1 || regnum == i)
|
||||
memset (regs + amd64_native_gregset_reg_offset (i), 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (num_regs > NUM_REGS)
|
||||
num_regs = NUM_REGS;
|
||||
|
||||
for (i = 0; i < num_regs; i++)
|
||||
{
|
||||
if (regnum == -1 || regnum == i)
|
||||
{
|
||||
int offset = amd64_native_gregset_reg_offset (i);
|
||||
|
||||
if (offset != -1)
|
||||
regcache_raw_collect (regcache, i, regs + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
53
contrib/gdb/gdb/amd64-nat.h
Normal file
53
contrib/gdb/gdb/amd64-nat.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* Native-dependent code for AMD64.
|
||||
|
||||
Copyright 2003 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 AMD64_NAT_H
|
||||
#define AMD64_NAT_H 1
|
||||
|
||||
struct regcache;
|
||||
|
||||
/* General-purpose register set description for native 32-bit code. */
|
||||
extern int *amd64_native_gregset32_reg_offset;
|
||||
extern int amd64_native_gregset32_num_regs;
|
||||
|
||||
/* General-purpose register set description for native 64-bit code. */
|
||||
extern int *amd64_native_gregset64_reg_offset;
|
||||
extern int amd64_native_gregset64_num_regs;
|
||||
|
||||
/* Return whether the native general-purpose register set supplies
|
||||
register REGNUM. */
|
||||
|
||||
extern int amd64_native_gregset_supplies_p (int regnum);
|
||||
|
||||
/* Supply register REGNUM, whose contents are store in BUF, to
|
||||
REGCACHE. If REGNUM is -1, supply all appropriate registers. */
|
||||
|
||||
extern void amd64_supply_native_gregset (struct regcache *regcache,
|
||||
const void *gregs, int regnum);
|
||||
|
||||
/* Collect register REGNUM from REGCACHE and store its contents in
|
||||
GREGS. If REGNUM is -1, collect and store all appropriate
|
||||
registers. */
|
||||
|
||||
extern void amd64_collect_native_gregset (const struct regcache *regcache,
|
||||
void *gregs, int regnum);
|
||||
|
||||
#endif /* amd64-nat.h */
|
||||
1199
contrib/gdb/gdb/amd64-tdep.c
Normal file
1199
contrib/gdb/gdb/amd64-tdep.c
Normal file
File diff suppressed because it is too large
Load diff
93
contrib/gdb/gdb/amd64-tdep.h
Normal file
93
contrib/gdb/gdb/amd64-tdep.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* Target-dependent definitions for AMD64.
|
||||
|
||||
Copyright 2001, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Jiri Smid, SuSE Labs.
|
||||
|
||||
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 AMD64_TDEP_H
|
||||
#define AMD64_TDEP_H
|
||||
|
||||
struct gdbarch;
|
||||
struct frame_info;
|
||||
struct regcache;
|
||||
|
||||
#include "i386-tdep.h"
|
||||
|
||||
/* Register numbers of various important registers. */
|
||||
|
||||
enum amd64_regnum
|
||||
{
|
||||
AMD64_RAX_REGNUM, /* %rax */
|
||||
AMD64_RBX_REGNUM, /* %rbx */
|
||||
AMD64_RCX_REGNUM, /* %rcx */
|
||||
AMD64_RDX_REGNUM, /* %rdx */
|
||||
AMD64_RSI_REGNUM, /* %rsi */
|
||||
AMD64_RDI_REGNUM, /* %rdi */
|
||||
AMD64_RBP_REGNUM, /* %rbp */
|
||||
AMD64_RSP_REGNUM, /* %rsp */
|
||||
AMD64_R8_REGNUM = 8, /* %r8 */
|
||||
AMD64_R15_REGNUM = 15, /* %r15 */
|
||||
AMD64_RIP_REGNUM, /* %rip */
|
||||
AMD64_EFLAGS_REGNUM, /* %eflags */
|
||||
AMD64_ST0_REGNUM = 24, /* %st0 */
|
||||
AMD64_XMM0_REGNUM = 40, /* %xmm0 */
|
||||
AMD64_XMM1_REGNUM /* %xmm1 */
|
||||
};
|
||||
|
||||
/* Number of general purpose registers. */
|
||||
#define AMD64_NUM_GREGS 24
|
||||
|
||||
extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch);
|
||||
|
||||
/* Fill register REGNUM in REGCACHE with the appropriate
|
||||
floating-point or SSE register value from *FXSAVE. If REGNUM is
|
||||
-1, do this for all registers. This function masks off any of the
|
||||
reserved bits in *FXSAVE. */
|
||||
|
||||
extern void amd64_supply_fxsave (struct regcache *regcache, int regnum,
|
||||
const void *fxsave);
|
||||
|
||||
/* Fill register REGNUM (if it is a floating-point or SSE register) in
|
||||
*FXSAVE with the value from REGCACHE. If REGNUM is -1, do this for
|
||||
all registers. This function doesn't touch any of the reserved
|
||||
bits in *FXSAVE. */
|
||||
|
||||
extern void amd64_collect_fxsave (const struct regcache *regcache, int regnum,
|
||||
void *fxsave);
|
||||
|
||||
/* Fill register REGNUM (if it is a floating-point or SSE register) in
|
||||
*FXSAVE with the value in GDB's register cache. If REGNUM is -1, do
|
||||
this for all registers. This function doesn't touch any of the
|
||||
reserved bits in *FXSAVE. */
|
||||
|
||||
extern void amd64_fill_fxsave (char *fxsave, int regnum);
|
||||
|
||||
|
||||
/* Variables exported from amd64nbsd-tdep.c. */
|
||||
extern int amd64nbsd_r_reg_offset[];
|
||||
|
||||
/* Variables exported from amd64obsd-tdep.c. */
|
||||
extern int amd64obsd_r_reg_offset[];
|
||||
|
||||
/* Variables exported from amd64fbsd-tdep.c. */
|
||||
extern CORE_ADDR amd64fbsd_sigtramp_start_addr;
|
||||
extern CORE_ADDR amd64fbsd_sigtramp_end_addr;
|
||||
extern int amd64fbsd_sc_reg_offset[];
|
||||
|
||||
#endif /* amd64-tdep.h */
|
||||
107
contrib/gdb/gdb/amd64bsd-nat.c
Normal file
107
contrib/gdb/gdb/amd64bsd-nat.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* Native-dependent code for AMD64 BSD's.
|
||||
|
||||
Copyright 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* We include <signal.h> to make sure `struct fxsave64' is defined on
|
||||
NetBSD, since NetBSD's <machine/reg.h> needs it. */
|
||||
#include "gdb_assert.h"
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <machine/reg.h>
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "amd64-nat.h"
|
||||
|
||||
|
||||
/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
|
||||
for all registers (including the floating-point registers). */
|
||||
|
||||
void
|
||||
fetch_inferior_registers (int regnum)
|
||||
{
|
||||
if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
|
||||
{
|
||||
struct reg regs;
|
||||
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) ®s, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
amd64_supply_native_gregset (current_regcache, ®s, -1);
|
||||
if (regnum != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (regnum == -1 || regnum >= AMD64_ST0_REGNUM)
|
||||
{
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
amd64_supply_fxsave (current_regcache, -1, &fpregs);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store register REGNUM back into the inferior. If REGNUM is -1, do
|
||||
this for all registers (including the floating-point registers). */
|
||||
|
||||
void
|
||||
store_inferior_registers (int regnum)
|
||||
{
|
||||
if (regnum == -1 || amd64_native_gregset_supplies_p (regnum))
|
||||
{
|
||||
struct reg regs;
|
||||
|
||||
if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) ®s, 0) == -1)
|
||||
perror_with_name ("Couldn't get registers");
|
||||
|
||||
amd64_collect_native_gregset (current_regcache, ®s, regnum);
|
||||
|
||||
if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) ®s, 0) == -1)
|
||||
perror_with_name ("Couldn't write registers");
|
||||
|
||||
if (regnum != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (regnum == -1 || regnum >= AMD64_ST0_REGNUM)
|
||||
{
|
||||
struct fpreg fpregs;
|
||||
|
||||
if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't get floating point status");
|
||||
|
||||
amd64_fill_fxsave ((char *) &fpregs, regnum);
|
||||
|
||||
if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
|
||||
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
|
||||
perror_with_name ("Couldn't write floating point status");
|
||||
}
|
||||
}
|
||||
235
contrib/gdb/gdb/amd64fbsd-nat.c
Normal file
235
contrib/gdb/gdb/amd64fbsd-nat.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/* Native-dependent code for FreeBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/reg.h>
|
||||
|
||||
#ifdef HAVE_SYS_PROCFS_H
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GREGSET_T
|
||||
typedef struct reg gregset_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FPREGSET_T
|
||||
typedef struct fpreg fpregset_t;
|
||||
#endif
|
||||
|
||||
#include "gregset.h"
|
||||
#include "amd64-tdep.h"
|
||||
#include "amd64-nat.h"
|
||||
|
||||
|
||||
/* Offset to the gregset_t location where REG is stored. */
|
||||
#define REG_OFFSET(reg) offsetof (gregset_t, reg)
|
||||
|
||||
/* At reg_offset[REGNUM] you'll find the offset to the gregset_t
|
||||
location where the GDB register REGNUM is stored. Unsupported
|
||||
registers are marked with `-1'. */
|
||||
static int reg_offset[] =
|
||||
{
|
||||
REG_OFFSET (r_rax),
|
||||
REG_OFFSET (r_rbx),
|
||||
REG_OFFSET (r_rcx),
|
||||
REG_OFFSET (r_rdx),
|
||||
REG_OFFSET (r_rsi),
|
||||
REG_OFFSET (r_rdi),
|
||||
REG_OFFSET (r_rbp),
|
||||
REG_OFFSET (r_rsp),
|
||||
REG_OFFSET (r_r8),
|
||||
REG_OFFSET (r_r9),
|
||||
REG_OFFSET (r_r10),
|
||||
REG_OFFSET (r_r11),
|
||||
REG_OFFSET (r_r12),
|
||||
REG_OFFSET (r_r13),
|
||||
REG_OFFSET (r_r14),
|
||||
REG_OFFSET (r_r15),
|
||||
REG_OFFSET (r_rip),
|
||||
REG_OFFSET (r_rflags),
|
||||
REG_OFFSET (r_cs),
|
||||
REG_OFFSET (r_ss),
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
|
||||
/* Mapping between the general-purpose registers in FreeBSD/amd64
|
||||
`struct reg' format and GDB's register cache layout for
|
||||
FreeBSD/i386.
|
||||
|
||||
Note that most FreeBSD/amd64 registers are 64-bit, while the
|
||||
FreeBSD/i386 registers are all 32-bit, but since we're
|
||||
little-endian we get away with that. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
|
||||
{
|
||||
14 * 8, 13 * 8, /* %eax, %ecx */
|
||||
12 * 8, 11 * 8, /* %edx, %ebx */
|
||||
20 * 8, 10 * 8, /* %esp, %ebp */
|
||||
9 * 8, 8 * 8, /* %esi, %edi */
|
||||
17 * 8, 19 * 8, /* %eip, %eflags */
|
||||
18 * 8, 21 * 8, /* %cs, %ss */
|
||||
-1, -1, -1, -1 /* %ds, %es, %fs, %gs */
|
||||
};
|
||||
|
||||
|
||||
/* Transfering the registers between GDB, inferiors and core files. */
|
||||
|
||||
/* Fill GDB's register array with the general-purpose register values
|
||||
in *GREGSETP. */
|
||||
|
||||
void
|
||||
supply_gregset (gregset_t *gregsetp)
|
||||
{
|
||||
amd64_supply_native_gregset (current_regcache, gregsetp, -1);
|
||||
}
|
||||
|
||||
/* Fill register REGNUM (if it is a general-purpose register) in
|
||||
*GREGSETPS with the value in GDB's register array. If REGNUM is -1,
|
||||
do this for all registers. */
|
||||
|
||||
void
|
||||
fill_gregset (gregset_t *gregsetp, int regnum)
|
||||
{
|
||||
amd64_collect_native_gregset (current_regcache, gregsetp, regnum);
|
||||
}
|
||||
|
||||
/* Fill GDB's register array with the floating-point register values
|
||||
in *FPREGSETP. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregset_t *fpregsetp)
|
||||
{
|
||||
amd64_supply_fxsave (current_regcache, -1, fpregsetp);
|
||||
}
|
||||
|
||||
/* Fill register REGNUM (if it is a floating-point register) in
|
||||
*FPREGSETP with the value in GDB's register array. If REGNUM is -1,
|
||||
do this for all registers. */
|
||||
|
||||
void
|
||||
fill_fpregset (fpregset_t *fpregsetp, int regnum)
|
||||
{
|
||||
amd64_fill_fxsave ((char *) fpregsetp, regnum);
|
||||
}
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64fbsd_nat (void);
|
||||
|
||||
void
|
||||
_initialize_amd64fbsd_nat (void)
|
||||
{
|
||||
int offset;
|
||||
|
||||
amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
|
||||
amd64_native_gregset64_reg_offset = reg_offset;
|
||||
|
||||
/* To support the recognition of signal handlers, i386bsd-tdep.c
|
||||
hardcodes some constants. Inclusion of this file means that we
|
||||
are compiling a native debugger, which means that we can use the
|
||||
system header files and sysctl(3) to get at the relevant
|
||||
information. */
|
||||
|
||||
#define SC_REG_OFFSET amd64fbsd_sc_reg_offset
|
||||
|
||||
/* We only check the program counter, stack pointer and frame
|
||||
pointer since these members of `struct sigcontext' are essential
|
||||
for providing backtraces. */
|
||||
|
||||
#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
|
||||
#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
|
||||
#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
|
||||
|
||||
/* Override the default value for the offset of the program counter
|
||||
in the sigcontext structure. */
|
||||
offset = offsetof (struct sigcontext, sc_rip);
|
||||
|
||||
if (SC_RIP_OFFSET != offset)
|
||||
{
|
||||
warning ("\
|
||||
offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
|
||||
Please report this to <bug-gdb@gnu.org>.",
|
||||
offset, SC_RIP_OFFSET);
|
||||
}
|
||||
|
||||
SC_RIP_OFFSET = offset;
|
||||
|
||||
/* Likewise for the stack pointer. */
|
||||
offset = offsetof (struct sigcontext, sc_rsp);
|
||||
|
||||
if (SC_RSP_OFFSET != offset)
|
||||
{
|
||||
warning ("\
|
||||
offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
|
||||
Please report this to <bug-gdb@gnu.org>.",
|
||||
offset, SC_RSP_OFFSET);
|
||||
}
|
||||
|
||||
SC_RSP_OFFSET = offset;
|
||||
|
||||
/* And the frame pointer. */
|
||||
offset = offsetof (struct sigcontext, sc_rbp);
|
||||
|
||||
if (SC_RBP_OFFSET != offset)
|
||||
{
|
||||
warning ("\
|
||||
offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
|
||||
Please report this to <bug-gdb@gnu.org>.",
|
||||
offset, SC_RBP_OFFSET);
|
||||
}
|
||||
|
||||
SC_RBP_OFFSET = offset;
|
||||
|
||||
/* FreeBSD provides a kern.ps_strings sysctl that we can use to
|
||||
locate the sigtramp. That way we can still recognize a sigtramp
|
||||
if its location is changed in a new kernel. Of course this is
|
||||
still based on the assumption that the sigtramp is placed
|
||||
directly under the location where the program arguments and
|
||||
environment can be found. */
|
||||
{
|
||||
int mib[2];
|
||||
long ps_strings;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PS_STRINGS;
|
||||
len = sizeof (ps_strings);
|
||||
if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
|
||||
{
|
||||
amd64fbsd_sigtramp_start_addr = ps_strings - 32;
|
||||
amd64fbsd_sigtramp_end_addr = ps_strings;
|
||||
}
|
||||
}
|
||||
}
|
||||
155
contrib/gdb/gdb/amd64fbsd-tdep.c
Normal file
155
contrib/gdb/gdb/amd64fbsd-tdep.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/* Target-dependent code for FreeBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 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 "arch-utils.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "regcache.h"
|
||||
#include "osabi.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
|
||||
routine, return the address of the associated sigcontext structure. */
|
||||
|
||||
static CORE_ADDR
|
||||
amd64fbsd_sigcontext_addr (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR sp;
|
||||
|
||||
/* The `struct sigcontext' (which really is an `ucontext_t' on
|
||||
FreeBSD/amd64) lives at a fixed offset in the signal frame. See
|
||||
<machine/sigframe.h>. */
|
||||
sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
|
||||
return sp + 16;
|
||||
}
|
||||
|
||||
/* FreeBSD 5.1-RELEASE or later. */
|
||||
|
||||
/* Mapping between the general-purpose registers in `struct reg'
|
||||
format and GDB's register cache layout.
|
||||
|
||||
Note that some registers are 32-bit, but since we're little-endian
|
||||
we get away with that. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
static int amd64fbsd_r_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %rax */
|
||||
11 * 8, /* %rbx */
|
||||
13 * 8, /* %rcx */
|
||||
12 * 8, /* %rdx */
|
||||
9 * 8, /* %rsi */
|
||||
8 * 8, /* %rdi */
|
||||
10 * 8, /* %rbp */
|
||||
20 * 8, /* %rsp */
|
||||
7 * 8, /* %r8 ... */
|
||||
6 * 8,
|
||||
5 * 8,
|
||||
4 * 8,
|
||||
3 * 8,
|
||||
2 * 8,
|
||||
1 * 8,
|
||||
0 * 8, /* ... %r15 */
|
||||
17 * 8, /* %rip */
|
||||
19 * 8, /* %eflags */
|
||||
18 * 8, /* %cs */
|
||||
21 * 8, /* %ss */
|
||||
-1, /* %ds */
|
||||
-1, /* %es */
|
||||
-1, /* %fs */
|
||||
-1 /* %gs */
|
||||
};
|
||||
|
||||
/* Location of the signal trampoline. */
|
||||
CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0;
|
||||
CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0;
|
||||
|
||||
/* From <machine/signal.h>. */
|
||||
int amd64fbsd_sc_reg_offset[] =
|
||||
{
|
||||
24 + 6 * 8, /* %rax */
|
||||
24 + 7 * 8, /* %rbx */
|
||||
24 + 3 * 8, /* %rcx */
|
||||
24 + 2 * 8, /* %rdx */
|
||||
24 + 1 * 8, /* %rsi */
|
||||
24 + 0 * 8, /* %rdi */
|
||||
24 + 8 * 8, /* %rbp */
|
||||
24 + 22 * 8, /* %rsp */
|
||||
24 + 4 * 8, /* %r8 ... */
|
||||
24 + 5 * 8,
|
||||
24 + 9 * 8,
|
||||
24 + 10 * 8,
|
||||
24 + 11 * 8,
|
||||
24 + 12 * 8,
|
||||
24 + 13 * 8,
|
||||
24 + 14 * 8, /* ... %r15 */
|
||||
24 + 19 * 8, /* %rip */
|
||||
24 + 21 * 8, /* %eflags */
|
||||
24 + 20 * 8, /* %cs */
|
||||
24 + 23 * 8, /* %ss */
|
||||
-1, /* %ds */
|
||||
-1, /* %es */
|
||||
-1, /* %fs */
|
||||
-1 /* %gs */
|
||||
};
|
||||
|
||||
void
|
||||
amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* Obviously FreeBSD is BSD-based. */
|
||||
i386bsd_init_abi (info, gdbarch);
|
||||
|
||||
tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
|
||||
tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
|
||||
tdep->sizeof_gregset = 22 * 8;
|
||||
|
||||
amd64_init_abi (info, gdbarch);
|
||||
|
||||
tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
|
||||
tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
|
||||
tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
|
||||
tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
|
||||
tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
|
||||
|
||||
/* FreeBSD uses SVR4-style shared libraries. */
|
||||
set_solib_svr4_fetch_link_map_offsets
|
||||
(gdbarch, svr4_lp64_fetch_link_map_offsets);
|
||||
}
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64fbsd_tdep (void);
|
||||
|
||||
void
|
||||
_initialize_amd64fbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
|
||||
GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi);
|
||||
}
|
||||
68
contrib/gdb/gdb/amd64nbsd-nat.c
Normal file
68
contrib/gdb/gdb/amd64nbsd-nat.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* Native-dependent code for NetBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 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 "gdb_assert.h"
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "amd64-nat.h"
|
||||
|
||||
/* Mapping between the general-purpose registers in NetBSD/amd64
|
||||
`struct reg' format and GDB's register cache layout for
|
||||
NetBSD/i386.
|
||||
|
||||
Note that most (if not all) NetBSD/amd64 registers are 64-bit,
|
||||
while the NetBSD/i386 registers are all 32-bit, but since we're
|
||||
little-endian we get away with that. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
static int amd64nbsd32_r_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %eax */
|
||||
3 * 8, /* %ecx */
|
||||
2 * 8, /* %edx */
|
||||
13 * 8, /* %ebx */
|
||||
24 * 8, /* %esp */
|
||||
12 * 8, /* %ebp */
|
||||
1 * 8, /* %esi */
|
||||
0 * 8, /* %edi */
|
||||
21 * 8, /* %eip */
|
||||
23 * 8, /* %eflags */
|
||||
22 * 8, /* %cs */
|
||||
25 * 8, /* %ss */
|
||||
18 * 8, /* %ds */
|
||||
17 * 8, /* %es */
|
||||
16 * 8, /* %fs */
|
||||
15 * 8 /* %gs */
|
||||
};
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64nbsd_nat (void);
|
||||
|
||||
void
|
||||
_initialize_amd64nbsd_nat (void)
|
||||
{
|
||||
amd64_native_gregset32_reg_offset = amd64nbsd32_r_reg_offset;
|
||||
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset);
|
||||
amd64_native_gregset64_reg_offset = amd64nbsd_r_reg_offset;
|
||||
}
|
||||
135
contrib/gdb/gdb/amd64nbsd-tdep.c
Normal file
135
contrib/gdb/gdb/amd64nbsd-tdep.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/* Target-dependent code for NetBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 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 "arch-utils.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "osabi.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
|
||||
routine, return the address of the associated sigcontext structure. */
|
||||
|
||||
static CORE_ADDR
|
||||
amd64nbsd_sigcontext_addr (struct frame_info *next_frame)
|
||||
{
|
||||
CORE_ADDR sp;
|
||||
|
||||
/* The stack pointer points at `struct sigcontext' upon entry of a
|
||||
signal trampoline. */
|
||||
sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
|
||||
return sp;
|
||||
}
|
||||
|
||||
/* NetBSD 2.0 or later. */
|
||||
|
||||
/* Mapping between the general-purpose registers in `struct reg'
|
||||
format and GDB's register cache layout. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
int amd64nbsd_r_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %rax */
|
||||
13 * 8, /* %rbx */
|
||||
3 * 8, /* %rcx */
|
||||
2 * 8, /* %rdx */
|
||||
1 * 8, /* %rsi */
|
||||
0 * 8, /* %rdi */
|
||||
12 * 8, /* %rbp */
|
||||
24 * 8, /* %rsp */
|
||||
4 * 8, /* %r8 .. */
|
||||
5 * 8,
|
||||
6 * 8,
|
||||
7 * 8,
|
||||
8 * 8,
|
||||
9 * 8,
|
||||
10 * 8,
|
||||
11 * 8, /* ... %r15 */
|
||||
21 * 8, /* %rip */
|
||||
23 * 8, /* %eflags */
|
||||
22 * 8, /* %cs */
|
||||
25 * 8, /* %ss */
|
||||
18 * 8, /* %ds */
|
||||
17 * 8, /* %es */
|
||||
16 * 8, /* %fs */
|
||||
15 * 8 /* %gs */
|
||||
};
|
||||
|
||||
static void
|
||||
amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
int *sc_reg_offset;
|
||||
int i;
|
||||
|
||||
/* Initialize general-purpose register set details first. */
|
||||
tdep->gregset_reg_offset = amd64nbsd_r_reg_offset;
|
||||
tdep->gregset_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset);
|
||||
tdep->sizeof_gregset = 26 * 8;
|
||||
|
||||
amd64_init_abi (info, gdbarch);
|
||||
|
||||
tdep->jb_pc_offset = 7 * 8;
|
||||
|
||||
/* NetBSD has its own convention for signal trampolines. */
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, nbsd_pc_in_sigtramp);
|
||||
tdep->sigcontext_addr = amd64nbsd_sigcontext_addr;
|
||||
|
||||
/* Initialize the array with register offsets in `struct
|
||||
sigcontext'. This `struct sigcontext' has an sc_mcontext member
|
||||
at offset 32, and in <machine/reg.h> we have an explicit comment
|
||||
saying that `struct reg' is the same as mcontext.__gregs. */
|
||||
tdep->sc_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset);
|
||||
tdep->sc_reg_offset = XCALLOC (tdep->sc_num_regs, int);
|
||||
for (i = 0; i < tdep->sc_num_regs; i++)
|
||||
{
|
||||
if (amd64nbsd_r_reg_offset[i] < 0)
|
||||
tdep->sc_reg_offset[i] = -1;
|
||||
else
|
||||
tdep->sc_reg_offset[i] = 32 + amd64nbsd_r_reg_offset[i];
|
||||
}
|
||||
|
||||
/* NetBSD uses SVR4-style shared libraries. */
|
||||
set_solib_svr4_fetch_link_map_offsets
|
||||
(gdbarch, svr4_lp64_fetch_link_map_offsets);
|
||||
}
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64nbsd_tdep (void);
|
||||
|
||||
void
|
||||
_initialize_amd64nbsd_ndep (void)
|
||||
{
|
||||
/* The NetBSD/amd64 native dependent code makes this assumption. */
|
||||
gdb_assert (ARRAY_SIZE (amd64nbsd_r_reg_offset) == AMD64_NUM_GREGS);
|
||||
|
||||
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
|
||||
GDB_OSABI_NETBSD_ELF, amd64nbsd_init_abi);
|
||||
}
|
||||
68
contrib/gdb/gdb/amd64obsd-nat.c
Normal file
68
contrib/gdb/gdb/amd64obsd-nat.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* Native-dependent code for OpenBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 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 "gdb_assert.h"
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "amd64-nat.h"
|
||||
|
||||
/* Mapping between the general-purpose registers in OpenBSD/amd64
|
||||
`struct reg' format and GDB's register cache layout for
|
||||
OpenBSD/i386.
|
||||
|
||||
Note that most (if not all) OpenBSD/amd64 registers are 64-bit,
|
||||
while the OpenBSD/i386 registers are all 32-bit, but since we're
|
||||
little-endian we get away with that. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
static int amd64obsd32_r_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %eax */
|
||||
3 * 8, /* %ecx */
|
||||
2 * 8, /* %edx */
|
||||
13 * 8, /* %ebx */
|
||||
15 * 8, /* %esp */
|
||||
12 * 8, /* %ebp */
|
||||
1 * 8, /* %esi */
|
||||
0 * 8, /* %edi */
|
||||
16 * 8, /* %eip */
|
||||
17 * 8, /* %eflags */
|
||||
18 * 8, /* %cs */
|
||||
19 * 8, /* %ss */
|
||||
20 * 8, /* %ds */
|
||||
21 * 8, /* %es */
|
||||
22 * 8, /* %fs */
|
||||
23 * 8 /* %gs */
|
||||
};
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64obsd_nat (void);
|
||||
|
||||
void
|
||||
_initialize_amd64obsd_nat (void)
|
||||
{
|
||||
amd64_native_gregset32_reg_offset = amd64obsd32_r_reg_offset;
|
||||
amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset);
|
||||
amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset;
|
||||
}
|
||||
224
contrib/gdb/gdb/amd64obsd-tdep.c
Normal file
224
contrib/gdb/gdb/amd64obsd-tdep.c
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/* Target-dependent code for OpenBSD/amd64.
|
||||
|
||||
Copyright 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "osabi.h"
|
||||
#include "regset.h"
|
||||
#include "target.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "amd64-tdep.h"
|
||||
#include "i387-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Support for core dumps. */
|
||||
|
||||
static void
|
||||
amd64obsd_supply_regset (const struct regset *regset,
|
||||
struct regcache *regcache, int regnum,
|
||||
const void *regs, size_t len)
|
||||
{
|
||||
const struct gdbarch_tdep *tdep = regset->descr;
|
||||
|
||||
gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE);
|
||||
|
||||
i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
|
||||
amd64_supply_fxsave (regcache, regnum, (char *)regs + tdep->sizeof_gregset);
|
||||
}
|
||||
|
||||
static const struct regset *
|
||||
amd64obsd_regset_from_core_section (struct gdbarch *gdbarch,
|
||||
const char *sect_name, size_t sect_size)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* OpenBSD core dumps don't use seperate register sets for the
|
||||
general-purpose and floating-point registers. */
|
||||
|
||||
if (strcmp (sect_name, ".reg") == 0
|
||||
&& sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE)
|
||||
{
|
||||
if (tdep->gregset == NULL)
|
||||
{
|
||||
tdep->gregset = XMALLOC (struct regset);
|
||||
tdep->gregset->descr = tdep;
|
||||
tdep->gregset->supply_regset = amd64obsd_supply_regset;
|
||||
}
|
||||
return tdep->gregset;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Support for signal handlers. */
|
||||
|
||||
static const int amd64obsd_page_size = 4096;
|
||||
|
||||
static int
|
||||
amd64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
|
||||
{
|
||||
CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
|
||||
const char sigreturn[] =
|
||||
{
|
||||
0x48, 0xc7, 0xc0,
|
||||
0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */
|
||||
0xcd, 0x80 /* int $0x80 */
|
||||
};
|
||||
char *buf;
|
||||
|
||||
if (name)
|
||||
return 0;
|
||||
|
||||
/* If we can't read the instructions at START_PC, return zero. */
|
||||
buf = alloca (sizeof sigreturn);
|
||||
if (target_read_memory (start_pc + 0x7, buf, sizeof sigreturn))
|
||||
return 0;
|
||||
|
||||
/* Check for sigreturn(2). */
|
||||
if (memcmp (buf, sigreturn, sizeof sigreturn))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Assuming NEXT_FRAME is for a frame following a BSD sigtramp
|
||||
routine, return the address of the associated sigcontext structure. */
|
||||
|
||||
static CORE_ADDR
|
||||
amd64obsd_sigcontext_addr (struct frame_info *next_frame)
|
||||
{
|
||||
/* The %rsp register points at `struct sigcontext' upon entry of a
|
||||
signal trampoline. */
|
||||
return frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
|
||||
}
|
||||
|
||||
/* OpenBSD 3.5 or later. */
|
||||
|
||||
/* Mapping between the general-purpose registers in `struct reg'
|
||||
format and GDB's register cache layout. */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
int amd64obsd_r_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %rax */
|
||||
13 * 8, /* %rbx */
|
||||
3 * 8, /* %rcx */
|
||||
2 * 8, /* %rdx */
|
||||
1 * 8, /* %rsi */
|
||||
0 * 8, /* %rdi */
|
||||
12 * 8, /* %rbp */
|
||||
15 * 8, /* %rsp */
|
||||
4 * 8, /* %r8 .. */
|
||||
5 * 8,
|
||||
6 * 8,
|
||||
7 * 8,
|
||||
8 * 8,
|
||||
9 * 8,
|
||||
10 * 8,
|
||||
11 * 8, /* ... %r15 */
|
||||
16 * 8, /* %rip */
|
||||
17 * 8, /* %eflags */
|
||||
18 * 8, /* %cs */
|
||||
19 * 8, /* %ss */
|
||||
20 * 8, /* %ds */
|
||||
21 * 8, /* %es */
|
||||
22 * 8, /* %fs */
|
||||
23 * 8 /* %gs */
|
||||
};
|
||||
|
||||
/* From <machine/signal.h>. */
|
||||
static int amd64obsd_sc_reg_offset[] =
|
||||
{
|
||||
14 * 8, /* %rax */
|
||||
13 * 8, /* %rbx */
|
||||
3 * 8, /* %rcx */
|
||||
2 * 8, /* %rdx */
|
||||
1 * 8, /* %rsi */
|
||||
0 * 8, /* %rdi */
|
||||
12 * 8, /* %rbp */
|
||||
24 * 8, /* %rsp */
|
||||
4 * 8, /* %r8 ... */
|
||||
5 * 8,
|
||||
6 * 8,
|
||||
7 * 8,
|
||||
8 * 8,
|
||||
9 * 8,
|
||||
10 * 8,
|
||||
11 * 8, /* ... %r15 */
|
||||
21 * 8, /* %rip */
|
||||
23 * 8, /* %eflags */
|
||||
22 * 8, /* %cs */
|
||||
25 * 8, /* %ss */
|
||||
18 * 8, /* %ds */
|
||||
17 * 8, /* %es */
|
||||
16 * 8, /* %fs */
|
||||
15 * 8 /* %gs */
|
||||
};
|
||||
|
||||
static void
|
||||
amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
amd64_init_abi (info, gdbarch);
|
||||
|
||||
/* Initialize general-purpose register set details. */
|
||||
tdep->gregset_reg_offset = amd64obsd_r_reg_offset;
|
||||
tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset);
|
||||
tdep->sizeof_gregset = 24 * 8;
|
||||
|
||||
set_gdbarch_regset_from_core_section (gdbarch,
|
||||
amd64obsd_regset_from_core_section);
|
||||
|
||||
tdep->jb_pc_offset = 7 * 8;
|
||||
|
||||
set_gdbarch_pc_in_sigtramp (gdbarch, amd64obsd_pc_in_sigtramp);
|
||||
tdep->sigcontext_addr = amd64obsd_sigcontext_addr;
|
||||
tdep->sc_reg_offset = amd64obsd_sc_reg_offset;
|
||||
tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset);
|
||||
|
||||
/* OpenBSD uses SVR4-style shared libraries. */
|
||||
set_solib_svr4_fetch_link_map_offsets
|
||||
(gdbarch, svr4_lp64_fetch_link_map_offsets);
|
||||
}
|
||||
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
void _initialize_amd64obsd_tdep (void);
|
||||
|
||||
void
|
||||
_initialize_amd64obsd_tdep (void)
|
||||
{
|
||||
/* The OpenBSD/amd64 native dependent code makes this assumption. */
|
||||
gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS);
|
||||
|
||||
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
|
||||
GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi);
|
||||
|
||||
/* OpenBSD uses traditional (a.out) NetBSD-style core dumps. */
|
||||
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
|
||||
GDB_OSABI_NETBSD_AOUT, amd64obsd_init_abi);
|
||||
}
|
||||
|
|
@ -155,28 +155,28 @@ annotate_signalled (void)
|
|||
void
|
||||
annotate_signal_name (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032signal-name\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032signal-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_string (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032signal-string\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_string_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032signal-string-end\n");
|
||||
}
|
||||
|
||||
|
|
@ -193,35 +193,35 @@ annotate_signal (void)
|
|||
void
|
||||
annotate_breakpoints_headers (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032breakpoints-headers\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field (int num)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032field %d\n", num);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoints_table (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032breakpoints-table\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_record (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032record\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_breakpoints_table_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032breakpoints-table-end\n");
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +238,7 @@ annotate_frames_invalid (void)
|
|||
void
|
||||
annotate_field_begin (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032field-begin ");
|
||||
print_value_flags (type);
|
||||
|
|
@ -249,21 +249,21 @@ annotate_field_begin (struct type *type)
|
|||
void
|
||||
annotate_field_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032field-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032field-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_field_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032field-end\n");
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ annotate_error_begin (void)
|
|||
void
|
||||
annotate_value_history_begin (int histindex, struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032value-history-begin %d ", histindex);
|
||||
print_value_flags (type);
|
||||
|
|
@ -302,7 +302,7 @@ annotate_value_history_begin (int histindex, struct type *type)
|
|||
void
|
||||
annotate_value_begin (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032value-begin ");
|
||||
print_value_flags (type);
|
||||
|
|
@ -313,91 +313,91 @@ annotate_value_begin (struct type *type)
|
|||
void
|
||||
annotate_value_history_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032value-history-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_history_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032value-history-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_value_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032value-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_number_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-number-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_format (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-format\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_expression (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-expression\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_expression_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-expression-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_value (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-value\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_display_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032display-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032arg-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_name_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032arg-name-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_arg_value (struct type *type)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032arg-value ");
|
||||
print_value_flags (type);
|
||||
|
|
@ -408,7 +408,7 @@ annotate_arg_value (struct type *type)
|
|||
void
|
||||
annotate_arg_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032arg-end\n");
|
||||
}
|
||||
|
||||
|
|
@ -430,7 +430,7 @@ annotate_source (char *filename, int line, int character, int mid, CORE_ADDR pc)
|
|||
void
|
||||
annotate_frame_begin (int level, CORE_ADDR pc)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032frame-begin %d 0x", level);
|
||||
print_address_numeric (pc, 0, gdb_stdout);
|
||||
|
|
@ -441,98 +441,98 @@ annotate_frame_begin (int level, CORE_ADDR pc)
|
|||
void
|
||||
annotate_function_call (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032function-call\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_signal_handler_caller (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032signal-handler-caller\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_address (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-address\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_address_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-address-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_function_name (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-function-name\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_args (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-args\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_begin (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-source-begin\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_file (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-source-file\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_file_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-source-file-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_line (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-source-line\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_source_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-source-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_where (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-where\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_frame_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032frame-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_array_section_begin (int index, struct type *elttype)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
{
|
||||
printf_filtered ("\n\032\032array-section-begin %d ", index);
|
||||
print_value_flags (elttype);
|
||||
|
|
@ -543,28 +543,28 @@ annotate_array_section_begin (int index, struct type *elttype)
|
|||
void
|
||||
annotate_elt_rep (unsigned int repcount)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032elt-rep %u\n", repcount);
|
||||
}
|
||||
|
||||
void
|
||||
annotate_elt_rep_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032elt-rep-end\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_elt (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032elt\n");
|
||||
}
|
||||
|
||||
void
|
||||
annotate_array_section_end (void)
|
||||
{
|
||||
if (annotation_level > 1)
|
||||
if (annotation_level == 2)
|
||||
printf_filtered ("\n\032\032array-section-end\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
/* Dynamic architecture support for GDB, the GNU debugger.
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -20,78 +22,66 @@
|
|||
|
||||
#include "defs.h"
|
||||
|
||||
#if GDB_MULTI_ARCH
|
||||
#include "arch-utils.h"
|
||||
#include "buildsym.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "inferior.h" /* enum CALL_DUMMY_LOCATION et.al. */
|
||||
#else
|
||||
/* Just include everything in sight so that the every old definition
|
||||
of macro is visible. */
|
||||
#include "gdb_string.h"
|
||||
#include "symtab.h"
|
||||
#include "frame.h"
|
||||
#include "inferior.h"
|
||||
#include "breakpoint.h"
|
||||
#include "gdb_wait.h"
|
||||
#include "gdbcore.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "target.h"
|
||||
#include "annotate.h"
|
||||
#endif
|
||||
#include "regcache.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "sim-regno.h"
|
||||
|
||||
#include "osabi.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "floatformat.h"
|
||||
|
||||
/* Use the program counter to determine the contents and size
|
||||
of a breakpoint instruction. If no target-dependent macro
|
||||
BREAKPOINT_FROM_PC has been defined to implement this function,
|
||||
assume that the breakpoint doesn't depend on the PC, and
|
||||
use the values of the BIG_BREAKPOINT and LITTLE_BREAKPOINT macros.
|
||||
Return a pointer to a string of bytes that encode a breakpoint
|
||||
instruction, stores the length of the string to *lenptr,
|
||||
and optionally adjust the pc to point to the correct memory location
|
||||
for inserting the breakpoint. */
|
||||
|
||||
unsigned char *
|
||||
legacy_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
|
||||
/* Implementation of extract return value that grubs around in the
|
||||
register cache. */
|
||||
void
|
||||
legacy_extract_return_value (struct type *type, struct regcache *regcache,
|
||||
void *valbuf)
|
||||
{
|
||||
/* {BIG_,LITTLE_}BREAKPOINT is the sequence of bytes we insert for a
|
||||
breakpoint. On some machines, breakpoints are handled by the
|
||||
target environment and we don't have to worry about them here. */
|
||||
#ifdef BIG_BREAKPOINT
|
||||
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||
{
|
||||
static unsigned char big_break_insn[] = BIG_BREAKPOINT;
|
||||
*lenptr = sizeof (big_break_insn);
|
||||
return big_break_insn;
|
||||
}
|
||||
#endif
|
||||
#ifdef LITTLE_BREAKPOINT
|
||||
if (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG)
|
||||
{
|
||||
static unsigned char little_break_insn[] = LITTLE_BREAKPOINT;
|
||||
*lenptr = sizeof (little_break_insn);
|
||||
return little_break_insn;
|
||||
}
|
||||
#endif
|
||||
#ifdef BREAKPOINT
|
||||
{
|
||||
static unsigned char break_insn[] = BREAKPOINT;
|
||||
*lenptr = sizeof (break_insn);
|
||||
return break_insn;
|
||||
}
|
||||
#endif
|
||||
*lenptr = 0;
|
||||
return NULL;
|
||||
char *registers = deprecated_grub_regcache_for_registers (regcache);
|
||||
bfd_byte *buf = valbuf;
|
||||
DEPRECATED_EXTRACT_RETURN_VALUE (type, registers, buf); /* OK */
|
||||
}
|
||||
|
||||
int
|
||||
generic_frameless_function_invocation_not (struct frame_info *fi)
|
||||
/* Implementation of store return value that grubs the register cache.
|
||||
Takes a local copy of the buffer to avoid const problems. */
|
||||
void
|
||||
legacy_store_return_value (struct type *type, struct regcache *regcache,
|
||||
const void *buf)
|
||||
{
|
||||
return 0;
|
||||
bfd_byte *b = alloca (TYPE_LENGTH (type));
|
||||
gdb_assert (regcache == current_regcache);
|
||||
memcpy (b, buf, TYPE_LENGTH (type));
|
||||
DEPRECATED_STORE_RETURN_VALUE (type, b);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
always_use_struct_convention (int gcc_p, struct type *value_type)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
legacy_register_sim_regno (int regnum)
|
||||
{
|
||||
/* Only makes sense to supply raw registers. */
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS);
|
||||
/* NOTE: cagney/2002-05-13: The old code did it this way and it is
|
||||
suspected that some GDB/SIM combinations may rely on this
|
||||
behavour. The default should be one2one_register_sim_regno
|
||||
(below). */
|
||||
if (REGISTER_NAME (regnum) != NULL
|
||||
&& REGISTER_NAME (regnum)[0] != '\0')
|
||||
return regnum;
|
||||
else
|
||||
return LEGACY_SIM_REGNO_IGNORE;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -106,34 +96,30 @@ generic_skip_trampoline_code (CORE_ADDR pc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
generic_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_solib_call_trampoline (CORE_ADDR pc, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_solib_return_trampoline (CORE_ADDR pc, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
legacy_register_name (int i)
|
||||
{
|
||||
#ifdef REGISTER_NAMES
|
||||
static char *names[] = REGISTER_NAMES;
|
||||
if (i < 0 || i >= (sizeof (names) / sizeof (*names)))
|
||||
return NULL;
|
||||
else
|
||||
return names[i];
|
||||
#else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"legacy_register_name: called.");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (CALL_DUMMY)
|
||||
LONGEST legacy_call_dummy_words[] = CALL_DUMMY;
|
||||
#else
|
||||
|
|
@ -142,31 +128,15 @@ LONGEST legacy_call_dummy_words[1];
|
|||
int legacy_sizeof_call_dummy_words = sizeof (legacy_call_dummy_words);
|
||||
|
||||
void
|
||||
generic_remote_translate_xfer_address (CORE_ADDR gdb_addr, int gdb_len,
|
||||
generic_remote_translate_xfer_address (struct gdbarch *gdbarch,
|
||||
struct regcache *regcache,
|
||||
CORE_ADDR gdb_addr, int gdb_len,
|
||||
CORE_ADDR * rem_addr, int *rem_len)
|
||||
{
|
||||
*rem_addr = gdb_addr;
|
||||
*rem_len = gdb_len;
|
||||
}
|
||||
|
||||
int
|
||||
generic_prologue_frameless_p (CORE_ADDR ip)
|
||||
{
|
||||
#ifdef SKIP_PROLOGUE_FRAMELESS_P
|
||||
return ip == SKIP_PROLOGUE_FRAMELESS_P (ip);
|
||||
#else
|
||||
return ip == SKIP_PROLOGUE (ip);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* New/multi-arched targets should use the correct gdbarch field
|
||||
instead of using this global pointer. */
|
||||
int
|
||||
legacy_print_insn (bfd_vma vma, disassemble_info *info)
|
||||
{
|
||||
return (*tm_print_insn) (vma, info);
|
||||
}
|
||||
|
||||
/* Helper functions for INNER_THAN */
|
||||
|
||||
int
|
||||
|
|
@ -187,11 +157,7 @@ core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs)
|
|||
const struct floatformat *
|
||||
default_float_format (struct gdbarch *gdbarch)
|
||||
{
|
||||
#if GDB_MULTI_ARCH
|
||||
int byte_order = gdbarch_byte_order (gdbarch);
|
||||
#else
|
||||
int byte_order = TARGET_BYTE_ORDER;
|
||||
#endif
|
||||
switch (byte_order)
|
||||
{
|
||||
case BFD_ENDIAN_BIG:
|
||||
|
|
@ -208,11 +174,7 @@ default_float_format (struct gdbarch *gdbarch)
|
|||
const struct floatformat *
|
||||
default_double_format (struct gdbarch *gdbarch)
|
||||
{
|
||||
#if GDB_MULTI_ARCH
|
||||
int byte_order = gdbarch_byte_order (gdbarch);
|
||||
#else
|
||||
int byte_order = TARGET_BYTE_ORDER;
|
||||
#endif
|
||||
switch (byte_order)
|
||||
{
|
||||
case BFD_ENDIAN_BIG:
|
||||
|
|
@ -225,151 +187,36 @@ default_double_format (struct gdbarch *gdbarch)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
default_print_float_info (void)
|
||||
{
|
||||
#ifdef FLOAT_INFO
|
||||
#if GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL
|
||||
#error "FLOAT_INFO defined in multi-arch"
|
||||
#endif
|
||||
FLOAT_INFO;
|
||||
#else
|
||||
printf_filtered ("No floating point info available for this processor.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Misc helper functions for targets. */
|
||||
|
||||
int
|
||||
frame_num_args_unknown (struct frame_info *fi)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
generic_register_convertible_not (int num)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Under some ABI's that specify the `struct convention' for returning
|
||||
structures by value, by the time we've returned from the function,
|
||||
the return value is sitting there in the caller's buffer, but GDB
|
||||
has no way to find the address of that buffer.
|
||||
|
||||
On such architectures, use this function as your
|
||||
extract_struct_value_address method. When asked to a struct
|
||||
returned by value in this fashion, GDB will print a nice error
|
||||
message, instead of garbage. */
|
||||
CORE_ADDR
|
||||
generic_cannot_extract_struct_value_address (char *dummy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
default_register_sim_regno (int num)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
CORE_ADDR
|
||||
core_addr_identity (CORE_ADDR addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
convert_from_func_ptr_addr_identity (struct gdbarch *gdbarch, CORE_ADDR addr,
|
||||
struct target_ops *targ)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
int
|
||||
no_op_reg_to_regnum (int reg)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* For use by frame_args_address and frame_locals_address. */
|
||||
CORE_ADDR
|
||||
default_frame_address (struct frame_info *fi)
|
||||
deprecated_init_frame_pc_default (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
return fi->frame;
|
||||
}
|
||||
|
||||
/* Default prepare_to_procced(). */
|
||||
int
|
||||
default_prepare_to_proceed (int select_it)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generic prepare_to_proceed(). This one should be suitable for most
|
||||
targets that support threads. */
|
||||
int
|
||||
generic_prepare_to_proceed (int select_it)
|
||||
{
|
||||
ptid_t wait_ptid;
|
||||
struct target_waitstatus wait_status;
|
||||
|
||||
/* Get the last target status returned by target_wait(). */
|
||||
get_last_target_status (&wait_ptid, &wait_status);
|
||||
|
||||
/* Make sure we were stopped either at a breakpoint, or because
|
||||
of a Ctrl-C. */
|
||||
if (wait_status.kind != TARGET_WAITKIND_STOPPED
|
||||
|| (wait_status.value.sig != TARGET_SIGNAL_TRAP &&
|
||||
wait_status.value.sig != TARGET_SIGNAL_INT))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ptid_equal (wait_ptid, minus_one_ptid)
|
||||
&& !ptid_equal (inferior_ptid, wait_ptid))
|
||||
{
|
||||
/* Switched over from WAIT_PID. */
|
||||
CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
|
||||
|
||||
if (wait_pc != read_pc ())
|
||||
{
|
||||
if (select_it)
|
||||
{
|
||||
/* Switch back to WAIT_PID thread. */
|
||||
inferior_ptid = wait_ptid;
|
||||
|
||||
/* FIXME: This stuff came from switch_to_thread() in
|
||||
thread.c (which should probably be a public function). */
|
||||
flush_cached_frames ();
|
||||
registers_changed ();
|
||||
stop_pc = wait_pc;
|
||||
select_frame (get_current_frame (), 0);
|
||||
}
|
||||
/* We return 1 to indicate that there is a breakpoint here,
|
||||
so we need to step over it before continuing to avoid
|
||||
hitting it straight away. */
|
||||
if (breakpoint_here_p (wait_pc))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
init_frame_pc_noop (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
init_frame_pc_default (int fromleaf, struct frame_info *prev)
|
||||
{
|
||||
if (fromleaf)
|
||||
prev->pc = SAVED_PC_AFTER_CALL (prev->next);
|
||||
else if (prev->next != NULL)
|
||||
prev->pc = FRAME_SAVED_PC (prev->next);
|
||||
if (fromleaf && DEPRECATED_SAVED_PC_AFTER_CALL_P ())
|
||||
return DEPRECATED_SAVED_PC_AFTER_CALL (get_next_frame (prev));
|
||||
else if (get_next_frame (prev) != NULL)
|
||||
return DEPRECATED_FRAME_SAVED_PC (get_next_frame (prev));
|
||||
else
|
||||
prev->pc = read_pc ();
|
||||
return read_pc ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -391,34 +238,118 @@ cannot_register_not (int regnum)
|
|||
}
|
||||
|
||||
/* Legacy version of target_virtual_frame_pointer(). Assumes that
|
||||
there is an FP_REGNUM and that it is the same, cooked or raw. */
|
||||
there is an DEPRECATED_FP_REGNUM and that it is the same, cooked or
|
||||
raw. */
|
||||
|
||||
void
|
||||
legacy_virtual_frame_pointer (CORE_ADDR pc,
|
||||
int *frame_regnum,
|
||||
LONGEST *frame_offset)
|
||||
{
|
||||
gdb_assert (FP_REGNUM >= 0);
|
||||
*frame_regnum = FP_REGNUM;
|
||||
/* FIXME: cagney/2002-09-13: This code is used when identifying the
|
||||
frame pointer of the current PC. It is assuming that a single
|
||||
register and an offset can determine this. I think it should
|
||||
instead generate a byte code expression as that would work better
|
||||
with things like Dwarf2's CFI. */
|
||||
if (DEPRECATED_FP_REGNUM >= 0 && DEPRECATED_FP_REGNUM < NUM_REGS)
|
||||
*frame_regnum = DEPRECATED_FP_REGNUM;
|
||||
else if (SP_REGNUM >= 0 && SP_REGNUM < NUM_REGS)
|
||||
*frame_regnum = SP_REGNUM;
|
||||
else
|
||||
/* Should this be an internal error? I guess so, it is reflecting
|
||||
an architectural limitation in the current design. */
|
||||
internal_error (__FILE__, __LINE__, "No virtual frame pointer available");
|
||||
*frame_offset = 0;
|
||||
}
|
||||
|
||||
/* Assume the world is flat. Every register is large enough to fit a
|
||||
target integer. */
|
||||
/* Assume the world is sane, every register's virtual and real size
|
||||
is identical. */
|
||||
|
||||
int
|
||||
generic_register_raw_size (int regnum)
|
||||
generic_register_size (int regnum)
|
||||
{
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
|
||||
return TARGET_INT_BIT / HOST_CHAR_BIT;
|
||||
if (gdbarch_register_type_p (current_gdbarch))
|
||||
return TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum));
|
||||
else
|
||||
/* FIXME: cagney/2003-03-01: Once all architectures implement
|
||||
gdbarch_register_type(), this entire function can go away. It
|
||||
is made obsolete by register_size(). */
|
||||
return TYPE_LENGTH (DEPRECATED_REGISTER_VIRTUAL_TYPE (regnum)); /* OK */
|
||||
}
|
||||
|
||||
/* Assume the virtual size corresponds to the virtual type. */
|
||||
/* Assume all registers are adjacent. */
|
||||
|
||||
int
|
||||
generic_register_virtual_size (int regnum)
|
||||
generic_register_byte (int regnum)
|
||||
{
|
||||
return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
|
||||
int byte;
|
||||
int i;
|
||||
gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS);
|
||||
byte = 0;
|
||||
for (i = 0; i < regnum; i++)
|
||||
{
|
||||
byte += generic_register_size (i);
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
legacy_pc_in_sigtramp (CORE_ADDR pc, char *name)
|
||||
{
|
||||
#if !defined (IN_SIGTRAMP)
|
||||
if (SIGTRAMP_START_P ())
|
||||
return (pc) >= SIGTRAMP_START (pc) && (pc) < SIGTRAMP_END (pc);
|
||||
else
|
||||
return name && strcmp ("_sigtramp", name) == 0;
|
||||
#else
|
||||
return IN_SIGTRAMP (pc, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
legacy_convert_register_p (int regnum, struct type *type)
|
||||
{
|
||||
return (DEPRECATED_REGISTER_CONVERTIBLE_P ()
|
||||
&& DEPRECATED_REGISTER_CONVERTIBLE (regnum));
|
||||
}
|
||||
|
||||
void
|
||||
legacy_register_to_value (struct frame_info *frame, int regnum,
|
||||
struct type *type, void *to)
|
||||
{
|
||||
char from[MAX_REGISTER_SIZE];
|
||||
get_frame_register (frame, regnum, from);
|
||||
DEPRECATED_REGISTER_CONVERT_TO_VIRTUAL (regnum, type, from, to);
|
||||
}
|
||||
|
||||
void
|
||||
legacy_value_to_register (struct frame_info *frame, int regnum,
|
||||
struct type *type, const void *tmp)
|
||||
{
|
||||
char to[MAX_REGISTER_SIZE];
|
||||
char *from = alloca (TYPE_LENGTH (type));
|
||||
memcpy (from, from, TYPE_LENGTH (type));
|
||||
DEPRECATED_REGISTER_CONVERT_TO_RAW (type, regnum, from, to);
|
||||
put_frame_register (frame, regnum, to);
|
||||
}
|
||||
|
||||
int
|
||||
default_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
|
||||
{
|
||||
if (DEPRECATED_REG_STRUCT_HAS_ADDR_P ()
|
||||
&& DEPRECATED_REG_STRUCT_HAS_ADDR (processing_gcc_compilation, type))
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
return (TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (type) == TYPE_CODE_UNION
|
||||
|| TYPE_CODE (type) == TYPE_CODE_SET
|
||||
|| TYPE_CODE (type) == TYPE_CODE_BITSTRING);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -431,8 +362,17 @@ generic_register_virtual_size (int regnum)
|
|||
The choice of initial value is entirely arbitrary. During startup,
|
||||
the function initialize_current_architecture() updates this value
|
||||
based on default byte-order information extracted from BFD. */
|
||||
int target_byte_order = BFD_ENDIAN_BIG;
|
||||
int target_byte_order_auto = 1;
|
||||
static int target_byte_order = BFD_ENDIAN_BIG;
|
||||
static int target_byte_order_auto = 1;
|
||||
|
||||
enum bfd_endian
|
||||
selected_byte_order (void)
|
||||
{
|
||||
if (target_byte_order_auto)
|
||||
return BFD_ENDIAN_UNKNOWN;
|
||||
else
|
||||
return target_byte_order;
|
||||
}
|
||||
|
||||
static const char endian_big[] = "big";
|
||||
static const char endian_little[] = "little";
|
||||
|
|
@ -451,7 +391,7 @@ static const char *set_endian_string;
|
|||
static void
|
||||
show_endian (char *args, int from_tty)
|
||||
{
|
||||
if (TARGET_BYTE_ORDER_AUTO)
|
||||
if (target_byte_order_auto)
|
||||
printf_unfiltered ("The target endianness is set automatically (currently %s endian)\n",
|
||||
(TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little"));
|
||||
else
|
||||
|
|
@ -468,39 +408,21 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
|||
}
|
||||
else if (set_endian_string == endian_little)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
target_byte_order_auto = 0;
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_LITTLE;
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
printf_unfiltered ("Little endian target not supported by GDB\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_byte_order = BFD_ENDIAN_LITTLE;
|
||||
}
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_LITTLE;
|
||||
if (! gdbarch_update_p (info))
|
||||
printf_unfiltered ("Little endian target not supported by GDB\n");
|
||||
}
|
||||
else if (set_endian_string == endian_big)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
target_byte_order_auto = 0;
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
printf_unfiltered ("Big endian target not supported by GDB\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_byte_order = BFD_ENDIAN_BIG;
|
||||
}
|
||||
gdbarch_info_init (&info);
|
||||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
if (! gdbarch_update_p (info))
|
||||
printf_unfiltered ("Big endian target not supported by GDB\n");
|
||||
}
|
||||
else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
|
|
@ -508,126 +430,23 @@ set_endian (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
|||
show_endian (NULL, from_tty);
|
||||
}
|
||||
|
||||
/* Set the endianness from a BFD. */
|
||||
|
||||
static void
|
||||
set_endian_from_file (bfd *abfd)
|
||||
{
|
||||
int want;
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_endian_from_file: not for multi-arch");
|
||||
if (bfd_big_endian (abfd))
|
||||
want = BFD_ENDIAN_BIG;
|
||||
else
|
||||
want = BFD_ENDIAN_LITTLE;
|
||||
if (TARGET_BYTE_ORDER_AUTO)
|
||||
target_byte_order = want;
|
||||
else if (TARGET_BYTE_ORDER != want)
|
||||
warning ("%s endian file does not match %s endian target.",
|
||||
want == BFD_ENDIAN_BIG ? "big" : "little",
|
||||
TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? "big" : "little");
|
||||
}
|
||||
|
||||
|
||||
/* Functions to manipulate the architecture of the target */
|
||||
|
||||
enum set_arch { set_arch_auto, set_arch_manual };
|
||||
|
||||
int target_architecture_auto = 1;
|
||||
static int target_architecture_auto = 1;
|
||||
|
||||
const char *set_architecture_string;
|
||||
static const char *set_architecture_string;
|
||||
|
||||
/* Old way of changing the current architecture. */
|
||||
|
||||
extern const struct bfd_arch_info bfd_default_arch_struct;
|
||||
const struct bfd_arch_info *target_architecture = &bfd_default_arch_struct;
|
||||
int (*target_architecture_hook) (const struct bfd_arch_info *ap);
|
||||
|
||||
static int
|
||||
arch_ok (const struct bfd_arch_info *arch)
|
||||
const char *
|
||||
selected_architecture_name (void)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"arch_ok: not multi-arched");
|
||||
/* Should be performing the more basic check that the binary is
|
||||
compatible with GDB. */
|
||||
/* Check with the target that the architecture is valid. */
|
||||
return (target_architecture_hook == NULL
|
||||
|| target_architecture_hook (arch));
|
||||
}
|
||||
|
||||
static void
|
||||
set_arch (const struct bfd_arch_info *arch,
|
||||
enum set_arch type)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_arch: not multi-arched");
|
||||
switch (type)
|
||||
{
|
||||
case set_arch_auto:
|
||||
if (!arch_ok (arch))
|
||||
warning ("Target may not support %s architecture",
|
||||
arch->printable_name);
|
||||
target_architecture = arch;
|
||||
break;
|
||||
case set_arch_manual:
|
||||
if (!arch_ok (arch))
|
||||
{
|
||||
printf_unfiltered ("Target does not support `%s' architecture.\n",
|
||||
arch->printable_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_architecture_auto = 0;
|
||||
target_architecture = arch;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (gdbarch_debug)
|
||||
gdbarch_dump (current_gdbarch, gdb_stdlog);
|
||||
}
|
||||
|
||||
/* Set the architecture from arch/machine (deprecated) */
|
||||
|
||||
void
|
||||
set_architecture_from_arch_mach (enum bfd_architecture arch,
|
||||
unsigned long mach)
|
||||
{
|
||||
const struct bfd_arch_info *wanted = bfd_lookup_arch (arch, mach);
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture_from_arch_mach: not multi-arched");
|
||||
if (wanted != NULL)
|
||||
set_arch (wanted, set_arch_manual);
|
||||
else
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"gdbarch: hardwired architecture/machine not recognized");
|
||||
}
|
||||
|
||||
/* Set the architecture from a BFD (deprecated) */
|
||||
|
||||
static void
|
||||
set_architecture_from_file (bfd *abfd)
|
||||
{
|
||||
const struct bfd_arch_info *wanted = bfd_get_arch_info (abfd);
|
||||
if (GDB_MULTI_ARCH)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture_from_file: not multi-arched");
|
||||
if (target_architecture_auto)
|
||||
{
|
||||
set_arch (wanted, set_arch_auto);
|
||||
}
|
||||
else if (wanted != target_architecture)
|
||||
{
|
||||
warning ("%s architecture file may be incompatible with %s target.",
|
||||
wanted->printable_name,
|
||||
target_architecture->printable_name);
|
||||
}
|
||||
return NULL;
|
||||
else
|
||||
return set_architecture_string;
|
||||
}
|
||||
|
||||
|
||||
/* Called if the user enters ``show architecture'' without an
|
||||
argument. */
|
||||
|
||||
|
|
@ -653,7 +472,7 @@ set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
|||
{
|
||||
target_architecture_auto = 1;
|
||||
}
|
||||
else if (GDB_MULTI_ARCH)
|
||||
else
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
|
|
@ -667,37 +486,75 @@ set_architecture (char *ignore_args, int from_tty, struct cmd_list_element *c)
|
|||
printf_unfiltered ("Architecture `%s' not recognized.\n",
|
||||
set_architecture_string);
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct bfd_arch_info *arch
|
||||
= bfd_scan_arch (set_architecture_string);
|
||||
if (arch == NULL)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"set_architecture: bfd_scan_arch failed");
|
||||
set_arch (arch, set_arch_manual);
|
||||
}
|
||||
show_architecture (NULL, from_tty);
|
||||
}
|
||||
|
||||
/* Try to select a global architecture that matches "info". Return
|
||||
non-zero if the attempt succeds. */
|
||||
int
|
||||
gdbarch_update_p (struct gdbarch_info info)
|
||||
{
|
||||
struct gdbarch *new_gdbarch = gdbarch_find_by_info (info);
|
||||
|
||||
/* If there no architecture by that name, reject the request. */
|
||||
if (new_gdbarch == NULL)
|
||||
{
|
||||
if (gdbarch_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
|
||||
"Architecture not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If it is the same old architecture, accept the request (but don't
|
||||
swap anything). */
|
||||
if (new_gdbarch == current_gdbarch)
|
||||
{
|
||||
if (gdbarch_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
|
||||
"Architecture 0x%08lx (%s) unchanged\n",
|
||||
(long) new_gdbarch,
|
||||
gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* It's a new architecture, swap it in. */
|
||||
if (gdbarch_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_update_p: "
|
||||
"New architecture 0x%08lx (%s) selected\n",
|
||||
(long) new_gdbarch,
|
||||
gdbarch_bfd_arch_info (new_gdbarch)->printable_name);
|
||||
deprecated_current_gdbarch_select_hack (new_gdbarch);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the architecture for ABFD. If no suitable architecture
|
||||
could be find, return NULL. */
|
||||
|
||||
struct gdbarch *
|
||||
gdbarch_from_bfd (bfd *abfd)
|
||||
{
|
||||
struct gdbarch *old_gdbarch = current_gdbarch;
|
||||
struct gdbarch *new_gdbarch;
|
||||
struct gdbarch_info info;
|
||||
|
||||
gdbarch_info_init (&info);
|
||||
info.abfd = abfd;
|
||||
return gdbarch_find_by_info (info);
|
||||
}
|
||||
|
||||
/* Set the dynamic target-system-dependent parameters (architecture,
|
||||
byte-order) using information found in the BFD */
|
||||
|
||||
void
|
||||
set_gdbarch_from_file (bfd *abfd)
|
||||
{
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
struct gdbarch_info info;
|
||||
gdbarch_info_init (&info);
|
||||
info.abfd = abfd;
|
||||
if (! gdbarch_update_p (info))
|
||||
error ("Architecture of file not recognized.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
set_architecture_from_file (abfd);
|
||||
set_endian_from_file (abfd);
|
||||
}
|
||||
struct gdbarch *gdbarch;
|
||||
|
||||
gdbarch = gdbarch_from_bfd (abfd);
|
||||
if (gdbarch == NULL)
|
||||
error ("Architecture of file not recognized.\n");
|
||||
deprecated_current_gdbarch_select_hack (gdbarch);
|
||||
}
|
||||
|
||||
/* Initialize the current architecture. Update the ``set
|
||||
|
|
@ -784,22 +641,9 @@ initialize_current_architecture (void)
|
|||
info.byte_order = BFD_ENDIAN_BIG;
|
||||
}
|
||||
|
||||
if (GDB_MULTI_ARCH)
|
||||
{
|
||||
if (! gdbarch_update_p (info))
|
||||
{
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"initialize_current_architecture: Selection of initial architecture failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the multi-arch logic comes up with a byte-order (from BFD)
|
||||
use it for the non-multi-arch case. */
|
||||
if (info.byte_order != BFD_ENDIAN_UNKNOWN)
|
||||
target_byte_order = info.byte_order;
|
||||
initialize_non_multiarch ();
|
||||
}
|
||||
if (! gdbarch_update_p (info))
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"initialize_current_architecture: Selection of initial architecture failed");
|
||||
|
||||
/* Create the ``set architecture'' command appending ``auto'' to the
|
||||
list of architectures. */
|
||||
|
|
@ -830,7 +674,7 @@ initialize_current_architecture (void)
|
|||
|
||||
/* Initialize a gdbarch info to values that will be automatically
|
||||
overridden. Note: Originally, this ``struct info'' was initialized
|
||||
using memset(0). Unfortunatly, that ran into problems, namely
|
||||
using memset(0). Unfortunately, that ran into problems, namely
|
||||
BFD_ENDIAN_BIG is zero. An explicit initialization function that
|
||||
can explicitly set each field to a well defined value is used. */
|
||||
|
||||
|
|
@ -839,11 +683,60 @@ gdbarch_info_init (struct gdbarch_info *info)
|
|||
{
|
||||
memset (info, 0, sizeof (struct gdbarch_info));
|
||||
info->byte_order = BFD_ENDIAN_UNKNOWN;
|
||||
info->osabi = GDB_OSABI_UNINITIALIZED;
|
||||
}
|
||||
|
||||
/* Similar to init, but this time fill in the blanks. Information is
|
||||
obtained from the specified architecture, global "set ..." options,
|
||||
and explicitly initialized INFO fields. */
|
||||
|
||||
void
|
||||
gdbarch_info_fill (struct gdbarch *gdbarch, struct gdbarch_info *info)
|
||||
{
|
||||
/* "(gdb) set architecture ...". */
|
||||
if (info->bfd_arch_info == NULL
|
||||
&& !target_architecture_auto
|
||||
&& gdbarch != NULL)
|
||||
info->bfd_arch_info = gdbarch_bfd_arch_info (gdbarch);
|
||||
if (info->bfd_arch_info == NULL
|
||||
&& info->abfd != NULL
|
||||
&& bfd_get_arch (info->abfd) != bfd_arch_unknown
|
||||
&& bfd_get_arch (info->abfd) != bfd_arch_obscure)
|
||||
info->bfd_arch_info = bfd_get_arch_info (info->abfd);
|
||||
if (info->bfd_arch_info == NULL
|
||||
&& gdbarch != NULL)
|
||||
info->bfd_arch_info = gdbarch_bfd_arch_info (gdbarch);
|
||||
|
||||
/* "(gdb) set byte-order ...". */
|
||||
if (info->byte_order == BFD_ENDIAN_UNKNOWN
|
||||
&& !target_byte_order_auto
|
||||
&& gdbarch != NULL)
|
||||
info->byte_order = gdbarch_byte_order (gdbarch);
|
||||
/* From the INFO struct. */
|
||||
if (info->byte_order == BFD_ENDIAN_UNKNOWN
|
||||
&& info->abfd != NULL)
|
||||
info->byte_order = (bfd_big_endian (info->abfd) ? BFD_ENDIAN_BIG
|
||||
: bfd_little_endian (info->abfd) ? BFD_ENDIAN_LITTLE
|
||||
: BFD_ENDIAN_UNKNOWN);
|
||||
/* From the current target. */
|
||||
if (info->byte_order == BFD_ENDIAN_UNKNOWN
|
||||
&& gdbarch != NULL)
|
||||
info->byte_order = gdbarch_byte_order (gdbarch);
|
||||
|
||||
/* "(gdb) set osabi ...". Handled by gdbarch_lookup_osabi. */
|
||||
if (info->osabi == GDB_OSABI_UNINITIALIZED)
|
||||
info->osabi = gdbarch_lookup_osabi (info->abfd);
|
||||
if (info->osabi == GDB_OSABI_UNINITIALIZED
|
||||
&& gdbarch != NULL)
|
||||
info->osabi = gdbarch_osabi (gdbarch);
|
||||
|
||||
/* Must have at least filled in the architecture. */
|
||||
gdb_assert (info->bfd_arch_info != NULL);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
extern initialize_file_ftype _initialize_gdbarch_utils;
|
||||
extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
_initialize_gdbarch_utils (void)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
/* Dynamic architecture support for GDB, the GNU debugger.
|
||||
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2002, 2003 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -21,37 +23,31 @@
|
|||
#ifndef GDBARCH_UTILS_H
|
||||
#define GDBARCH_UTILS_H
|
||||
|
||||
struct gdbarch;
|
||||
struct frame_info;
|
||||
struct minimal_symbol;
|
||||
struct type;
|
||||
struct gdbarch_info;
|
||||
|
||||
/* gdbarch trace variable */
|
||||
extern int gdbarch_debug;
|
||||
|
||||
/* Fallback for register convertible. */
|
||||
extern gdbarch_register_convertible_ftype generic_register_convertible_not;
|
||||
/* Implementation of extract return value that grubs around in the
|
||||
register cache. */
|
||||
extern gdbarch_extract_return_value_ftype legacy_extract_return_value;
|
||||
|
||||
extern CORE_ADDR generic_cannot_extract_struct_value_address (char *dummy);
|
||||
/* Implementation of store return value that grubs the register cache. */
|
||||
extern gdbarch_store_return_value_ftype legacy_store_return_value;
|
||||
|
||||
/* Helper function for targets that don't know how my arguments are
|
||||
being passed */
|
||||
extern gdbarch_frame_num_args_ftype frame_num_args_unknown;
|
||||
|
||||
/* Implementation of breakpoint from PC using any of the deprecated
|
||||
macros BREAKPOINT, LITTLE_BREAKPOINT, BIG_BREAPOINT. For legacy
|
||||
targets that don't yet implement their own breakpoint_from_pc(). */
|
||||
extern gdbarch_breakpoint_from_pc_ftype legacy_breakpoint_from_pc;
|
||||
|
||||
/* Frameless functions not identifable. */
|
||||
extern gdbarch_frameless_function_invocation_ftype generic_frameless_function_invocation_not;
|
||||
/* To return any structure or union type by value, store it at the
|
||||
address passed as an invisible first argument to the function. */
|
||||
extern gdbarch_use_struct_convention_ftype always_use_struct_convention;
|
||||
|
||||
/* Only structures, unions, and arrays are returned using the struct
|
||||
convention. Note that arrays are never passed by value in the C
|
||||
language family, so that case is irrelevant for C. */
|
||||
extern gdbarch_return_value_on_stack_ftype generic_return_value_on_stack_not;
|
||||
|
||||
/* Map onto old REGISTER_NAMES. */
|
||||
extern char *legacy_register_name (int i);
|
||||
|
||||
/* Accessor for old global function pointer for disassembly. */
|
||||
extern int legacy_print_insn (bfd_vma vma, disassemble_info *info);
|
||||
|
||||
/* Backward compatible call_dummy_words. */
|
||||
extern LONGEST legacy_call_dummy_words[];
|
||||
extern int legacy_sizeof_call_dummy_words;
|
||||
|
|
@ -59,11 +55,6 @@ extern int legacy_sizeof_call_dummy_words;
|
|||
/* Typical remote_translate_xfer_address */
|
||||
extern gdbarch_remote_translate_xfer_address_ftype generic_remote_translate_xfer_address;
|
||||
|
||||
/* Generic implementation of prologue_frameless_p. Just calls
|
||||
SKIP_PROLOG and checks the return value to see if it actually
|
||||
changed. */
|
||||
extern gdbarch_prologue_frameless_p_ftype generic_prologue_frameless_p;
|
||||
|
||||
/* The only possible cases for inner_than. */
|
||||
extern int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
||||
extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
||||
|
|
@ -72,55 +63,18 @@ extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
|||
extern const struct floatformat *default_float_format (struct gdbarch *gdbarch);
|
||||
extern const struct floatformat *default_double_format (struct gdbarch *gdbarch);
|
||||
|
||||
/* Helper function for targets that don't know how my arguments are
|
||||
being passed */
|
||||
extern int frame_num_args_unknown (struct frame_info *fi);
|
||||
|
||||
|
||||
/* The following DEPRECATED interfaces are for pre- multi-arch legacy
|
||||
targets. */
|
||||
|
||||
/* DEPRECATED pre- multi-arch interface. Explicitly set the dynamic
|
||||
target-system-dependent parameters based on bfd_architecture and
|
||||
machine. This function is deprecated, use
|
||||
set_gdbarch_from_arch_machine(). */
|
||||
|
||||
extern void set_architecture_from_arch_mach (enum bfd_architecture, unsigned long);
|
||||
|
||||
/* DEPRECATED pre- multi-arch interface. Notify the target dependent
|
||||
backend of a change to the selected architecture. A zero return
|
||||
status indicates that the target did not like the change. */
|
||||
|
||||
extern int (*target_architecture_hook) (const struct bfd_arch_info *);
|
||||
|
||||
|
||||
/* Default raw->sim register re-numbering - does nothing. */
|
||||
|
||||
extern int default_register_sim_regno (int reg_nr);
|
||||
|
||||
/* Identity function on a CORE_ADDR. Just returns its parameter. */
|
||||
/* Identity functions on a CORE_ADDR. Just return the "addr". */
|
||||
|
||||
extern CORE_ADDR core_addr_identity (CORE_ADDR addr);
|
||||
extern gdbarch_convert_from_func_ptr_addr_ftype convert_from_func_ptr_addr_identity;
|
||||
|
||||
/* No-op conversion of reg to regnum. */
|
||||
|
||||
extern int no_op_reg_to_regnum (int reg);
|
||||
|
||||
/* Default frame_args_address and frame_locals_address. */
|
||||
|
||||
extern CORE_ADDR default_frame_address (struct frame_info *);
|
||||
|
||||
/* Default prepare_to_procced. */
|
||||
|
||||
extern int default_prepare_to_proceed (int select_it);
|
||||
|
||||
extern int generic_prepare_to_proceed (int select_it);
|
||||
|
||||
/* Versions of init_frame_pc(). Do nothing; do the default. */
|
||||
|
||||
void init_frame_pc_noop (int fromleaf, struct frame_info *prev);
|
||||
|
||||
void init_frame_pc_default (int fromleaf, struct frame_info *prev);
|
||||
extern CORE_ADDR deprecated_init_frame_pc_default (int fromleaf, struct frame_info *prev);
|
||||
|
||||
/* Do nothing version of elf_make_msymbol_special. */
|
||||
|
||||
|
|
@ -136,28 +90,78 @@ void default_coff_make_msymbol_special (int val, struct minimal_symbol *msym);
|
|||
int cannot_register_not (int regnum);
|
||||
|
||||
/* Legacy version of target_virtual_frame_pointer(). Assumes that
|
||||
there is an FP_REGNUM and that it is the same, cooked or raw. */
|
||||
there is an DEPRECATED_FP_REGNUM and that it is the same, cooked or
|
||||
raw. */
|
||||
|
||||
extern gdbarch_virtual_frame_pointer_ftype legacy_virtual_frame_pointer;
|
||||
|
||||
extern CORE_ADDR generic_skip_trampoline_code (CORE_ADDR pc);
|
||||
|
||||
extern CORE_ADDR generic_skip_solib_resolver (struct gdbarch *gdbarch,
|
||||
CORE_ADDR pc);
|
||||
|
||||
extern int generic_in_solib_call_trampoline (CORE_ADDR pc, char *name);
|
||||
|
||||
extern int generic_in_solib_return_trampoline (CORE_ADDR pc, char *name);
|
||||
|
||||
extern int generic_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc);
|
||||
|
||||
extern void default_print_float_info (void);
|
||||
/* Assume that the world is sane, a registers raw and virtual size
|
||||
both match its type. */
|
||||
|
||||
/* Assume all registers are the same size and a size identical to that
|
||||
of the integer type. */
|
||||
extern int generic_register_raw_size (int regnum);
|
||||
extern int generic_register_size (int regnum);
|
||||
|
||||
/* Assume the virtual size of registers corresponds to the virtual type. */
|
||||
/* Assume that the world is sane, the registers are all adjacent. */
|
||||
extern int generic_register_byte (int regnum);
|
||||
|
||||
extern int generic_register_virtual_size (int regnum);
|
||||
/* Prop up old targets that use various IN_SIGTRAMP() macros. */
|
||||
extern int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name);
|
||||
|
||||
/* The orginal register_convert*() functions were overloaded. They
|
||||
were used to both: convert between virtual and raw register formats
|
||||
(something that is discouraged); and to convert a register to the
|
||||
type of a corresponding variable. These legacy functions preserve
|
||||
that overloaded behavour in existing targets. */
|
||||
extern int legacy_convert_register_p (int regnum, struct type *type);
|
||||
extern void legacy_register_to_value (struct frame_info *frame, int regnum,
|
||||
struct type *type, void *to);
|
||||
extern void legacy_value_to_register (struct frame_info *frame, int regnum,
|
||||
struct type *type, const void *from);
|
||||
|
||||
extern int default_stabs_argument_has_addr (struct gdbarch *gdbarch,
|
||||
struct type *type);
|
||||
|
||||
/* For compatibility with older architectures, returns
|
||||
(LEGACY_SIM_REGNO_IGNORE) when the register doesn't have a valid
|
||||
name. */
|
||||
|
||||
extern int legacy_register_sim_regno (int regnum);
|
||||
|
||||
/* Return the selected byte order, or BFD_ENDIAN_UNKNOWN if no byte
|
||||
order was explicitly selected. */
|
||||
extern enum bfd_endian selected_byte_order (void);
|
||||
|
||||
/* Return the selected architecture's name, or NULL if no architecture
|
||||
was explicitly selected. */
|
||||
extern const char *selected_architecture_name (void);
|
||||
|
||||
/* Initialize a ``struct info''. Can't use memset(0) since some
|
||||
default values are not zero. */
|
||||
default values are not zero. "fill" takes all available
|
||||
information and fills in any unspecified fields. */
|
||||
|
||||
extern void gdbarch_info_init (struct gdbarch_info *info);
|
||||
extern void gdbarch_info_fill (struct gdbarch *gdbarch,
|
||||
struct gdbarch_info *info);
|
||||
|
||||
/* Similar to init, but this time fill in the blanks. Information is
|
||||
obtained from the specified architecture, global "set ..." options,
|
||||
and explicitly initialized INFO fields. */
|
||||
extern void gdbarch_info_fill (struct gdbarch *gdbarch,
|
||||
struct gdbarch_info *info);
|
||||
|
||||
/* Return the architecture for ABFD. If no suitable architecture
|
||||
could be find, return NULL. */
|
||||
|
||||
extern struct gdbarch *gdbarch_from_bfd (bfd *abfd);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Common target dependent code for GDB on ARM systems.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -25,39 +25,33 @@
|
|||
the user is concerned but do serve to get the desired values when
|
||||
passed to read_register. */
|
||||
|
||||
#define ARM_A1_REGNUM 0 /* first integer-like argument */
|
||||
#define ARM_A4_REGNUM 3 /* last integer-like argument */
|
||||
#define ARM_AP_REGNUM 11
|
||||
#define ARM_SP_REGNUM 13 /* Contains address of top of stack */
|
||||
#define ARM_LR_REGNUM 14 /* address to return to from a function call */
|
||||
#define ARM_PC_REGNUM 15 /* Contains program counter */
|
||||
#define ARM_F0_REGNUM 16 /* first floating point register */
|
||||
#define ARM_F3_REGNUM 19 /* last floating point argument register */
|
||||
#define ARM_F7_REGNUM 23 /* last floating point register */
|
||||
#define ARM_FPS_REGNUM 24 /* floating point status register */
|
||||
#define ARM_PS_REGNUM 25 /* Contains processor status */
|
||||
|
||||
#define ARM_FP_REGNUM 11 /* Frame register in ARM code, if used. */
|
||||
#define THUMB_FP_REGNUM 7 /* Frame register in Thumb code, if used. */
|
||||
|
||||
#define ARM_NUM_ARG_REGS 4
|
||||
#define ARM_LAST_ARG_REGNUM ARM_A4_REGNUM
|
||||
#define ARM_NUM_FP_ARG_REGS 4
|
||||
#define ARM_LAST_FP_ARG_REGNUM ARM_F3_REGNUM
|
||||
enum gdb_regnum {
|
||||
ARM_A1_REGNUM = 0, /* first integer-like argument */
|
||||
ARM_A4_REGNUM = 3, /* last integer-like argument */
|
||||
ARM_AP_REGNUM = 11,
|
||||
ARM_SP_REGNUM = 13, /* Contains address of top of stack */
|
||||
ARM_LR_REGNUM = 14, /* address to return to from a function call */
|
||||
ARM_PC_REGNUM = 15, /* Contains program counter */
|
||||
ARM_F0_REGNUM = 16, /* first floating point register */
|
||||
ARM_F3_REGNUM = 19, /* last floating point argument register */
|
||||
ARM_F7_REGNUM = 23, /* last floating point register */
|
||||
ARM_FPS_REGNUM = 24, /* floating point status register */
|
||||
ARM_PS_REGNUM = 25, /* Contains processor status */
|
||||
ARM_FP_REGNUM = 11, /* Frame register in ARM code, if used. */
|
||||
THUMB_FP_REGNUM = 7, /* Frame register in Thumb code, if used. */
|
||||
ARM_NUM_ARG_REGS = 4,
|
||||
ARM_LAST_ARG_REGNUM = ARM_A4_REGNUM,
|
||||
ARM_NUM_FP_ARG_REGS = 4,
|
||||
ARM_LAST_FP_ARG_REGNUM = ARM_F3_REGNUM
|
||||
};
|
||||
|
||||
/* Size of integer registers. */
|
||||
#define INT_REGISTER_RAW_SIZE 4
|
||||
#define INT_REGISTER_VIRTUAL_SIZE 4
|
||||
#define INT_REGISTER_SIZE 4
|
||||
|
||||
/* Say how long FP registers are. Used for documentation purposes and
|
||||
code readability in this header. IEEE extended doubles are 80
|
||||
bits. DWORD aligned they use 96 bits. */
|
||||
#define FP_REGISTER_RAW_SIZE 12
|
||||
|
||||
/* GCC doesn't support long doubles (extended IEEE values). The FP
|
||||
register virtual size is therefore 64 bits. Used for documentation
|
||||
purposes and code readability in this header. */
|
||||
#define FP_REGISTER_VIRTUAL_SIZE 8
|
||||
#define FP_REGISTER_SIZE 12
|
||||
|
||||
/* Status registers are the same size as general purpose registers.
|
||||
Used for documentation purposes and code readability in this
|
||||
|
|
@ -99,44 +93,32 @@
|
|||
#define FLAG_C 0x20000000
|
||||
#define FLAG_V 0x10000000
|
||||
|
||||
/* ABI variants that we know about. If you add to this enum, please
|
||||
update the table of names in tm-arm.c. */
|
||||
enum arm_abi
|
||||
{
|
||||
ARM_ABI_UNKNOWN = 0,
|
||||
ARM_ABI_EABI_V1,
|
||||
ARM_ABI_EABI_V2,
|
||||
ARM_ABI_LINUX,
|
||||
ARM_ABI_NETBSD_AOUT,
|
||||
ARM_ABI_NETBSD_ELF,
|
||||
ARM_ABI_APCS,
|
||||
ARM_ABI_FREEBSD,
|
||||
ARM_ABI_WINCE,
|
||||
|
||||
ARM_ABI_INVALID /* Keep this last. */
|
||||
};
|
||||
|
||||
/* Type of floating-point code in use by inferior. There are really 3 models
|
||||
that are traditionally supported (plus the endianness issue), but gcc can
|
||||
only generate 2 of those. The third is APCS_FLOAT, where arguments to
|
||||
functions are passed in floating-point registers.
|
||||
|
||||
In addition to the traditional models, VFP adds two more. */
|
||||
In addition to the traditional models, VFP adds two more.
|
||||
|
||||
If you update this enum, don't forget to update fp_model_strings in
|
||||
arm-tdep.c. */
|
||||
|
||||
enum arm_float_model
|
||||
{
|
||||
ARM_FLOAT_SOFT,
|
||||
ARM_FLOAT_FPA,
|
||||
ARM_FLOAT_SOFT_VFP,
|
||||
ARM_FLOAT_VFP
|
||||
ARM_FLOAT_AUTO, /* Automatic detection. Do not set in tdep. */
|
||||
ARM_FLOAT_SOFT_FPA, /* Traditional soft-float (mixed-endian on LE ARM). */
|
||||
ARM_FLOAT_FPA, /* FPA co-processor. GCC calling convention. */
|
||||
ARM_FLOAT_SOFT_VFP, /* Soft-float with pure-endian doubles. */
|
||||
ARM_FLOAT_VFP, /* Full VFP calling convention. */
|
||||
ARM_FLOAT_LAST /* Keep at end. */
|
||||
};
|
||||
|
||||
/* A method to the setting based on user's choice and ABI setting. */
|
||||
enum arm_float_model arm_get_fp_model (struct gdbarch *);
|
||||
|
||||
/* Target-dependent structure in gdbarch. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
enum arm_abi arm_abi; /* OS/ABI of inferior. */
|
||||
const char *abi_name; /* Name of the above. */
|
||||
|
||||
enum arm_float_model fp_model; /* Floating point calling conventions. */
|
||||
|
||||
CORE_ADDR lowest_pc; /* Lowest address at which instructions
|
||||
|
|
@ -165,10 +147,3 @@ int arm_pc_is_thumb (CORE_ADDR);
|
|||
CORE_ADDR thumb_get_next_pc (CORE_ADDR);
|
||||
|
||||
CORE_ADDR arm_get_next_pc (CORE_ADDR);
|
||||
|
||||
/* How a OS variant tells the ARM generic code that it can handle an ABI
|
||||
type. */
|
||||
void
|
||||
arm_gdbarch_register_os_abi (enum arm_abi abi,
|
||||
void (*init_abi)(struct gdbarch_info,
|
||||
struct gdbarch *));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Target-specific functions for ARM running under NetBSD.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -19,12 +19,15 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "osabi.h"
|
||||
|
||||
#include "arm-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
|
||||
/* Description of the longjmp buffer. */
|
||||
#define JB_PC 24
|
||||
#define JB_ELEMENT_SIZE INT_REGISTER_RAW_SIZE
|
||||
#define ARM_NBSD_JB_PC 24
|
||||
#define ARM_NBSD_JB_ELEMENT_SIZE INT_REGISTER_SIZE
|
||||
|
||||
/* For compatibility with previous implemenations of GDB on arm/NetBSD,
|
||||
override the default little-endian breakpoint. */
|
||||
|
|
@ -49,8 +52,8 @@ arm_netbsd_init_abi_common (struct gdbarch_info info,
|
|||
tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint;
|
||||
tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint);
|
||||
|
||||
tdep->jb_pc = JB_PC;
|
||||
tdep->jb_elt_size = JB_ELEMENT_SIZE;
|
||||
tdep->jb_pc = ARM_NBSD_JB_PC;
|
||||
tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -63,7 +66,7 @@ arm_netbsd_aout_init_abi (struct gdbarch_info info,
|
|||
|
||||
set_gdbarch_in_solib_call_trampoline
|
||||
(gdbarch, arm_netbsd_aout_in_solib_call_trampoline);
|
||||
tdep->fp_model = ARM_FLOAT_SOFT;
|
||||
tdep->fp_model = ARM_FLOAT_SOFT_FPA;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -74,12 +77,29 @@ arm_netbsd_elf_init_abi (struct gdbarch_info info,
|
|||
|
||||
arm_netbsd_init_abi_common (info, gdbarch);
|
||||
|
||||
set_solib_svr4_fetch_link_map_offsets (gdbarch,
|
||||
nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
|
||||
|
||||
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
|
||||
}
|
||||
|
||||
static enum gdb_osabi
|
||||
arm_netbsd_aout_osabi_sniffer (bfd *abfd)
|
||||
{
|
||||
if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0)
|
||||
return GDB_OSABI_NETBSD_AOUT;
|
||||
|
||||
return GDB_OSABI_UNKNOWN;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arm_netbsd_tdep (void)
|
||||
{
|
||||
arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_AOUT, arm_netbsd_aout_init_abi);
|
||||
arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_ELF, arm_netbsd_elf_init_abi);
|
||||
gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour,
|
||||
arm_netbsd_aout_osabi_sniffer);
|
||||
|
||||
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_AOUT,
|
||||
arm_netbsd_aout_init_abi);
|
||||
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_ELF,
|
||||
arm_netbsd_elf_init_abi);
|
||||
}
|
||||
|
|
|
|||
300
contrib/gdb/gdb/auxv.c
Normal file
300
contrib/gdb/gdb/auxv.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/* Auxiliary vector support for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2004 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 "target.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "command.h"
|
||||
#include "inferior.h"
|
||||
#include "valprint.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
#include "auxv.h"
|
||||
#include "elf/common.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
/* This function is called like a to_xfer_partial hook,
|
||||
but must be called with TARGET_OBJECT_AUXV.
|
||||
It handles access via /proc/PID/auxv, which is the common method.
|
||||
This function is appropriate for doing:
|
||||
#define NATIVE_XFER_AUXV procfs_xfer_auxv
|
||||
for a native target that uses inftarg.c's child_xfer_partial hook. */
|
||||
|
||||
LONGEST
|
||||
procfs_xfer_auxv (struct target_ops *ops,
|
||||
int /* enum target_object */ object,
|
||||
const char *annex,
|
||||
void *readbuf,
|
||||
const void *writebuf,
|
||||
ULONGEST offset,
|
||||
LONGEST len)
|
||||
{
|
||||
char *pathname;
|
||||
int fd;
|
||||
LONGEST n;
|
||||
|
||||
gdb_assert (object == TARGET_OBJECT_AUXV);
|
||||
gdb_assert (readbuf || writebuf);
|
||||
|
||||
pathname = xstrprintf ("/proc/%d/auxv", PIDGET (inferior_ptid));
|
||||
fd = open (pathname, writebuf != NULL ? O_WRONLY : O_RDONLY);
|
||||
xfree (pathname);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (offset != (ULONGEST) 0
|
||||
&& lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
|
||||
n = -1;
|
||||
else if (readbuf != NULL)
|
||||
n = read (fd, readbuf, len);
|
||||
else
|
||||
n = write (fd, writebuf, len);
|
||||
|
||||
(void) close (fd);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Read all the auxv data into a contiguous xmalloc'd buffer,
|
||||
stored in *DATA. Return the size in bytes of this data.
|
||||
If zero, there is no data and *DATA is null.
|
||||
if < 0, there was an error and *DATA is null. */
|
||||
LONGEST
|
||||
target_auxv_read (struct target_ops *ops, char **data)
|
||||
{
|
||||
size_t auxv_alloc = 512, auxv_pos = 0;
|
||||
char *auxv = xmalloc (auxv_alloc);
|
||||
int n;
|
||||
|
||||
while (1)
|
||||
{
|
||||
n = target_read_partial (ops, TARGET_OBJECT_AUXV,
|
||||
NULL, &auxv[auxv_pos], 0,
|
||||
auxv_alloc - auxv_pos);
|
||||
if (n <= 0)
|
||||
break;
|
||||
auxv_pos += n;
|
||||
if (auxv_pos < auxv_alloc) /* Read all there was. */
|
||||
break;
|
||||
gdb_assert (auxv_pos == auxv_alloc);
|
||||
auxv_alloc *= 2;
|
||||
auxv = xrealloc (auxv, auxv_alloc);
|
||||
}
|
||||
|
||||
if (auxv_pos == 0)
|
||||
{
|
||||
xfree (auxv);
|
||||
*data = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
*data = auxv;
|
||||
return auxv_pos;
|
||||
}
|
||||
|
||||
/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
|
||||
Return 0 if *READPTR is already at the end of the buffer.
|
||||
Return -1 if there is insufficient buffer for a whole entry.
|
||||
Return 1 if an entry was read into *TYPEP and *VALP. */
|
||||
int
|
||||
target_auxv_parse (struct target_ops *ops, char **readptr, char *endptr,
|
||||
CORE_ADDR *typep, CORE_ADDR *valp)
|
||||
{
|
||||
const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
|
||||
char *ptr = *readptr;
|
||||
|
||||
if (endptr == ptr)
|
||||
return 0;
|
||||
|
||||
if (endptr - ptr < sizeof_auxv_field * 2)
|
||||
return -1;
|
||||
|
||||
*typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
|
||||
ptr += sizeof_auxv_field;
|
||||
*valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
|
||||
ptr += sizeof_auxv_field;
|
||||
|
||||
*readptr = ptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Extract the auxiliary vector entry with a_type matching MATCH.
|
||||
Return zero if no such entry was found, or -1 if there was
|
||||
an error getting the information. On success, return 1 after
|
||||
storing the entry's value field in *VALP. */
|
||||
int
|
||||
target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
|
||||
{
|
||||
CORE_ADDR type, val;
|
||||
char *data;
|
||||
int n = target_auxv_read (ops, &data);
|
||||
char *ptr = data;
|
||||
int ents = 0;
|
||||
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
while (1)
|
||||
switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
|
||||
{
|
||||
case 1: /* Here's an entry, check it. */
|
||||
if (type == match)
|
||||
{
|
||||
xfree (data);
|
||||
*valp = val;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0: /* End of the vector. */
|
||||
xfree (data);
|
||||
return 0;
|
||||
default: /* Bogosity. */
|
||||
xfree (data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
||||
/* Print the contents of the target's AUXV on the specified file. */
|
||||
int
|
||||
fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
|
||||
{
|
||||
CORE_ADDR type, val;
|
||||
char *data;
|
||||
int len = target_auxv_read (ops, &data);
|
||||
char *ptr = data;
|
||||
int ents = 0;
|
||||
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
|
||||
{
|
||||
extern int addressprint;
|
||||
const char *name = "???";
|
||||
const char *description = "";
|
||||
enum { dec, hex, str } flavor = hex;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
#define TAG(tag, text, kind) \
|
||||
case tag: name = #tag; description = text; flavor = kind; break
|
||||
TAG (AT_NULL, "End of vector", hex);
|
||||
TAG (AT_IGNORE, "Entry should be ignored", hex);
|
||||
TAG (AT_EXECFD, "File descriptor of program", dec);
|
||||
TAG (AT_PHDR, "Program headers for program", hex);
|
||||
TAG (AT_PHENT, "Size of program header entry", dec);
|
||||
TAG (AT_PHNUM, "Number of program headers", dec);
|
||||
TAG (AT_PAGESZ, "System page size", dec);
|
||||
TAG (AT_BASE, "Base address of interpreter", hex);
|
||||
TAG (AT_FLAGS, "Flags", hex);
|
||||
TAG (AT_ENTRY, "Entry point of program", hex);
|
||||
TAG (AT_NOTELF, "Program is not ELF", dec);
|
||||
TAG (AT_UID, "Real user ID", dec);
|
||||
TAG (AT_EUID, "Effective user ID", dec);
|
||||
TAG (AT_GID, "Real group ID", dec);
|
||||
TAG (AT_EGID, "Effective group ID", dec);
|
||||
TAG (AT_CLKTCK, "Frequency of times()", dec);
|
||||
TAG (AT_PLATFORM, "String identifying platform", str);
|
||||
TAG (AT_HWCAP, "Machine-dependent CPU capability hints", hex);
|
||||
TAG (AT_FPUCW, "Used FPU control word", dec);
|
||||
TAG (AT_DCACHEBSIZE, "Data cache block size", dec);
|
||||
TAG (AT_ICACHEBSIZE, "Instruction cache block size", dec);
|
||||
TAG (AT_UCACHEBSIZE, "Unified cache block size", dec);
|
||||
TAG (AT_IGNOREPPC, "Entry should be ignored", dec);
|
||||
TAG (AT_SYSINFO, "Special system info/entry points", hex);
|
||||
TAG (AT_SYSINFO_EHDR, "System-supplied DSO's ELF header", hex);
|
||||
TAG (AT_SECURE, "Boolean, was exec setuid-like?", dec);
|
||||
TAG (AT_SUN_UID, "Effective user ID", dec);
|
||||
TAG (AT_SUN_RUID, "Real user ID", dec);
|
||||
TAG (AT_SUN_GID, "Effective group ID", dec);
|
||||
TAG (AT_SUN_RGID, "Real group ID", dec);
|
||||
TAG (AT_SUN_LDELF, "Dynamic linker's ELF header", hex);
|
||||
TAG (AT_SUN_LDSHDR, "Dynamic linker's section headers", hex);
|
||||
TAG (AT_SUN_LDNAME, "String giving name of dynamic linker", str);
|
||||
TAG (AT_SUN_LPAGESZ, "Large pagesize", dec);
|
||||
TAG (AT_SUN_PLATFORM, "Platform name string", str);
|
||||
TAG (AT_SUN_HWCAP, "Machine-dependent CPU capability hints", hex);
|
||||
TAG (AT_SUN_IFLUSH, "Should flush icache?", dec);
|
||||
TAG (AT_SUN_CPU, "CPU name string", str);
|
||||
TAG (AT_SUN_EMUL_ENTRY, "COFF entry point address", hex);
|
||||
TAG (AT_SUN_EMUL_EXECFD, "COFF executable file descriptor", dec);
|
||||
TAG (AT_SUN_EXECNAME,
|
||||
"Canonicalized file name given to execve", str);
|
||||
TAG (AT_SUN_MMU, "String for name of MMU module", str);
|
||||
TAG (AT_SUN_LDDATA, "Dynamic linker's data segment address", hex);
|
||||
}
|
||||
|
||||
fprintf_filtered (file, "%-4s %-20s %-30s ",
|
||||
paddr_d (type), name, description);
|
||||
switch (flavor)
|
||||
{
|
||||
case dec:
|
||||
fprintf_filtered (file, "%s\n", paddr_d (val));
|
||||
break;
|
||||
case hex:
|
||||
fprintf_filtered (file, "0x%s\n", paddr_nz (val));
|
||||
break;
|
||||
case str:
|
||||
if (addressprint)
|
||||
fprintf_filtered (file, "0x%s", paddr_nz (val));
|
||||
val_print_string (val, -1, 1, file);
|
||||
fprintf_filtered (file, "\n");
|
||||
break;
|
||||
}
|
||||
++ents;
|
||||
}
|
||||
|
||||
xfree (data);
|
||||
|
||||
return ents;
|
||||
}
|
||||
|
||||
static void
|
||||
info_auxv_command (char *cmd, int from_tty)
|
||||
{
|
||||
if (! target_has_stack)
|
||||
error ("The program has no auxiliary information now.");
|
||||
else
|
||||
{
|
||||
int ents = fprint_target_auxv (gdb_stdout, ¤t_target);
|
||||
if (ents < 0)
|
||||
error ("No auxiliary vector found, or failed reading it.");
|
||||
else if (ents == 0)
|
||||
error ("Auxiliary vector is empty.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern initialize_file_ftype _initialize_auxv; /* -Wmissing-prototypes; */
|
||||
|
||||
void
|
||||
_initialize_auxv (void)
|
||||
{
|
||||
add_info ("auxv", info_auxv_command,
|
||||
"Display the inferior's auxiliary vector.\n\
|
||||
This is information provided by the operating system at program startup.");
|
||||
}
|
||||
75
contrib/gdb/gdb/auxv.h
Normal file
75
contrib/gdb/gdb/auxv.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* Auxiliary vector support for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2004 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 AUXV_H
|
||||
#define AUXV_H
|
||||
|
||||
/* See "include/elf/common.h" for the definition of valid AT_* values. */
|
||||
|
||||
|
||||
/* Avoid miscellaneous includes in this file, so that it can be
|
||||
included by nm-*.h for the procfs_xfer_auxv decl if that is
|
||||
used in NATIVE_XFER_AUXV. */
|
||||
struct target_ops; /* Forward declaration. */
|
||||
|
||||
|
||||
/* Read all the auxv data into a contiguous xmalloc'd buffer,
|
||||
stored in *DATA. Return the size in bytes of this data.
|
||||
If zero, there is no data and *DATA is null.
|
||||
if < 0, there was an error and *DATA is null. */
|
||||
extern LONGEST target_auxv_read (struct target_ops *ops, char **data);
|
||||
|
||||
/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
|
||||
Return 0 if *READPTR is already at the end of the buffer.
|
||||
Return -1 if there is insufficient buffer for a whole entry.
|
||||
Return 1 if an entry was read into *TYPEP and *VALP. */
|
||||
extern int target_auxv_parse (struct target_ops *ops,
|
||||
char **readptr, char *endptr,
|
||||
CORE_ADDR *typep, CORE_ADDR *valp);
|
||||
|
||||
/* Extract the auxiliary vector entry with a_type matching MATCH.
|
||||
Return zero if no such entry was found, or -1 if there was
|
||||
an error getting the information. On success, return 1 after
|
||||
storing the entry's value field in *VALP. */
|
||||
extern int target_auxv_search (struct target_ops *ops,
|
||||
CORE_ADDR match, CORE_ADDR *valp);
|
||||
|
||||
/* Print the contents of the target's AUXV on the specified file. */
|
||||
extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
|
||||
|
||||
|
||||
/* This function is called like a to_xfer_partial hook,
|
||||
but must be called with TARGET_OBJECT_AUXV.
|
||||
It handles access via /proc/PID/auxv, which is the common method.
|
||||
This function is appropriate for doing:
|
||||
#define NATIVE_XFER_AUXV procfs_xfer_auxv
|
||||
for a native target that uses inftarg.c's child_xfer_partial hook. */
|
||||
|
||||
extern LONGEST procfs_xfer_auxv (struct target_ops *ops,
|
||||
int /* enum target_object */ object,
|
||||
const char *annex,
|
||||
void *readbuf,
|
||||
const void *writebuf,
|
||||
ULONGEST offset,
|
||||
LONGEST len);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
/* GDB-specific functions for operating on agent expressions
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
/* GDB-specific functions for operating on agent expressions.
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001, 2003 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -30,6 +32,9 @@
|
|||
#include "target.h"
|
||||
#include "ax.h"
|
||||
#include "ax-gdb.h"
|
||||
#include "gdb_string.h"
|
||||
#include "block.h"
|
||||
#include "regcache.h"
|
||||
|
||||
/* To make sense of this file, you should read doc/agentexpr.texi.
|
||||
Then look at the types and enums in ax-gdb.h. For the code itself,
|
||||
|
|
@ -129,7 +134,6 @@ static void gen_sizeof (union exp_element **pc,
|
|||
static void gen_expr (union exp_element **pc,
|
||||
struct agent_expr *ax, struct axs_value *value);
|
||||
|
||||
static void print_axs_value (struct ui_file *f, struct axs_value * value);
|
||||
static void agent_command (char *exp, int from_tty);
|
||||
|
||||
|
||||
|
|
@ -353,7 +357,7 @@ gen_sign_extend (struct agent_expr *ax, struct type *type)
|
|||
{
|
||||
/* Do we need to sign-extend this? */
|
||||
if (!TYPE_UNSIGNED (type))
|
||||
ax_ext (ax, type->length * TARGET_CHAR_BIT);
|
||||
ax_ext (ax, TYPE_LENGTH (type) * TARGET_CHAR_BIT);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -363,7 +367,7 @@ gen_sign_extend (struct agent_expr *ax, struct type *type)
|
|||
static void
|
||||
gen_extend (struct agent_expr *ax, struct type *type)
|
||||
{
|
||||
int bits = type->length * TARGET_CHAR_BIT;
|
||||
int bits = TYPE_LENGTH (type) * TARGET_CHAR_BIT;
|
||||
/* I just had to. */
|
||||
((TYPE_UNSIGNED (type) ? ax_zero_ext : ax_ext) (ax, bits));
|
||||
}
|
||||
|
|
@ -381,7 +385,7 @@ gen_fetch (struct agent_expr *ax, struct type *type)
|
|||
ax_trace_quick (ax, TYPE_LENGTH (type));
|
||||
}
|
||||
|
||||
switch (type->code)
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_ENUM:
|
||||
|
|
@ -389,7 +393,7 @@ gen_fetch (struct agent_expr *ax, struct type *type)
|
|||
case TYPE_CODE_CHAR:
|
||||
/* It's a scalar value, so we know how to dereference it. How
|
||||
many bytes long is it? */
|
||||
switch (type->length)
|
||||
switch (TYPE_LENGTH (type))
|
||||
{
|
||||
case 8 / TARGET_CHAR_BIT:
|
||||
ax_simple (ax, aop_ref8);
|
||||
|
|
@ -575,7 +579,7 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
|
|||
|
||||
case LOC_TYPEDEF:
|
||||
error ("Cannot compute value of typedef `%s'.",
|
||||
SYMBOL_SOURCE_NAME (var));
|
||||
SYMBOL_PRINT_NAME (var));
|
||||
break;
|
||||
|
||||
case LOC_BLOCK:
|
||||
|
|
@ -604,9 +608,9 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
|
|||
case LOC_UNRESOLVED:
|
||||
{
|
||||
struct minimal_symbol *msym
|
||||
= lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
|
||||
= lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (var), NULL, NULL);
|
||||
if (!msym)
|
||||
error ("Couldn't resolve symbol `%s'.", SYMBOL_SOURCE_NAME (var));
|
||||
error ("Couldn't resolve symbol `%s'.", SYMBOL_PRINT_NAME (var));
|
||||
|
||||
/* Push the address of the variable. */
|
||||
ax_const_l (ax, SYMBOL_VALUE_ADDRESS (msym));
|
||||
|
|
@ -614,14 +618,24 @@ gen_var_ref (struct agent_expr *ax, struct axs_value *value, struct symbol *var)
|
|||
}
|
||||
break;
|
||||
|
||||
case LOC_COMPUTED:
|
||||
case LOC_COMPUTED_ARG:
|
||||
/* FIXME: cagney/2004-01-26: It should be possible to
|
||||
unconditionally call the SYMBOL_OPS method when available.
|
||||
Unfortunately DWARF 2 stores the frame-base (instead of the
|
||||
function) location in a function's symbol. Oops! For the
|
||||
moment enable this when/where applicable. */
|
||||
SYMBOL_OPS (var)->tracepoint_var_ref (var, ax, value);
|
||||
break;
|
||||
|
||||
case LOC_OPTIMIZED_OUT:
|
||||
error ("The variable `%s' has been optimized out.",
|
||||
SYMBOL_SOURCE_NAME (var));
|
||||
SYMBOL_PRINT_NAME (var));
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Cannot find value of botched symbol `%s'.",
|
||||
SYMBOL_SOURCE_NAME (var));
|
||||
SYMBOL_PRINT_NAME (var));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -699,7 +713,7 @@ gen_usual_unary (struct agent_expr *ax, struct axs_value *value)
|
|||
the stack. Should we tweak the type? */
|
||||
|
||||
/* Some types require special handling. */
|
||||
switch (value->type->code)
|
||||
switch (TYPE_CODE (value->type))
|
||||
{
|
||||
/* Functions get converted to a pointer to the function. */
|
||||
case TYPE_CODE_FUNC:
|
||||
|
|
@ -874,7 +888,7 @@ gen_cast (struct agent_expr *ax, struct axs_value *value, struct type *type)
|
|||
/* Dereference typedefs. */
|
||||
type = check_typedef (type);
|
||||
|
||||
switch (type->code)
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_PTR:
|
||||
/* It's implementation-defined, and I'll bet this is what GCC
|
||||
|
|
@ -925,9 +939,9 @@ gen_scale (struct agent_expr *ax, enum agent_op op, struct type *type)
|
|||
{
|
||||
struct type *element = TYPE_TARGET_TYPE (type);
|
||||
|
||||
if (element->length != 1)
|
||||
if (TYPE_LENGTH (element) != 1)
|
||||
{
|
||||
ax_const_l (ax, element->length);
|
||||
ax_const_l (ax, TYPE_LENGTH (element));
|
||||
ax_simple (ax, op);
|
||||
}
|
||||
}
|
||||
|
|
@ -943,8 +957,8 @@ gen_add (struct agent_expr *ax, struct axs_value *value,
|
|||
struct axs_value *value1, struct axs_value *value2, char *name)
|
||||
{
|
||||
/* Is it INT+PTR? */
|
||||
if (value1->type->code == TYPE_CODE_INT
|
||||
&& value2->type->code == TYPE_CODE_PTR)
|
||||
if (TYPE_CODE (value1->type) == TYPE_CODE_INT
|
||||
&& TYPE_CODE (value2->type) == TYPE_CODE_PTR)
|
||||
{
|
||||
/* Swap the values and proceed normally. */
|
||||
ax_simple (ax, aop_swap);
|
||||
|
|
@ -955,8 +969,8 @@ gen_add (struct agent_expr *ax, struct axs_value *value,
|
|||
}
|
||||
|
||||
/* Is it PTR+INT? */
|
||||
else if (value1->type->code == TYPE_CODE_PTR
|
||||
&& value2->type->code == TYPE_CODE_INT)
|
||||
else if (TYPE_CODE (value1->type) == TYPE_CODE_PTR
|
||||
&& TYPE_CODE (value2->type) == TYPE_CODE_INT)
|
||||
{
|
||||
gen_scale (ax, aop_mul, value1->type);
|
||||
ax_simple (ax, aop_add);
|
||||
|
|
@ -966,8 +980,8 @@ gen_add (struct agent_expr *ax, struct axs_value *value,
|
|||
|
||||
/* Must be number + number; the usual binary conversions will have
|
||||
brought them both to the same width. */
|
||||
else if (value1->type->code == TYPE_CODE_INT
|
||||
&& value2->type->code == TYPE_CODE_INT)
|
||||
else if (TYPE_CODE (value1->type) == TYPE_CODE_INT
|
||||
&& TYPE_CODE (value2->type) == TYPE_CODE_INT)
|
||||
{
|
||||
ax_simple (ax, aop_add);
|
||||
gen_extend (ax, value1->type); /* Catch overflow. */
|
||||
|
|
@ -989,10 +1003,10 @@ static void
|
|||
gen_sub (struct agent_expr *ax, struct axs_value *value,
|
||||
struct axs_value *value1, struct axs_value *value2)
|
||||
{
|
||||
if (value1->type->code == TYPE_CODE_PTR)
|
||||
if (TYPE_CODE (value1->type) == TYPE_CODE_PTR)
|
||||
{
|
||||
/* Is it PTR - INT? */
|
||||
if (value2->type->code == TYPE_CODE_INT)
|
||||
if (TYPE_CODE (value2->type) == TYPE_CODE_INT)
|
||||
{
|
||||
gen_scale (ax, aop_mul, value1->type);
|
||||
ax_simple (ax, aop_sub);
|
||||
|
|
@ -1003,7 +1017,7 @@ gen_sub (struct agent_expr *ax, struct axs_value *value,
|
|||
/* Is it PTR - PTR? Strictly speaking, the types ought to
|
||||
match, but this is what the normal GDB expression evaluator
|
||||
tests for. */
|
||||
else if (value2->type->code == TYPE_CODE_PTR
|
||||
else if (TYPE_CODE (value2->type) == TYPE_CODE_PTR
|
||||
&& (TYPE_LENGTH (TYPE_TARGET_TYPE (value1->type))
|
||||
== TYPE_LENGTH (TYPE_TARGET_TYPE (value2->type))))
|
||||
{
|
||||
|
|
@ -1018,8 +1032,8 @@ an integer nor a pointer of the same type.");
|
|||
}
|
||||
|
||||
/* Must be number + number. */
|
||||
else if (value1->type->code == TYPE_CODE_INT
|
||||
&& value2->type->code == TYPE_CODE_INT)
|
||||
else if (TYPE_CODE (value1->type) == TYPE_CODE_INT
|
||||
&& TYPE_CODE (value2->type) == TYPE_CODE_INT)
|
||||
{
|
||||
ax_simple (ax, aop_sub);
|
||||
gen_extend (ax, value1->type); /* Catch overflow. */
|
||||
|
|
@ -1044,8 +1058,8 @@ gen_binop (struct agent_expr *ax, struct axs_value *value,
|
|||
enum agent_op op_unsigned, int may_carry, char *name)
|
||||
{
|
||||
/* We only handle INT op INT. */
|
||||
if ((value1->type->code != TYPE_CODE_INT)
|
||||
|| (value2->type->code != TYPE_CODE_INT))
|
||||
if ((TYPE_CODE (value1->type) != TYPE_CODE_INT)
|
||||
|| (TYPE_CODE (value2->type) != TYPE_CODE_INT))
|
||||
error ("Illegal combination of types in %s.", name);
|
||||
|
||||
ax_simple (ax,
|
||||
|
|
@ -1092,7 +1106,7 @@ gen_deref (struct agent_expr *ax, struct axs_value *value)
|
|||
{
|
||||
/* The caller should check the type, because several operators use
|
||||
this, and we don't know what error message to generate. */
|
||||
if (value->type->code != TYPE_CODE_PTR)
|
||||
if (TYPE_CODE (value->type) != TYPE_CODE_PTR)
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"gen_deref: expected a pointer");
|
||||
|
||||
|
|
@ -1102,7 +1116,7 @@ gen_deref (struct agent_expr *ax, struct axs_value *value)
|
|||
T" to "T", and mark the value as an lvalue in memory. Leave it
|
||||
to the consumer to actually dereference it. */
|
||||
value->type = check_typedef (TYPE_TARGET_TYPE (value->type));
|
||||
value->kind = ((value->type->code == TYPE_CODE_FUNC)
|
||||
value->kind = ((TYPE_CODE (value->type) == TYPE_CODE_FUNC)
|
||||
? axs_rvalue : axs_lvalue_memory);
|
||||
}
|
||||
|
||||
|
|
@ -1114,7 +1128,7 @@ gen_address_of (struct agent_expr *ax, struct axs_value *value)
|
|||
/* Special case for taking the address of a function. The ANSI
|
||||
standard describes this as a special case, too, so this
|
||||
arrangement is not without motivation. */
|
||||
if (value->type->code == TYPE_CODE_FUNC)
|
||||
if (TYPE_CODE (value->type) == TYPE_CODE_FUNC)
|
||||
/* The value's already an rvalue on the stack, so we just need to
|
||||
change the type. */
|
||||
value->type = lookup_pointer_type (value->type);
|
||||
|
|
@ -1156,7 +1170,7 @@ find_field (struct type *type, char *name)
|
|||
{
|
||||
char *this_name = TYPE_FIELD_NAME (type, i);
|
||||
|
||||
if (this_name && STREQ (name, this_name))
|
||||
if (this_name && strcmp (name, this_name) == 0)
|
||||
return i;
|
||||
|
||||
if (this_name[0] == '\0')
|
||||
|
|
@ -1346,7 +1360,7 @@ gen_struct_ref (struct agent_expr *ax, struct axs_value *value, char *field,
|
|||
/* Follow pointers until we reach a non-pointer. These aren't the C
|
||||
semantics, but they're what the normal GDB evaluator does, so we
|
||||
should at least be consistent. */
|
||||
while (value->type->code == TYPE_CODE_PTR)
|
||||
while (TYPE_CODE (value->type) == TYPE_CODE_PTR)
|
||||
{
|
||||
gen_usual_unary (ax, value);
|
||||
gen_deref (ax, value);
|
||||
|
|
@ -1410,7 +1424,7 @@ gen_repeat (union exp_element **pc, struct agent_expr *ax,
|
|||
|
||||
if (!v)
|
||||
error ("Right operand of `@' must be a constant, in agent expressions.");
|
||||
if (v->type->code != TYPE_CODE_INT)
|
||||
if (TYPE_CODE (v->type) != TYPE_CODE_INT)
|
||||
error ("Right operand of `@' must be an integer.");
|
||||
length = value_as_long (v);
|
||||
if (length <= 0)
|
||||
|
|
@ -1586,7 +1600,7 @@ gen_expr (union exp_element **pc, struct agent_expr *ax,
|
|||
(*pc) += 3;
|
||||
value->kind = axs_lvalue_register;
|
||||
value->u.reg = reg;
|
||||
value->type = REGISTER_VIRTUAL_TYPE (reg);
|
||||
value->type = register_type (current_gdbarch, reg);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1787,33 +1801,6 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
|
|||
discard_cleanups (old_chain);
|
||||
return ax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The "agent" command, for testing: compile and disassemble an expression. */
|
||||
|
||||
static void
|
||||
print_axs_value (struct ui_file *f, struct axs_value *value)
|
||||
{
|
||||
switch (value->kind)
|
||||
{
|
||||
case axs_rvalue:
|
||||
fputs_filtered ("rvalue", f);
|
||||
break;
|
||||
|
||||
case axs_lvalue_memory:
|
||||
fputs_filtered ("memory lvalue", f);
|
||||
break;
|
||||
|
||||
case axs_lvalue_register:
|
||||
fprintf_filtered (f, "register %d lvalue", value->u.reg);
|
||||
break;
|
||||
}
|
||||
|
||||
fputs_filtered (" : ", f);
|
||||
type_print (value->type, "", f, -1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
agent_command (char *exp, int from_tty)
|
||||
|
|
@ -1835,7 +1822,7 @@ agent_command (char *exp, int from_tty)
|
|||
|
||||
expr = parse_expression (exp);
|
||||
old_chain = make_cleanup (free_current_contents, &expr);
|
||||
agent = gen_trace_for_expr (fi->pc, expr);
|
||||
agent = gen_trace_for_expr (get_frame_pc (fi), expr);
|
||||
make_cleanup_free_agent_expr (agent);
|
||||
ax_print (gdb_stdout, agent);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
#ifndef AX_GDB_H
|
||||
#define AX_GDB_H
|
||||
|
||||
|
||||
struct expression;
|
||||
|
||||
/* Types and enums */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "ax.h"
|
||||
|
||||
#include "value.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
static void grow_expr (struct agent_expr *x, int n);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Written by Fred Fish <fnf@cygnus.com>
|
||||
Rewritten by Jim Blandy <jimb@cygnus.com>
|
||||
|
||||
Copyright 1999, 2000, 2002 Free Software Foundation, Inc.
|
||||
Copyright 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -22,13 +22,76 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "bcache.h"
|
||||
#include "gdb_string.h" /* For memcpy declaration */
|
||||
#include "gdb_assert.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* The type used to hold a single bcache string. The user data is
|
||||
stored in d.data. Since it can be any type, it needs to have the
|
||||
same alignment as the most strict alignment of any type on the host
|
||||
machine. I don't know of any really correct way to do this in
|
||||
stock ANSI C, so just do it the same way obstack.h does. */
|
||||
|
||||
struct bstring
|
||||
{
|
||||
/* Hash chain. */
|
||||
struct bstring *next;
|
||||
/* Assume the data length is no more than 64k. */
|
||||
unsigned short length;
|
||||
/* The half hash hack. This contains the upper 16 bits of the hash
|
||||
value and is used as a pre-check when comparing two strings and
|
||||
avoids the need to do length or memcmp calls. It proves to be
|
||||
roughly 100% effective. */
|
||||
unsigned short half_hash;
|
||||
|
||||
union
|
||||
{
|
||||
char data[1];
|
||||
double dummy;
|
||||
}
|
||||
d;
|
||||
};
|
||||
|
||||
|
||||
/* The structure for a bcache itself. The bcache is initialized, in
|
||||
bcache_xmalloc(), by filling it with zeros and then setting the
|
||||
corresponding obstack's malloc() and free() methods. */
|
||||
|
||||
struct bcache
|
||||
{
|
||||
/* All the bstrings are allocated here. */
|
||||
struct obstack cache;
|
||||
|
||||
/* How many hash buckets we're using. */
|
||||
unsigned int num_buckets;
|
||||
|
||||
/* Hash buckets. This table is allocated using malloc, so when we
|
||||
grow the table we can return the old table to the system. */
|
||||
struct bstring **bucket;
|
||||
|
||||
/* Statistics. */
|
||||
unsigned long unique_count; /* number of unique strings */
|
||||
long total_count; /* total number of strings cached, including dups */
|
||||
long unique_size; /* size of unique strings, in bytes */
|
||||
long total_size; /* total number of bytes cached, including dups */
|
||||
long structure_size; /* total size of bcache, including infrastructure */
|
||||
/* Number of times that the hash table is expanded and hence
|
||||
re-built, and the corresponding number of times that a string is
|
||||
[re]hashed as part of entering it into the expanded table. The
|
||||
total number of hashes can be computed by adding TOTAL_COUNT to
|
||||
expand_hash_count. */
|
||||
unsigned long expand_count;
|
||||
unsigned long expand_hash_count;
|
||||
/* Number of times that the half-hash compare hit (compare the upper
|
||||
16 bits of hash values) hit, but the corresponding combined
|
||||
length/data compare missed. */
|
||||
unsigned long half_hash_miss_count;
|
||||
};
|
||||
|
||||
/* The old hash function was stolen from SDBM. This is what DB 3.0 uses now,
|
||||
* and is better than the old one.
|
||||
*/
|
||||
|
|
@ -73,6 +136,11 @@ expand_hash_table (struct bcache *bcache)
|
|||
struct bstring **new_buckets;
|
||||
unsigned int i;
|
||||
|
||||
/* Count the stats. Every unique item needs to be re-hashed and
|
||||
re-entered. */
|
||||
bcache->expand_count++;
|
||||
bcache->expand_hash_count += bcache->unique_count;
|
||||
|
||||
/* Find the next size. */
|
||||
new_num_buckets = bcache->num_buckets * 2;
|
||||
for (i = 0; i < (sizeof (sizes) / sizeof (sizes[0])); i++)
|
||||
|
|
@ -127,9 +195,11 @@ expand_hash_table (struct bcache *bcache)
|
|||
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
|
||||
never seen those bytes before, add a copy of them to BCACHE. In
|
||||
either case, return a pointer to BCACHE's copy of that string. */
|
||||
void *
|
||||
bcache (const void *addr, int length, struct bcache *bcache)
|
||||
static void *
|
||||
bcache_data (const void *addr, int length, struct bcache *bcache)
|
||||
{
|
||||
unsigned long full_hash;
|
||||
unsigned short half_hash;
|
||||
int hash_index;
|
||||
struct bstring *s;
|
||||
|
||||
|
|
@ -140,13 +210,24 @@ bcache (const void *addr, int length, struct bcache *bcache)
|
|||
bcache->total_count++;
|
||||
bcache->total_size += length;
|
||||
|
||||
hash_index = hash (addr, length) % bcache->num_buckets;
|
||||
full_hash = hash (addr, length);
|
||||
half_hash = (full_hash >> 16);
|
||||
hash_index = full_hash % bcache->num_buckets;
|
||||
|
||||
/* Search the hash bucket for a string identical to the caller's. */
|
||||
/* Search the hash bucket for a string identical to the caller's.
|
||||
As a short-circuit first compare the upper part of each hash
|
||||
values. */
|
||||
for (s = bcache->bucket[hash_index]; s; s = s->next)
|
||||
if (s->length == length
|
||||
&& ! memcmp (&s->d.data, addr, length))
|
||||
return &s->d.data;
|
||||
{
|
||||
if (s->half_hash == half_hash)
|
||||
{
|
||||
if (s->length == length
|
||||
&& ! memcmp (&s->d.data, addr, length))
|
||||
return &s->d.data;
|
||||
else
|
||||
bcache->half_hash_miss_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* The user's string isn't in the list. Insert it after *ps. */
|
||||
{
|
||||
|
|
@ -155,6 +236,7 @@ bcache (const void *addr, int length, struct bcache *bcache)
|
|||
memcpy (&new->d.data, addr, length);
|
||||
new->length = length;
|
||||
new->next = bcache->bucket[hash_index];
|
||||
new->half_hash = half_hash;
|
||||
bcache->bucket[hash_index] = new;
|
||||
|
||||
bcache->unique_count++;
|
||||
|
|
@ -165,20 +247,41 @@ bcache (const void *addr, int length, struct bcache *bcache)
|
|||
}
|
||||
}
|
||||
|
||||
void *
|
||||
deprecated_bcache (const void *addr, int length, struct bcache *bcache)
|
||||
{
|
||||
return bcache_data (addr, length, bcache);
|
||||
}
|
||||
|
||||
const void *
|
||||
bcache (const void *addr, int length, struct bcache *bcache)
|
||||
{
|
||||
return bcache_data (addr, length, bcache);
|
||||
}
|
||||
|
||||
/* Freeing bcaches. */
|
||||
/* Allocating and freeing bcaches. */
|
||||
|
||||
struct bcache *
|
||||
bcache_xmalloc (void)
|
||||
{
|
||||
/* Allocate the bcache pre-zeroed. */
|
||||
struct bcache *b = XCALLOC (1, struct bcache);
|
||||
/* We could use obstack_specify_allocation here instead, but
|
||||
gdb_obstack.h specifies the allocation/deallocation
|
||||
functions. */
|
||||
obstack_init (&b->cache);
|
||||
return b;
|
||||
}
|
||||
|
||||
/* Free all the storage associated with BCACHE. */
|
||||
void
|
||||
free_bcache (struct bcache *bcache)
|
||||
bcache_xfree (struct bcache *bcache)
|
||||
{
|
||||
if (bcache == NULL)
|
||||
return;
|
||||
obstack_free (&bcache->cache, 0);
|
||||
if (bcache->bucket)
|
||||
xfree (bcache->bucket);
|
||||
|
||||
/* This isn't necessary, but at least the bcache is always in a
|
||||
consistent state. */
|
||||
memset (bcache, 0, sizeof (*bcache));
|
||||
xfree (bcache->bucket);
|
||||
xfree (bcache);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -214,12 +317,16 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
int occupied_buckets;
|
||||
int max_chain_length;
|
||||
int median_chain_length;
|
||||
int max_entry_size;
|
||||
int median_entry_size;
|
||||
|
||||
/* Count the number of occupied buckets, and measure chain lengths. */
|
||||
/* Count the number of occupied buckets, tally the various string
|
||||
lengths, and measure chain lengths. */
|
||||
{
|
||||
unsigned int b;
|
||||
int *chain_length
|
||||
= (int *) alloca (c->num_buckets * sizeof (*chain_length));
|
||||
int *chain_length = XCALLOC (c->num_buckets + 1, int);
|
||||
int *entry_size = XCALLOC (c->unique_count + 1, int);
|
||||
int stringi = 0;
|
||||
|
||||
occupied_buckets = 0;
|
||||
|
||||
|
|
@ -235,7 +342,10 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
|
||||
while (s)
|
||||
{
|
||||
gdb_assert (b < c->num_buckets);
|
||||
chain_length[b]++;
|
||||
gdb_assert (stringi < c->unique_count);
|
||||
entry_size[stringi++] = s->length;
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
|
|
@ -244,6 +354,8 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
/* To compute the median, we need the set of chain lengths sorted. */
|
||||
qsort (chain_length, c->num_buckets, sizeof (chain_length[0]),
|
||||
compare_ints);
|
||||
qsort (entry_size, c->unique_count, sizeof (entry_size[0]),
|
||||
compare_ints);
|
||||
|
||||
if (c->num_buckets > 0)
|
||||
{
|
||||
|
|
@ -255,6 +367,19 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
max_chain_length = 0;
|
||||
median_chain_length = 0;
|
||||
}
|
||||
if (c->unique_count > 0)
|
||||
{
|
||||
max_entry_size = entry_size[c->unique_count - 1];
|
||||
median_entry_size = entry_size[c->unique_count / 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
max_entry_size = 0;
|
||||
median_entry_size = 0;
|
||||
}
|
||||
|
||||
xfree (chain_length);
|
||||
xfree (entry_size);
|
||||
}
|
||||
|
||||
printf_filtered (" Cached '%s' statistics:\n", type);
|
||||
|
|
@ -270,6 +395,15 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
print_percentage (c->total_size - c->unique_size, c->total_size);
|
||||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Max entry size: %d\n", max_entry_size);
|
||||
printf_filtered (" Average entry size: ");
|
||||
if (c->unique_count > 0)
|
||||
printf_filtered ("%ld\n", c->unique_size / c->unique_count);
|
||||
else
|
||||
printf_filtered ("(not applicable)\n");
|
||||
printf_filtered (" Median entry size: %d\n", median_entry_size);
|
||||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Total memory used by bcache, including overhead: %ld\n",
|
||||
c->structure_size);
|
||||
printf_filtered (" Percentage memory overhead: ");
|
||||
|
|
@ -279,6 +413,12 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
printf_filtered ("\n");
|
||||
|
||||
printf_filtered (" Hash table size: %3d\n", c->num_buckets);
|
||||
printf_filtered (" Hash table expands: %lu\n",
|
||||
c->expand_count);
|
||||
printf_filtered (" Hash table hashes: %lu\n",
|
||||
c->total_count + c->expand_hash_count);
|
||||
printf_filtered (" Half hash misses: %lu\n",
|
||||
c->half_hash_miss_count);
|
||||
printf_filtered (" Hash table population: ");
|
||||
print_percentage (occupied_buckets, c->num_buckets);
|
||||
printf_filtered (" Median hash chain length: %3d\n",
|
||||
|
|
@ -291,3 +431,9 @@ print_bcache_statistics (struct bcache *c, char *type)
|
|||
printf_filtered (" Maximum hash chain length: %3d\n", max_chain_length);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
|
||||
int
|
||||
bcache_memory_used (struct bcache *bcache)
|
||||
{
|
||||
return obstack_memory_used (&bcache->cache);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/* Include file cached obstack implementation.
|
||||
Written by Fred Fish <fnf@cygnus.com>
|
||||
Rewritten by Jim Blandy <jimb@cygnus.com>
|
||||
Copyright 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -47,84 +48,123 @@
|
|||
You shouldn't modify the strings you get from a bcache, because:
|
||||
|
||||
- You don't necessarily know who you're sharing space with. If I
|
||||
stick eight bytes of text in a bcache, and then stick an
|
||||
eight-byte structure in the same bcache, there's no guarantee
|
||||
those two objects don't actually comprise the same sequence of
|
||||
bytes. If they happen to, the bcache will use a single byte
|
||||
string for both of them. Then, modifying the structure will
|
||||
change the string. In bizarre ways.
|
||||
stick eight bytes of text in a bcache, and then stick an eight-byte
|
||||
structure in the same bcache, there's no guarantee those two
|
||||
objects don't actually comprise the same sequence of bytes. If
|
||||
they happen to, the bcache will use a single byte string for both
|
||||
of them. Then, modifying the structure will change the string. In
|
||||
bizarre ways.
|
||||
|
||||
- Even if you know for some other reason that all that's okay,
|
||||
there's another problem. A bcache stores all its strings in a
|
||||
hash table. If you modify a string's contents, you will probably
|
||||
change its hash value. This means that the modified string is
|
||||
now in the wrong place in the hash table, and future bcache
|
||||
probes will never find it. So by mutating a string, you give up
|
||||
any chance of sharing its space with future duplicates. */
|
||||
there's another problem. A bcache stores all its strings in a hash
|
||||
table. If you modify a string's contents, you will probably change
|
||||
its hash value. This means that the modified string is now in the
|
||||
wrong place in the hash table, and future bcache probes will never
|
||||
find it. So by mutating a string, you give up any chance of
|
||||
sharing its space with future duplicates.
|
||||
|
||||
|
||||
/* The type used to hold a single bcache string. The user data is
|
||||
stored in d.data. Since it can be any type, it needs to have the
|
||||
same alignment as the most strict alignment of any type on the host
|
||||
machine. I don't know of any really correct way to do this in
|
||||
stock ANSI C, so just do it the same way obstack.h does.
|
||||
Size of bcache VS hashtab:
|
||||
|
||||
It would be nicer to have this stuff hidden away in bcache.c, but
|
||||
struct objstack contains a struct bcache directly --- not a pointer
|
||||
to one --- and then the memory-mapped stuff makes this a real pain.
|
||||
We don't strictly need to expose struct bstring, but it's better to
|
||||
have it all in one place. */
|
||||
For bcache, the most critical cost is size (or more exactly the
|
||||
overhead added by the bcache). It turns out that the bcache is
|
||||
remarkably efficient.
|
||||
|
||||
struct bstring {
|
||||
struct bstring *next;
|
||||
size_t length;
|
||||
Assuming a 32-bit system (the hash table slots are 4 bytes),
|
||||
ignoring alignment, and limit strings to 255 bytes (1 byte length)
|
||||
we get ...
|
||||
|
||||
union
|
||||
{
|
||||
char data[1];
|
||||
double dummy;
|
||||
}
|
||||
d;
|
||||
};
|
||||
bcache: This uses a separate linked list to track the hash chain.
|
||||
The numbers show roughly 100% occupancy of the hash table and an
|
||||
average chain length of 4. Spreading the slot cost over the 4
|
||||
chain elements:
|
||||
|
||||
4 (slot) / 4 (chain length) + 1 (length) + 4 (chain) = 6 bytes
|
||||
|
||||
hashtab: This uses a more traditional re-hash algorithm where the
|
||||
chain is maintained within the hash table. The table occupancy is
|
||||
kept below 75% but we'll assume its perfect:
|
||||
|
||||
4 (slot) x 4/3 (occupancy) + 1 (length) = 6 1/3 bytes
|
||||
|
||||
So a perfect hashtab has just slightly larger than an average
|
||||
bcache.
|
||||
|
||||
It turns out that an average hashtab is far worse. Two things
|
||||
hurt:
|
||||
|
||||
- Hashtab's occupancy is more like 50% (it ranges between 38% and
|
||||
75%) giving a per slot cost of 4x2 vs 4x4/3.
|
||||
|
||||
- the string structure needs to be aligned to 8 bytes which for
|
||||
hashtab wastes 7 bytes, while for bcache wastes only 3.
|
||||
|
||||
This gives:
|
||||
|
||||
hashtab: 4 x 2 + 1 + 7 = 16 bytes
|
||||
|
||||
bcache 4 / 4 + 1 + 4 + 3 = 9 bytes
|
||||
|
||||
The numbers of GDB debugging GDB support this. ~40% vs ~70% overhead.
|
||||
|
||||
|
||||
/* The structure for a bcache itself.
|
||||
To initialize a bcache, just fill it with zeros. */
|
||||
struct bcache {
|
||||
/* All the bstrings are allocated here. */
|
||||
struct obstack cache;
|
||||
Speed of bcache VS hashtab (the half hash hack):
|
||||
|
||||
/* How many hash buckets we're using. */
|
||||
unsigned int num_buckets;
|
||||
While hashtab has a typical chain length of 1, bcache has a chain
|
||||
length of round 4. This means that the bcache will require
|
||||
something like double the number of compares after that initial
|
||||
hash. In both cases the comparison takes the form:
|
||||
|
||||
a.length == b.length && memcmp (a.data, b.data, a.length) == 0
|
||||
|
||||
That is lengths are checked before doing the memcmp.
|
||||
|
||||
For GDB debugging GDB, it turned out that all lengths were 24 bytes
|
||||
(no C++ so only psymbols were cached) and hence, all compares
|
||||
required a call to memcmp. As a hack, two bytes of padding
|
||||
(mentioned above) are used to store the upper 16 bits of the
|
||||
string's hash value and then that is used in the comparison vis:
|
||||
|
||||
a.half_hash == b.half_hash && a.length == b.length && memcmp
|
||||
(a.data, b.data, a.length)
|
||||
|
||||
The numbers from GDB debugging GDB show this to be a remarkable
|
||||
100% effective (only necessary length and memcmp tests being
|
||||
performed).
|
||||
|
||||
Mind you, looking at the wall clock, the same GDB debugging GDB
|
||||
showed only marginal speed up (0.780 vs 0.773s). Seems GDB is too
|
||||
busy doing something else :-(
|
||||
|
||||
/* Hash buckets. This table is allocated using malloc, so when we
|
||||
grow the table we can return the old table to the system. */
|
||||
struct bstring **bucket;
|
||||
*/
|
||||
|
||||
/* Statistics. */
|
||||
unsigned long unique_count; /* number of unique strings */
|
||||
long total_count; /* total number of strings cached, including dups */
|
||||
long unique_size; /* size of unique strings, in bytes */
|
||||
long total_size; /* total number of bytes cached, including dups */
|
||||
long structure_size; /* total size of bcache, including infrastructure */
|
||||
};
|
||||
|
||||
struct bcache;
|
||||
|
||||
/* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has
|
||||
never seen those bytes before, add a copy of them to BCACHE. In
|
||||
either case, return a pointer to BCACHE's copy of that string. */
|
||||
extern void *bcache (const void *addr, int length, struct bcache *bcache);
|
||||
either case, return a pointer to BCACHE's copy of that string.
|
||||
Since the cached value is ment to be read-only, return a const
|
||||
buffer. */
|
||||
extern void *deprecated_bcache (const void *addr, int length,
|
||||
struct bcache *bcache);
|
||||
extern const void *bcache (const void *addr, int length,
|
||||
struct bcache *bcache);
|
||||
|
||||
/* Free all the storage that BCACHE refers to. The result is a valid,
|
||||
but empty, bcache. This does not free BCACHE itself, since that
|
||||
might be part of some larger object. */
|
||||
extern void free_bcache (struct bcache *bcache);
|
||||
/* Free all the storage used by BCACHE. */
|
||||
extern void bcache_xfree (struct bcache *bcache);
|
||||
|
||||
/* Create a new bcache object. */
|
||||
extern struct bcache *bcache_xmalloc (void);
|
||||
|
||||
/* Print statistics on BCACHE's memory usage and efficacity at
|
||||
eliminating duplication. TYPE should be a string describing the
|
||||
kind of data BCACHE holds. Statistics are printed using
|
||||
`printf_filtered' and its ilk. */
|
||||
extern void print_bcache_statistics (struct bcache *bcache, char *type);
|
||||
extern int bcache_memory_used (struct bcache *bcache);
|
||||
|
||||
/* The hash function */
|
||||
extern unsigned long hash(const void *addr, int length);
|
||||
|
||||
#endif /* BCACHE_H */
|
||||
|
|
|
|||
131
contrib/gdb/gdb/bfd-target.c
Normal file
131
contrib/gdb/gdb/bfd-target.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/* Very simple "bfd" target, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2003 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 "target.h"
|
||||
#include "bfd-target.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
/* Locate all mappable sections of a BFD file, filling in a target
|
||||
section for each. */
|
||||
|
||||
struct section_closure
|
||||
{
|
||||
struct section_table *end;
|
||||
};
|
||||
|
||||
static void
|
||||
add_to_section_table (struct bfd *abfd, struct bfd_section *asect,
|
||||
void *closure)
|
||||
{
|
||||
struct section_closure *pp = closure;
|
||||
flagword aflag;
|
||||
|
||||
/* NOTE: cagney/2003-10-22: Is this pruning useful? */
|
||||
aflag = bfd_get_section_flags (abfd, asect);
|
||||
if (!(aflag & SEC_ALLOC))
|
||||
return;
|
||||
if (bfd_section_size (abfd, asect) == 0)
|
||||
return;
|
||||
pp->end->bfd = abfd;
|
||||
pp->end->the_bfd_section = asect;
|
||||
pp->end->addr = bfd_section_vma (abfd, asect);
|
||||
pp->end->endaddr = pp->end->addr + bfd_section_size (abfd, asect);
|
||||
pp->end++;
|
||||
}
|
||||
|
||||
void
|
||||
build_target_sections_from_bfd (struct target_ops *targ, struct bfd *abfd)
|
||||
{
|
||||
unsigned count;
|
||||
struct section_table *start;
|
||||
struct section_closure cl;
|
||||
|
||||
count = bfd_count_sections (abfd);
|
||||
target_resize_to_sections (targ, count);
|
||||
start = targ->to_sections;
|
||||
cl.end = targ->to_sections;
|
||||
bfd_map_over_sections (abfd, add_to_section_table, &cl);
|
||||
gdb_assert (cl.end - start <= count);
|
||||
}
|
||||
|
||||
LONGEST
|
||||
target_bfd_xfer_partial (struct target_ops *ops,
|
||||
enum target_object object,
|
||||
const char *annex, void *readbuf,
|
||||
const void *writebuf, ULONGEST offset, LONGEST len)
|
||||
{
|
||||
switch (object)
|
||||
{
|
||||
case TARGET_OBJECT_MEMORY:
|
||||
{
|
||||
struct section_table *s = target_section_by_addr (ops, offset);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
/* If the length extends beyond the section, truncate it. Be
|
||||
careful to not suffer from overflow (wish S contained a
|
||||
length). */
|
||||
if ((offset - s->addr + len) > (s->endaddr - s->addr))
|
||||
len = (s->endaddr - s->addr) - (offset - s->addr);
|
||||
if (readbuf != NULL
|
||||
&& !bfd_get_section_contents (s->bfd, s->the_bfd_section,
|
||||
readbuf, offset - s->addr, len))
|
||||
return -1;
|
||||
#if 1
|
||||
if (writebuf != NULL)
|
||||
return -1;
|
||||
#else
|
||||
/* FIXME: cagney/2003-10-31: The BFD interface doesn't yet
|
||||
take a const buffer. */
|
||||
if (writebuf != NULL
|
||||
&& !bfd_set_section_contents (s->bfd, s->the_bfd_section,
|
||||
writebuf, offset - s->addr, len))
|
||||
return -1;
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
target_bfd_xclose (struct target_ops *t, int quitting)
|
||||
{
|
||||
bfd_close (t->to_data);
|
||||
xfree (t->to_sections);
|
||||
xfree (t);
|
||||
}
|
||||
|
||||
struct target_ops *
|
||||
target_bfd_reopen (struct bfd *bfd)
|
||||
{
|
||||
struct target_ops *t = XZALLOC (struct target_ops);
|
||||
t->to_shortname = "bfd";
|
||||
t->to_longname = "BFD backed target";
|
||||
t->to_doc = "You should never see this";
|
||||
t->to_xfer_partial = target_bfd_xfer_partial;
|
||||
t->to_xclose = target_bfd_xclose;
|
||||
t->to_data = bfd;
|
||||
build_target_sections_from_bfd (t, bfd);
|
||||
return t;
|
||||
}
|
||||
39
contrib/gdb/gdb/bfd-target.h
Normal file
39
contrib/gdb/gdb/bfd-target.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* Very simple "bfd" target, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2003 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 BFD_TARGET_H
|
||||
#define BFD_TARGET_H
|
||||
|
||||
struct bfd;
|
||||
struct target_ops;
|
||||
|
||||
/* Given an existing BFD, re-open it as a "struct target_ops". On
|
||||
close, it will also close the corresponding BFD (which is like
|
||||
freopen and fdopen). */
|
||||
struct target_ops *target_bfd_reopen (struct bfd *bfd);
|
||||
|
||||
/* Map over ABFD's sections, creating corresponding entries in the
|
||||
target's section table. */
|
||||
|
||||
void build_target_sections_from_bfd (struct target_ops *targ,
|
||||
struct bfd *abfd);
|
||||
|
||||
#endif
|
||||
295
contrib/gdb/gdb/block.c
Normal file
295
contrib/gdb/gdb/block.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/* Block-related functions for the GNU debugger, GDB.
|
||||
|
||||
Copyright 2003 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 "block.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "cp-support.h"
|
||||
|
||||
/* This is used by struct block to store namespace-related info for
|
||||
C++ files, namely using declarations and the current namespace in
|
||||
scope. */
|
||||
|
||||
struct block_namespace_info
|
||||
{
|
||||
const char *scope;
|
||||
struct using_direct *using;
|
||||
};
|
||||
|
||||
static void block_initialize_namespace (struct block *block,
|
||||
struct obstack *obstack);
|
||||
|
||||
/* Return Nonzero if block a is lexically nested within block b,
|
||||
or if a and b have the same pc range.
|
||||
Return zero otherwise. */
|
||||
|
||||
int
|
||||
contained_in (const struct block *a, const struct block *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return 0;
|
||||
return BLOCK_START (a) >= BLOCK_START (b)
|
||||
&& BLOCK_END (a) <= BLOCK_END (b);
|
||||
}
|
||||
|
||||
|
||||
/* Return the symbol for the function which contains a specified
|
||||
lexical block, described by a struct block BL. */
|
||||
|
||||
struct symbol *
|
||||
block_function (const struct block *bl)
|
||||
{
|
||||
while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
|
||||
bl = BLOCK_SUPERBLOCK (bl);
|
||||
|
||||
return BLOCK_FUNCTION (bl);
|
||||
}
|
||||
|
||||
/* Return the blockvector immediately containing the innermost lexical block
|
||||
containing the specified pc value and section, or 0 if there is none.
|
||||
PINDEX is a pointer to the index value of the block. If PINDEX
|
||||
is NULL, we don't pass this information back to the caller. */
|
||||
|
||||
struct blockvector *
|
||||
blockvector_for_pc_sect (CORE_ADDR pc, struct bfd_section *section,
|
||||
int *pindex, struct symtab *symtab)
|
||||
{
|
||||
struct block *b;
|
||||
int bot, top, half;
|
||||
struct blockvector *bl;
|
||||
|
||||
if (symtab == 0) /* if no symtab specified by caller */
|
||||
{
|
||||
/* First search all symtabs for one whose file contains our pc */
|
||||
symtab = find_pc_sect_symtab (pc, section);
|
||||
if (symtab == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bl = BLOCKVECTOR (symtab);
|
||||
b = BLOCKVECTOR_BLOCK (bl, 0);
|
||||
|
||||
/* Then search that symtab for the smallest block that wins. */
|
||||
/* Use binary search to find the last block that starts before PC. */
|
||||
|
||||
bot = 0;
|
||||
top = BLOCKVECTOR_NBLOCKS (bl);
|
||||
|
||||
while (top - bot > 1)
|
||||
{
|
||||
half = (top - bot + 1) >> 1;
|
||||
b = BLOCKVECTOR_BLOCK (bl, bot + half);
|
||||
if (BLOCK_START (b) <= pc)
|
||||
bot += half;
|
||||
else
|
||||
top = bot + half;
|
||||
}
|
||||
|
||||
/* Now search backward for a block that ends after PC. */
|
||||
|
||||
while (bot >= 0)
|
||||
{
|
||||
b = BLOCKVECTOR_BLOCK (bl, bot);
|
||||
if (BLOCK_END (b) > pc)
|
||||
{
|
||||
if (pindex)
|
||||
*pindex = bot;
|
||||
return bl;
|
||||
}
|
||||
bot--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the blockvector immediately containing the innermost lexical block
|
||||
containing the specified pc value, or 0 if there is none.
|
||||
Backward compatibility, no section. */
|
||||
|
||||
struct blockvector *
|
||||
blockvector_for_pc (CORE_ADDR pc, int *pindex)
|
||||
{
|
||||
return blockvector_for_pc_sect (pc, find_pc_mapped_section (pc),
|
||||
pindex, NULL);
|
||||
}
|
||||
|
||||
/* Return the innermost lexical block containing the specified pc value
|
||||
in the specified section, or 0 if there is none. */
|
||||
|
||||
struct block *
|
||||
block_for_pc_sect (CORE_ADDR pc, struct bfd_section *section)
|
||||
{
|
||||
struct blockvector *bl;
|
||||
int index;
|
||||
|
||||
bl = blockvector_for_pc_sect (pc, section, &index, NULL);
|
||||
if (bl)
|
||||
return BLOCKVECTOR_BLOCK (bl, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the innermost lexical block containing the specified pc value,
|
||||
or 0 if there is none. Backward compatibility, no section. */
|
||||
|
||||
struct block *
|
||||
block_for_pc (CORE_ADDR pc)
|
||||
{
|
||||
return block_for_pc_sect (pc, find_pc_mapped_section (pc));
|
||||
}
|
||||
|
||||
/* Now come some functions designed to deal with C++ namespace issues.
|
||||
The accessors are safe to use even in the non-C++ case. */
|
||||
|
||||
/* This returns the namespace that BLOCK is enclosed in, or "" if it
|
||||
isn't enclosed in a namespace at all. This travels the chain of
|
||||
superblocks looking for a scope, if necessary. */
|
||||
|
||||
const char *
|
||||
block_scope (const struct block *block)
|
||||
{
|
||||
for (; block != NULL; block = BLOCK_SUPERBLOCK (block))
|
||||
{
|
||||
if (BLOCK_NAMESPACE (block) != NULL
|
||||
&& BLOCK_NAMESPACE (block)->scope != NULL)
|
||||
return BLOCK_NAMESPACE (block)->scope;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/* Set BLOCK's scope member to SCOPE; if needed, allocate memory via
|
||||
OBSTACK. (It won't make a copy of SCOPE, however, so that already
|
||||
has to be allocated correctly.) */
|
||||
|
||||
void
|
||||
block_set_scope (struct block *block, const char *scope,
|
||||
struct obstack *obstack)
|
||||
{
|
||||
block_initialize_namespace (block, obstack);
|
||||
|
||||
BLOCK_NAMESPACE (block)->scope = scope;
|
||||
}
|
||||
|
||||
/* This returns the first using directives associated to BLOCK, if
|
||||
any. */
|
||||
|
||||
/* FIXME: carlton/2003-04-23: This uses the fact that we currently
|
||||
only have using directives in static blocks, because we only
|
||||
generate using directives from anonymous namespaces. Eventually,
|
||||
when we support using directives everywhere, we'll want to replace
|
||||
this by some iterator functions. */
|
||||
|
||||
struct using_direct *
|
||||
block_using (const struct block *block)
|
||||
{
|
||||
const struct block *static_block = block_static_block (block);
|
||||
|
||||
if (static_block == NULL
|
||||
|| BLOCK_NAMESPACE (static_block) == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return BLOCK_NAMESPACE (static_block)->using;
|
||||
}
|
||||
|
||||
/* Set BLOCK's using member to USING; if needed, allocate memory via
|
||||
OBSTACK. (It won't make a copy of USING, however, so that already
|
||||
has to be allocated correctly.) */
|
||||
|
||||
void
|
||||
block_set_using (struct block *block,
|
||||
struct using_direct *using,
|
||||
struct obstack *obstack)
|
||||
{
|
||||
block_initialize_namespace (block, obstack);
|
||||
|
||||
BLOCK_NAMESPACE (block)->using = using;
|
||||
}
|
||||
|
||||
/* If BLOCK_NAMESPACE (block) is NULL, allocate it via OBSTACK and
|
||||
ititialize its members to zero. */
|
||||
|
||||
static void
|
||||
block_initialize_namespace (struct block *block, struct obstack *obstack)
|
||||
{
|
||||
if (BLOCK_NAMESPACE (block) == NULL)
|
||||
{
|
||||
BLOCK_NAMESPACE (block)
|
||||
= obstack_alloc (obstack, sizeof (struct block_namespace_info));
|
||||
BLOCK_NAMESPACE (block)->scope = NULL;
|
||||
BLOCK_NAMESPACE (block)->using = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the static block associated to BLOCK. Return NULL if block
|
||||
is NULL or if block is a global block. */
|
||||
|
||||
const struct block *
|
||||
block_static_block (const struct block *block)
|
||||
{
|
||||
if (block == NULL || BLOCK_SUPERBLOCK (block) == NULL)
|
||||
return NULL;
|
||||
|
||||
while (BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) != NULL)
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Return the static block associated to BLOCK. Return NULL if block
|
||||
is NULL. */
|
||||
|
||||
const struct block *
|
||||
block_global_block (const struct block *block)
|
||||
{
|
||||
if (block == NULL)
|
||||
return NULL;
|
||||
|
||||
while (BLOCK_SUPERBLOCK (block) != NULL)
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Allocate a block on OBSTACK, and initialize its elements to
|
||||
zero/NULL. This is useful for creating "dummy" blocks that don't
|
||||
correspond to actual source files.
|
||||
|
||||
Warning: it sets the block's BLOCK_DICT to NULL, which isn't a
|
||||
valid value. If you really don't want the block to have a
|
||||
dictionary, then you should subsequently set its BLOCK_DICT to
|
||||
dict_create_linear (obstack, NULL). */
|
||||
|
||||
struct block *
|
||||
allocate_block (struct obstack *obstack)
|
||||
{
|
||||
struct block *bl = obstack_alloc (obstack, sizeof (struct block));
|
||||
|
||||
BLOCK_START (bl) = 0;
|
||||
BLOCK_END (bl) = 0;
|
||||
BLOCK_FUNCTION (bl) = NULL;
|
||||
BLOCK_SUPERBLOCK (bl) = NULL;
|
||||
BLOCK_DICT (bl) = NULL;
|
||||
BLOCK_NAMESPACE (bl) = NULL;
|
||||
BLOCK_GCC_COMPILED (bl) = 0;
|
||||
|
||||
return bl;
|
||||
}
|
||||
174
contrib/gdb/gdb/block.h
Normal file
174
contrib/gdb/gdb/block.h
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/* Code dealing with blocks for GDB.
|
||||
|
||||
Copyright 2003 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 BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
/* Opaque declarations. */
|
||||
|
||||
struct symbol;
|
||||
struct symtab;
|
||||
struct block_namespace_info;
|
||||
struct using_direct;
|
||||
struct obstack;
|
||||
struct dictionary;
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
are represented by `struct block' objects.
|
||||
All of these objects are pointed to by the blockvector.
|
||||
|
||||
Each block represents one name scope.
|
||||
Each lexical context has its own block.
|
||||
|
||||
The blockvector begins with some special blocks.
|
||||
The GLOBAL_BLOCK contains all the symbols defined in this compilation
|
||||
whose scope is the entire program linked together.
|
||||
The STATIC_BLOCK contains all the symbols whose scope is the
|
||||
entire compilation excluding other separate compilations.
|
||||
Blocks starting with the FIRST_LOCAL_BLOCK are not special.
|
||||
|
||||
Each block records a range of core addresses for the code that
|
||||
is in the scope of the block. The STATIC_BLOCK and GLOBAL_BLOCK
|
||||
give, for the range of code, the entire range of code produced
|
||||
by the compilation that the symbol segment belongs to.
|
||||
|
||||
The blocks appear in the blockvector
|
||||
in order of increasing starting-address,
|
||||
and, within that, in order of decreasing ending-address.
|
||||
|
||||
This implies that within the body of one function
|
||||
the blocks appear in the order of a depth-first tree walk. */
|
||||
|
||||
struct block
|
||||
{
|
||||
|
||||
/* Addresses in the executable code that are in this block. */
|
||||
|
||||
CORE_ADDR startaddr;
|
||||
CORE_ADDR endaddr;
|
||||
|
||||
/* The symbol that names this block, if the block is the body of a
|
||||
function; otherwise, zero. */
|
||||
|
||||
struct symbol *function;
|
||||
|
||||
/* The `struct block' for the containing block, or 0 if none.
|
||||
|
||||
The superblock of a top-level local block (i.e. a function in the
|
||||
case of C) is the STATIC_BLOCK. The superblock of the
|
||||
STATIC_BLOCK is the GLOBAL_BLOCK. */
|
||||
|
||||
struct block *superblock;
|
||||
|
||||
/* This is used to store the symbols in the block. */
|
||||
|
||||
struct dictionary *dict;
|
||||
|
||||
/* Used for language-specific info. */
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* Contains information about namespace-related info relevant to
|
||||
this block: using directives and the current namespace
|
||||
scope. */
|
||||
|
||||
struct block_namespace_info *namespace;
|
||||
}
|
||||
cplus_specific;
|
||||
}
|
||||
language_specific;
|
||||
|
||||
/* Version of GCC used to compile the function corresponding
|
||||
to this block, or 0 if not compiled with GCC. When possible,
|
||||
GCC should be compatible with the native compiler, or if that
|
||||
is not feasible, the differences should be fixed during symbol
|
||||
reading. As of 16 Apr 93, this flag is never used to distinguish
|
||||
between gcc2 and the native compiler.
|
||||
|
||||
If there is no function corresponding to this block, this meaning
|
||||
of this flag is undefined. */
|
||||
|
||||
unsigned char gcc_compile_flag;
|
||||
};
|
||||
|
||||
#define BLOCK_START(bl) (bl)->startaddr
|
||||
#define BLOCK_END(bl) (bl)->endaddr
|
||||
#define BLOCK_FUNCTION(bl) (bl)->function
|
||||
#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
|
||||
#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
|
||||
#define BLOCK_DICT(bl) (bl)->dict
|
||||
#define BLOCK_NAMESPACE(bl) (bl)->language_specific.cplus_specific.namespace
|
||||
|
||||
/* Macro to loop through all symbols in a block BL, in no particular
|
||||
order. ITER helps keep track of the iteration, and should be a
|
||||
struct dict_iterator. SYM points to the current symbol. */
|
||||
|
||||
#define ALL_BLOCK_SYMBOLS(block, iter, sym) \
|
||||
ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
|
||||
|
||||
struct blockvector
|
||||
{
|
||||
/* Number of blocks in the list. */
|
||||
int nblocks;
|
||||
/* The blocks themselves. */
|
||||
struct block *block[1];
|
||||
};
|
||||
|
||||
#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
|
||||
#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
|
||||
|
||||
/* Special block numbers */
|
||||
|
||||
enum { GLOBAL_BLOCK = 0, STATIC_BLOCK = 1, FIRST_LOCAL_BLOCK = 2 };
|
||||
|
||||
extern struct symbol *block_function (const struct block *);
|
||||
|
||||
extern int contained_in (const struct block *, const struct block *);
|
||||
|
||||
extern struct blockvector *blockvector_for_pc (CORE_ADDR, int *);
|
||||
|
||||
extern struct blockvector *blockvector_for_pc_sect (CORE_ADDR, asection *,
|
||||
int *, struct symtab *);
|
||||
|
||||
extern struct block *block_for_pc (CORE_ADDR);
|
||||
|
||||
extern struct block *block_for_pc_sect (CORE_ADDR, asection *);
|
||||
|
||||
extern const char *block_scope (const struct block *block);
|
||||
|
||||
extern void block_set_scope (struct block *block, const char *scope,
|
||||
struct obstack *obstack);
|
||||
|
||||
extern struct using_direct *block_using (const struct block *block);
|
||||
|
||||
extern void block_set_using (struct block *block,
|
||||
struct using_direct *using,
|
||||
struct obstack *obstack);
|
||||
|
||||
extern const struct block *block_static_block (const struct block *block);
|
||||
|
||||
extern const struct block *block_global_block (const struct block *block);
|
||||
|
||||
extern struct block *allocate_block (struct obstack *obstack);
|
||||
|
||||
#endif /* BLOCK_H */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,6 @@
|
|||
/* Data structures associated with breakpoints in GDB.
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
#include "gdb-events.h"
|
||||
|
||||
struct value;
|
||||
struct block;
|
||||
|
||||
/* This is the maximum number of bytes a breakpoint instruction can take.
|
||||
Feel free to increase it. It's just used in a few places to size
|
||||
|
|
@ -183,6 +185,97 @@ enum target_hw_bp_type
|
|||
hw_execute = 3 /* Execute HW breakpoint */
|
||||
};
|
||||
|
||||
/* GDB maintains two types of information about each breakpoint (or
|
||||
watchpoint, or other related event). The first type corresponds
|
||||
to struct breakpoint; this is a relatively high-level structure
|
||||
which contains the source location(s), stopping conditions, user
|
||||
commands to execute when the breakpoint is hit, and so forth.
|
||||
|
||||
The second type of information corresponds to struct bp_location.
|
||||
Each breakpoint has one or (eventually) more locations associated
|
||||
with it, which represent target-specific and machine-specific
|
||||
mechanisms for stopping the program. For instance, a watchpoint
|
||||
expression may require multiple hardware watchpoints in order to
|
||||
catch all changes in the value of the expression being watched. */
|
||||
|
||||
enum bp_loc_type
|
||||
{
|
||||
bp_loc_software_breakpoint,
|
||||
bp_loc_hardware_breakpoint,
|
||||
bp_loc_hardware_watchpoint,
|
||||
bp_loc_other /* Miscellaneous... */
|
||||
};
|
||||
|
||||
struct bp_location
|
||||
{
|
||||
/* Chain pointer to the next breakpoint location. */
|
||||
struct bp_location *next;
|
||||
|
||||
/* Type of this breakpoint location. */
|
||||
enum bp_loc_type loc_type;
|
||||
|
||||
/* Each breakpoint location must belong to exactly one higher-level
|
||||
breakpoint. This and the DUPLICATE flag are more straightforward
|
||||
than reference counting. */
|
||||
struct breakpoint *owner;
|
||||
|
||||
/* Nonzero if this breakpoint is now inserted. */
|
||||
char inserted;
|
||||
|
||||
/* Nonzero if this is not the first breakpoint in the list
|
||||
for the given address. */
|
||||
char duplicate;
|
||||
|
||||
/* If we someday support real thread-specific breakpoints, then
|
||||
the breakpoint location will need a thread identifier. */
|
||||
|
||||
/* Data for specific breakpoint types. These could be a union, but
|
||||
simplicity is more important than memory usage for breakpoints. */
|
||||
|
||||
/* Note that zero is a perfectly valid code address on some platforms
|
||||
(for example, the mn10200 (OBSOLETE) and mn10300 simulators). NULL
|
||||
is not a special value for this field. Valid for all types except
|
||||
bp_loc_other. */
|
||||
CORE_ADDR address;
|
||||
|
||||
/* For any breakpoint type with an address, this is the BFD section
|
||||
associated with the address. Used primarily for overlay debugging. */
|
||||
asection *section;
|
||||
|
||||
/* "Real" contents of byte where breakpoint has been inserted.
|
||||
Valid only when breakpoints are in the program. Under the complete
|
||||
control of the target insert_breakpoint and remove_breakpoint routines.
|
||||
No other code should assume anything about the value(s) here.
|
||||
Valid only for bp_loc_software_breakpoint. */
|
||||
char shadow_contents[BREAKPOINT_MAX];
|
||||
|
||||
/* Address at which breakpoint was requested, either by the user or
|
||||
by GDB for internal breakpoints. This will usually be the same
|
||||
as ``address'' (above) except for cases in which
|
||||
ADJUST_BREAKPOINT_ADDRESS has computed a different address at
|
||||
which to place the breakpoint in order to comply with a
|
||||
processor's architectual constraints. */
|
||||
CORE_ADDR requested_address;
|
||||
};
|
||||
|
||||
/* This structure is a collection of function pointers that, if available,
|
||||
will be called instead of the performing the default action for this
|
||||
bptype. */
|
||||
|
||||
struct breakpoint_ops
|
||||
{
|
||||
/* The normal print routine for this breakpoint, called when we
|
||||
hit it. */
|
||||
enum print_stop_action (*print_it) (struct breakpoint *);
|
||||
|
||||
/* Display information about this breakpoint, for "info breakpoints". */
|
||||
void (*print_one) (struct breakpoint *, CORE_ADDR *);
|
||||
|
||||
/* Display information about this breakpoint after setting it (roughly
|
||||
speaking; this is called from "mention"). */
|
||||
void (*print_mention) (struct breakpoint *);
|
||||
};
|
||||
|
||||
/* Note that the ->silent field is not currently used by any commands
|
||||
(though the code is in there if it was to be, and set_raw_breakpoint
|
||||
does set it to 0). I implemented it because I thought it would be
|
||||
|
|
@ -203,11 +296,8 @@ struct breakpoint
|
|||
/* Number assigned to distinguish breakpoints. */
|
||||
int number;
|
||||
|
||||
/* Address to break at.
|
||||
Note that zero is a perfectly valid code address on some
|
||||
platforms (for example, the mn10200 and mn10300 simulators).
|
||||
NULL is not a special value for this field. */
|
||||
CORE_ADDR address;
|
||||
/* Location(s) associated with this high-level breakpoint. */
|
||||
struct bp_location *loc;
|
||||
|
||||
/* Line number of this address. */
|
||||
|
||||
|
|
@ -223,21 +313,11 @@ struct breakpoint
|
|||
/* Number of stops at this breakpoint that should
|
||||
be continued automatically before really stopping. */
|
||||
int ignore_count;
|
||||
/* "Real" contents of byte where breakpoint has been inserted.
|
||||
Valid only when breakpoints are in the program. Under the complete
|
||||
control of the target insert_breakpoint and remove_breakpoint routines.
|
||||
No other code should assume anything about the value(s) here. */
|
||||
char shadow_contents[BREAKPOINT_MAX];
|
||||
/* Nonzero if this breakpoint is now inserted. */
|
||||
char inserted;
|
||||
/* Nonzero if this is not the first breakpoint in the list
|
||||
for the given address. */
|
||||
char duplicate;
|
||||
/* Chain of command lines to execute when this breakpoint is hit. */
|
||||
struct command_line *commands;
|
||||
/* Stack depth (address of frame). If nonzero, break only if fp
|
||||
equals this. */
|
||||
CORE_ADDR frame;
|
||||
struct frame_id frame_id;
|
||||
/* Conditional. Break only if this expression's value is nonzero. */
|
||||
struct expression *cond;
|
||||
|
||||
|
|
@ -270,10 +350,10 @@ struct breakpoint
|
|||
it the watchpoint_scope breakpoint or something like that. FIXME). */
|
||||
struct breakpoint *related_breakpoint;
|
||||
|
||||
/* Holds the frame address which identifies the frame this watchpoint
|
||||
should be evaluated in, or NULL if the watchpoint should be evaluated
|
||||
on the outermost frame. */
|
||||
CORE_ADDR watchpoint_frame;
|
||||
/* Holds the frame address which identifies the frame this
|
||||
watchpoint should be evaluated in, or `null' if the watchpoint
|
||||
should be evaluated on the outermost frame. */
|
||||
struct frame_id watchpoint_frame;
|
||||
|
||||
/* Thread number for thread-specific breakpoint, or -1 if don't care */
|
||||
int thread;
|
||||
|
|
@ -304,7 +384,19 @@ struct breakpoint
|
|||
triggered. */
|
||||
char *exec_pathname;
|
||||
|
||||
asection *section;
|
||||
/* Methods associated with this breakpoint. */
|
||||
struct breakpoint_ops *ops;
|
||||
|
||||
/* Was breakpoint issued from a tty? Saved for the use of pending breakpoints. */
|
||||
int from_tty;
|
||||
|
||||
/* Flag value for pending breakpoint.
|
||||
first bit : 0 non-temporary, 1 temporary.
|
||||
second bit : 0 normal breakpoint, 1 hardware breakpoint. */
|
||||
int flag;
|
||||
|
||||
/* Is breakpoint pending on shlib loads? */
|
||||
int pending;
|
||||
};
|
||||
|
||||
/* The following stuff is an abstract data type "bpstat" ("breakpoint
|
||||
|
|
@ -322,7 +414,7 @@ extern void bpstat_clear (bpstat *);
|
|||
is part of the bpstat is copied as well. */
|
||||
extern bpstat bpstat_copy (bpstat);
|
||||
|
||||
extern bpstat bpstat_stop_status (CORE_ADDR *, int);
|
||||
extern bpstat bpstat_stop_status (CORE_ADDR pc, ptid_t ptid);
|
||||
|
||||
/* This bpstat_what stuff tells wait_for_inferior what to do with a
|
||||
breakpoint (a challenging task). */
|
||||
|
|
@ -521,18 +613,22 @@ enum breakpoint_here
|
|||
|
||||
/* Prototypes for breakpoint-related functions. */
|
||||
|
||||
/* Forward declarations for prototypes */
|
||||
struct frame_info;
|
||||
|
||||
extern enum breakpoint_here breakpoint_here_p (CORE_ADDR);
|
||||
|
||||
extern int breakpoint_inserted_here_p (CORE_ADDR);
|
||||
|
||||
extern int frame_in_dummy (struct frame_info *);
|
||||
extern int software_breakpoint_inserted_here_p (CORE_ADDR);
|
||||
|
||||
/* FIXME: cagney/2002-11-10: The current [generic] dummy-frame code
|
||||
implements a functional superset of this function. The only reason
|
||||
it hasn't been removed is because some architectures still don't
|
||||
use the new framework. Once they have been fixed, this can go. */
|
||||
struct frame_info;
|
||||
extern int deprecated_frame_in_dummy (struct frame_info *);
|
||||
|
||||
extern int breakpoint_thread_match (CORE_ADDR, ptid_t);
|
||||
|
||||
extern void until_break_command (char *, int);
|
||||
extern void until_break_command (char *, int, int);
|
||||
|
||||
extern void breakpoint_re_set (void);
|
||||
|
||||
|
|
@ -541,7 +637,7 @@ extern void breakpoint_re_set_thread (struct breakpoint *);
|
|||
extern int ep_is_exception_catchpoint (struct breakpoint *);
|
||||
|
||||
extern struct breakpoint *set_momentary_breakpoint
|
||||
(struct symtab_and_line, struct frame_info *, enum bptype);
|
||||
(struct symtab_and_line, struct frame_id, enum bptype);
|
||||
|
||||
extern void set_ignore_count (int, int, int);
|
||||
|
||||
|
|
@ -615,12 +711,12 @@ extern void disable_longjmp_breakpoint (void);
|
|||
extern void enable_overlay_breakpoints (void);
|
||||
extern void disable_overlay_breakpoints (void);
|
||||
|
||||
extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_info *);
|
||||
extern void set_longjmp_resume_breakpoint (CORE_ADDR, struct frame_id);
|
||||
/* These functions respectively disable or reenable all currently
|
||||
enabled watchpoints. When disabled, the watchpoints are marked
|
||||
call_disabled. When reenabled, they are marked enabled.
|
||||
|
||||
The intended client of these functions is infcmd.c\run_stack_dummy.
|
||||
The intended client of these functions is call_function_by_hand.
|
||||
|
||||
The inferior must be stopped, and all breakpoints removed, when
|
||||
these functions are used.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* Support routines for building symbol tables in GDB's internal format.
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
|
||||
1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -28,17 +29,24 @@
|
|||
|
||||
#include "defs.h"
|
||||
#include "bfd.h"
|
||||
#include "obstack.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "symtab.h"
|
||||
#include "symfile.h" /* Needed for "struct complaint" */
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "complaints.h"
|
||||
#include "gdb_string.h"
|
||||
#include "expression.h" /* For "enum exp_opcode" used by... */
|
||||
#include "language.h" /* For "longest_local_hex_string_custom" */
|
||||
#include "language.h" /* For "local_hex_string" */
|
||||
#include "bcache.h"
|
||||
#include "filenames.h" /* For DOSish file names */
|
||||
#include "macrotab.h"
|
||||
#include "demangle.h" /* Needed by SYMBOL_INIT_DEMANGLED_NAME. */
|
||||
#include "block.h"
|
||||
#include "cp-support.h"
|
||||
#include "dictionary.h"
|
||||
|
||||
/* Ask buildsym.h to define the vars it normally declares `extern'. */
|
||||
#define EXTERN
|
||||
/**/
|
||||
|
|
@ -70,30 +78,13 @@ static int compare_line_numbers (const void *ln1p, const void *ln2p);
|
|||
#define INITIAL_LINE_VECTOR_LENGTH 1000
|
||||
|
||||
|
||||
/* Complaints about the symbols we have encountered. */
|
||||
|
||||
struct complaint block_end_complaint =
|
||||
{"block end address less than block start address in %s (patched it)", 0, 0};
|
||||
|
||||
struct complaint anon_block_end_complaint =
|
||||
{"block end address 0x%lx less than block start address 0x%lx (patched it)", 0, 0};
|
||||
|
||||
struct complaint innerblock_complaint =
|
||||
{"inner block not inside outer block in %s", 0, 0};
|
||||
|
||||
struct complaint innerblock_anon_complaint =
|
||||
{"inner block (0x%lx-0x%lx) not inside outer block (0x%lx-0x%lx)", 0, 0};
|
||||
|
||||
struct complaint blockvector_complaint =
|
||||
{"block at %s out of order", 0, 0};
|
||||
|
||||
/* maintain the lists of symbols and blocks */
|
||||
|
||||
/* Add a pending list to free_pendings. */
|
||||
void
|
||||
add_free_pendings (struct pending *list)
|
||||
{
|
||||
register struct pending *link = list;
|
||||
struct pending *link = list;
|
||||
|
||||
if (list)
|
||||
{
|
||||
|
|
@ -103,12 +94,15 @@ add_free_pendings (struct pending *list)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add a symbol to one of the lists of symbols. */
|
||||
/* Add a symbol to one of the lists of symbols. While we're at it, if
|
||||
we're in the C++ case and don't have full namespace debugging info,
|
||||
check to see if it references an anonymous namespace; if so, add an
|
||||
appropriate using directive. */
|
||||
|
||||
void
|
||||
add_symbol_to_list (struct symbol *symbol, struct pending **listhead)
|
||||
{
|
||||
register struct pending *link;
|
||||
struct pending *link;
|
||||
|
||||
/* If this is an alias for another symbol, don't add it. */
|
||||
if (symbol->ginfo.name && symbol->ginfo.name[0] == '#')
|
||||
|
|
@ -134,6 +128,12 @@ add_symbol_to_list (struct symbol *symbol, struct pending **listhead)
|
|||
}
|
||||
|
||||
(*listhead)->symbol[(*listhead)->nsyms++] = symbol;
|
||||
|
||||
/* Check to see if we might need to look for a mention of anonymous
|
||||
namespaces. */
|
||||
|
||||
if (SYMBOL_LANGUAGE (symbol) == language_cplus)
|
||||
cp_scan_for_anonymous_namespaces (symbol);
|
||||
}
|
||||
|
||||
/* Find a symbol named NAME on a LIST. NAME need not be
|
||||
|
|
@ -149,7 +149,7 @@ find_symbol_in_list (struct pending *list, char *name, int length)
|
|||
{
|
||||
for (j = list->nsyms; --j >= 0;)
|
||||
{
|
||||
pp = SYMBOL_NAME (list->symbol[j]);
|
||||
pp = DEPRECATED_SYMBOL_NAME (list->symbol[j]);
|
||||
if (*pp == *name && strncmp (pp, name, length) == 0 &&
|
||||
pp[length] == '\0')
|
||||
{
|
||||
|
|
@ -164,9 +164,8 @@ find_symbol_in_list (struct pending *list, char *name, int length)
|
|||
/* At end of reading syms, or in case of quit, really free as many
|
||||
`struct pending's as we can easily find. */
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
really_free_pendings (PTR dummy)
|
||||
really_free_pendings (void *dummy)
|
||||
{
|
||||
struct pending *next, *next1;
|
||||
|
||||
|
|
@ -192,6 +191,9 @@ really_free_pendings (PTR dummy)
|
|||
xfree ((void *) next);
|
||||
}
|
||||
global_symbols = NULL;
|
||||
|
||||
if (pending_macros)
|
||||
free_macro_table (pending_macros);
|
||||
}
|
||||
|
||||
/* This function is called to discard any pending blocks. */
|
||||
|
|
@ -200,7 +202,7 @@ void
|
|||
free_pending_blocks (void)
|
||||
{
|
||||
#if 0 /* Now we make the links in the
|
||||
symbol_obstack, so don't free
|
||||
objfile_obstack, so don't free
|
||||
them. */
|
||||
struct pending_block *bnext, *bnext1;
|
||||
|
||||
|
|
@ -223,40 +225,29 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
CORE_ADDR start, CORE_ADDR end,
|
||||
struct objfile *objfile)
|
||||
{
|
||||
register struct pending *next, *next1;
|
||||
register struct block *block;
|
||||
register struct pending_block *pblock;
|
||||
struct pending *next, *next1;
|
||||
struct block *block;
|
||||
struct pending_block *pblock;
|
||||
struct pending_block *opblock;
|
||||
register int i;
|
||||
register int j;
|
||||
|
||||
/* Count the length of the list of symbols. */
|
||||
block = allocate_block (&objfile->objfile_obstack);
|
||||
|
||||
for (next = *listhead, i = 0;
|
||||
next;
|
||||
i += next->nsyms, next = next->next)
|
||||
if (symbol)
|
||||
{
|
||||
/* EMPTY */ ;
|
||||
BLOCK_DICT (block) = dict_create_linear (&objfile->objfile_obstack,
|
||||
*listhead);
|
||||
}
|
||||
|
||||
block = (struct block *) obstack_alloc (&objfile->symbol_obstack,
|
||||
(sizeof (struct block) + ((i - 1) * sizeof (struct symbol *))));
|
||||
|
||||
/* Copy the symbols into the block. */
|
||||
|
||||
BLOCK_NSYMS (block) = i;
|
||||
for (next = *listhead; next; next = next->next)
|
||||
else
|
||||
{
|
||||
for (j = next->nsyms - 1; j >= 0; j--)
|
||||
{
|
||||
BLOCK_SYM (block, --i) = next->symbol[j];
|
||||
}
|
||||
BLOCK_DICT (block) = dict_create_hashed (&objfile->objfile_obstack,
|
||||
*listhead);
|
||||
}
|
||||
|
||||
BLOCK_START (block) = start;
|
||||
BLOCK_END (block) = end;
|
||||
/* Superblock filled in when containing block is made */
|
||||
BLOCK_SUPERBLOCK (block) = NULL;
|
||||
BLOCK_NAMESPACE (block) = NULL;
|
||||
|
||||
BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
|
||||
|
||||
|
|
@ -265,6 +256,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
if (symbol)
|
||||
{
|
||||
struct type *ftype = SYMBOL_TYPE (symbol);
|
||||
struct dict_iterator iter;
|
||||
SYMBOL_BLOCK_VALUE (symbol) = block;
|
||||
BLOCK_FUNCTION (block) = symbol;
|
||||
|
||||
|
|
@ -275,7 +267,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
parameter symbols. */
|
||||
int nparams = 0, iparams;
|
||||
struct symbol *sym;
|
||||
ALL_BLOCK_SYMBOLS (block, i, sym)
|
||||
ALL_BLOCK_SYMBOLS (block, iter, sym)
|
||||
{
|
||||
switch (SYMBOL_CLASS (sym))
|
||||
{
|
||||
|
|
@ -285,6 +277,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
case LOC_REGPARM_ADDR:
|
||||
case LOC_BASEREG_ARG:
|
||||
case LOC_LOCAL_ARG:
|
||||
case LOC_COMPUTED_ARG:
|
||||
nparams++;
|
||||
break;
|
||||
case LOC_UNDEF:
|
||||
|
|
@ -300,6 +293,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
case LOC_BASEREG:
|
||||
case LOC_UNRESOLVED:
|
||||
case LOC_OPTIMIZED_OUT:
|
||||
case LOC_COMPUTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -310,9 +304,12 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
TYPE_FIELDS (ftype) = (struct field *)
|
||||
TYPE_ALLOC (ftype, nparams * sizeof (struct field));
|
||||
|
||||
for (i = iparams = 0; iparams < nparams; i++)
|
||||
iparams = 0;
|
||||
ALL_BLOCK_SYMBOLS (block, iter, sym)
|
||||
{
|
||||
sym = BLOCK_SYM (block, i);
|
||||
if (iparams == nparams)
|
||||
break;
|
||||
|
||||
switch (SYMBOL_CLASS (sym))
|
||||
{
|
||||
case LOC_ARG:
|
||||
|
|
@ -321,6 +318,7 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
case LOC_REGPARM_ADDR:
|
||||
case LOC_BASEREG_ARG:
|
||||
case LOC_LOCAL_ARG:
|
||||
case LOC_COMPUTED_ARG:
|
||||
TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
|
||||
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
|
||||
iparams++;
|
||||
|
|
@ -338,12 +336,19 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
case LOC_BASEREG:
|
||||
case LOC_UNRESOLVED:
|
||||
case LOC_OPTIMIZED_OUT:
|
||||
case LOC_COMPUTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're in the C++ case, set the block's scope. */
|
||||
if (SYMBOL_LANGUAGE (symbol) == language_cplus)
|
||||
{
|
||||
cp_set_block_scope (symbol, block, &objfile->objfile_obstack);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -368,11 +373,15 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
{
|
||||
if (symbol)
|
||||
{
|
||||
complain (&block_end_complaint, SYMBOL_SOURCE_NAME (symbol));
|
||||
complaint (&symfile_complaints,
|
||||
"block end address less than block start address in %s (patched it)",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
}
|
||||
else
|
||||
{
|
||||
complain (&anon_block_end_complaint, BLOCK_END (block), BLOCK_START (block));
|
||||
complaint (&symfile_complaints,
|
||||
"block end address 0x%s less than block start address 0x%s (patched it)",
|
||||
paddr_nz (BLOCK_END (block)), paddr_nz (BLOCK_START (block)));
|
||||
}
|
||||
/* Better than nothing */
|
||||
BLOCK_END (block) = BLOCK_START (block);
|
||||
|
|
@ -383,7 +392,9 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
start of this scope that don't have superblocks yet. */
|
||||
|
||||
opblock = NULL;
|
||||
for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
|
||||
for (pblock = pending_blocks;
|
||||
pblock && pblock != old_blocks;
|
||||
pblock = pblock->next)
|
||||
{
|
||||
if (BLOCK_SUPERBLOCK (pblock->block) == NULL)
|
||||
{
|
||||
|
|
@ -396,14 +407,18 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
{
|
||||
if (symbol)
|
||||
{
|
||||
complain (&innerblock_complaint,
|
||||
SYMBOL_SOURCE_NAME (symbol));
|
||||
complaint (&symfile_complaints,
|
||||
"inner block not inside outer block in %s",
|
||||
SYMBOL_PRINT_NAME (symbol));
|
||||
}
|
||||
else
|
||||
{
|
||||
complain (&innerblock_anon_complaint, BLOCK_START (pblock->block),
|
||||
BLOCK_END (pblock->block), BLOCK_START (block),
|
||||
BLOCK_END (block));
|
||||
complaint (&symfile_complaints,
|
||||
"inner block (0x%s-0x%s) not inside outer block (0x%s-0x%s)",
|
||||
paddr_nz (BLOCK_START (pblock->block)),
|
||||
paddr_nz (BLOCK_END (pblock->block)),
|
||||
paddr_nz (BLOCK_START (block)),
|
||||
paddr_nz (BLOCK_END (block)));
|
||||
}
|
||||
if (BLOCK_START (pblock->block) < BLOCK_START (block))
|
||||
BLOCK_START (pblock->block) = BLOCK_START (block);
|
||||
|
|
@ -419,21 +434,22 @@ finish_block (struct symbol *symbol, struct pending **listhead,
|
|||
record_pending_block (objfile, block, opblock);
|
||||
}
|
||||
|
||||
|
||||
/* Record BLOCK on the list of all blocks in the file. Put it after
|
||||
OPBLOCK, or at the beginning if opblock is NULL. This puts the
|
||||
block in the list after all its subblocks.
|
||||
|
||||
Allocate the pending block struct in the symbol_obstack to save
|
||||
Allocate the pending block struct in the objfile_obstack to save
|
||||
time. This wastes a little space. FIXME: Is it worth it? */
|
||||
|
||||
void
|
||||
record_pending_block (struct objfile *objfile, struct block *block,
|
||||
struct pending_block *opblock)
|
||||
{
|
||||
register struct pending_block *pblock;
|
||||
struct pending_block *pblock;
|
||||
|
||||
pblock = (struct pending_block *)
|
||||
obstack_alloc (&objfile->symbol_obstack, sizeof (struct pending_block));
|
||||
obstack_alloc (&objfile->objfile_obstack, sizeof (struct pending_block));
|
||||
pblock->block = block;
|
||||
if (opblock)
|
||||
{
|
||||
|
|
@ -447,16 +463,12 @@ record_pending_block (struct objfile *objfile, struct block *block,
|
|||
}
|
||||
}
|
||||
|
||||
/* Note that this is only used in this file and in dstread.c, which
|
||||
should be fixed to not need direct access to this function. When
|
||||
that is done, it can be made static again. */
|
||||
|
||||
struct blockvector *
|
||||
static struct blockvector *
|
||||
make_blockvector (struct objfile *objfile)
|
||||
{
|
||||
register struct pending_block *next;
|
||||
register struct blockvector *blockvector;
|
||||
register int i;
|
||||
struct pending_block *next;
|
||||
struct blockvector *blockvector;
|
||||
int i;
|
||||
|
||||
/* Count the length of the list of blocks. */
|
||||
|
||||
|
|
@ -465,7 +477,7 @@ make_blockvector (struct objfile *objfile)
|
|||
}
|
||||
|
||||
blockvector = (struct blockvector *)
|
||||
obstack_alloc (&objfile->symbol_obstack,
|
||||
obstack_alloc (&objfile->objfile_obstack,
|
||||
(sizeof (struct blockvector)
|
||||
+ (i - 1) * sizeof (struct block *)));
|
||||
|
||||
|
|
@ -508,8 +520,8 @@ make_blockvector (struct objfile *objfile)
|
|||
CORE_ADDR start
|
||||
= BLOCK_START (BLOCKVECTOR_BLOCK (blockvector, i));
|
||||
|
||||
complain (&blockvector_complaint,
|
||||
longest_local_hex_string ((LONGEST) start));
|
||||
complaint (&symfile_complaints, "block at %s out of order",
|
||||
local_hex_string ((LONGEST) start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -526,7 +538,7 @@ make_blockvector (struct objfile *objfile)
|
|||
void
|
||||
start_subfile (char *name, char *dirname)
|
||||
{
|
||||
register struct subfile *subfile;
|
||||
struct subfile *subfile;
|
||||
|
||||
/* See if this subfile is already known as a subfile of the current
|
||||
main source file. */
|
||||
|
|
@ -580,15 +592,9 @@ start_subfile (char *name, char *dirname)
|
|||
later via a call to record_debugformat. */
|
||||
subfile->debugformat = NULL;
|
||||
|
||||
/* cfront output is a C program, so in most ways it looks like a C
|
||||
program. But to demangle we need to set the language to C++. We
|
||||
can distinguish cfront code by the fact that it has #line
|
||||
directives which specify a file name ending in .C.
|
||||
|
||||
So if the filename of this subfile ends in .C, then change the
|
||||
/* If the filename of this subfile ends in .C, then change the
|
||||
language of any pending subfiles from C to C++. We also accept
|
||||
any other C++ suffixes accepted by deduce_language_from_filename
|
||||
(in particular, some people use .cxx with cfront). */
|
||||
any other C++ suffixes accepted by deduce_language_from_filename. */
|
||||
/* Likewise for f2c. */
|
||||
|
||||
if (subfile->name)
|
||||
|
|
@ -662,7 +668,7 @@ patch_subfile_names (struct subfile *subfile, char *name)
|
|||
void
|
||||
push_subfile (void)
|
||||
{
|
||||
register struct subfile_stack *tem
|
||||
struct subfile_stack *tem
|
||||
= (struct subfile_stack *) xmalloc (sizeof (struct subfile_stack));
|
||||
|
||||
tem->next = subfile_stack;
|
||||
|
|
@ -677,8 +683,8 @@ push_subfile (void)
|
|||
char *
|
||||
pop_subfile (void)
|
||||
{
|
||||
register char *name;
|
||||
register struct subfile_stack *link = subfile_stack;
|
||||
char *name;
|
||||
struct subfile_stack *link = subfile_stack;
|
||||
|
||||
if (link == NULL)
|
||||
{
|
||||
|
|
@ -694,7 +700,7 @@ pop_subfile (void)
|
|||
line vector for SUBFILE. */
|
||||
|
||||
void
|
||||
record_line (register struct subfile *subfile, int line, CORE_ADDR pc)
|
||||
record_line (struct subfile *subfile, int line, CORE_ADDR pc)
|
||||
{
|
||||
struct linetable_entry *e;
|
||||
/* Ignore the dummy line number in libg.o */
|
||||
|
|
@ -777,6 +783,10 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
|
|||
}
|
||||
context_stack_depth = 0;
|
||||
|
||||
/* Set up support for C++ namespace support, in case we need it. */
|
||||
|
||||
cp_initialize_namespace ();
|
||||
|
||||
/* Initialize the list of sub source files with one entry for this
|
||||
file (the top-level source file). */
|
||||
|
||||
|
|
@ -805,10 +815,10 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
|
|||
struct symtab *
|
||||
end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
||||
{
|
||||
register struct symtab *symtab = NULL;
|
||||
register struct blockvector *blockvector;
|
||||
register struct subfile *subfile;
|
||||
register struct context_stack *cstk;
|
||||
struct symtab *symtab = NULL;
|
||||
struct blockvector *blockvector;
|
||||
struct subfile *subfile;
|
||||
struct context_stack *cstk;
|
||||
struct subfile *nextsub;
|
||||
|
||||
/* Finish the lexical context of the last function in the file; pop
|
||||
|
|
@ -828,9 +838,8 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
same. FIXME: Find out why it is happening. This is not
|
||||
believed to happen in most cases (even for coffread.c);
|
||||
it used to be an abort(). */
|
||||
static struct complaint msg =
|
||||
{"Context stack not empty in end_symtab", 0, 0};
|
||||
complain (&msg);
|
||||
complaint (&symfile_complaints,
|
||||
"Context stack not empty in end_symtab");
|
||||
context_stack_depth = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -883,7 +892,8 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
if (pending_blocks == NULL
|
||||
&& file_symbols == NULL
|
||||
&& global_symbols == NULL
|
||||
&& have_line_numbers == 0)
|
||||
&& have_line_numbers == 0
|
||||
&& pending_macros == NULL)
|
||||
{
|
||||
/* Ignore symtabs that have no functions with real debugging
|
||||
info. */
|
||||
|
|
@ -898,6 +908,8 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr,
|
||||
objfile);
|
||||
blockvector = make_blockvector (objfile);
|
||||
cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
|
||||
&objfile->objfile_obstack);
|
||||
}
|
||||
|
||||
#ifndef PROCESS_LINENUMBER_HOOK
|
||||
|
|
@ -944,11 +956,12 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
|
||||
/* Fill in its components. */
|
||||
symtab->blockvector = blockvector;
|
||||
symtab->macro_table = pending_macros;
|
||||
if (subfile->line_vector)
|
||||
{
|
||||
/* Reallocate the line table on the symbol obstack */
|
||||
symtab->linetable = (struct linetable *)
|
||||
obstack_alloc (&objfile->symbol_obstack, linetablesize);
|
||||
obstack_alloc (&objfile->objfile_obstack, linetablesize);
|
||||
memcpy (symtab->linetable, subfile->line_vector, linetablesize);
|
||||
}
|
||||
else
|
||||
|
|
@ -960,7 +973,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
{
|
||||
/* Reallocate the dirname on the symbol obstack */
|
||||
symtab->dirname = (char *)
|
||||
obstack_alloc (&objfile->symbol_obstack,
|
||||
obstack_alloc (&objfile->objfile_obstack,
|
||||
strlen (subfile->dirname) + 1);
|
||||
strcpy (symtab->dirname, subfile->dirname);
|
||||
}
|
||||
|
|
@ -969,7 +982,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
symtab->dirname = NULL;
|
||||
}
|
||||
symtab->free_code = free_linetable;
|
||||
symtab->free_ptr = NULL;
|
||||
symtab->free_func = NULL;
|
||||
|
||||
/* Use whatever language we have been using for this
|
||||
subfile, not the one that was deduced in allocate_symtab
|
||||
|
|
@ -984,7 +997,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
{
|
||||
symtab->debugformat = obsavestring (subfile->debugformat,
|
||||
strlen (subfile->debugformat),
|
||||
&objfile->symbol_obstack);
|
||||
&objfile->objfile_obstack);
|
||||
}
|
||||
|
||||
/* All symtabs for the main file and the subfiles share a
|
||||
|
|
@ -1022,6 +1035,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
|
||||
last_source_file = NULL;
|
||||
current_subfile = NULL;
|
||||
pending_macros = NULL;
|
||||
|
||||
return symtab;
|
||||
}
|
||||
|
|
@ -1033,7 +1047,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
|
|||
struct context_stack *
|
||||
push_context (int desc, CORE_ADDR valu)
|
||||
{
|
||||
register struct context_stack *new;
|
||||
struct context_stack *new;
|
||||
|
||||
if (context_stack_depth == context_stack_size)
|
||||
{
|
||||
|
|
@ -1056,6 +1070,17 @@ push_context (int desc, CORE_ADDR valu)
|
|||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Pop a context block. Returns the address of the context block just
|
||||
popped. */
|
||||
|
||||
struct context_stack *
|
||||
pop_context (void)
|
||||
{
|
||||
gdb_assert (context_stack_depth > 0);
|
||||
return (&context_stack[--context_stack_depth]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Compute a small integer hash code for the given name. */
|
||||
|
|
@ -1084,7 +1109,7 @@ record_debugformat (char *format)
|
|||
void
|
||||
merge_symbol_lists (struct pending **srclist, struct pending **targetlist)
|
||||
{
|
||||
register int i;
|
||||
int i;
|
||||
|
||||
if (!srclist || !*srclist)
|
||||
return;
|
||||
|
|
@ -1112,6 +1137,7 @@ buildsym_init (void)
|
|||
file_symbols = NULL;
|
||||
global_symbols = NULL;
|
||||
pending_blocks = NULL;
|
||||
pending_macros = NULL;
|
||||
}
|
||||
|
||||
/* Initialize anything that needs initializing when a completely new
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* Build symbol tables in GDB's internal format.
|
||||
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1996,
|
||||
1997, 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
1997, 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -22,6 +22,9 @@
|
|||
#if !defined (BUILDSYM_H)
|
||||
#define BUILDSYM_H 1
|
||||
|
||||
struct objfile;
|
||||
struct symbol;
|
||||
|
||||
/* This module provides definitions used for creating and adding to
|
||||
the symbol table. These routines are called from various symbol-
|
||||
file-reading routines.
|
||||
|
|
@ -34,6 +37,8 @@
|
|||
normally extern, but which get defined in a single module using
|
||||
this technique. */
|
||||
|
||||
struct block;
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
|
@ -83,16 +88,6 @@ EXTERN unsigned char processing_gcc_compilation;
|
|||
|
||||
EXTERN unsigned char processing_acc_compilation;
|
||||
|
||||
/* elz: added this flag to know when a block is compiled with HP
|
||||
compilers (cc, aCC). This is necessary because of the macro
|
||||
COERCE_FLOAT_TO_DOUBLE defined in tm_hppa.h, which causes a
|
||||
coercion of float to double to always occur in parameter passing
|
||||
for a function called by gdb (see the function value_arg_coerce in
|
||||
valops.c). This is necessary only if the target was compiled with
|
||||
gcc, not with HP compilers or with g++ */
|
||||
|
||||
EXTERN unsigned char processing_hp_compilation;
|
||||
|
||||
/* Count symbols as they are processed, for error messages. */
|
||||
|
||||
EXTERN unsigned int symnum;
|
||||
|
|
@ -173,11 +168,8 @@ EXTERN int context_stack_depth;
|
|||
|
||||
EXTERN int context_stack_size;
|
||||
|
||||
/* Macro "function" for popping contexts from the stack. Pushing is
|
||||
done by a real function, push_context. This returns a pointer to a
|
||||
struct context_stack. */
|
||||
|
||||
#define pop_context() (&context_stack[--context_stack_depth]);
|
||||
/* Non-zero if the context stack is empty. */
|
||||
#define outermost_context_p() (context_stack_depth == 0)
|
||||
|
||||
/* Nonzero if within a function (so symbols should be local, if
|
||||
nothing says specifically). */
|
||||
|
|
@ -246,7 +238,7 @@ extern void finish_block (struct symbol *symbol,
|
|||
CORE_ADDR start, CORE_ADDR end,
|
||||
struct objfile *objfile);
|
||||
|
||||
extern void really_free_pendings (PTR dummy);
|
||||
extern void really_free_pendings (void *dummy);
|
||||
|
||||
extern void start_subfile (char *name, char *dirname);
|
||||
|
||||
|
|
@ -269,6 +261,8 @@ extern void buildsym_init (void);
|
|||
|
||||
extern struct context_stack *push_context (int desc, CORE_ADDR valu);
|
||||
|
||||
extern struct context_stack *pop_context (void);
|
||||
|
||||
extern void record_line (struct subfile *subfile, int line, CORE_ADDR pc);
|
||||
|
||||
extern void start_symtab (char *name, char *dirname, CORE_ADDR start_addr);
|
||||
|
|
@ -277,12 +271,6 @@ extern int hashname (char *name);
|
|||
|
||||
extern void free_pending_blocks (void);
|
||||
|
||||
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
|
||||
which should be fixed to not need direct access to
|
||||
make_blockvector. */
|
||||
|
||||
extern struct blockvector *make_blockvector (struct objfile *objfile);
|
||||
|
||||
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
|
||||
which should be fixed to not need direct access to
|
||||
record_pending_block. */
|
||||
|
|
@ -296,6 +284,10 @@ extern void record_debugformat (char *format);
|
|||
extern void merge_symbol_lists (struct pending **srclist,
|
||||
struct pending **targetlist);
|
||||
|
||||
/* The macro table for the compilation unit whose symbols we're
|
||||
currently reading. All the symtabs for this CU will point to this. */
|
||||
EXTERN struct macro_table *pending_macros;
|
||||
|
||||
#undef EXTERN
|
||||
|
||||
#endif /* defined (BUILDSYM_H) */
|
||||
|
|
|
|||
3443
contrib/gdb/gdb/c-exp.c
Normal file
3443
contrib/gdb/gdb/c-exp.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
/* YACC parser for C expressions, for GDB.
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 1999, 2000
|
||||
1998, 1999, 2000, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
|
@ -49,6 +49,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
#include "bfd.h" /* Required by objfiles.h. */
|
||||
#include "symfile.h" /* Required by objfiles.h. */
|
||||
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
|
||||
#include "charset.h"
|
||||
#include "block.h"
|
||||
#include "cp-support.h"
|
||||
|
||||
/* Flag indicating we're dealing with HP-compiled objects */
|
||||
extern int hp_som_som_object_present;
|
||||
|
|
@ -89,6 +92,8 @@ extern int hp_som_som_object_present;
|
|||
#define yylloc c_lloc
|
||||
#define yyreds c_reds /* With YYDEBUG defined */
|
||||
#define yytoks c_toks /* With YYDEBUG defined */
|
||||
#define yyname c_name /* With YYDEBUG defined */
|
||||
#define yyrule c_rule /* With YYDEBUG defined */
|
||||
#define yylhs c_yylhs
|
||||
#define yylen c_yylen
|
||||
#define yydefred c_yydefred
|
||||
|
|
@ -100,9 +105,11 @@ extern int hp_som_som_object_present;
|
|||
#define yycheck c_yycheck
|
||||
|
||||
#ifndef YYDEBUG
|
||||
#define YYDEBUG 0 /* Default to no yydebug support */
|
||||
#define YYDEBUG 1 /* Default to yydebug support */
|
||||
#endif
|
||||
|
||||
#define YYFPRINTF parser_fprintf
|
||||
|
||||
int yyparse (void);
|
||||
|
||||
static int yylex (void);
|
||||
|
|
@ -147,7 +154,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
|
|||
|
||||
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
|
||||
%type <lval> rcurly
|
||||
%type <tval> type typebase
|
||||
%type <tval> type typebase qualified_type
|
||||
%type <tvec> nonempty_typelist
|
||||
/* %type <bval> block */
|
||||
|
||||
|
|
@ -194,7 +201,6 @@ static int parse_number (char *, int, int, YYSTYPE *);
|
|||
%token <opcode> ASSIGN_MODIFY
|
||||
|
||||
/* C++ */
|
||||
%token THIS
|
||||
%token TRUEKEYWORD
|
||||
%token FALSEKEYWORD
|
||||
|
||||
|
|
@ -243,9 +249,11 @@ exp1 : exp
|
|||
/* Expressions, not including the comma operator. */
|
||||
exp : '*' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_IND); }
|
||||
;
|
||||
|
||||
exp : '&' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_ADDR); }
|
||||
;
|
||||
|
||||
exp : '-' exp %prec UNARY
|
||||
{ write_exp_elt_opcode (UNOP_NEG); }
|
||||
|
|
@ -527,11 +535,6 @@ exp : STRING
|
|||
;
|
||||
|
||||
/* C++. */
|
||||
exp : THIS
|
||||
{ write_exp_elt_opcode (OP_THIS);
|
||||
write_exp_elt_opcode (OP_THIS); }
|
||||
;
|
||||
|
||||
exp : TRUEKEYWORD
|
||||
{ write_exp_elt_opcode (OP_LONG);
|
||||
write_exp_elt_type (builtin_type_bool);
|
||||
|
|
@ -565,7 +568,7 @@ block : BLOCKNAME
|
|||
block : block COLONCOLON name
|
||||
{ struct symbol *tem
|
||||
= lookup_symbol (copy_name ($3), $1,
|
||||
VAR_NAMESPACE, (int *) NULL,
|
||||
VAR_DOMAIN, (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
|
||||
error ("No function \"%s\" in specified context.",
|
||||
|
|
@ -576,7 +579,7 @@ block : block COLONCOLON name
|
|||
variable: block COLONCOLON name
|
||||
{ struct symbol *sym;
|
||||
sym = lookup_symbol (copy_name ($3), $1,
|
||||
VAR_NAMESPACE, (int *) NULL,
|
||||
VAR_DOMAIN, (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
if (sym == 0)
|
||||
error ("No symbol \"%s\" in specified context.",
|
||||
|
|
@ -593,7 +596,8 @@ qualified_name: typebase COLONCOLON name
|
|||
{
|
||||
struct type *type = $1;
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
||||
error ("`%s' is not defined as an aggregate type.",
|
||||
TYPE_NAME (type));
|
||||
|
||||
|
|
@ -607,7 +611,8 @@ qualified_name: typebase COLONCOLON name
|
|||
struct type *type = $1;
|
||||
struct stoken tmp_token;
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
||||
error ("`%s' is not defined as an aggregate type.",
|
||||
TYPE_NAME (type));
|
||||
|
||||
|
|
@ -635,7 +640,7 @@ variable: qualified_name
|
|||
|
||||
sym =
|
||||
lookup_symbol (name, (const struct block *) NULL,
|
||||
VAR_NAMESPACE, (int *) NULL,
|
||||
VAR_DOMAIN, (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
if (sym)
|
||||
{
|
||||
|
|
@ -699,7 +704,7 @@ variable: name_not_typename
|
|||
else
|
||||
{
|
||||
struct minimal_symbol *msymbol;
|
||||
register char *arg = copy_name ($1.stoken);
|
||||
char *arg = copy_name ($1.stoken);
|
||||
|
||||
msymbol =
|
||||
lookup_minimal_symbol (arg, NULL, NULL);
|
||||
|
|
@ -780,7 +785,7 @@ array_mod: '[' ']'
|
|||
func_mod: '(' ')'
|
||||
{ $$ = 0; }
|
||||
| '(' nonempty_typelist ')'
|
||||
{ free ((PTR)$2); $$ = 0; }
|
||||
{ free ($2); $$ = 0; }
|
||||
;
|
||||
|
||||
/* We used to try to recognize more pointer to member types here, but
|
||||
|
|
@ -807,24 +812,50 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
|||
{ $$ = builtin_type_short; }
|
||||
| LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_long; }
|
||||
| LONG SIGNED_KEYWORD INT_KEYWORD
|
||||
{ $$ = builtin_type_long; }
|
||||
| LONG SIGNED_KEYWORD
|
||||
{ $$ = builtin_type_long; }
|
||||
| SIGNED_KEYWORD LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_long; }
|
||||
| UNSIGNED LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_long; }
|
||||
| LONG UNSIGNED INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_long; }
|
||||
| LONG UNSIGNED
|
||||
{ $$ = builtin_type_unsigned_long; }
|
||||
| LONG LONG
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| LONG LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| LONG LONG SIGNED_KEYWORD INT_KEYWORD
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| LONG LONG SIGNED_KEYWORD
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| SIGNED_KEYWORD LONG LONG
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| SIGNED_KEYWORD LONG LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_long_long; }
|
||||
| UNSIGNED LONG LONG
|
||||
{ $$ = builtin_type_unsigned_long_long; }
|
||||
| UNSIGNED LONG LONG INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_long_long; }
|
||||
| SIGNED_KEYWORD LONG LONG
|
||||
{ $$ = lookup_signed_typename ("long long"); }
|
||||
| SIGNED_KEYWORD LONG LONG INT_KEYWORD
|
||||
{ $$ = lookup_signed_typename ("long long"); }
|
||||
| LONG LONG UNSIGNED
|
||||
{ $$ = builtin_type_unsigned_long_long; }
|
||||
| LONG LONG UNSIGNED INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_long_long; }
|
||||
| SHORT INT_KEYWORD
|
||||
{ $$ = builtin_type_short; }
|
||||
| SHORT SIGNED_KEYWORD INT_KEYWORD
|
||||
{ $$ = builtin_type_short; }
|
||||
| SHORT SIGNED_KEYWORD
|
||||
{ $$ = builtin_type_short; }
|
||||
| UNSIGNED SHORT INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_short; }
|
||||
| SHORT UNSIGNED
|
||||
{ $$ = builtin_type_unsigned_short; }
|
||||
| SHORT UNSIGNED INT_KEYWORD
|
||||
{ $$ = builtin_type_unsigned_short; }
|
||||
| DOUBLE_KEYWORD
|
||||
{ $$ = builtin_type_double; }
|
||||
| LONG DOUBLE_KEYWORD
|
||||
|
|
@ -860,6 +891,77 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
|||
{ $$ = follow_types ($2); }
|
||||
| typebase const_or_volatile_or_space_identifier_noopt
|
||||
{ $$ = follow_types ($1); }
|
||||
| qualified_type
|
||||
;
|
||||
|
||||
/* FIXME: carlton/2003-09-25: This next bit leads to lots of
|
||||
reduce-reduce conflicts, because the parser doesn't know whether or
|
||||
not to use qualified_name or qualified_type: the rules are
|
||||
identical. If the parser is parsing 'A::B::x', then, when it sees
|
||||
the second '::', it knows that the expression to the left of it has
|
||||
to be a type, so it uses qualified_type. But if it is parsing just
|
||||
'A::B', then it doesn't have any way of knowing which rule to use,
|
||||
so there's a reduce-reduce conflict; it picks qualified_name, since
|
||||
that occurs earlier in this file than qualified_type.
|
||||
|
||||
There's no good way to fix this with the grammar as it stands; as
|
||||
far as I can tell, some of the problems arise from ambiguities that
|
||||
GDB introduces ('start' can be either an expression or a type), but
|
||||
some of it is inherent to the nature of C++ (you want to treat the
|
||||
input "(FOO)" fairly differently depending on whether FOO is an
|
||||
expression or a type, and if FOO is a complex expression, this can
|
||||
be hard to determine at the right time). Fortunately, it works
|
||||
pretty well in most cases. For example, if you do 'ptype A::B',
|
||||
where A::B is a nested type, then the parser will mistakenly
|
||||
misidentify it as an expression; but evaluate_subexp will get
|
||||
called with 'noside' set to EVAL_AVOID_SIDE_EFFECTS, and everything
|
||||
will work out anyways. But there are situations where the parser
|
||||
will get confused: the most common one that I've run into is when
|
||||
you want to do
|
||||
|
||||
print *((A::B *) x)"
|
||||
|
||||
where the parser doesn't realize that A::B has to be a type until
|
||||
it hits the first right paren, at which point it's too late. (The
|
||||
workaround is to type "print *(('A::B' *) x)" instead.) (And
|
||||
another solution is to fix our symbol-handling code so that the
|
||||
user never wants to type something like that in the first place,
|
||||
because we get all the types right without the user's help!)
|
||||
|
||||
Perhaps we could fix this by making the lexer smarter. Some of
|
||||
this functionality used to be in the lexer, but in a way that
|
||||
worked even less well than the current solution: that attempt
|
||||
involved having the parser sometimes handle '::' and having the
|
||||
lexer sometimes handle it, and without a clear division of
|
||||
responsibility, it quickly degenerated into a big mess. Probably
|
||||
the eventual correct solution will give more of a role to the lexer
|
||||
(ideally via code that is shared between the lexer and
|
||||
decode_line_1), but I'm not holding my breath waiting for somebody
|
||||
to get around to cleaning this up... */
|
||||
|
||||
qualified_type: typebase COLONCOLON name
|
||||
{
|
||||
struct type *type = $1;
|
||||
struct type *new_type;
|
||||
char *ncopy = alloca ($3.length + 1);
|
||||
|
||||
memcpy (ncopy, $3.ptr, $3.length);
|
||||
ncopy[$3.length] = '\0';
|
||||
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
||||
error ("`%s' is not defined as an aggregate type.",
|
||||
TYPE_NAME (type));
|
||||
|
||||
new_type = cp_lookup_nested_type (type, ncopy,
|
||||
expression_context_block);
|
||||
if (new_type == NULL)
|
||||
error ("No type \"%s\" within class or namespace \"%s\".",
|
||||
ncopy, TYPE_NAME (type));
|
||||
|
||||
$$ = new_type;
|
||||
}
|
||||
;
|
||||
|
||||
typename: TYPENAME
|
||||
|
|
@ -942,20 +1044,20 @@ name_not_typename : NAME
|
|||
|
||||
static int
|
||||
parse_number (p, len, parsed_float, putithere)
|
||||
register char *p;
|
||||
register int len;
|
||||
char *p;
|
||||
int len;
|
||||
int parsed_float;
|
||||
YYSTYPE *putithere;
|
||||
{
|
||||
/* FIXME: Shouldn't these be unsigned? We don't deal with negative values
|
||||
here, and we do kind of silly things like cast to unsigned. */
|
||||
register LONGEST n = 0;
|
||||
register LONGEST prevn = 0;
|
||||
LONGEST n = 0;
|
||||
LONGEST prevn = 0;
|
||||
ULONGEST un;
|
||||
|
||||
register int i = 0;
|
||||
register int c;
|
||||
register int base = input_radix;
|
||||
int i = 0;
|
||||
int c;
|
||||
int base = input_radix;
|
||||
int unsigned_p = 0;
|
||||
|
||||
/* Number of "L" suffixes encountered. */
|
||||
|
|
@ -1218,12 +1320,24 @@ yylex ()
|
|||
|
||||
retry:
|
||||
|
||||
/* Check if this is a macro invocation that we need to expand. */
|
||||
if (! scanning_macro_expansion ())
|
||||
{
|
||||
char *expanded = macro_expand_next (&lexptr,
|
||||
expression_macro_lookup_func,
|
||||
expression_macro_lookup_baton);
|
||||
|
||||
if (expanded)
|
||||
scan_macro_expansion (expanded);
|
||||
}
|
||||
|
||||
prev_lexptr = lexptr;
|
||||
unquoted_expr = 1;
|
||||
|
||||
tokstart = lexptr;
|
||||
/* See if it is a special token of length 3. */
|
||||
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
|
||||
if (STREQN (tokstart, tokentab3[i].operator, 3))
|
||||
if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
|
||||
{
|
||||
lexptr += 3;
|
||||
yylval.opcode = tokentab3[i].opcode;
|
||||
|
|
@ -1232,7 +1346,7 @@ yylex ()
|
|||
|
||||
/* See if it is a special token of length 2. */
|
||||
for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
|
||||
if (STREQN (tokstart, tokentab2[i].operator, 2))
|
||||
if (strncmp (tokstart, tokentab2[i].operator, 2) == 0)
|
||||
{
|
||||
lexptr += 2;
|
||||
yylval.opcode = tokentab2[i].opcode;
|
||||
|
|
@ -1242,7 +1356,17 @@ yylex ()
|
|||
switch (c = *tokstart)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
/* If we were just scanning the result of a macro expansion,
|
||||
then we need to resume scanning the original text.
|
||||
Otherwise, we were already scanning the original text, and
|
||||
we're really done. */
|
||||
if (scanning_macro_expansion ())
|
||||
{
|
||||
finished_macro_expansion ();
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
|
|
@ -1260,6 +1384,15 @@ yylex ()
|
|||
c = parse_escape (&lexptr);
|
||||
else if (c == '\'')
|
||||
error ("Empty character constant.");
|
||||
else if (! host_char_to_target (c, &c))
|
||||
{
|
||||
int toklen = lexptr - tokstart + 1;
|
||||
char *tok = alloca (toklen + 1);
|
||||
memcpy (tok, tokstart, toklen);
|
||||
tok[toklen] = '\0';
|
||||
error ("There is no character corresponding to %s in the target "
|
||||
"character set `%s'.", tok, target_charset ());
|
||||
}
|
||||
|
||||
yylval.typed_val_int.val = c;
|
||||
yylval.typed_val_int.type = builtin_type_char;
|
||||
|
|
@ -1295,7 +1428,9 @@ yylex ()
|
|||
return c;
|
||||
|
||||
case ',':
|
||||
if (comma_terminates && paren_depth == 0)
|
||||
if (comma_terminates
|
||||
&& paren_depth == 0
|
||||
&& ! scanning_macro_expansion ())
|
||||
return 0;
|
||||
lexptr++;
|
||||
return c;
|
||||
|
|
@ -1319,7 +1454,7 @@ yylex ()
|
|||
{
|
||||
/* It's a number. */
|
||||
int got_dot = 0, got_e = 0, toktype;
|
||||
register char *p = tokstart;
|
||||
char *p = tokstart;
|
||||
int hex = input_radix > 10;
|
||||
|
||||
if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
|
||||
|
|
@ -1408,6 +1543,8 @@ yylex ()
|
|||
tempbufindex = 0;
|
||||
|
||||
do {
|
||||
char *char_start_pos = tokptr;
|
||||
|
||||
/* Grow the static temp buffer if necessary, including allocating
|
||||
the first one on demand. */
|
||||
if (tempbufindex + 1 >= tempbufsize)
|
||||
|
|
@ -1430,7 +1567,19 @@ yylex ()
|
|||
tempbuf[tempbufindex++] = c;
|
||||
break;
|
||||
default:
|
||||
tempbuf[tempbufindex++] = *tokptr++;
|
||||
c = *tokptr++;
|
||||
if (! host_char_to_target (c, &c))
|
||||
{
|
||||
int len = tokptr - char_start_pos;
|
||||
char *copy = alloca (len + 1);
|
||||
memcpy (copy, char_start_pos, len);
|
||||
copy[len] = '\0';
|
||||
|
||||
error ("There is no character corresponding to `%s' "
|
||||
"in the target character set `%s'.",
|
||||
copy, target_charset ());
|
||||
}
|
||||
tempbuf[tempbufindex++] = c;
|
||||
break;
|
||||
}
|
||||
} while ((*tokptr != '"') && (*tokptr != '\0'));
|
||||
|
|
@ -1474,9 +1623,13 @@ yylex ()
|
|||
c = tokstart[++namelen];
|
||||
}
|
||||
|
||||
/* The token "if" terminates the expression and is NOT
|
||||
removed from the input stream. */
|
||||
if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
|
||||
/* The token "if" terminates the expression and is NOT removed from
|
||||
the input stream. It doesn't count if it appears in the
|
||||
expansion of a macro. */
|
||||
if (namelen == 2
|
||||
&& tokstart[0] == 'i'
|
||||
&& tokstart[1] == 'f'
|
||||
&& ! scanning_macro_expansion ())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1489,63 +1642,52 @@ yylex ()
|
|||
switch (namelen)
|
||||
{
|
||||
case 8:
|
||||
if (STREQN (tokstart, "unsigned", 8))
|
||||
if (strncmp (tokstart, "unsigned", 8) == 0)
|
||||
return UNSIGNED;
|
||||
if (current_language->la_language == language_cplus
|
||||
&& STREQN (tokstart, "template", 8))
|
||||
&& strncmp (tokstart, "template", 8) == 0)
|
||||
return TEMPLATE;
|
||||
if (STREQN (tokstart, "volatile", 8))
|
||||
if (strncmp (tokstart, "volatile", 8) == 0)
|
||||
return VOLATILE_KEYWORD;
|
||||
break;
|
||||
case 6:
|
||||
if (STREQN (tokstart, "struct", 6))
|
||||
if (strncmp (tokstart, "struct", 6) == 0)
|
||||
return STRUCT;
|
||||
if (STREQN (tokstart, "signed", 6))
|
||||
if (strncmp (tokstart, "signed", 6) == 0)
|
||||
return SIGNED_KEYWORD;
|
||||
if (STREQN (tokstart, "sizeof", 6))
|
||||
if (strncmp (tokstart, "sizeof", 6) == 0)
|
||||
return SIZEOF;
|
||||
if (STREQN (tokstart, "double", 6))
|
||||
if (strncmp (tokstart, "double", 6) == 0)
|
||||
return DOUBLE_KEYWORD;
|
||||
break;
|
||||
case 5:
|
||||
if (current_language->la_language == language_cplus)
|
||||
{
|
||||
if (STREQN (tokstart, "false", 5))
|
||||
if (strncmp (tokstart, "false", 5) == 0)
|
||||
return FALSEKEYWORD;
|
||||
if (STREQN (tokstart, "class", 5))
|
||||
if (strncmp (tokstart, "class", 5) == 0)
|
||||
return CLASS;
|
||||
}
|
||||
if (STREQN (tokstart, "union", 5))
|
||||
if (strncmp (tokstart, "union", 5) == 0)
|
||||
return UNION;
|
||||
if (STREQN (tokstart, "short", 5))
|
||||
if (strncmp (tokstart, "short", 5) == 0)
|
||||
return SHORT;
|
||||
if (STREQN (tokstart, "const", 5))
|
||||
if (strncmp (tokstart, "const", 5) == 0)
|
||||
return CONST_KEYWORD;
|
||||
break;
|
||||
case 4:
|
||||
if (STREQN (tokstart, "enum", 4))
|
||||
if (strncmp (tokstart, "enum", 4) == 0)
|
||||
return ENUM;
|
||||
if (STREQN (tokstart, "long", 4))
|
||||
if (strncmp (tokstart, "long", 4) == 0)
|
||||
return LONG;
|
||||
if (current_language->la_language == language_cplus)
|
||||
{
|
||||
if (STREQN (tokstart, "true", 4))
|
||||
if (strncmp (tokstart, "true", 4) == 0)
|
||||
return TRUEKEYWORD;
|
||||
|
||||
if (STREQN (tokstart, "this", 4))
|
||||
{
|
||||
static const char this_name[] =
|
||||
{ CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
|
||||
|
||||
if (lookup_symbol (this_name, expression_context_block,
|
||||
VAR_NAMESPACE, (int *) NULL,
|
||||
(struct symtab **) NULL))
|
||||
return THIS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (STREQN (tokstart, "int", 3))
|
||||
if (strncmp (tokstart, "int", 3) == 0)
|
||||
return INT_KEYWORD;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1565,7 +1707,13 @@ yylex ()
|
|||
string to get a reasonable class/namespace spec or a
|
||||
fully-qualified name. This is a kludge to get around the
|
||||
HP aCC compiler's generation of symbol names with embedded
|
||||
colons for namespace and nested classes. */
|
||||
colons for namespace and nested classes. */
|
||||
|
||||
/* NOTE: carlton/2003-09-24: I don't entirely understand the
|
||||
HP-specific code, either here or in linespec. Having said that,
|
||||
I suspect that we're actually moving towards their model: we want
|
||||
symbols whose names are fully qualified, which matches the
|
||||
description above. */
|
||||
if (unquoted_expr)
|
||||
{
|
||||
/* Only do it if not inside single quotes */
|
||||
|
|
@ -1591,7 +1739,7 @@ yylex ()
|
|||
int hextype;
|
||||
|
||||
sym = lookup_symbol (tmp, expression_context_block,
|
||||
VAR_NAMESPACE,
|
||||
VAR_DOMAIN,
|
||||
current_language->la_language == language_cplus
|
||||
? &is_a_field_of_this : (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
|
|
@ -1619,92 +1767,10 @@ yylex ()
|
|||
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||
{
|
||||
#if 1
|
||||
/* Despite the following flaw, we need to keep this code enabled.
|
||||
Because we can get called from check_stub_method, if we don't
|
||||
handle nested types then it screws many operations in any
|
||||
program which uses nested types. */
|
||||
/* In "A::x", if x is a member function of A and there happens
|
||||
to be a type (nested or not, since the stabs don't make that
|
||||
distinction) named x, then this code incorrectly thinks we
|
||||
are dealing with nested types rather than a member function. */
|
||||
|
||||
char *p;
|
||||
char *namestart;
|
||||
struct symbol *best_sym;
|
||||
|
||||
/* Look ahead to detect nested types. This probably should be
|
||||
done in the grammar, but trying seemed to introduce a lot
|
||||
of shift/reduce and reduce/reduce conflicts. It's possible
|
||||
that it could be done, though. Or perhaps a non-grammar, but
|
||||
less ad hoc, approach would work well. */
|
||||
|
||||
/* Since we do not currently have any way of distinguishing
|
||||
a nested type from a non-nested one (the stabs don't tell
|
||||
us whether a type is nested), we just ignore the
|
||||
containing type. */
|
||||
|
||||
p = lexptr;
|
||||
best_sym = sym;
|
||||
while (1)
|
||||
{
|
||||
/* Skip whitespace. */
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n')
|
||||
++p;
|
||||
if (*p == ':' && p[1] == ':')
|
||||
{
|
||||
/* Skip the `::'. */
|
||||
p += 2;
|
||||
/* Skip whitespace. */
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n')
|
||||
++p;
|
||||
namestart = p;
|
||||
while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
|
||||
|| (*p >= 'a' && *p <= 'z')
|
||||
|| (*p >= 'A' && *p <= 'Z'))
|
||||
++p;
|
||||
if (p != namestart)
|
||||
{
|
||||
struct symbol *cur_sym;
|
||||
/* As big as the whole rest of the expression, which is
|
||||
at least big enough. */
|
||||
char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
|
||||
char *tmp1;
|
||||
|
||||
tmp1 = ncopy;
|
||||
memcpy (tmp1, tmp, strlen (tmp));
|
||||
tmp1 += strlen (tmp);
|
||||
memcpy (tmp1, "::", 2);
|
||||
tmp1 += 2;
|
||||
memcpy (tmp1, namestart, p - namestart);
|
||||
tmp1[p - namestart] = '\0';
|
||||
cur_sym = lookup_symbol (ncopy, expression_context_block,
|
||||
VAR_NAMESPACE, (int *) NULL,
|
||||
(struct symtab **) NULL);
|
||||
if (cur_sym)
|
||||
{
|
||||
if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
|
||||
{
|
||||
best_sym = cur_sym;
|
||||
lexptr = p;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
yylval.tsym.type = SYMBOL_TYPE (best_sym);
|
||||
#else /* not 0 */
|
||||
/* NOTE: carlton/2003-09-25: There used to be code here to
|
||||
handle nested types. It didn't work very well. See the
|
||||
comment before qualified_type for more info. */
|
||||
yylval.tsym.type = SYMBOL_TYPE (sym);
|
||||
#endif /* not 0 */
|
||||
return TYPENAME;
|
||||
}
|
||||
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
|
||||
|
|
@ -1738,5 +1804,8 @@ void
|
|||
yyerror (msg)
|
||||
char *msg;
|
||||
{
|
||||
if (prev_lexptr)
|
||||
lexptr = prev_lexptr;
|
||||
|
||||
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* C language support routines for GDB, the GNU debugger.
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002
|
||||
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
|
@ -27,6 +27,12 @@
|
|||
#include "language.h"
|
||||
#include "c-lang.h"
|
||||
#include "valprint.h"
|
||||
#include "macroscope.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "charset.h"
|
||||
#include "gdb_string.h"
|
||||
#include "demangle.h"
|
||||
#include "cp-support.h"
|
||||
|
||||
extern void _initialize_c_language (void);
|
||||
static void c_emit_char (int c, struct ui_file * stream, int quoter);
|
||||
|
|
@ -36,54 +42,32 @@ static void c_emit_char (int c, struct ui_file * stream, int quoter);
|
|||
characters and strings is language specific. */
|
||||
|
||||
static void
|
||||
c_emit_char (register int c, struct ui_file *stream, int quoter)
|
||||
c_emit_char (int c, struct ui_file *stream, int quoter)
|
||||
{
|
||||
const char *escape;
|
||||
int host_char;
|
||||
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
if (PRINT_LITERAL_FORM (c))
|
||||
escape = c_target_char_has_backslash_escape (c);
|
||||
if (escape)
|
||||
{
|
||||
if (c == '\\' || c == quoter)
|
||||
{
|
||||
fputs_filtered ("\\", stream);
|
||||
}
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
if (quoter == '"' && strcmp (escape, "0") == 0)
|
||||
/* Print nulls embedded in double quoted strings as \000 to
|
||||
prevent ambiguity. */
|
||||
fprintf_filtered (stream, "\\000");
|
||||
else
|
||||
fprintf_filtered (stream, "\\%s", escape);
|
||||
}
|
||||
else if (target_char_to_host (c, &host_char)
|
||||
&& host_char_print_literally (host_char))
|
||||
{
|
||||
if (host_char == '\\' || host_char == quoter)
|
||||
fputs_filtered ("\\", stream);
|
||||
fprintf_filtered (stream, "%c", host_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
fputs_filtered ("\\n", stream);
|
||||
break;
|
||||
case '\b':
|
||||
fputs_filtered ("\\b", stream);
|
||||
break;
|
||||
case '\t':
|
||||
fputs_filtered ("\\t", stream);
|
||||
break;
|
||||
case '\f':
|
||||
fputs_filtered ("\\f", stream);
|
||||
break;
|
||||
case '\r':
|
||||
fputs_filtered ("\\r", stream);
|
||||
break;
|
||||
case '\013':
|
||||
fputs_filtered ("\\v", stream);
|
||||
break;
|
||||
case '\033':
|
||||
fputs_filtered ("\\e", stream);
|
||||
break;
|
||||
case '\007':
|
||||
fputs_filtered ("\\a", stream);
|
||||
break;
|
||||
case '\0':
|
||||
fputs_filtered ("\\0", stream);
|
||||
break;
|
||||
default:
|
||||
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -104,11 +88,10 @@ void
|
|||
c_printstr (struct ui_file *stream, char *string, unsigned int length,
|
||||
int width, int force_ellipses)
|
||||
{
|
||||
register unsigned int i;
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
extern int inspect_it;
|
||||
|
||||
/* If the string was not truncated due to `set print elements', and
|
||||
the last byte of it is a null, we don't print that, in traditional C
|
||||
|
|
@ -224,7 +207,7 @@ c_printstr (struct ui_file *stream, char *string, unsigned int length,
|
|||
struct type *
|
||||
c_create_fundamental_type (struct objfile *objfile, int typeid)
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
struct type *type = NULL;
|
||||
|
||||
switch (typeid)
|
||||
{
|
||||
|
|
@ -338,6 +321,30 @@ c_create_fundamental_type (struct objfile *objfile, int typeid)
|
|||
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "long double", objfile);
|
||||
break;
|
||||
case FT_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex float", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "float", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex double", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "double", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_COMPLEX:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "complex long double", objfile);
|
||||
TYPE_TARGET_TYPE (type)
|
||||
= init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "long double", objfile);
|
||||
break;
|
||||
case FT_TEMPLATE_ARG:
|
||||
type = init_type (TYPE_CODE_TEMPLATE_ARG,
|
||||
0,
|
||||
|
|
@ -347,7 +354,128 @@ c_create_fundamental_type (struct objfile *objfile, int typeid)
|
|||
return (type);
|
||||
}
|
||||
|
||||
/* Preprocessing and parsing C and C++ expressions. */
|
||||
|
||||
|
||||
/* When we find that lexptr (the global var defined in parse.c) is
|
||||
pointing at a macro invocation, we expand the invocation, and call
|
||||
scan_macro_expansion to save the old lexptr here and point lexptr
|
||||
into the expanded text. When we reach the end of that, we call
|
||||
end_macro_expansion to pop back to the value we saved here. The
|
||||
macro expansion code promises to return only fully-expanded text,
|
||||
so we don't need to "push" more than one level.
|
||||
|
||||
This is disgusting, of course. It would be cleaner to do all macro
|
||||
expansion beforehand, and then hand that to lexptr. But we don't
|
||||
really know where the expression ends. Remember, in a command like
|
||||
|
||||
(gdb) break *ADDRESS if CONDITION
|
||||
|
||||
we evaluate ADDRESS in the scope of the current frame, but we
|
||||
evaluate CONDITION in the scope of the breakpoint's location. So
|
||||
it's simply wrong to try to macro-expand the whole thing at once. */
|
||||
static char *macro_original_text;
|
||||
static char *macro_expanded_text;
|
||||
|
||||
|
||||
void
|
||||
scan_macro_expansion (char *expansion)
|
||||
{
|
||||
/* We'd better not be trying to push the stack twice. */
|
||||
gdb_assert (! macro_original_text);
|
||||
gdb_assert (! macro_expanded_text);
|
||||
|
||||
/* Save the old lexptr value, so we can return to it when we're done
|
||||
parsing the expanded text. */
|
||||
macro_original_text = lexptr;
|
||||
lexptr = expansion;
|
||||
|
||||
/* Save the expanded text, so we can free it when we're finished. */
|
||||
macro_expanded_text = expansion;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
scanning_macro_expansion (void)
|
||||
{
|
||||
return macro_original_text != 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
finished_macro_expansion (void)
|
||||
{
|
||||
/* There'd better be something to pop back to, and we better have
|
||||
saved a pointer to the start of the expanded text. */
|
||||
gdb_assert (macro_original_text);
|
||||
gdb_assert (macro_expanded_text);
|
||||
|
||||
/* Pop back to the original text. */
|
||||
lexptr = macro_original_text;
|
||||
macro_original_text = 0;
|
||||
|
||||
/* Free the expanded text. */
|
||||
xfree (macro_expanded_text);
|
||||
macro_expanded_text = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scan_macro_cleanup (void *dummy)
|
||||
{
|
||||
if (macro_original_text)
|
||||
finished_macro_expansion ();
|
||||
}
|
||||
|
||||
|
||||
/* We set these global variables before calling c_parse, to tell it
|
||||
how it to find macro definitions for the expression at hand. */
|
||||
macro_lookup_ftype *expression_macro_lookup_func;
|
||||
void *expression_macro_lookup_baton;
|
||||
|
||||
|
||||
static struct macro_definition *
|
||||
null_macro_lookup (const char *name, void *baton)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
c_preprocess_and_parse (void)
|
||||
{
|
||||
/* Set up a lookup function for the macro expander. */
|
||||
struct macro_scope *scope = 0;
|
||||
struct cleanup *back_to = make_cleanup (free_current_contents, &scope);
|
||||
|
||||
if (expression_context_block)
|
||||
scope = sal_macro_scope (find_pc_line (expression_context_pc, 0));
|
||||
else
|
||||
scope = default_macro_scope ();
|
||||
|
||||
if (scope)
|
||||
{
|
||||
expression_macro_lookup_func = standard_macro_lookup;
|
||||
expression_macro_lookup_baton = (void *) scope;
|
||||
}
|
||||
else
|
||||
{
|
||||
expression_macro_lookup_func = null_macro_lookup;
|
||||
expression_macro_lookup_baton = 0;
|
||||
}
|
||||
|
||||
gdb_assert (! macro_original_text);
|
||||
make_cleanup (scan_macro_cleanup, 0);
|
||||
|
||||
{
|
||||
int result = c_parse ();
|
||||
do_cleanups (back_to);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
|
|
@ -415,9 +543,9 @@ const struct language_defn c_language_defn =
|
|||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_parse,
|
||||
&exp_descriptor_standard,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
|
|
@ -425,6 +553,11 @@ const struct language_defn c_language_defn =
|
|||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
|
|
@ -433,6 +566,7 @@ const struct language_defn c_language_defn =
|
|||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
default_word_break_characters,
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
|
|
@ -467,9 +601,9 @@ const struct language_defn cplus_language_defn =
|
|||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_parse,
|
||||
&exp_descriptor_standard,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
|
|
@ -477,6 +611,11 @@ const struct language_defn cplus_language_defn =
|
|||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
value_of_this, /* value_of_this */
|
||||
cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
cp_lookup_transparent_type, /* lookup_transparent_type */
|
||||
cplus_demangle, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
|
|
@ -485,6 +624,7 @@ const struct language_defn cplus_language_defn =
|
|||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
default_word_break_characters,
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
|
|
@ -496,9 +636,9 @@ const struct language_defn asm_language_defn =
|
|||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
c_parse,
|
||||
&exp_descriptor_standard,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
evaluate_subexp_standard,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
|
|
@ -506,6 +646,11 @@ const struct language_defn asm_language_defn =
|
|||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
|
|
@ -514,6 +659,47 @@ const struct language_defn asm_language_defn =
|
|||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
default_word_break_characters,
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
/* The following language_defn does not represent a real language.
|
||||
It just provides a minimal support a-la-C that should allow users
|
||||
to do some simple operations when debugging applications that use
|
||||
a language currently not supported by GDB. */
|
||||
|
||||
const struct language_defn minimal_language_defn =
|
||||
{
|
||||
"minimal", /* Language name */
|
||||
language_minimal,
|
||||
c_builtin_types,
|
||||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
&exp_descriptor_standard,
|
||||
c_preprocess_and_parse,
|
||||
c_error,
|
||||
c_printchar, /* Print a character constant */
|
||||
c_printstr, /* Function to print string constant */
|
||||
c_emit_char, /* Print a single char */
|
||||
c_create_fundamental_type, /* Create fundamental type in this language */
|
||||
c_print_type, /* Print a type using appropriate syntax */
|
||||
c_val_print, /* Print a value using appropriate syntax */
|
||||
c_value_print, /* Print a top-level value */
|
||||
NULL, /* Language specific skip_trampoline */
|
||||
NULL, /* value_of_this */
|
||||
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
|
||||
basic_lookup_transparent_type,/* lookup_transparent_type */
|
||||
NULL, /* Language specific symbol demangler */
|
||||
{"", "", "", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
{"0x%lx", "0x", "x", ""}, /* Hex format info */
|
||||
c_op_print_tab, /* expression operators for printing */
|
||||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
default_word_break_characters,
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
|
|
@ -523,4 +709,5 @@ _initialize_c_language (void)
|
|||
add_language (&c_language_defn);
|
||||
add_language (&cplus_language_defn);
|
||||
add_language (&asm_language_defn);
|
||||
add_language (&minimal_language_defn);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@
|
|||
#if !defined (C_LANG_H)
|
||||
#define C_LANG_H 1
|
||||
|
||||
struct ui_file;
|
||||
|
||||
#include "value.h"
|
||||
#include "macroexp.h"
|
||||
|
||||
|
||||
extern int c_parse (void); /* Defined in c-exp.y */
|
||||
|
|
@ -49,6 +52,13 @@ extern void c_printstr (struct ui_file * stream, char *string,
|
|||
unsigned int length, int width,
|
||||
int force_ellipses);
|
||||
|
||||
extern void scan_macro_expansion (char *expansion);
|
||||
extern int scanning_macro_expansion (void);
|
||||
extern void finished_macro_expansion (void);
|
||||
|
||||
extern macro_lookup_ftype *expression_macro_lookup_func;
|
||||
extern void *expression_macro_lookup_baton;
|
||||
|
||||
extern struct type *c_create_fundamental_type (struct objfile *, int);
|
||||
|
||||
extern struct type **const (c_builtin_types[]);
|
||||
|
|
@ -57,9 +67,6 @@ extern struct type **const (c_builtin_types[]);
|
|||
|
||||
extern void c_type_print_base (struct type *, struct ui_file *, int, int);
|
||||
|
||||
extern void c_type_print_varspec_prefix (struct type *, struct ui_file *,
|
||||
int, int);
|
||||
|
||||
/* These are in cp-valprint.c */
|
||||
|
||||
extern int vtblprint; /* Controls printing of vtbl's */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* Support for printing C and C++ types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998,
|
||||
1999, 2000, 2001, 2002
|
||||
1999, 2000, 2001, 2002, 2003
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "obstack.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "bfd.h" /* Binary File Description */
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
/* Flag indicating target was compiled by HP compiler */
|
||||
extern int hp_som_som_object_present;
|
||||
|
||||
static void cp_type_print_method_args (struct type ** args, char *prefix,
|
||||
static void cp_type_print_method_args (struct type *mtype, char *prefix,
|
||||
char *varstring, int staticp,
|
||||
struct ui_file *stream);
|
||||
|
||||
|
|
@ -49,8 +49,8 @@ static void c_type_print_args (struct type *, struct ui_file *);
|
|||
|
||||
static void cp_type_print_derivation_info (struct ui_file *, struct type *);
|
||||
|
||||
void c_type_print_varspec_prefix (struct type *, struct ui_file *, int,
|
||||
int);
|
||||
static void c_type_print_varspec_prefix (struct type *, struct ui_file *, int,
|
||||
int, int);
|
||||
|
||||
/* Print "const", "volatile", or address space modifiers. */
|
||||
static void c_type_print_modifier (struct type *, struct ui_file *,
|
||||
|
|
@ -65,8 +65,9 @@ void
|
|||
c_print_type (struct type *type, char *varstring, struct ui_file *stream,
|
||||
int show, int level)
|
||||
{
|
||||
register enum type_code code;
|
||||
enum type_code code;
|
||||
int demangled_args;
|
||||
int need_post_space;
|
||||
|
||||
if (show > 0)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
|
@ -85,7 +86,8 @@ c_print_type (struct type *type, char *varstring, struct ui_file *stream,
|
|||
|| code == TYPE_CODE_MEMBER
|
||||
|| code == TYPE_CODE_REF)))
|
||||
fputs_filtered (" ", stream);
|
||||
c_type_print_varspec_prefix (type, stream, show, 0);
|
||||
need_post_space = (varstring != NULL && strcmp (varstring, "") != 0);
|
||||
c_type_print_varspec_prefix (type, stream, show, 0, need_post_space);
|
||||
|
||||
if (varstring != NULL)
|
||||
{
|
||||
|
|
@ -147,40 +149,40 @@ cp_type_print_derivation_info (struct ui_file *stream, struct type *type)
|
|||
fputs_filtered (" ", stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the C++ method arguments ARGS to the file STREAM. */
|
||||
|
||||
static void
|
||||
cp_type_print_method_args (struct type **args, char *prefix, char *varstring,
|
||||
cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring,
|
||||
int staticp, struct ui_file *stream)
|
||||
{
|
||||
struct field *args = TYPE_FIELDS (mtype);
|
||||
int nargs = TYPE_NFIELDS (mtype);
|
||||
int varargs = TYPE_VARARGS (mtype);
|
||||
int i;
|
||||
|
||||
fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI);
|
||||
fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI);
|
||||
fputs_filtered ("(", stream);
|
||||
if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
|
||||
|
||||
/* Skip the class variable. */
|
||||
i = staticp ? 0 : 1;
|
||||
if (nargs > i)
|
||||
{
|
||||
i = !staticp; /* skip the class variable */
|
||||
while (1)
|
||||
while (i < nargs)
|
||||
{
|
||||
type_print (args[i++], "", stream, 0);
|
||||
if (!args[i])
|
||||
{
|
||||
fprintf_filtered (stream, " ...");
|
||||
break;
|
||||
}
|
||||
else if (args[i]->code != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
else
|
||||
break;
|
||||
type_print (args[i++].type, "", stream, 0);
|
||||
|
||||
if (i == nargs && varargs)
|
||||
fprintf_filtered (stream, ", ...");
|
||||
else if (i < nargs)
|
||||
fprintf_filtered (stream, ", ");
|
||||
}
|
||||
}
|
||||
else if (varargs)
|
||||
fprintf_filtered (stream, "...");
|
||||
else if (current_language->la_language == language_cplus)
|
||||
{
|
||||
fprintf_filtered (stream, "void");
|
||||
}
|
||||
fprintf_filtered (stream, "void");
|
||||
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
|
|
@ -192,11 +194,15 @@ cp_type_print_method_args (struct type **args, char *prefix, char *varstring,
|
|||
On outermost call, pass 0 for PASSED_A_PTR.
|
||||
On outermost call, SHOW > 0 means should ignore
|
||||
any typename for TYPE and show its details.
|
||||
SHOW is always zero on recursive calls. */
|
||||
SHOW is always zero on recursive calls.
|
||||
|
||||
NEED_POST_SPACE is non-zero when a space will be be needed
|
||||
between a trailing qualifier and a field, variable, or function
|
||||
name. */
|
||||
|
||||
void
|
||||
c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
|
||||
int show, int passed_a_ptr)
|
||||
int show, int passed_a_ptr, int need_post_space)
|
||||
{
|
||||
char *name;
|
||||
if (type == 0)
|
||||
|
|
@ -210,15 +216,15 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
|
|||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_PTR:
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 1);
|
||||
fprintf_filtered (stream, "*");
|
||||
c_type_print_modifier (type, stream, 1, 0);
|
||||
c_type_print_modifier (type, stream, 1, need_post_space);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
|
||||
fprintf_filtered (stream, " ");
|
||||
name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
|
||||
if (name)
|
||||
|
|
@ -231,7 +237,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
|
|||
case TYPE_CODE_METHOD:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
{
|
||||
fprintf_filtered (stream, " ");
|
||||
|
|
@ -241,23 +247,27 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
|
|||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 0);
|
||||
fprintf_filtered (stream, "&");
|
||||
c_type_print_modifier (type, stream, 1, 0);
|
||||
c_type_print_modifier (type, stream, 1, need_post_space);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_UNDEF:
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
|
|
@ -273,8 +283,8 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream,
|
|||
case TYPE_CODE_STRING:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
case TYPE_CODE_TEMPLATE:
|
||||
case TYPE_CODE_NAMESPACE:
|
||||
/* These types need no prefix. They are listed here so that
|
||||
gcc -Wall will reveal any types that haven't been handled. */
|
||||
break;
|
||||
|
|
@ -294,7 +304,7 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
|
|||
int need_pre_space, int need_post_space)
|
||||
{
|
||||
int did_print_modifier = 0;
|
||||
char *address_space_id;
|
||||
const char *address_space_id;
|
||||
|
||||
/* We don't print `const' qualifiers for references --- since all
|
||||
operators affect the thing referenced, not the reference itself,
|
||||
|
|
@ -316,7 +326,7 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
|
|||
did_print_modifier = 1;
|
||||
}
|
||||
|
||||
address_space_id = address_space_int_to_name (TYPE_FLAGS (type));
|
||||
address_space_id = address_space_int_to_name (TYPE_INSTANCE_FLAGS (type));
|
||||
if (address_space_id)
|
||||
{
|
||||
if (did_print_modifier || need_pre_space)
|
||||
|
|
@ -336,39 +346,31 @@ static void
|
|||
c_type_print_args (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
int i;
|
||||
struct type **args;
|
||||
struct field *args;
|
||||
|
||||
fprintf_filtered (stream, "(");
|
||||
args = TYPE_ARG_TYPES (type);
|
||||
args = TYPE_FIELDS (type);
|
||||
if (args != NULL)
|
||||
{
|
||||
if (args[1] == NULL)
|
||||
int i;
|
||||
|
||||
/* FIXME drow/2002-05-31: Always skips the first argument,
|
||||
should we be checking for static members? */
|
||||
|
||||
for (i = 1; i < TYPE_NFIELDS (type); i++)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
else if ((args[1]->code == TYPE_CODE_VOID) &&
|
||||
(current_language->la_language == language_cplus))
|
||||
{
|
||||
fprintf_filtered (stream, "void");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1;
|
||||
args[i] != NULL && args[i]->code != TYPE_CODE_VOID;
|
||||
i++)
|
||||
c_print_type (args[i].type, "", stream, -1, 0);
|
||||
if (i != TYPE_NFIELDS (type))
|
||||
{
|
||||
c_print_type (args[i], "", stream, -1, 0);
|
||||
if (args[i + 1] == NULL)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
else if (args[i + 1]->code != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, ",");
|
||||
wrap_here (" ");
|
||||
}
|
||||
fprintf_filtered (stream, ",");
|
||||
wrap_here (" ");
|
||||
}
|
||||
}
|
||||
if (TYPE_VARARGS (type))
|
||||
fprintf_filtered (stream, "...");
|
||||
else if (i == 1
|
||||
&& (current_language->la_language == language_cplus))
|
||||
fprintf_filtered (stream, "void");
|
||||
}
|
||||
else if (current_language->la_language == language_cplus)
|
||||
{
|
||||
|
|
@ -545,19 +547,22 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
|
|||
/ TYPE_LENGTH (TYPE_TARGET_TYPE (type))));
|
||||
fprintf_filtered (stream, "]");
|
||||
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_METHOD:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
0, 0);
|
||||
if (passed_a_ptr)
|
||||
{
|
||||
c_type_print_args (type, stream);
|
||||
|
|
@ -566,7 +571,8 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
|
|||
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_REF:
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
1, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
|
|
@ -594,7 +600,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
|
|||
}
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
passed_a_ptr, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
|
||||
passed_a_ptr, 0);
|
||||
break;
|
||||
|
||||
|
|
@ -613,8 +624,8 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
|
|||
case TYPE_CODE_STRING:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
case TYPE_CODE_TEMPLATE:
|
||||
case TYPE_CODE_NAMESPACE:
|
||||
/* These types do not need a suffix. They are listed so that
|
||||
gcc -Wall will report types that may not have been considered. */
|
||||
break;
|
||||
|
|
@ -848,10 +859,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
|
|||
QUIT;
|
||||
/* Don't print out virtual function table. */
|
||||
/* HP ANSI C++ case */
|
||||
if (TYPE_HAS_VTABLE (type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5)))
|
||||
if (TYPE_HAS_VTABLE (type)
|
||||
&& (strncmp (TYPE_FIELD_NAME (type, i), "__vfp", 5) == 0))
|
||||
continue;
|
||||
/* Other compilers */
|
||||
if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
|
||||
if (strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5) == 0
|
||||
&& is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
|
||||
continue;
|
||||
|
||||
|
|
@ -933,7 +945,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
|
|||
int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
|
||||
char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
|
||||
char *name = type_name_no_tag (type);
|
||||
int is_constructor = name && STREQ (method_name, name);
|
||||
int is_constructor = name && strcmp (method_name, name) == 0;
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
|
||||
|
|
@ -1010,10 +1022,15 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
|
|||
Let's try to reconstruct the function signature from
|
||||
the symbol information */
|
||||
if (!TYPE_FN_FIELD_STUB (f, j))
|
||||
cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
|
||||
method_name,
|
||||
TYPE_FN_FIELD_STATIC_P (f, j),
|
||||
stream);
|
||||
{
|
||||
int staticp = TYPE_FN_FIELD_STATIC_P (f, j);
|
||||
struct type *mtype = TYPE_FN_FIELD_TYPE (f, j);
|
||||
cp_type_print_method_args (mtype,
|
||||
"",
|
||||
method_name,
|
||||
staticp,
|
||||
stream);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "<badly mangled name '%s'>",
|
||||
mangled_name);
|
||||
|
|
@ -1168,6 +1185,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show,
|
|||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_NAMESPACE:
|
||||
fputs_filtered ("namespace ", stream);
|
||||
fputs_filtered (TYPE_TAG_NAME (type), stream);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Handle types not explicitly handled by the other cases,
|
||||
such as fundamental types. For these, just print whatever
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* Support for printing C values for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
||||
1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
|
||||
1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_string.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
|
|
@ -29,6 +30,7 @@
|
|||
#include "language.h"
|
||||
#include "c-lang.h"
|
||||
#include "cp-abi.h"
|
||||
#include "target.h"
|
||||
|
||||
|
||||
/* Print function pointer with inferior address ADDRESS onto stdio
|
||||
|
|
@ -37,7 +39,9 @@
|
|||
static void
|
||||
print_function_pointer_address (CORE_ADDR address, struct ui_file *stream)
|
||||
{
|
||||
CORE_ADDR func_addr = CONVERT_FROM_FUNC_PTR_ADDR (address);
|
||||
CORE_ADDR func_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
|
||||
address,
|
||||
¤t_target);
|
||||
|
||||
/* If the function pointer is represented by a description, print the
|
||||
address of the description. */
|
||||
|
|
@ -69,7 +73,7 @@ c_val_print (struct type *type, char *valaddr, int embedded_offset,
|
|||
CORE_ADDR address, struct ui_file *stream, int format,
|
||||
int deref_ref, int recurse, enum val_prettyprint pretty)
|
||||
{
|
||||
register unsigned int i = 0; /* Number of characters printed */
|
||||
unsigned int i = 0; /* Number of characters printed */
|
||||
unsigned len;
|
||||
struct type *elttype;
|
||||
unsigned eltlen;
|
||||
|
|
@ -204,7 +208,7 @@ c_val_print (struct type *type, char *valaddr, int embedded_offset,
|
|||
(vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
|
||||
{
|
||||
fputs_filtered (" <", stream);
|
||||
fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream);
|
||||
fputs_filtered (SYMBOL_PRINT_NAME (msymbol), stream);
|
||||
fputs_filtered (">", stream);
|
||||
}
|
||||
if (vt_address && vtblprint)
|
||||
|
|
@ -212,13 +216,12 @@ c_val_print (struct type *type, char *valaddr, int embedded_offset,
|
|||
struct value *vt_val;
|
||||
struct symbol *wsym = (struct symbol *) NULL;
|
||||
struct type *wtype;
|
||||
struct symtab *s;
|
||||
struct block *block = (struct block *) NULL;
|
||||
int is_this_fld;
|
||||
|
||||
if (msymbol != NULL)
|
||||
wsym = lookup_symbol (SYMBOL_NAME (msymbol), block,
|
||||
VAR_NAMESPACE, &is_this_fld, &s);
|
||||
wsym = lookup_symbol (DEPRECATED_SYMBOL_NAME (msymbol), block,
|
||||
VAR_DOMAIN, &is_this_fld, NULL);
|
||||
|
||||
if (wsym)
|
||||
{
|
||||
|
|
@ -514,7 +517,7 @@ c_value_print (struct value *val, struct ui_file *stream, int format,
|
|||
if (TYPE_CODE (type) == TYPE_CODE_PTR &&
|
||||
TYPE_NAME (type) == NULL &&
|
||||
TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
|
||||
STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char"))
|
||||
strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0)
|
||||
{
|
||||
/* Print nothing */
|
||||
}
|
||||
|
|
@ -592,7 +595,8 @@ c_value_print (struct value *val, struct ui_file *stream, int format,
|
|||
/* Otherwise, we end up at the return outside this "if" */
|
||||
}
|
||||
|
||||
return val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val),
|
||||
VALUE_ADDRESS (val),
|
||||
return val_print (type, VALUE_CONTENTS_ALL (val),
|
||||
VALUE_EMBEDDED_OFFSET (val),
|
||||
VALUE_ADDRESS (val) + VALUE_OFFSET (val),
|
||||
stream, format, 1, 0, pretty);
|
||||
}
|
||||
|
|
|
|||
1277
contrib/gdb/gdb/charset.c
Normal file
1277
contrib/gdb/gdb/charset.c
Normal file
File diff suppressed because it is too large
Load diff
109
contrib/gdb/gdb/charset.h
Normal file
109
contrib/gdb/gdb/charset.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* Character set conversion support for GDB.
|
||||
Copyright 2001 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 CHARSET_H
|
||||
#define CHARSET_H
|
||||
|
||||
|
||||
/* If the target program uses a different character set than the host,
|
||||
GDB has some support for translating between the two; GDB converts
|
||||
characters and strings to the host character set before displaying
|
||||
them, and converts characters and strings appearing in expressions
|
||||
entered by the user to the target character set.
|
||||
|
||||
At the moment, GDB only supports single-byte, stateless character
|
||||
sets. This includes the ISO-8859 family (ASCII extended with
|
||||
accented characters, and (I think) Cyrillic, for European
|
||||
languages), and the EBCDIC family (used on IBM's mainframes).
|
||||
Unfortunately, it excludes many Asian scripts, the fixed- and
|
||||
variable-width Unicode encodings, and other desireable things.
|
||||
Patches are welcome! (For example, it would be nice if the Java
|
||||
string support could simply get absorbed into some more general
|
||||
multi-byte encoding support.)
|
||||
|
||||
Furthermore, GDB's code pretty much assumes that the host character
|
||||
set is some superset of ASCII; there are plenty if ('0' + n)
|
||||
expressions and the like.
|
||||
|
||||
When the `iconv' library routine supports a character set meeting
|
||||
the requirements above, it's easy to plug an entry into GDB's table
|
||||
that uses iconv to handle the details. */
|
||||
|
||||
/* Return the name of the current host/target character set. The
|
||||
result is owned by the charset module; the caller should not free
|
||||
it. */
|
||||
const char *host_charset (void);
|
||||
const char *target_charset (void);
|
||||
|
||||
/* In general, the set of C backslash escapes (\n, \f) is specific to
|
||||
the character set. Not all character sets will have form feed
|
||||
characters, for example.
|
||||
|
||||
The following functions allow GDB to parse and print control
|
||||
characters in a character-set-independent way. They are both
|
||||
language-specific (to C and C++) and character-set-specific.
|
||||
Putting them here is a compromise. */
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR have a backslash escape in the
|
||||
C language (i.e., a character like 'n' or 't'), return the host
|
||||
character string that should follow the backslash. Otherwise,
|
||||
return zero.
|
||||
|
||||
When this function returns non-zero, the string it returns is
|
||||
statically allocated; the caller is not responsible for freeing it. */
|
||||
const char *c_target_char_has_backslash_escape (int target_char);
|
||||
|
||||
|
||||
/* If the host character HOST_CHAR is a valid backslash escape in the
|
||||
C language for the target character set, return non-zero, and set
|
||||
*TARGET_CHAR to the target character the backslash escape represents.
|
||||
Otherwise, return zero. */
|
||||
int c_parse_backslash (int host_char, int *target_char);
|
||||
|
||||
|
||||
/* Return non-zero if the host character HOST_CHAR can be printed
|
||||
literally --- that is, if it can be readably printed as itself in a
|
||||
character or string constant. Return zero if it should be printed
|
||||
using some kind of numeric escape, like '\031' in C, '^(25)' in
|
||||
Chill, or #25 in Pascal. */
|
||||
int host_char_print_literally (int host_char);
|
||||
|
||||
|
||||
/* If the host character HOST_CHAR has an equivalent in the target
|
||||
character set, set *TARGET_CHAR to that equivalent, and return
|
||||
non-zero. Otherwise, return zero. */
|
||||
int host_char_to_target (int host_char, int *target_char);
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR has an equivalent in the host
|
||||
character set, set *HOST_CHAR to that equivalent, and return
|
||||
non-zero. Otherwise, return zero. */
|
||||
int target_char_to_host (int target_char, int *host_char);
|
||||
|
||||
|
||||
/* If the target character TARGET_CHAR has a corresponding control
|
||||
character (also in the target character set), set *TARGET_CTRL_CHAR
|
||||
to the control character, and return non-zero. Otherwise, return
|
||||
zero. */
|
||||
int target_char_to_control_char (int target_char, int *target_ctrl_char);
|
||||
|
||||
|
||||
#endif /* CHARSET_H */
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
/* Output generating routines for GDB CLI.
|
||||
Copyright 1999, 2000 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Cygnus Solutions.
|
||||
Written by Fernando Nasser for Cygnus.
|
||||
|
||||
|
|
@ -26,17 +28,13 @@
|
|||
#include "gdb_string.h"
|
||||
#include "gdb_assert.h"
|
||||
|
||||
/* Convenience macro for allocting typesafe memory. */
|
||||
|
||||
#ifndef XMALLOC
|
||||
#define XMALLOC(TYPE) (TYPE*) xmalloc (sizeof (TYPE))
|
||||
#endif
|
||||
|
||||
struct ui_out_data
|
||||
{
|
||||
struct ui_file *stream;
|
||||
struct ui_file *original_stream;
|
||||
int suppress_output;
|
||||
};
|
||||
typedef struct ui_out_data cli_out_data;
|
||||
|
||||
/* These are the CLI output functions */
|
||||
|
||||
|
|
@ -67,6 +65,7 @@ static void cli_message (struct ui_out *uiout, int verbosity,
|
|||
const char *format, va_list args);
|
||||
static void cli_wrap_hint (struct ui_out *uiout, char *identstring);
|
||||
static void cli_flush (struct ui_out *uiout);
|
||||
static int cli_redirect (struct ui_out *uiout, struct ui_file *outstream);
|
||||
|
||||
/* This is the CLI ui-out implementation functions vector */
|
||||
|
||||
|
|
@ -90,6 +89,7 @@ static struct ui_out_impl cli_ui_out_impl =
|
|||
cli_message,
|
||||
cli_wrap_hint,
|
||||
cli_flush,
|
||||
cli_redirect,
|
||||
0, /* Does not need MI hacks (i.e. needs CLI hacks). */
|
||||
};
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ cli_table_begin (struct ui_out *uiout, int nbrofcols,
|
|||
int nr_rows,
|
||||
const char *tblid)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (nr_rows == 0)
|
||||
data->suppress_output = 1;
|
||||
else
|
||||
/* Only the table suppresses the output and, fortunatly, a table
|
||||
/* Only the table suppresses the output and, fortunately, a table
|
||||
is not a recursive data structure. */
|
||||
gdb_assert (data->suppress_output == 0);
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ cli_table_begin (struct ui_out *uiout, int nbrofcols,
|
|||
void
|
||||
cli_table_body (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
/* first, close the table header line */
|
||||
|
|
@ -140,7 +140,7 @@ cli_table_body (struct ui_out *uiout)
|
|||
void
|
||||
cli_table_end (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
data->suppress_output = 0;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ cli_table_header (struct ui_out *uiout, int width, enum ui_align alignment,
|
|||
const char *col_name,
|
||||
const char *colhdr)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
cli_field_string (uiout, 0, width, alignment, 0, colhdr);
|
||||
|
|
@ -165,7 +165,7 @@ cli_begin (struct ui_out *uiout,
|
|||
int level,
|
||||
const char *id)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ cli_end (struct ui_out *uiout,
|
|||
enum ui_out_type type,
|
||||
int level)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ cli_field_int (struct ui_out *uiout, int fldno, int width,
|
|||
{
|
||||
char buffer[20]; /* FIXME: how many chars long a %d can become? */
|
||||
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
sprintf (buffer, "%d", value);
|
||||
|
|
@ -205,7 +205,7 @@ cli_field_skip (struct ui_out *uiout, int fldno, int width,
|
|||
enum ui_align alignment,
|
||||
const char *fldname)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
cli_field_string (uiout, fldno, width, alignment, fldname, "");
|
||||
|
|
@ -225,7 +225,7 @@ cli_field_string (struct ui_out *uiout,
|
|||
int before = 0;
|
||||
int after = 0;
|
||||
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ cli_field_fmt (struct ui_out *uiout, int fldno,
|
|||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
|
||||
|
|
@ -285,7 +285,7 @@ cli_field_fmt (struct ui_out *uiout, int fldno,
|
|||
void
|
||||
cli_spaces (struct ui_out *uiout, int numspaces)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
print_spaces_filtered (numspaces, data->stream);
|
||||
|
|
@ -294,7 +294,7 @@ cli_spaces (struct ui_out *uiout, int numspaces)
|
|||
void
|
||||
cli_text (struct ui_out *uiout, const char *string)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
fputs_filtered (string, data->stream);
|
||||
|
|
@ -304,7 +304,7 @@ void
|
|||
cli_message (struct ui_out *uiout, int verbosity,
|
||||
const char *format, va_list args)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
if (ui_out_get_verblvl (uiout) >= verbosity)
|
||||
|
|
@ -314,7 +314,7 @@ cli_message (struct ui_out *uiout, int verbosity,
|
|||
void
|
||||
cli_wrap_hint (struct ui_out *uiout, char *identstring)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
if (data->suppress_output)
|
||||
return;
|
||||
wrap_here (identstring);
|
||||
|
|
@ -323,10 +323,28 @@ cli_wrap_hint (struct ui_out *uiout, char *identstring)
|
|||
void
|
||||
cli_flush (struct ui_out *uiout)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
gdb_flush (data->stream);
|
||||
}
|
||||
|
||||
int
|
||||
cli_redirect (struct ui_out *uiout, struct ui_file *outstream)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
if (outstream != NULL)
|
||||
{
|
||||
data->original_stream = data->stream;
|
||||
data->stream = outstream;
|
||||
}
|
||||
else if (data->original_stream != NULL)
|
||||
{
|
||||
data->stream = data->original_stream;
|
||||
data->original_stream = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
|
||||
/* Like cli_field_fmt, but takes a variable number of args
|
||||
|
|
@ -338,7 +356,7 @@ out_field_fmt (struct ui_out *uiout, int fldno,
|
|||
const char *fldname,
|
||||
const char *format,...)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
|
|
@ -352,7 +370,7 @@ out_field_fmt (struct ui_out *uiout, int fldno,
|
|||
static void
|
||||
field_separator (void)
|
||||
{
|
||||
struct ui_out_data *data = ui_out_data (uiout);
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
fputc_filtered (' ', data->stream);
|
||||
}
|
||||
|
||||
|
|
@ -363,12 +381,22 @@ cli_out_new (struct ui_file *stream)
|
|||
{
|
||||
int flags = ui_source_list;
|
||||
|
||||
struct ui_out_data *data = XMALLOC (struct ui_out_data);
|
||||
cli_out_data *data = XMALLOC (cli_out_data);
|
||||
data->stream = stream;
|
||||
data->original_stream = NULL;
|
||||
data->suppress_output = 0;
|
||||
return ui_out_new (&cli_ui_out_impl, data, flags);
|
||||
}
|
||||
|
||||
struct ui_file *
|
||||
cli_out_set_stream (struct ui_out *uiout, struct ui_file *stream)
|
||||
{
|
||||
cli_out_data *data = ui_out_data (uiout);
|
||||
struct ui_file *old = data->stream;
|
||||
data->stream = stream;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* standard gdb initialization hook */
|
||||
void
|
||||
_initialize_cli_out (void)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@
|
|||
#ifndef CLI_OUT_H
|
||||
#define CLI_OUT_H
|
||||
|
||||
struct ui_file;
|
||||
|
||||
extern struct ui_out *cli_out_new (struct ui_file *stream);
|
||||
|
||||
extern struct ui_file *cli_out_set_stream (struct ui_out *uiout,
|
||||
struct ui_file *stream);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* GDB CLI commands.
|
||||
|
||||
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -20,11 +20,23 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "readline/readline.h"
|
||||
#include "readline/tilde.h"
|
||||
#include "completer.h"
|
||||
#include "target.h" /* For baud_rate, remote_debug and remote_timeout */
|
||||
#include "gdb_wait.h" /* For shell escape implementation */
|
||||
#include "gdb_regex.h" /* Used by apropos_command */
|
||||
#include "gdb_string.h"
|
||||
#include "gdb_vfork.h"
|
||||
#include "linespec.h"
|
||||
#include "expression.h"
|
||||
#include "frame.h"
|
||||
#include "value.h"
|
||||
#include "language.h"
|
||||
#include "filenames.h" /* for DOSish file names */
|
||||
#include "objfiles.h"
|
||||
#include "source.h"
|
||||
#include "disasm.h"
|
||||
|
||||
#include "ui-out.h"
|
||||
|
||||
|
|
@ -34,23 +46,15 @@
|
|||
#include "cli/cli-setshow.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
|
||||
#ifdef TUI
|
||||
#include "tui/tui.h" /* For tui_active et.al. */
|
||||
#endif
|
||||
|
||||
#ifndef GDBINIT_FILENAME
|
||||
#define GDBINIT_FILENAME ".gdbinit"
|
||||
#endif
|
||||
|
||||
/* From gdb/top.c */
|
||||
|
||||
extern void dont_repeat (void);
|
||||
|
||||
extern void set_verbose (char *, int, struct cmd_list_element *);
|
||||
|
||||
extern void show_history (char *, int);
|
||||
|
||||
extern void set_history (char *, int);
|
||||
|
||||
extern void show_commands (char *, int);
|
||||
|
||||
/* Prototypes for local functions */
|
||||
/* Prototypes for local command functions */
|
||||
|
||||
static void complete_command (char *, int);
|
||||
|
||||
|
|
@ -60,8 +64,6 @@ static void pwd_command (char *, int);
|
|||
|
||||
static void show_version (char *, int);
|
||||
|
||||
static void validate_comname (char *);
|
||||
|
||||
static void help_command (char *, int);
|
||||
|
||||
static void show_command (char *, int);
|
||||
|
|
@ -78,8 +80,19 @@ static void make_command (char *, int);
|
|||
|
||||
static void shell_escape (char *, int);
|
||||
|
||||
static void edit_command (char *, int);
|
||||
|
||||
static void list_command (char *, int);
|
||||
|
||||
void apropos_command (char *, int);
|
||||
|
||||
/* Prototypes for local utility functions */
|
||||
|
||||
static void ambiguous_line_spec (struct symtabs_and_lines *);
|
||||
|
||||
/* Limit the call depth of user-defined commands */
|
||||
int max_user_call_depth;
|
||||
|
||||
/* Define all cmd_list_elements. */
|
||||
|
||||
/* Chain containing all defined commands. */
|
||||
|
|
@ -174,7 +187,6 @@ error_no_arg (char *why)
|
|||
/* The "info" command is defined as a prefix, with allow_unknown = 0.
|
||||
Therefore, its own definition is called only for "info" with no args. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
info_command (char *arg, int from_tty)
|
||||
{
|
||||
|
|
@ -184,7 +196,6 @@ info_command (char *arg, int from_tty)
|
|||
|
||||
/* The "show" command with no arguments shows all the settings. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_command (char *arg, int from_tty)
|
||||
{
|
||||
|
|
@ -194,7 +205,6 @@ show_command (char *arg, int from_tty)
|
|||
/* Provide documentation on command or list given by COMMAND. FROM_TTY
|
||||
is ignored. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
help_command (char *command, int from_tty)
|
||||
{
|
||||
|
|
@ -212,13 +222,12 @@ compare_strings (const void *arg1, const void *arg2)
|
|||
|
||||
/* The "complete" command is used by Emacs to implement completion. */
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
complete_command (char *arg, int from_tty)
|
||||
{
|
||||
int i;
|
||||
int argpoint;
|
||||
char **completions;
|
||||
char **completions, *point, *arg_prefix;
|
||||
|
||||
dont_repeat ();
|
||||
|
||||
|
|
@ -226,7 +235,23 @@ complete_command (char *arg, int from_tty)
|
|||
arg = "";
|
||||
argpoint = strlen (arg);
|
||||
|
||||
completions = complete_line (arg, arg, argpoint);
|
||||
/* complete_line assumes that its first argument is somewhere within,
|
||||
and except for filenames at the beginning of, the word to be completed.
|
||||
The following crude imitation of readline's word-breaking tries to
|
||||
accomodate this. */
|
||||
point = arg + argpoint;
|
||||
while (point > arg)
|
||||
{
|
||||
if (strchr (rl_completer_word_break_characters, point[-1]) != 0)
|
||||
break;
|
||||
point--;
|
||||
}
|
||||
|
||||
arg_prefix = alloca (point - arg + 1);
|
||||
memcpy (arg_prefix, arg, point - arg);
|
||||
arg_prefix[point - arg] = 0;
|
||||
|
||||
completions = complete_line (point, arg, argpoint);
|
||||
|
||||
if (completions)
|
||||
{
|
||||
|
|
@ -242,7 +267,7 @@ complete_command (char *arg, int from_tty)
|
|||
while (item < size)
|
||||
{
|
||||
int next_item;
|
||||
printf_unfiltered ("%s\n", completions[item]);
|
||||
printf_unfiltered ("%s%s\n", arg_prefix, completions[item]);
|
||||
next_item = item + 1;
|
||||
while (next_item < size
|
||||
&& ! strcmp (completions[item], completions[next_item]))
|
||||
|
|
@ -265,7 +290,6 @@ is_complete_command (struct cmd_list_element *c)
|
|||
return cmd_cfunc_eq (c, complete_command);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_version (char *args, int from_tty)
|
||||
{
|
||||
|
|
@ -285,7 +309,6 @@ quit_command (char *args, int from_tty)
|
|||
quit_force (args, from_tty);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
pwd_command (char *args, int from_tty)
|
||||
{
|
||||
|
|
@ -293,7 +316,7 @@ pwd_command (char *args, int from_tty)
|
|||
error ("The \"pwd\" command does not take an argument: %s", args);
|
||||
getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
|
||||
|
||||
if (!STREQ (gdb_dirbuf, current_directory))
|
||||
if (strcmp (gdb_dirbuf, current_directory) != 0)
|
||||
printf_unfiltered ("Working directory %s\n (canonically %s).\n",
|
||||
current_directory, gdb_dirbuf);
|
||||
else
|
||||
|
|
@ -429,12 +452,11 @@ source_command (char *args, int from_tty)
|
|||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
echo_command (char *text, int from_tty)
|
||||
{
|
||||
char *p = text;
|
||||
register int c;
|
||||
int c;
|
||||
|
||||
if (text)
|
||||
while ((c = *p++) != '\0')
|
||||
|
|
@ -459,7 +481,6 @@ echo_command (char *text, int from_tty)
|
|||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
shell_escape (char *arg, int from_tty)
|
||||
{
|
||||
|
|
@ -489,23 +510,24 @@ shell_escape (char *arg, int from_tty)
|
|||
#endif
|
||||
#else /* Can fork. */
|
||||
int rc, status, pid;
|
||||
char *p, *user_shell;
|
||||
|
||||
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
|
||||
user_shell = "/bin/sh";
|
||||
|
||||
/* Get the name of the shell for arg0 */
|
||||
if ((p = strrchr (user_shell, '/')) == NULL)
|
||||
p = user_shell;
|
||||
else
|
||||
p++; /* Get past '/' */
|
||||
|
||||
if ((pid = fork ()) == 0)
|
||||
if ((pid = vfork ()) == 0)
|
||||
{
|
||||
if (!arg)
|
||||
execl (user_shell, p, 0);
|
||||
char *p, *user_shell;
|
||||
|
||||
if ((user_shell = (char *) getenv ("SHELL")) == NULL)
|
||||
user_shell = "/bin/sh";
|
||||
|
||||
/* Get the name of the shell for arg0 */
|
||||
if ((p = strrchr (user_shell, '/')) == NULL)
|
||||
p = user_shell;
|
||||
else
|
||||
execl (user_shell, p, "-c", arg, 0);
|
||||
p++; /* Get past '/' */
|
||||
|
||||
if (!arg)
|
||||
execl (user_shell, p, (char *) 0);
|
||||
else
|
||||
execl (user_shell, p, "-c", arg, (char *) 0);
|
||||
|
||||
fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
|
||||
safe_strerror (errno));
|
||||
|
|
@ -521,6 +543,378 @@ shell_escape (char *arg, int from_tty)
|
|||
#endif /* Can fork. */
|
||||
}
|
||||
|
||||
static void
|
||||
edit_command (char *arg, int from_tty)
|
||||
{
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtab_and_line sal;
|
||||
struct symbol *sym;
|
||||
char *arg1;
|
||||
int cmdlen, log10;
|
||||
unsigned m;
|
||||
char *editor;
|
||||
char *p;
|
||||
|
||||
/* Pull in the current default source line if necessary */
|
||||
if (arg == 0)
|
||||
{
|
||||
set_default_source_symtab_and_line ();
|
||||
sal = get_current_source_symtab_and_line ();
|
||||
}
|
||||
|
||||
/* bare "edit" edits file with present line. */
|
||||
|
||||
if (arg == 0)
|
||||
{
|
||||
if (sal.symtab == 0)
|
||||
error ("No default source file yet.");
|
||||
sal.line += get_lines_to_list () / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Now should only be one argument -- decode it in SAL */
|
||||
|
||||
arg1 = arg;
|
||||
sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
|
||||
|
||||
if (! sals.nelts) return; /* C++ */
|
||||
if (sals.nelts > 1) {
|
||||
ambiguous_line_spec (&sals);
|
||||
xfree (sals.sals);
|
||||
return;
|
||||
}
|
||||
|
||||
sal = sals.sals[0];
|
||||
xfree (sals.sals);
|
||||
|
||||
if (*arg1)
|
||||
error ("Junk at end of line specification.");
|
||||
|
||||
/* if line was specified by address,
|
||||
first print exactly which line, and which file.
|
||||
In this case, sal.symtab == 0 means address is outside
|
||||
of all known source files, not that user failed to give a filename. */
|
||||
if (*arg == '*')
|
||||
{
|
||||
if (sal.symtab == 0)
|
||||
/* FIXME-32x64--assumes sal.pc fits in long. */
|
||||
error ("No source file for address %s.",
|
||||
local_hex_string((unsigned long) sal.pc));
|
||||
sym = find_pc_function (sal.pc);
|
||||
if (sym)
|
||||
{
|
||||
print_address_numeric (sal.pc, 1, gdb_stdout);
|
||||
printf_filtered (" is in ");
|
||||
fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout);
|
||||
printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_address_numeric (sal.pc, 1, gdb_stdout);
|
||||
printf_filtered (" is at %s:%d.\n",
|
||||
sal.symtab->filename, sal.line);
|
||||
}
|
||||
}
|
||||
|
||||
/* If what was given does not imply a symtab, it must be an undebuggable
|
||||
symbol which means no source code. */
|
||||
|
||||
if (sal.symtab == 0)
|
||||
error ("No line number known for %s.", arg);
|
||||
}
|
||||
|
||||
if ((editor = (char *) getenv ("EDITOR")) == NULL)
|
||||
editor = "/bin/ex";
|
||||
|
||||
/* Approximate base-10 log of line to 1 unit for digit count */
|
||||
for(log10=32, m=0x80000000; !(sal.line & m) && log10>0; log10--, m=m>>1);
|
||||
log10 = 1 + (int)((log10 + (0 == ((m-1) & sal.line)))/3.32192809);
|
||||
|
||||
cmdlen = strlen(editor) + 1
|
||||
+ (NULL == sal.symtab->dirname ? 0 : strlen(sal.symtab->dirname) + 1)
|
||||
+ (NULL == sal.symtab->filename? 0 : strlen(sal.symtab->filename)+ 1)
|
||||
+ log10 + 2;
|
||||
|
||||
p = xmalloc(cmdlen);
|
||||
sprintf(p,"%s +%d %s%s",editor,sal.line,
|
||||
(NULL == sal.symtab->dirname ? "./" :
|
||||
(NULL != sal.symtab->filename && *(sal.symtab->filename) != '/') ?
|
||||
sal.symtab->dirname : ""),
|
||||
(NULL == sal.symtab->filename ? "unknown" : sal.symtab->filename)
|
||||
);
|
||||
shell_escape(p, from_tty);
|
||||
|
||||
xfree(p);
|
||||
}
|
||||
|
||||
static void
|
||||
list_command (char *arg, int from_tty)
|
||||
{
|
||||
struct symtabs_and_lines sals, sals_end;
|
||||
struct symtab_and_line sal, sal_end, cursal;
|
||||
struct symbol *sym;
|
||||
char *arg1;
|
||||
int no_end = 1;
|
||||
int dummy_end = 0;
|
||||
int dummy_beg = 0;
|
||||
int linenum_beg = 0;
|
||||
char *p;
|
||||
|
||||
/* Pull in the current default source line if necessary */
|
||||
if (arg == 0 || arg[0] == '+' || arg[0] == '-')
|
||||
{
|
||||
set_default_source_symtab_and_line ();
|
||||
cursal = get_current_source_symtab_and_line ();
|
||||
}
|
||||
|
||||
/* "l" or "l +" lists next ten lines. */
|
||||
|
||||
if (arg == 0 || strcmp (arg, "+") == 0)
|
||||
{
|
||||
print_source_lines (cursal.symtab, cursal.line,
|
||||
cursal.line + get_lines_to_list (), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* "l -" lists previous ten lines, the ones before the ten just listed. */
|
||||
if (strcmp (arg, "-") == 0)
|
||||
{
|
||||
print_source_lines (cursal.symtab,
|
||||
max (get_first_line_listed () - get_lines_to_list (), 1),
|
||||
get_first_line_listed (), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now if there is only one argument, decode it in SAL
|
||||
and set NO_END.
|
||||
If there are two arguments, decode them in SAL and SAL_END
|
||||
and clear NO_END; however, if one of the arguments is blank,
|
||||
set DUMMY_BEG or DUMMY_END to record that fact. */
|
||||
|
||||
if (!have_full_symbols () && !have_partial_symbols ())
|
||||
error ("No symbol table is loaded. Use the \"file\" command.");
|
||||
|
||||
arg1 = arg;
|
||||
if (*arg1 == ',')
|
||||
dummy_beg = 1;
|
||||
else
|
||||
{
|
||||
sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
|
||||
|
||||
if (!sals.nelts)
|
||||
return; /* C++ */
|
||||
if (sals.nelts > 1)
|
||||
{
|
||||
ambiguous_line_spec (&sals);
|
||||
xfree (sals.sals);
|
||||
return;
|
||||
}
|
||||
|
||||
sal = sals.sals[0];
|
||||
xfree (sals.sals);
|
||||
}
|
||||
|
||||
/* Record whether the BEG arg is all digits. */
|
||||
|
||||
for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
|
||||
linenum_beg = (p == arg1);
|
||||
|
||||
while (*arg1 == ' ' || *arg1 == '\t')
|
||||
arg1++;
|
||||
if (*arg1 == ',')
|
||||
{
|
||||
no_end = 0;
|
||||
arg1++;
|
||||
while (*arg1 == ' ' || *arg1 == '\t')
|
||||
arg1++;
|
||||
if (*arg1 == 0)
|
||||
dummy_end = 1;
|
||||
else
|
||||
{
|
||||
if (dummy_beg)
|
||||
sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
|
||||
else
|
||||
sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0);
|
||||
if (sals_end.nelts == 0)
|
||||
return;
|
||||
if (sals_end.nelts > 1)
|
||||
{
|
||||
ambiguous_line_spec (&sals_end);
|
||||
xfree (sals_end.sals);
|
||||
return;
|
||||
}
|
||||
sal_end = sals_end.sals[0];
|
||||
xfree (sals_end.sals);
|
||||
}
|
||||
}
|
||||
|
||||
if (*arg1)
|
||||
error ("Junk at end of line specification.");
|
||||
|
||||
if (!no_end && !dummy_beg && !dummy_end
|
||||
&& sal.symtab != sal_end.symtab)
|
||||
error ("Specified start and end are in different files.");
|
||||
if (dummy_beg && dummy_end)
|
||||
error ("Two empty args do not say what lines to list.");
|
||||
|
||||
/* if line was specified by address,
|
||||
first print exactly which line, and which file.
|
||||
In this case, sal.symtab == 0 means address is outside
|
||||
of all known source files, not that user failed to give a filename. */
|
||||
if (*arg == '*')
|
||||
{
|
||||
if (sal.symtab == 0)
|
||||
/* FIXME-32x64--assumes sal.pc fits in long. */
|
||||
error ("No source file for address %s.",
|
||||
local_hex_string ((unsigned long) sal.pc));
|
||||
sym = find_pc_function (sal.pc);
|
||||
if (sym)
|
||||
{
|
||||
print_address_numeric (sal.pc, 1, gdb_stdout);
|
||||
printf_filtered (" is in ");
|
||||
fputs_filtered (SYMBOL_PRINT_NAME (sym), gdb_stdout);
|
||||
printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
|
||||
}
|
||||
else
|
||||
{
|
||||
print_address_numeric (sal.pc, 1, gdb_stdout);
|
||||
printf_filtered (" is at %s:%d.\n",
|
||||
sal.symtab->filename, sal.line);
|
||||
}
|
||||
}
|
||||
|
||||
/* If line was not specified by just a line number,
|
||||
and it does not imply a symtab, it must be an undebuggable symbol
|
||||
which means no source code. */
|
||||
|
||||
if (!linenum_beg && sal.symtab == 0)
|
||||
error ("No line number known for %s.", arg);
|
||||
|
||||
/* If this command is repeated with RET,
|
||||
turn it into the no-arg variant. */
|
||||
|
||||
if (from_tty)
|
||||
*arg = 0;
|
||||
|
||||
if (dummy_beg && sal_end.symtab == 0)
|
||||
error ("No default source file yet. Do \"help list\".");
|
||||
if (dummy_beg)
|
||||
print_source_lines (sal_end.symtab,
|
||||
max (sal_end.line - (get_lines_to_list () - 1), 1),
|
||||
sal_end.line + 1, 0);
|
||||
else if (sal.symtab == 0)
|
||||
error ("No default source file yet. Do \"help list\".");
|
||||
else if (no_end)
|
||||
{
|
||||
int first_line = sal.line - get_lines_to_list () / 2;
|
||||
|
||||
if (first_line < 1) first_line = 1;
|
||||
|
||||
print_source_lines (sal.symtab,
|
||||
first_line,
|
||||
first_line + get_lines_to_list (),
|
||||
0);
|
||||
}
|
||||
else
|
||||
print_source_lines (sal.symtab, sal.line,
|
||||
(dummy_end
|
||||
? sal.line + get_lines_to_list ()
|
||||
: sal_end.line + 1),
|
||||
0);
|
||||
}
|
||||
|
||||
/* Dump a specified section of assembly code. With no command line
|
||||
arguments, this command will dump the assembly code for the
|
||||
function surrounding the pc value in the selected frame. With one
|
||||
argument, it will dump the assembly code surrounding that pc value.
|
||||
Two arguments are interpeted as bounds within which to dump
|
||||
assembly. */
|
||||
|
||||
static void
|
||||
disassemble_command (char *arg, int from_tty)
|
||||
{
|
||||
CORE_ADDR low, high;
|
||||
char *name;
|
||||
CORE_ADDR pc, pc_masked;
|
||||
char *space_index;
|
||||
#if 0
|
||||
asection *section;
|
||||
#endif
|
||||
|
||||
name = NULL;
|
||||
if (!arg)
|
||||
{
|
||||
if (!deprecated_selected_frame)
|
||||
error ("No frame selected.\n");
|
||||
|
||||
pc = get_frame_pc (deprecated_selected_frame);
|
||||
if (find_pc_partial_function (pc, &name, &low, &high) == 0)
|
||||
error ("No function contains program counter for selected frame.\n");
|
||||
#if defined(TUI)
|
||||
/* NOTE: cagney/2003-02-13 The `tui_active' was previously
|
||||
`tui_version'. */
|
||||
if (tui_active)
|
||||
/* FIXME: cagney/2004-02-07: This should be an observer. */
|
||||
low = tui_get_low_disassembly_address (low, pc);
|
||||
#endif
|
||||
low += FUNCTION_START_OFFSET;
|
||||
}
|
||||
else if (!(space_index = (char *) strchr (arg, ' ')))
|
||||
{
|
||||
/* One argument. */
|
||||
pc = parse_and_eval_address (arg);
|
||||
if (find_pc_partial_function (pc, &name, &low, &high) == 0)
|
||||
error ("No function contains specified address.\n");
|
||||
#if defined(TUI)
|
||||
/* NOTE: cagney/2003-02-13 The `tui_active' was previously
|
||||
`tui_version'. */
|
||||
if (tui_active)
|
||||
/* FIXME: cagney/2004-02-07: This should be an observer. */
|
||||
low = tui_get_low_disassembly_address (low, pc);
|
||||
#endif
|
||||
low += FUNCTION_START_OFFSET;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Two arguments. */
|
||||
*space_index = '\0';
|
||||
low = parse_and_eval_address (arg);
|
||||
high = parse_and_eval_address (space_index + 1);
|
||||
}
|
||||
|
||||
#if defined(TUI)
|
||||
if (!tui_is_window_visible (DISASSEM_WIN))
|
||||
#endif
|
||||
{
|
||||
printf_filtered ("Dump of assembler code ");
|
||||
if (name != NULL)
|
||||
{
|
||||
printf_filtered ("for function %s:\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf_filtered ("from ");
|
||||
print_address_numeric (low, 1, gdb_stdout);
|
||||
printf_filtered (" to ");
|
||||
print_address_numeric (high, 1, gdb_stdout);
|
||||
printf_filtered (":\n");
|
||||
}
|
||||
|
||||
/* Dump the specified range. */
|
||||
gdb_disassembly (uiout, 0, 0, 0, -1, low, high);
|
||||
|
||||
printf_filtered ("End of assembler dump.\n");
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
#if defined(TUI)
|
||||
else
|
||||
{
|
||||
tui_show_assembly (low);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
make_command (char *arg, int from_tty)
|
||||
{
|
||||
|
|
@ -538,7 +932,6 @@ make_command (char *arg, int from_tty)
|
|||
shell_escape (p, from_tty);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
show_user (char *args, int from_tty)
|
||||
{
|
||||
|
|
@ -590,6 +983,21 @@ apropos_command (char *searchstr, int from_tty)
|
|||
xfree (pattern_fastmap);
|
||||
}
|
||||
|
||||
/* Print a list of files and line numbers which a user may choose from
|
||||
in order to list a function which was specified ambiguously (as with
|
||||
`list classname::overloadedfuncname', for example). The vector in
|
||||
SALS provides the filenames and line numbers. */
|
||||
|
||||
static void
|
||||
ambiguous_line_spec (struct symtabs_and_lines *sals)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sals->nelts; ++i)
|
||||
printf_filtered ("file: \"%s\", line number: %d\n",
|
||||
sals->sals[i].symtab->filename, sals->sals[i].line);
|
||||
}
|
||||
|
||||
static void
|
||||
set_debug (char *arg, int from_tty)
|
||||
{
|
||||
|
|
@ -606,6 +1014,8 @@ show_debug (char *args, int from_tty)
|
|||
void
|
||||
init_cmd_lists (void)
|
||||
{
|
||||
max_user_call_depth = 1024;
|
||||
|
||||
cmdlist = NULL;
|
||||
infolist = NULL;
|
||||
enablelist = NULL;
|
||||
|
|
@ -673,7 +1083,7 @@ The commands below can be used to select other frames by number or address.",
|
|||
"Set working directory to DIR for debugger and program being debugged.\n\
|
||||
The change does not take effect for the program being debugged\n\
|
||||
until the next time it is started.", &cmdlist);
|
||||
c->completer = filename_completer;
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
add_com ("echo", class_support, echo_command,
|
||||
"Print a constant string. Give string as argument.\n\
|
||||
|
|
@ -698,11 +1108,11 @@ Commands defined in this way may have up to ten arguments.");
|
|||
"Read commands from a file named FILE.\n\
|
||||
Note that the file \"" GDBINIT_FILENAME "\" is read automatically in this way\n\
|
||||
when gdb is started.", &cmdlist);
|
||||
c->completer = filename_completer;
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
add_com ("quit", class_support, quit_command, "Exit gdb.");
|
||||
c = add_com ("help", class_support, help_command, "Print list of commands.");
|
||||
c->completer = command_completer;
|
||||
set_cmd_completer (c, command_completer);
|
||||
add_com_alias ("q", "quit", class_support, 1);
|
||||
add_com_alias ("h", "help", class_support, 1);
|
||||
|
||||
|
|
@ -802,9 +1212,54 @@ from the target.", &setlist),
|
|||
&showdebuglist, "show debug ", 0, &showlist);
|
||||
|
||||
c = add_com ("shell", class_support, shell_escape,
|
||||
"Execute the rest of the line as a shell command. \n\
|
||||
"Execute the rest of the line as a shell command.\n\
|
||||
With no arguments, run an inferior shell.");
|
||||
c->completer = filename_completer;
|
||||
set_cmd_completer (c, filename_completer);
|
||||
|
||||
c = add_com ("edit", class_files, edit_command,
|
||||
concat ("Edit specified file or function.\n\
|
||||
With no argument, edits file containing most recent line listed.\n\
|
||||
", "\
|
||||
Editing targets can be specified in these ways:\n\
|
||||
FILE:LINENUM, to edit at that line in that file,\n\
|
||||
FUNCTION, to edit at the beginning of that function,\n\
|
||||
FILE:FUNCTION, to distinguish among like-named static functions.\n\
|
||||
*ADDRESS, to edit at the line containing that address.\n\
|
||||
Uses EDITOR environment variable contents as editor (or ex as default).",NULL));
|
||||
|
||||
c->completer = location_completer;
|
||||
|
||||
add_com ("list", class_files, list_command,
|
||||
concat ("List specified function or line.\n\
|
||||
With no argument, lists ten more lines after or around previous listing.\n\
|
||||
\"list -\" lists the ten lines before a previous ten-line listing.\n\
|
||||
One argument specifies a line, and ten lines are listed around that line.\n\
|
||||
Two arguments with comma between specify starting and ending lines to list.\n\
|
||||
", "\
|
||||
Lines can be specified in these ways:\n\
|
||||
LINENUM, to list around that line in current file,\n\
|
||||
FILE:LINENUM, to list around that line in that file,\n\
|
||||
FUNCTION, to list around beginning of that function,\n\
|
||||
FILE:FUNCTION, to distinguish among like-named static functions.\n\
|
||||
*ADDRESS, to list around the line containing that address.\n\
|
||||
With two args if one is empty it stands for ten lines away from the other arg.", NULL));
|
||||
|
||||
if (!xdb_commands)
|
||||
add_com_alias ("l", "list", class_files, 1);
|
||||
else
|
||||
add_com_alias ("v", "list", class_files, 1);
|
||||
|
||||
if (dbx_commands)
|
||||
add_com_alias ("file", "list", class_files, 1);
|
||||
|
||||
c = add_com ("disassemble", class_vars, disassemble_command,
|
||||
"Disassemble a specified section of memory.\n\
|
||||
Default is the function surrounding the pc of the selected frame.\n\
|
||||
With a single argument, the function surrounding that address is dumped.\n\
|
||||
Two arguments are taken as a range of memory to dump.");
|
||||
set_cmd_completer (c, location_completer);
|
||||
if (xdb_commands)
|
||||
add_com_alias ("va", "disassemble", class_xdb, 0);
|
||||
|
||||
/* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would
|
||||
be a really useful feature. Unfortunately, the below wont do
|
||||
|
|
@ -817,10 +1272,17 @@ With no arguments, run an inferior shell.");
|
|||
|
||||
c = add_com ("make", class_support, make_command,
|
||||
"Run the ``make'' program using the rest of the line as arguments.");
|
||||
c->completer = filename_completer;
|
||||
set_cmd_completer (c, filename_completer);
|
||||
add_cmd ("user", no_class, show_user,
|
||||
"Show definitions of user defined commands.\n\
|
||||
Argument is the name of the user defined command.\n\
|
||||
With no argument, show definitions of all user defined commands.", &showlist);
|
||||
add_com ("apropos", class_support, apropos_command, "Search for commands matching a REGEXP");
|
||||
|
||||
add_show_from_set (
|
||||
add_set_cmd ("max-user-call-depth", no_class, var_integer,
|
||||
(char *) &max_user_call_depth,
|
||||
"Set the max call depth for user-defined commands.\n",
|
||||
&setlist),
|
||||
&showlist);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,19 @@
|
|||
#include "symtab.h"
|
||||
#include <ctype.h>
|
||||
#include "gdb_regex.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "ui-out.h"
|
||||
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "cli/cli-decode.h"
|
||||
|
||||
#ifdef TUI
|
||||
#include "tui/tui.h" /* For tui_active et.al. */
|
||||
#endif
|
||||
|
||||
#include "gdb_assert.h"
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void undef_cmd_error (char *, char *);
|
||||
|
|
@ -51,8 +58,7 @@ do_cfunc (struct cmd_list_element *c, char *args, int from_tty)
|
|||
}
|
||||
|
||||
void
|
||||
set_cmd_cfunc (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty))
|
||||
set_cmd_cfunc (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc)
|
||||
{
|
||||
if (cfunc == NULL)
|
||||
cmd->func = NULL;
|
||||
|
|
@ -68,9 +74,7 @@ do_sfunc (struct cmd_list_element *c, char *args, int from_tty)
|
|||
}
|
||||
|
||||
void
|
||||
set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||
void (*sfunc) (char *args, int from_tty,
|
||||
struct cmd_list_element * c))
|
||||
set_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc)
|
||||
{
|
||||
if (sfunc == NULL)
|
||||
cmd->func = NULL;
|
||||
|
|
@ -86,6 +90,31 @@ cmd_cfunc_eq (struct cmd_list_element *cmd,
|
|||
return cmd->func == do_cfunc && cmd->function.cfunc == cfunc;
|
||||
}
|
||||
|
||||
void
|
||||
set_cmd_context (struct cmd_list_element *cmd, void *context)
|
||||
{
|
||||
cmd->context = context;
|
||||
}
|
||||
|
||||
void *
|
||||
get_cmd_context (struct cmd_list_element *cmd)
|
||||
{
|
||||
return cmd->context;
|
||||
}
|
||||
|
||||
enum cmd_types
|
||||
cmd_type (struct cmd_list_element *cmd)
|
||||
{
|
||||
return cmd->type;
|
||||
}
|
||||
|
||||
void
|
||||
set_cmd_completer (struct cmd_list_element *cmd,
|
||||
char **(*completer) (char *text, char *word))
|
||||
{
|
||||
cmd->completer = completer; /* Ok. */
|
||||
}
|
||||
|
||||
|
||||
/* Add element named NAME.
|
||||
CLASS is the top level category into which commands are broken down
|
||||
|
|
@ -108,7 +137,7 @@ struct cmd_list_element *
|
|||
add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
||||
char *doc, struct cmd_list_element **list)
|
||||
{
|
||||
register struct cmd_list_element *c
|
||||
struct cmd_list_element *c
|
||||
= (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
|
||||
struct cmd_list_element *p;
|
||||
|
||||
|
|
@ -133,6 +162,7 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
|||
c->name = name;
|
||||
c->class = class;
|
||||
set_cmd_cfunc (c, fun);
|
||||
set_cmd_context (c, NULL);
|
||||
c->doc = doc;
|
||||
c->flags = 0;
|
||||
c->replacement = NULL;
|
||||
|
|
@ -144,7 +174,7 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
|||
c->prefixname = NULL;
|
||||
c->allow_unknown = 0;
|
||||
c->abbrev_flag = 0;
|
||||
c->completer = make_symbol_completion_list;
|
||||
set_cmd_completer (c, make_symbol_completion_list);
|
||||
c->type = not_set_cmd;
|
||||
c->var = NULL;
|
||||
c->var_type = var_boolean;
|
||||
|
|
@ -157,20 +187,6 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
|||
return c;
|
||||
}
|
||||
|
||||
/* Same as above, except that the abbrev_flag is set. */
|
||||
/* Note: Doesn't seem to be used anywhere currently. */
|
||||
|
||||
struct cmd_list_element *
|
||||
add_abbrev_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
||||
char *doc, struct cmd_list_element **list)
|
||||
{
|
||||
register struct cmd_list_element *c
|
||||
= add_cmd (name, class, fun, doc, list);
|
||||
|
||||
c->abbrev_flag = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Deprecates a command CMD.
|
||||
REPLACEMENT is the name of the command which should be used in place
|
||||
of this command, or NULL if no such command exists.
|
||||
|
|
@ -200,8 +216,8 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
|
|||
{
|
||||
/* Must do this since lookup_cmd tries to side-effect its first arg */
|
||||
char *copied_name;
|
||||
register struct cmd_list_element *old;
|
||||
register struct cmd_list_element *c;
|
||||
struct cmd_list_element *old;
|
||||
struct cmd_list_element *c;
|
||||
copied_name = (char *) alloca (strlen (oldname) + 1);
|
||||
strcpy (copied_name, oldname);
|
||||
old = lookup_cmd (&copied_name, *list, "", 1, 1);
|
||||
|
|
@ -235,7 +251,7 @@ add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int),
|
|||
char *prefixname, int allow_unknown,
|
||||
struct cmd_list_element **list)
|
||||
{
|
||||
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
|
||||
struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
|
||||
c->prefixlist = prefixlist;
|
||||
c->prefixname = prefixname;
|
||||
c->allow_unknown = allow_unknown;
|
||||
|
|
@ -250,7 +266,7 @@ add_abbrev_prefix_cmd (char *name, enum command_class class,
|
|||
struct cmd_list_element **prefixlist, char *prefixname,
|
||||
int allow_unknown, struct cmd_list_element **list)
|
||||
{
|
||||
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
|
||||
struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
|
||||
c->prefixlist = prefixlist;
|
||||
c->prefixname = prefixname;
|
||||
c->allow_unknown = allow_unknown;
|
||||
|
|
@ -272,13 +288,90 @@ empty_sfunc (char *args, int from_tty, struct cmd_list_element *c)
|
|||
{
|
||||
}
|
||||
|
||||
/* Add element named NAME to command list LIST (the list for set
|
||||
/* Add element named NAME to command list LIST (the list for set/show
|
||||
or some sublist thereof).
|
||||
TYPE is set_cmd or show_cmd.
|
||||
CLASS is as in add_cmd.
|
||||
VAR_TYPE is the kind of thing we are setting.
|
||||
VAR is address of the variable being controlled by this command.
|
||||
DOC is the documentation string. */
|
||||
|
||||
static struct cmd_list_element *
|
||||
add_set_or_show_cmd (char *name,
|
||||
enum cmd_types type,
|
||||
enum command_class class,
|
||||
var_types var_type,
|
||||
void *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list)
|
||||
{
|
||||
struct cmd_list_element *c = add_cmd (name, class, NULL, doc, list);
|
||||
gdb_assert (type == set_cmd || type == show_cmd);
|
||||
c->type = type;
|
||||
c->var_type = var_type;
|
||||
c->var = var;
|
||||
/* This needs to be something besides NULL so that this isn't
|
||||
treated as a help class. */
|
||||
set_cmd_sfunc (c, empty_sfunc);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Add element named NAME to both the command SET_LIST and SHOW_LIST.
|
||||
CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are
|
||||
setting. VAR is address of the variable being controlled by this
|
||||
command. SET_FUNC and SHOW_FUNC are the callback functions (if
|
||||
non-NULL). SET_DOC and SHOW_DOC are the documentation strings.
|
||||
SET_RESULT and SHOW_RESULT, if not NULL, are set to the resulting
|
||||
command structures. */
|
||||
|
||||
void
|
||||
add_setshow_cmd_full (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list,
|
||||
struct cmd_list_element **set_result,
|
||||
struct cmd_list_element **show_result)
|
||||
{
|
||||
struct cmd_list_element *set;
|
||||
struct cmd_list_element *show;
|
||||
set = add_set_or_show_cmd (name, set_cmd, class, var_type, var,
|
||||
set_doc, set_list);
|
||||
if (set_func != NULL)
|
||||
set_cmd_sfunc (set, set_func);
|
||||
show = add_set_or_show_cmd (name, show_cmd, class, var_type, var,
|
||||
show_doc, show_list);
|
||||
if (show_func != NULL)
|
||||
set_cmd_sfunc (show, show_func);
|
||||
|
||||
if (set_result != NULL)
|
||||
*set_result = set;
|
||||
if (show_result != NULL)
|
||||
*show_result = show;
|
||||
}
|
||||
|
||||
/* Add element named NAME to both the command SET_LIST and SHOW_LIST.
|
||||
CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are
|
||||
setting. VAR is address of the variable being controlled by this
|
||||
command. SET_FUNC and SHOW_FUNC are the callback functions (if
|
||||
non-NULL). SET_DOC and SHOW_DOC are the documentation strings. */
|
||||
|
||||
void
|
||||
add_setshow_cmd (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list)
|
||||
{
|
||||
add_setshow_cmd_full (name, class, var_type, var, set_doc, show_doc,
|
||||
set_func, show_func, set_list, show_list,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
struct cmd_list_element *
|
||||
add_set_cmd (char *name,
|
||||
enum command_class class,
|
||||
|
|
@ -287,15 +380,7 @@ add_set_cmd (char *name,
|
|||
char *doc,
|
||||
struct cmd_list_element **list)
|
||||
{
|
||||
struct cmd_list_element *c = add_cmd (name, class, NULL, doc, list);
|
||||
|
||||
c->type = set_cmd;
|
||||
c->var_type = var_type;
|
||||
c->var = var;
|
||||
/* This needs to be something besides NULL so that this isn't
|
||||
treated as a help class. */
|
||||
set_cmd_sfunc (c, empty_sfunc);
|
||||
return c;
|
||||
return add_set_or_show_cmd (name, set_cmd, class, var_type, var, doc, list);
|
||||
}
|
||||
|
||||
/* Add element named NAME to command list LIST (the list for set
|
||||
|
|
@ -321,83 +406,97 @@ add_set_enum_cmd (char *name,
|
|||
return c;
|
||||
}
|
||||
|
||||
/* Add element named NAME to command list LIST (the list for set
|
||||
or some sublist thereof).
|
||||
CLASS is as in add_cmd.
|
||||
VAR is address of the variable which will contain the value.
|
||||
DOC is the documentation string. */
|
||||
struct cmd_list_element *
|
||||
add_set_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum cmd_auto_boolean *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list)
|
||||
/* Add an auto-boolean command named NAME to both the set and show
|
||||
command list lists. CLASS is as in add_cmd. VAR is address of the
|
||||
variable which will contain the value. DOC is the documentation
|
||||
string. FUNC is the corresponding callback. */
|
||||
void
|
||||
add_setshow_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum auto_boolean *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list)
|
||||
{
|
||||
static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL };
|
||||
struct cmd_list_element *c;
|
||||
c = add_set_cmd (name, class, var_auto_boolean, var, doc, list);
|
||||
add_setshow_cmd_full (name, class, var_auto_boolean, var,
|
||||
set_doc, show_doc, set_func, show_func,
|
||||
set_list, show_list,
|
||||
&c, NULL);
|
||||
c->enums = auto_boolean_enums;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Add element named NAME to command list LIST (the list for set
|
||||
or some sublist thereof).
|
||||
CLASS is as in add_cmd.
|
||||
VAR is address of the variable which will contain the value.
|
||||
DOC is the documentation string. */
|
||||
struct cmd_list_element *
|
||||
add_set_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list)
|
||||
/* Add element named NAME to both the set and show command LISTs (the
|
||||
list for set/show or some sublist thereof). CLASS is as in
|
||||
add_cmd. VAR is address of the variable which will contain the
|
||||
value. SET_DOC and SHOW_DOR are the documentation strings. */
|
||||
void
|
||||
add_setshow_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var, char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list)
|
||||
{
|
||||
static const char *boolean_enums[] = { "on", "off", NULL };
|
||||
struct cmd_list_element *c;
|
||||
c = add_set_cmd (name, class, var_boolean, var, doc, list);
|
||||
add_setshow_cmd_full (name, class, var_boolean, var,
|
||||
set_doc, show_doc,
|
||||
set_func, show_func,
|
||||
set_list, show_list,
|
||||
&c, NULL);
|
||||
c->enums = boolean_enums;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Add element named NAME to both the set and show command LISTs (the
|
||||
list for set/show or some sublist thereof). CLASS is as in
|
||||
add_cmd. VAR is address of the variable which will contain the
|
||||
value. SET_DOC and SHOW_DOR are the documentation strings. */
|
||||
void
|
||||
add_setshow_uinteger_cmd (char *name,
|
||||
enum command_class class,
|
||||
unsigned int *var, char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list)
|
||||
{
|
||||
add_setshow_cmd_full (name, class, var_uinteger, var,
|
||||
set_doc, show_doc,
|
||||
set_func, show_func,
|
||||
set_list, show_list,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* Where SETCMD has already been added, add the corresponding show
|
||||
command to LIST and return a pointer to the added command (not
|
||||
command to LIST and return a pointer to the added command (not
|
||||
necessarily the head of LIST). */
|
||||
/* NOTE: cagney/2002-03-17: The original version of add_show_from_set
|
||||
used memcpy() to clone `set' into `show'. This meant that in
|
||||
addition to all the needed fields (var, name, et.al.) some
|
||||
unnecessary fields were copied (namely the callback function). The
|
||||
function explictly copies relevant fields. For a `set' and `show'
|
||||
command to share the same callback, the caller must set both
|
||||
explicitly. */
|
||||
struct cmd_list_element *
|
||||
add_show_from_set (struct cmd_list_element *setcmd,
|
||||
struct cmd_list_element **list)
|
||||
{
|
||||
struct cmd_list_element *showcmd =
|
||||
(struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
|
||||
struct cmd_list_element *p;
|
||||
char *doc;
|
||||
const static char setstring[] = "Set ";
|
||||
|
||||
memcpy (showcmd, setcmd, sizeof (struct cmd_list_element));
|
||||
delete_cmd (showcmd->name, list);
|
||||
showcmd->type = show_cmd;
|
||||
/* Create a doc string by replacing "Set " at the start of the
|
||||
`set'' command's doco with "Show ". */
|
||||
gdb_assert (strncmp (setcmd->doc, setstring, sizeof (setstring) - 1) == 0);
|
||||
doc = concat ("Show ", setcmd->doc + sizeof (setstring) - 1, NULL);
|
||||
|
||||
/* Replace "set " at start of docstring with "show ". */
|
||||
if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e'
|
||||
&& setcmd->doc[2] == 't' && setcmd->doc[3] == ' ')
|
||||
showcmd->doc = concat ("Show ", setcmd->doc + 4, NULL);
|
||||
else
|
||||
fprintf_unfiltered (gdb_stderr, "GDB internal error: Bad docstring for set command\n");
|
||||
|
||||
if (*list == NULL || strcmp ((*list)->name, showcmd->name) >= 0)
|
||||
{
|
||||
showcmd->next = *list;
|
||||
*list = showcmd;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = *list;
|
||||
while (p->next && strcmp (p->next->name, showcmd->name) <= 0)
|
||||
{
|
||||
p = p->next;
|
||||
}
|
||||
showcmd->next = p->next;
|
||||
p->next = showcmd;
|
||||
}
|
||||
|
||||
return showcmd;
|
||||
/* Insert the basic command. */
|
||||
return add_set_or_show_cmd (setcmd->name, show_cmd, setcmd->class,
|
||||
setcmd->var_type, setcmd->var, doc, list);
|
||||
}
|
||||
|
||||
/* Remove the command named NAME from the command list. */
|
||||
|
|
@ -405,10 +504,10 @@ add_show_from_set (struct cmd_list_element *setcmd,
|
|||
void
|
||||
delete_cmd (char *name, struct cmd_list_element **list)
|
||||
{
|
||||
register struct cmd_list_element *c;
|
||||
struct cmd_list_element *c;
|
||||
struct cmd_list_element *p;
|
||||
|
||||
while (*list && STREQ ((*list)->name, name))
|
||||
while (*list && strcmp ((*list)->name, name) == 0)
|
||||
{
|
||||
if ((*list)->hookee_pre)
|
||||
(*list)->hookee_pre->hook_pre = 0; /* Hook slips out of its mouth */
|
||||
|
|
@ -422,7 +521,7 @@ delete_cmd (char *name, struct cmd_list_element **list)
|
|||
if (*list)
|
||||
for (c = *list; c->next;)
|
||||
{
|
||||
if (STREQ (c->next->name, name))
|
||||
if (strcmp (c->next->name, name) == 0)
|
||||
{
|
||||
if (c->next->hookee_pre)
|
||||
c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */
|
||||
|
|
@ -482,7 +581,7 @@ void
|
|||
apropos_cmd (struct ui_file *stream, struct cmd_list_element *commandlist,
|
||||
struct re_pattern_buffer *regex, char *prefix)
|
||||
{
|
||||
register struct cmd_list_element *c;
|
||||
struct cmd_list_element *c;
|
||||
int returnvalue=1; /*Needed to avoid double printing*/
|
||||
/* Walk through the commands */
|
||||
for (c=commandlist;c;c=c->next)
|
||||
|
|
@ -645,14 +744,24 @@ help_list (struct cmd_list_element *list, char *cmdtype,
|
|||
help_cmd_list (list, class, cmdtype, (int) class >= 0, stream);
|
||||
|
||||
if (class == all_classes)
|
||||
fprintf_filtered (stream, "\n\
|
||||
Type \"help%s\" followed by a class name for a list of commands in that class.",
|
||||
cmdtype1);
|
||||
{
|
||||
fprintf_filtered (stream, "\n\
|
||||
Type \"help%s\" followed by a class name for a list of commands in ",
|
||||
cmdtype1);
|
||||
wrap_here ("");
|
||||
fprintf_filtered (stream, "that class.");
|
||||
}
|
||||
|
||||
fprintf_filtered (stream, "\n\
|
||||
Type \"help%s\" followed by %scommand name for full documentation.\n\
|
||||
Command name abbreviations are allowed if unambiguous.\n",
|
||||
fprintf_filtered (stream, "\nType \"help%s\" followed by %scommand name ",
|
||||
cmdtype1, cmdtype2);
|
||||
wrap_here ("");
|
||||
fputs_filtered ("for ", stream);
|
||||
wrap_here ("");
|
||||
fputs_filtered ("full ", stream);
|
||||
wrap_here ("");
|
||||
fputs_filtered ("documentation.\n", stream);
|
||||
fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n",
|
||||
stream);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -681,7 +790,7 @@ print_doc_line (struct ui_file *stream, char *str)
|
|||
{
|
||||
static char *line_buffer = 0;
|
||||
static int line_size;
|
||||
register char *p;
|
||||
char *p;
|
||||
|
||||
if (!line_buffer)
|
||||
{
|
||||
|
|
@ -725,7 +834,7 @@ void
|
|||
help_cmd_list (struct cmd_list_element *list, enum command_class class,
|
||||
char *prefix, int recurse, struct ui_file *stream)
|
||||
{
|
||||
register struct cmd_list_element *c;
|
||||
struct cmd_list_element *c;
|
||||
|
||||
for (c = list; c; c = c->next)
|
||||
{
|
||||
|
|
@ -824,10 +933,14 @@ lookup_cmd_1 (char **text, struct cmd_list_element *clist,
|
|||
/* Treating underscores as part of command words is important
|
||||
so that "set args_foo()" doesn't get interpreted as
|
||||
"set args _foo()". */
|
||||
/* NOTE: cagney/2003-02-13 The `tui_active' was previously
|
||||
`tui_version'. */
|
||||
for (p = *text;
|
||||
*p && (isalnum (*p) || *p == '-' || *p == '_' ||
|
||||
(tui_version &&
|
||||
#if defined(TUI)
|
||||
(tui_active &&
|
||||
(*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
|
||||
#endif
|
||||
(xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
|
||||
p++)
|
||||
;
|
||||
|
|
@ -949,7 +1062,7 @@ undef_cmd_error (char *cmdtype, char *q)
|
|||
cmdtype,
|
||||
q,
|
||||
*cmdtype ? " " : "",
|
||||
strlen (cmdtype) - 1,
|
||||
(int) strlen (cmdtype) - 1,
|
||||
cmdtype);
|
||||
}
|
||||
|
||||
|
|
@ -1194,10 +1307,14 @@ lookup_cmd_composition (char *text,
|
|||
/* Treating underscores as part of command words is important
|
||||
so that "set args_foo()" doesn't get interpreted as
|
||||
"set args _foo()". */
|
||||
/* NOTE: cagney/2003-02-13 The `tui_active' was previously
|
||||
`tui_version'. */
|
||||
for (p = text;
|
||||
*p && (isalnum (*p) || *p == '-' || *p == '_' ||
|
||||
(tui_version &&
|
||||
#if defined(TUI)
|
||||
(tui_active &&
|
||||
(*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
|
||||
#endif
|
||||
(xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
|
||||
p++)
|
||||
;
|
||||
|
|
@ -1407,3 +1524,23 @@ complete_on_enum (const char *enumlist[],
|
|||
return matchlist;
|
||||
}
|
||||
|
||||
|
||||
/* check function pointer */
|
||||
int
|
||||
cmd_func_p (struct cmd_list_element *cmd)
|
||||
{
|
||||
return (cmd->func != NULL);
|
||||
}
|
||||
|
||||
|
||||
/* call the command function */
|
||||
void
|
||||
cmd_func (struct cmd_list_element *cmd, char *args, int from_tty)
|
||||
{
|
||||
if (cmd_func_p (cmd))
|
||||
(*cmd->func) (cmd, args, from_tty);
|
||||
else
|
||||
error ("Invalid command");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* Header file for GDB command decoding library.
|
||||
Copyright 2000 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 2000, 2003 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
|
|
@ -19,25 +20,13 @@
|
|||
#if !defined (CLI_DECODE_H)
|
||||
#define CLI_DECODE_H 1
|
||||
|
||||
#include "gdb_regex.h" /* Needed by apropos_cmd. */
|
||||
#include "command.h"
|
||||
|
||||
/* Command classes are top-level categories into which commands are broken
|
||||
down for "help" purposes.
|
||||
Notes on classes: class_alias is for alias commands which are not
|
||||
abbreviations of the original command. class-pseudo is for
|
||||
commands which are not really commands nor help topics ("stop"). */
|
||||
|
||||
enum command_class
|
||||
{
|
||||
/* Special args to help_list */
|
||||
class_deprecated, all_classes = -2, all_commands = -1,
|
||||
/* Classes of commands */
|
||||
no_class = -1, class_run = 0, class_vars, class_stack,
|
||||
class_files, class_support, class_info, class_breakpoint, class_trace,
|
||||
class_alias, class_obscure, class_user, class_maintenance,
|
||||
class_pseudo, class_tui, class_xdb
|
||||
};
|
||||
struct re_pattern_buffer;
|
||||
|
||||
#if 0
|
||||
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
|
||||
cmd_types'' can be moved from "command.h" to "cli-decode.h". */
|
||||
/* Not a set/show command. Note that some commands which begin with
|
||||
"set" or "show" might be in this category, if their syntax does
|
||||
not fall into one of the following categories. */
|
||||
|
|
@ -48,55 +37,7 @@ typedef enum cmd_types
|
|||
show_cmd
|
||||
}
|
||||
cmd_types;
|
||||
|
||||
/* Reasonable values for an AUTO_BOOLEAN variable. */
|
||||
enum cmd_auto_boolean
|
||||
{
|
||||
CMD_AUTO_BOOLEAN_TRUE,
|
||||
CMD_AUTO_BOOLEAN_FALSE,
|
||||
CMD_AUTO_BOOLEAN_AUTO
|
||||
};
|
||||
|
||||
/* Types of "set" or "show" command. */
|
||||
typedef enum var_types
|
||||
{
|
||||
/* "on" or "off". *VAR is an integer which is nonzero for on,
|
||||
zero for off. */
|
||||
var_boolean,
|
||||
|
||||
/* "on" / "true" / "enable" or "off" / "false" / "disable" or
|
||||
"auto. *VAR is an ``enum cmd_auto_boolean''. NOTE: In general
|
||||
a custom show command will need to be implemented - one that
|
||||
for "auto" prints both the "auto" and the current auto-selected
|
||||
value. */
|
||||
var_auto_boolean,
|
||||
|
||||
/* Unsigned Integer. *VAR is an unsigned int. The user can type 0
|
||||
to mean "unlimited", which is stored in *VAR as UINT_MAX. */
|
||||
var_uinteger,
|
||||
|
||||
/* Like var_uinteger but signed. *VAR is an int. The user can type 0
|
||||
to mean "unlimited", which is stored in *VAR as INT_MAX. */
|
||||
var_integer,
|
||||
|
||||
/* String which the user enters with escapes (e.g. the user types \n and
|
||||
it is a real newline in the stored string).
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_string,
|
||||
/* String which stores what the user types verbatim.
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_string_noescape,
|
||||
/* String which stores a filename.
|
||||
*VAR is a malloc'd string, or NULL if the string is empty. */
|
||||
var_filename,
|
||||
/* ZeroableInteger. *VAR is an int. Like Unsigned Integer except
|
||||
that zero really means zero. */
|
||||
var_zinteger,
|
||||
/* Enumerated type. Can only have one of the specified values. *VAR is a
|
||||
char pointer to the name of the element that we find. */
|
||||
var_enum
|
||||
}
|
||||
var_types;
|
||||
#endif
|
||||
|
||||
/* This structure records one command'd definition. */
|
||||
|
||||
|
|
@ -130,15 +71,17 @@ struct cmd_list_element
|
|||
to one of the below. */
|
||||
union
|
||||
{
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
void (*cfunc) (char *args, int from_tty);
|
||||
|
||||
/* If type is set_cmd or show_cmd, first set the variables, and
|
||||
then call this. */
|
||||
void (*sfunc) (char *args, int from_tty, struct cmd_list_element * c);
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
cmd_cfunc_ftype *cfunc;
|
||||
/* If type is set_cmd or show_cmd, first set the variables,
|
||||
and then call this: */
|
||||
cmd_sfunc_ftype *sfunc;
|
||||
}
|
||||
function;
|
||||
|
||||
/* Local state (context) for this command. This can be anything. */
|
||||
void *context;
|
||||
|
||||
/* Documentation of this command (or help topic).
|
||||
First line is brief documentation; remaining lines form, with it,
|
||||
the full documentation. First line should end with a period.
|
||||
|
|
@ -286,11 +229,18 @@ extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
|||
void (*sfunc) (char *args, int from_tty,
|
||||
struct cmd_list_element * c));
|
||||
|
||||
extern void set_cmd_completer (struct cmd_list_element *cmd,
|
||||
char **(*completer) (char *text, char *word));
|
||||
|
||||
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
|
||||
around in cmd objects to test the value of the commands sfunc(). */
|
||||
extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
|
||||
/* Access to the command's local context. */
|
||||
extern void set_cmd_context (struct cmd_list_element *cmd, void *context);
|
||||
extern void *get_cmd_context (struct cmd_list_element *cmd);
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd (char **,
|
||||
struct cmd_list_element *, char *,
|
||||
int, int);
|
||||
|
|
@ -345,18 +295,6 @@ extern struct cmd_list_element *add_set_enum_cmd (char *name,
|
|||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_set_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum cmd_auto_boolean *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_set_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_show_from_set (struct cmd_list_element *,
|
||||
struct cmd_list_element
|
||||
**);
|
||||
|
|
|
|||
796
contrib/gdb/gdb/cli/cli-dump.c
Normal file
796
contrib/gdb/gdb/cli/cli-dump.c
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
/* Dump-to-file commands, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Red Hat.
|
||||
|
||||
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 "gdb_string.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "value.h"
|
||||
#include "completer.h"
|
||||
#include "cli/cli-dump.h"
|
||||
#include "gdb_assert.h"
|
||||
#include <ctype.h>
|
||||
#include "target.h"
|
||||
#include "readline/readline.h"
|
||||
|
||||
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
|
||||
|
||||
|
||||
char *
|
||||
skip_spaces (char *chp)
|
||||
{
|
||||
if (chp == NULL)
|
||||
return NULL;
|
||||
while (isspace (*chp))
|
||||
chp++;
|
||||
return chp;
|
||||
}
|
||||
|
||||
char *
|
||||
scan_expression_with_cleanup (char **cmd, const char *def)
|
||||
{
|
||||
if ((*cmd) == NULL || (**cmd) == '\0')
|
||||
{
|
||||
char *exp = xstrdup (def);
|
||||
make_cleanup (xfree, exp);
|
||||
return exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *exp;
|
||||
char *end;
|
||||
|
||||
end = (*cmd) + strcspn (*cmd, " \t");
|
||||
exp = savestring ((*cmd), end - (*cmd));
|
||||
make_cleanup (xfree, exp);
|
||||
(*cmd) = skip_spaces (end);
|
||||
return exp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_fclose_cleanup (void *arg)
|
||||
{
|
||||
FILE *file = arg;
|
||||
fclose (arg);
|
||||
}
|
||||
|
||||
static struct cleanup *
|
||||
make_cleanup_fclose (FILE *file)
|
||||
{
|
||||
return make_cleanup (do_fclose_cleanup, file);
|
||||
}
|
||||
|
||||
char *
|
||||
scan_filename_with_cleanup (char **cmd, const char *defname)
|
||||
{
|
||||
char *filename;
|
||||
char *fullname;
|
||||
|
||||
/* FIXME: Need to get the ``/a(ppend)'' flag from somewhere. */
|
||||
|
||||
/* File. */
|
||||
if ((*cmd) == NULL)
|
||||
{
|
||||
if (defname == NULL)
|
||||
error ("Missing filename.");
|
||||
filename = xstrdup (defname);
|
||||
make_cleanup (xfree, filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: should parse a possibly quoted string. */
|
||||
char *end;
|
||||
|
||||
(*cmd) = skip_spaces (*cmd);
|
||||
end = *cmd + strcspn (*cmd, " \t");
|
||||
filename = savestring ((*cmd), end - (*cmd));
|
||||
make_cleanup (xfree, filename);
|
||||
(*cmd) = skip_spaces (end);
|
||||
}
|
||||
gdb_assert (filename != NULL);
|
||||
|
||||
fullname = tilde_expand (filename);
|
||||
make_cleanup (xfree, fullname);
|
||||
|
||||
return fullname;
|
||||
}
|
||||
|
||||
FILE *
|
||||
fopen_with_cleanup (char *filename, const char *mode)
|
||||
{
|
||||
FILE *file = fopen (filename, mode);
|
||||
if (file == NULL)
|
||||
perror_with_name (filename);
|
||||
make_cleanup_fclose (file);
|
||||
return file;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
bfd_openr_with_cleanup (const char *filename, const char *target)
|
||||
{
|
||||
bfd *ibfd;
|
||||
|
||||
ibfd = bfd_openr (filename, target);
|
||||
if (ibfd == NULL)
|
||||
error ("Failed to open %s: %s.", filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
make_cleanup_bfd_close (ibfd);
|
||||
if (!bfd_check_format (ibfd, bfd_object))
|
||||
error ("'%s' is not a recognized file format.", filename);
|
||||
|
||||
return ibfd;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
bfd_openw_with_cleanup (char *filename, const char *target, char *mode)
|
||||
{
|
||||
bfd *obfd;
|
||||
|
||||
if (*mode == 'w') /* Write: create new file */
|
||||
{
|
||||
obfd = bfd_openw (filename, target);
|
||||
if (obfd == NULL)
|
||||
error ("Failed to open %s: %s.", filename,
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
make_cleanup_bfd_close (obfd);
|
||||
if (!bfd_set_format (obfd, bfd_object))
|
||||
error ("bfd_openw_with_cleanup: %s.", bfd_errmsg (bfd_get_error ()));
|
||||
}
|
||||
else if (*mode == 'a') /* Append to existing file */
|
||||
{ /* FIXME -- doesn't work... */
|
||||
error ("bfd_openw does not work with append.");
|
||||
}
|
||||
else
|
||||
error ("bfd_openw_with_cleanup: unknown mode %s.", mode);
|
||||
|
||||
return obfd;
|
||||
}
|
||||
|
||||
struct cmd_list_element *dump_cmdlist;
|
||||
struct cmd_list_element *append_cmdlist;
|
||||
struct cmd_list_element *srec_cmdlist;
|
||||
struct cmd_list_element *ihex_cmdlist;
|
||||
struct cmd_list_element *tekhex_cmdlist;
|
||||
struct cmd_list_element *binary_dump_cmdlist;
|
||||
struct cmd_list_element *binary_append_cmdlist;
|
||||
|
||||
static void
|
||||
dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump\" must be followed by a subcommand.\n\n");
|
||||
help_list (dump_cmdlist, "dump ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
append_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"append\" must be followed by a subcommand.\n\n");
|
||||
help_list (dump_cmdlist, "append ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_file (char *filename, char *mode,
|
||||
char *buf, int len)
|
||||
{
|
||||
FILE *file;
|
||||
int status;
|
||||
|
||||
file = fopen_with_cleanup (filename, mode);
|
||||
status = fwrite (buf, len, 1, file);
|
||||
if (status != 1)
|
||||
perror_with_name (filename);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_bfd_file (char *filename, char *mode,
|
||||
char *target, CORE_ADDR vaddr,
|
||||
char *buf, int len)
|
||||
{
|
||||
bfd *obfd;
|
||||
asection *osection;
|
||||
|
||||
obfd = bfd_openw_with_cleanup (filename, target, mode);
|
||||
osection = bfd_make_section_anyway (obfd, ".newsec");
|
||||
bfd_set_section_size (obfd, osection, len);
|
||||
bfd_set_section_vma (obfd, osection, vaddr);
|
||||
bfd_set_section_alignment (obfd, osection, 0);
|
||||
bfd_set_section_flags (obfd, osection, 0x203);
|
||||
osection->entsize = 0;
|
||||
bfd_set_section_contents (obfd, osection, buf, 0, len);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_memory_to_file (char *cmd, char *mode, char *file_format)
|
||||
{
|
||||
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
|
||||
CORE_ADDR lo;
|
||||
CORE_ADDR hi;
|
||||
ULONGEST count;
|
||||
char *filename;
|
||||
void *buf;
|
||||
char *lo_exp;
|
||||
char *hi_exp;
|
||||
int len;
|
||||
|
||||
/* Open the file. */
|
||||
filename = scan_filename_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the low address. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("Missing start address.");
|
||||
lo_exp = scan_expression_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the second address - rest of line. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("Missing stop address.");
|
||||
hi_exp = cmd;
|
||||
|
||||
lo = parse_and_eval_address (lo_exp);
|
||||
hi = parse_and_eval_address (hi_exp);
|
||||
if (hi <= lo)
|
||||
error ("Invalid memory address range (start >= end).");
|
||||
count = hi - lo;
|
||||
|
||||
/* FIXME: Should use read_memory_partial() and a magic blocking
|
||||
value. */
|
||||
buf = xmalloc (count);
|
||||
make_cleanup (xfree, buf);
|
||||
target_read_memory (lo, buf, count);
|
||||
|
||||
/* Have everything. Open/write the data. */
|
||||
if (file_format == NULL || strcmp (file_format, "binary") == 0)
|
||||
{
|
||||
dump_binary_file (filename, mode, buf, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_bfd_file (filename, mode, file_format, lo, buf, count);
|
||||
}
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_memory_command (char *cmd, char *mode)
|
||||
{
|
||||
dump_memory_to_file (cmd, mode, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_value_to_file (char *cmd, char *mode, char *file_format)
|
||||
{
|
||||
struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
|
||||
struct value *val;
|
||||
char *filename;
|
||||
|
||||
/* Open the file. */
|
||||
filename = scan_filename_with_cleanup (&cmd, NULL);
|
||||
|
||||
/* Find the value. */
|
||||
if (cmd == NULL || *cmd == '\0')
|
||||
error ("No value to %s.", *mode == 'a' ? "append" : "dump");
|
||||
val = parse_and_eval (cmd);
|
||||
if (val == NULL)
|
||||
error ("Invalid expression.");
|
||||
|
||||
/* Have everything. Open/write the data. */
|
||||
if (file_format == NULL || strcmp (file_format, "binary") == 0)
|
||||
{
|
||||
dump_binary_file (filename, mode, VALUE_CONTENTS (val),
|
||||
TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_ADDR vaddr;
|
||||
|
||||
if (VALUE_LVAL (val))
|
||||
{
|
||||
vaddr = VALUE_ADDRESS (val);
|
||||
}
|
||||
else
|
||||
{
|
||||
vaddr = 0;
|
||||
warning ("value is not an lval: address assumed to be zero");
|
||||
}
|
||||
|
||||
dump_bfd_file (filename, mode, file_format, vaddr,
|
||||
VALUE_CONTENTS (val),
|
||||
TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
}
|
||||
|
||||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_value_command (char *cmd, char *mode)
|
||||
{
|
||||
dump_value_to_file (cmd, mode, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_srec_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_srec_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "srec");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_ihex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "ihex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_tekhex_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "tekhex");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_WB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
dump_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_WB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_memory (char *args, int from_tty)
|
||||
{
|
||||
dump_memory_to_file (args, FOPEN_AB, "binary");
|
||||
}
|
||||
|
||||
static void
|
||||
append_binary_value (char *args, int from_tty)
|
||||
{
|
||||
dump_value_to_file (args, FOPEN_AB, "binary");
|
||||
}
|
||||
|
||||
struct dump_context
|
||||
{
|
||||
void (*func) (char *cmd, char *mode);
|
||||
char *mode;
|
||||
};
|
||||
|
||||
static void
|
||||
call_dump_func (struct cmd_list_element *c, char *args, int from_tty)
|
||||
{
|
||||
struct dump_context *d = get_cmd_context (c);
|
||||
d->func (args, d->mode);
|
||||
}
|
||||
|
||||
void
|
||||
add_dump_command (char *name, void (*func) (char *args, char *mode),
|
||||
char *descr)
|
||||
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
struct dump_context *d;
|
||||
|
||||
c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist);
|
||||
c->completer = filename_completer;
|
||||
d = XMALLOC (struct dump_context);
|
||||
d->func = func;
|
||||
d->mode = FOPEN_WB;
|
||||
set_cmd_context (c, d);
|
||||
c->func = call_dump_func;
|
||||
|
||||
c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist);
|
||||
c->completer = filename_completer;
|
||||
d = XMALLOC (struct dump_context);
|
||||
d->func = func;
|
||||
d->mode = FOPEN_AB;
|
||||
set_cmd_context (c, d);
|
||||
c->func = call_dump_func;
|
||||
|
||||
/* Replace "Dump " at start of docstring with "Append "
|
||||
(borrowed from add_show_from_set). */
|
||||
if ( c->doc[0] == 'W'
|
||||
&& c->doc[1] == 'r'
|
||||
&& c->doc[2] == 'i'
|
||||
&& c->doc[3] == 't'
|
||||
&& c->doc[4] == 'e'
|
||||
&& c->doc[5] == ' ')
|
||||
c->doc = concat ("Append ", c->doc + 6, NULL);
|
||||
}
|
||||
|
||||
/* Opaque data for restore_section_callback. */
|
||||
struct callback_data {
|
||||
unsigned long load_offset;
|
||||
CORE_ADDR load_start;
|
||||
CORE_ADDR load_end;
|
||||
};
|
||||
|
||||
/* Function: restore_section_callback.
|
||||
|
||||
Callback function for bfd_map_over_sections.
|
||||
Selectively loads the sections into memory. */
|
||||
|
||||
static void
|
||||
restore_section_callback (bfd *ibfd, asection *isec, void *args)
|
||||
{
|
||||
struct callback_data *data = args;
|
||||
bfd_vma sec_start = bfd_section_vma (ibfd, isec);
|
||||
bfd_size_type size = bfd_section_size (ibfd, isec);
|
||||
bfd_vma sec_end = sec_start + size;
|
||||
bfd_size_type sec_offset = 0;
|
||||
bfd_size_type sec_load_count = size;
|
||||
struct cleanup *old_chain;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
/* Ignore non-loadable sections, eg. from elf files. */
|
||||
if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
|
||||
return;
|
||||
|
||||
/* Does the section overlap with the desired restore range? */
|
||||
if (sec_end <= data->load_start
|
||||
|| (data->load_end > 0 && sec_start >= data->load_end))
|
||||
{
|
||||
/* No, no useable data in this section. */
|
||||
printf_filtered ("skipping section %s...\n",
|
||||
bfd_section_name (ibfd, isec));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compare section address range with user-requested
|
||||
address range (if any). Compute where the actual
|
||||
transfer should start and end. */
|
||||
if (sec_start < data->load_start)
|
||||
sec_offset = data->load_start - sec_start;
|
||||
/* Size of a partial transfer: */
|
||||
sec_load_count -= sec_offset;
|
||||
if (data->load_end > 0 && sec_end > data->load_end)
|
||||
sec_load_count -= sec_end - data->load_end;
|
||||
|
||||
/* Get the data. */
|
||||
buf = xmalloc (size);
|
||||
old_chain = make_cleanup (xfree, buf);
|
||||
if (!bfd_get_section_contents (ibfd, isec, buf, 0, size))
|
||||
error ("Failed to read bfd file %s: '%s'.", bfd_get_filename (ibfd),
|
||||
bfd_errmsg (bfd_get_error ()));
|
||||
|
||||
printf_filtered ("Restoring section %s (0x%lx to 0x%lx)",
|
||||
bfd_section_name (ibfd, isec),
|
||||
(unsigned long) sec_start,
|
||||
(unsigned long) sec_end);
|
||||
|
||||
if (data->load_offset != 0 || data->load_start != 0 || data->load_end != 0)
|
||||
printf_filtered (" into memory (0x%s to 0x%s)\n",
|
||||
paddr_nz ((unsigned long) sec_start
|
||||
+ sec_offset + data->load_offset),
|
||||
paddr_nz ((unsigned long) sec_start + sec_offset
|
||||
+ data->load_offset + sec_load_count));
|
||||
else
|
||||
puts_filtered ("\n");
|
||||
|
||||
/* Write the data. */
|
||||
ret = target_write_memory (sec_start + sec_offset + data->load_offset,
|
||||
buf + sec_offset, sec_load_count);
|
||||
if (ret != 0)
|
||||
warning ("restore: memory write failed (%s).", safe_strerror (ret));
|
||||
do_cleanups (old_chain);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_binary_file (char *filename, struct callback_data *data)
|
||||
{
|
||||
FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
|
||||
int status;
|
||||
char *buf;
|
||||
long len;
|
||||
|
||||
/* Get the file size for reading. */
|
||||
if (fseek (file, 0, SEEK_END) == 0)
|
||||
len = ftell (file);
|
||||
else
|
||||
perror_with_name (filename);
|
||||
|
||||
if (len <= data->load_start)
|
||||
error ("Start address is greater than length of binary file %s.",
|
||||
filename);
|
||||
|
||||
/* Chop off "len" if it exceeds the requested load_end addr. */
|
||||
if (data->load_end != 0 && data->load_end < len)
|
||||
len = data->load_end;
|
||||
/* Chop off "len" if the requested load_start addr skips some bytes. */
|
||||
if (data->load_start > 0)
|
||||
len -= data->load_start;
|
||||
|
||||
printf_filtered
|
||||
("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
|
||||
filename,
|
||||
(unsigned long) data->load_start + data->load_offset,
|
||||
(unsigned long) data->load_start + data->load_offset + len);
|
||||
|
||||
/* Now set the file pos to the requested load start pos. */
|
||||
if (fseek (file, data->load_start, SEEK_SET) != 0)
|
||||
perror_with_name (filename);
|
||||
|
||||
/* Now allocate a buffer and read the file contents. */
|
||||
buf = xmalloc (len);
|
||||
make_cleanup (xfree, buf);
|
||||
if (fread (buf, 1, len, file) != len)
|
||||
perror_with_name (filename);
|
||||
|
||||
/* Now write the buffer into target memory. */
|
||||
len = target_write_memory (data->load_start + data->load_offset, buf, len);
|
||||
if (len != 0)
|
||||
warning ("restore: memory write failed (%s).", safe_strerror (len));
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
restore_command (char *args, int from_tty)
|
||||
{
|
||||
char *filename;
|
||||
struct callback_data data;
|
||||
bfd *ibfd;
|
||||
int binary_flag = 0;
|
||||
|
||||
if (!target_has_execution)
|
||||
noprocess ();
|
||||
|
||||
data.load_offset = 0;
|
||||
data.load_start = 0;
|
||||
data.load_end = 0;
|
||||
|
||||
/* Parse the input arguments. First is filename (required). */
|
||||
filename = scan_filename_with_cleanup (&args, NULL);
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
char *binary_string = "binary";
|
||||
|
||||
/* Look for optional "binary" flag. */
|
||||
if (strncmp (args, binary_string, strlen (binary_string)) == 0)
|
||||
{
|
||||
binary_flag = 1;
|
||||
args += strlen (binary_string);
|
||||
args = skip_spaces (args);
|
||||
}
|
||||
/* Parse offset (optional). */
|
||||
if (args != NULL && *args != '\0')
|
||||
data.load_offset =
|
||||
parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
/* Parse start address (optional). */
|
||||
data.load_start =
|
||||
parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
|
||||
if (args != NULL && *args != '\0')
|
||||
{
|
||||
/* Parse end address (optional). */
|
||||
data.load_end = parse_and_eval_long (args);
|
||||
if (data.load_end <= data.load_start)
|
||||
error ("Start must be less than end.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info_verbose)
|
||||
printf_filtered ("Restore file %s offset 0x%lx start 0x%lx end 0x%lx\n",
|
||||
filename, (unsigned long) data.load_offset,
|
||||
(unsigned long) data.load_start,
|
||||
(unsigned long) data.load_end);
|
||||
|
||||
if (binary_flag)
|
||||
{
|
||||
restore_binary_file (filename, &data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Open the file for loading. */
|
||||
ibfd = bfd_openr_with_cleanup (filename, NULL);
|
||||
|
||||
/* Process the sections. */
|
||||
bfd_map_over_sections (ibfd, restore_section_callback, &data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
srec_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump srec\" must be followed by a subcommand.\n");
|
||||
help_list (srec_cmdlist, "dump srec ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
ihex_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump ihex\" must be followed by a subcommand.\n");
|
||||
help_list (ihex_cmdlist, "dump ihex ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
tekhex_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump tekhex\" must be followed by a subcommand.\n");
|
||||
help_list (tekhex_cmdlist, "dump tekhex ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
binary_dump_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"dump binary\" must be followed by a subcommand.\n");
|
||||
help_list (binary_dump_cmdlist, "dump binary ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
binary_append_command (char *cmd, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"append binary\" must be followed by a subcommand.\n");
|
||||
help_list (binary_append_cmdlist, "append binary ", -1, gdb_stdout);
|
||||
}
|
||||
|
||||
extern initialize_file_ftype _initialize_cli_dump; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
_initialize_cli_dump (void)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
add_prefix_cmd ("dump", class_vars, dump_command, "\
|
||||
Dump target code/data to a local file.",
|
||||
&dump_cmdlist, "dump ",
|
||||
0/*allow-unknown*/,
|
||||
&cmdlist);
|
||||
add_prefix_cmd ("append", class_vars, append_command, "\
|
||||
Append target code/data to a local file.",
|
||||
&append_cmdlist, "append ",
|
||||
0/*allow-unknown*/,
|
||||
&cmdlist);
|
||||
|
||||
add_dump_command ("memory", dump_memory_command, "\
|
||||
Write contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within the\n\
|
||||
range [START .. STOP) to the specifed FILE in raw target ordered bytes.");
|
||||
|
||||
add_dump_command ("value", dump_value_command, "\
|
||||
Write the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION to\n\
|
||||
the specified FILE in raw target ordered bytes.");
|
||||
|
||||
add_prefix_cmd ("srec", all_commands, srec_dump_command, "\
|
||||
Write target code/data to an srec file.",
|
||||
&srec_cmdlist, "dump srec ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("ihex", all_commands, ihex_dump_command, "\
|
||||
Write target code/data to an intel hex file.",
|
||||
&ihex_cmdlist, "dump ihex ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("tekhex", all_commands, tekhex_dump_command, "\
|
||||
Write target code/data to a tekhex file.",
|
||||
&tekhex_cmdlist, "dump tekhex ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("binary", all_commands, binary_dump_command, "\
|
||||
Write target code/data to a raw binary file.",
|
||||
&binary_dump_cmdlist, "dump binary ",
|
||||
0 /*allow-unknown*/,
|
||||
&dump_cmdlist);
|
||||
|
||||
add_prefix_cmd ("binary", all_commands, binary_append_command, "\
|
||||
Append target code/data to a raw binary file.",
|
||||
&binary_append_cmdlist, "append binary ",
|
||||
0 /*allow-unknown*/,
|
||||
&append_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_srec_memory, "\
|
||||
Write contents of memory to an srec file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in srec format.",
|
||||
&srec_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_srec_value, "\
|
||||
Write the value of an expression to an srec file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in srec format.",
|
||||
&srec_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_ihex_memory, "\
|
||||
Write contents of memory to an ihex file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within\n\
|
||||
the range [START .. STOP) to the specifed FILE in intel hex format.",
|
||||
&ihex_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_ihex_value, "\
|
||||
Write the value of an expression to an ihex file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in intel hex format.",
|
||||
&ihex_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_tekhex_memory, "\
|
||||
Write contents of memory to a tekhex file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in tekhex format.",
|
||||
&tekhex_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_tekhex_value, "\
|
||||
Write the value of an expression to a tekhex file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in tekhex format.",
|
||||
&tekhex_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, dump_binary_memory, "\
|
||||
Write contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory\n\
|
||||
within the range [START .. STOP) to the specifed FILE in binary format.",
|
||||
&binary_dump_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, dump_binary_value, "\
|
||||
Write the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in raw target ordered bytes.",
|
||||
&binary_dump_cmdlist);
|
||||
|
||||
add_cmd ("memory", all_commands, append_binary_memory, "\
|
||||
Append contents of memory to a raw binary file.\n\
|
||||
Arguments are FILE START STOP. Writes the contents of memory within the\n\
|
||||
range [START .. STOP) to the specifed FILE in raw target ordered bytes.",
|
||||
&binary_append_cmdlist);
|
||||
|
||||
add_cmd ("value", all_commands, append_binary_value, "\
|
||||
Append the value of an expression to a raw binary file.\n\
|
||||
Arguments are FILE EXPRESSION. Writes the value of EXPRESSION\n\
|
||||
to the specified FILE in raw target ordered bytes.",
|
||||
&binary_append_cmdlist);
|
||||
|
||||
c = add_com ("restore", class_vars, restore_command,
|
||||
"Restore the contents of FILE to target memory.\n\
|
||||
Arguments are FILE OFFSET START END where all except FILE are optional.\n\
|
||||
OFFSET will be added to the base address of the file (default zero).\n\
|
||||
If START and END are given, only the file contents within that range\n\
|
||||
(file relative) will be restored to target memory.");
|
||||
c->completer = filename_completer;
|
||||
/* FIXME: completers for other commands. */
|
||||
}
|
||||
40
contrib/gdb/gdb/cli/cli-dump.h
Normal file
40
contrib/gdb/gdb/cli/cli-dump.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* Dump-to-file commands, for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2001 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 CLI_DUMP_H
|
||||
#define CLI_DUMP_H
|
||||
|
||||
extern void add_dump_command (char *name,
|
||||
void (*func) (char *args, char *mode),
|
||||
char *descr);
|
||||
|
||||
/* Utilities for doing the dump. */
|
||||
extern char *scan_filename_with_cleanup (char **cmd, const char *defname);
|
||||
|
||||
extern char *scan_expression_with_cleanup (char **cmd, const char *defname);
|
||||
|
||||
extern FILE *fopen_with_cleanup (char *filename, const char *mode);
|
||||
|
||||
extern char *skip_spaces (char *inp);
|
||||
|
||||
extern struct value *parse_and_eval_with_error (char *exp, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
|
||||
|
||||
#endif
|
||||
157
contrib/gdb/gdb/cli/cli-interp.c
Normal file
157
contrib/gdb/gdb/cli/cli-interp.c
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/* CLI Definitions for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2002, 2003 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 "interps.h"
|
||||
#include "wrapper.h"
|
||||
#include "event-top.h"
|
||||
#include "ui-out.h"
|
||||
#include "cli-out.h"
|
||||
#include "top.h" /* for "execute_command" */
|
||||
#include "gdb_string.h"
|
||||
|
||||
struct ui_out *cli_uiout;
|
||||
|
||||
/* These are the ui_out and the interpreter for the console interpreter. */
|
||||
|
||||
/* Longjmp-safe wrapper for "execute_command" */
|
||||
static int do_captured_execute_command (struct ui_out *uiout, void *data);
|
||||
static enum gdb_rc safe_execute_command (struct ui_out *uiout, char *command,
|
||||
int from_tty);
|
||||
struct captured_execute_command_args
|
||||
{
|
||||
char *command;
|
||||
int from_tty;
|
||||
};
|
||||
|
||||
/* These implement the cli out interpreter: */
|
||||
|
||||
static void *
|
||||
cli_interpreter_init (void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_resume (void *data)
|
||||
{
|
||||
struct ui_file *stream;
|
||||
|
||||
/*sync_execution = 1; */
|
||||
|
||||
/* gdb_setup_readline will change gdb_stdout. If the CLI was previously
|
||||
writing to gdb_stdout, then set it to the new gdb_stdout afterwards. */
|
||||
|
||||
stream = cli_out_set_stream (cli_uiout, gdb_stdout);
|
||||
if (stream != gdb_stdout)
|
||||
{
|
||||
cli_out_set_stream (cli_uiout, stream);
|
||||
stream = NULL;
|
||||
}
|
||||
|
||||
gdb_setup_readline ();
|
||||
|
||||
if (stream != NULL)
|
||||
cli_out_set_stream (cli_uiout, gdb_stdout);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_suspend (void *data)
|
||||
{
|
||||
gdb_disable_readline ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Don't display the prompt if we are set quiet. */
|
||||
static int
|
||||
cli_interpreter_display_prompt_p (void *data)
|
||||
{
|
||||
if (interp_quiet_p (NULL))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
cli_interpreter_exec (void *data, const char *command_str)
|
||||
{
|
||||
int result;
|
||||
struct ui_file *old_stream;
|
||||
|
||||
/* FIXME: cagney/2003-02-01: Need to const char *propogate
|
||||
safe_execute_command. */
|
||||
char *str = strcpy (alloca (strlen (command_str) + 1), command_str);
|
||||
|
||||
/* gdb_stdout could change between the time cli_uiout was initialized
|
||||
and now. Since we're probably using a different interpreter which has
|
||||
a new ui_file for gdb_stdout, use that one instead of the default.
|
||||
|
||||
It is important that it gets reset everytime, since the user could
|
||||
set gdb to use a different interpreter. */
|
||||
old_stream = cli_out_set_stream (cli_uiout, gdb_stdout);
|
||||
result = safe_execute_command (cli_uiout, str, 1);
|
||||
cli_out_set_stream (cli_uiout, old_stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
do_captured_execute_command (struct ui_out *uiout, void *data)
|
||||
{
|
||||
struct captured_execute_command_args *args =
|
||||
(struct captured_execute_command_args *) data;
|
||||
execute_command (args->command, args->from_tty);
|
||||
return GDB_RC_OK;
|
||||
}
|
||||
|
||||
static enum gdb_rc
|
||||
safe_execute_command (struct ui_out *uiout, char *command, int from_tty)
|
||||
{
|
||||
struct captured_execute_command_args args;
|
||||
args.command = command;
|
||||
args.from_tty = from_tty;
|
||||
return catch_exceptions (uiout, do_captured_execute_command, &args,
|
||||
NULL, RETURN_MASK_ALL);
|
||||
}
|
||||
|
||||
|
||||
/* standard gdb initialization hook */
|
||||
extern initialize_file_ftype _initialize_cli_interp; /* -Wmissing-prototypes */
|
||||
|
||||
void
|
||||
_initialize_cli_interp (void)
|
||||
{
|
||||
static const struct interp_procs procs = {
|
||||
cli_interpreter_init, /* init_proc */
|
||||
cli_interpreter_resume, /* resume_proc */
|
||||
cli_interpreter_suspend, /* suspend_proc */
|
||||
cli_interpreter_exec, /* exec_proc */
|
||||
cli_interpreter_display_prompt_p /* prompt_proc_p */
|
||||
};
|
||||
struct interp *cli_interp;
|
||||
|
||||
/* Create a default uiout builder for the CLI. */
|
||||
cli_uiout = cli_out_new (gdb_stdout);
|
||||
cli_interp = interp_new (INTERP_CONSOLE, NULL, cli_uiout, &procs);
|
||||
|
||||
interp_add (cli_interp);
|
||||
}
|
||||
205
contrib/gdb/gdb/cli/cli-logging.c
Normal file
205
contrib/gdb/gdb/cli/cli-logging.c
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/* Command-line output logging for GDB, the GNU debugger.
|
||||
|
||||
Copyright 2003
|
||||
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 "gdbcmd.h"
|
||||
#include "ui-out.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
|
||||
/* These hold the pushed copies of the gdb output files.
|
||||
If NULL then nothing has yet been pushed. */
|
||||
struct saved_output_files
|
||||
{
|
||||
struct ui_file *out;
|
||||
struct ui_file *err;
|
||||
struct ui_file *log;
|
||||
struct ui_file *targ;
|
||||
};
|
||||
static struct saved_output_files saved_output;
|
||||
static char *saved_filename;
|
||||
|
||||
static char *logging_filename;
|
||||
int logging_overwrite, logging_redirect;
|
||||
|
||||
/* If we've pushed output files, close them and pop them. */
|
||||
static void
|
||||
pop_output_files (void)
|
||||
{
|
||||
/* Only delete one of the files -- they are all set to the same
|
||||
value. */
|
||||
ui_file_delete (gdb_stdout);
|
||||
gdb_stdout = saved_output.out;
|
||||
gdb_stderr = saved_output.err;
|
||||
gdb_stdlog = saved_output.log;
|
||||
gdb_stdtarg = saved_output.targ;
|
||||
saved_output.out = NULL;
|
||||
saved_output.err = NULL;
|
||||
saved_output.log = NULL;
|
||||
saved_output.targ = NULL;
|
||||
|
||||
ui_out_redirect (uiout, NULL);
|
||||
}
|
||||
|
||||
/* This is a helper for the `set logging' command. */
|
||||
static void
|
||||
handle_redirections (int from_tty)
|
||||
{
|
||||
struct ui_file *output;
|
||||
|
||||
if (saved_filename != NULL)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n",
|
||||
saved_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a");
|
||||
if (output == NULL)
|
||||
perror_with_name ("set logging");
|
||||
|
||||
/* Redirects everything to gdb_stdout while this is running. */
|
||||
if (!logging_redirect)
|
||||
{
|
||||
output = tee_file_new (gdb_stdout, 0, output, 1);
|
||||
if (output == NULL)
|
||||
perror_with_name ("set logging");
|
||||
if (from_tty)
|
||||
fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
|
||||
logging_filename);
|
||||
}
|
||||
else if (from_tty)
|
||||
fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
|
||||
logging_filename);
|
||||
|
||||
saved_filename = xstrdup (logging_filename);
|
||||
saved_output.out = gdb_stdout;
|
||||
saved_output.err = gdb_stderr;
|
||||
saved_output.log = gdb_stdlog;
|
||||
saved_output.targ = gdb_stdtarg;
|
||||
|
||||
gdb_stdout = output;
|
||||
gdb_stderr = output;
|
||||
gdb_stdlog = output;
|
||||
gdb_stdtarg = output;
|
||||
|
||||
if (ui_out_redirect (uiout, gdb_stdout) < 0)
|
||||
warning ("Current output protocol does not support redirection");
|
||||
}
|
||||
|
||||
static void
|
||||
set_logging_on (char *args, int from_tty)
|
||||
{
|
||||
char *rest = args;
|
||||
if (rest && *rest)
|
||||
{
|
||||
xfree (logging_filename);
|
||||
logging_filename = xstrdup (rest);
|
||||
}
|
||||
handle_redirections (from_tty);
|
||||
}
|
||||
|
||||
static void
|
||||
set_logging_off (char *args, int from_tty)
|
||||
{
|
||||
if (saved_filename == NULL)
|
||||
return;
|
||||
|
||||
pop_output_files ();
|
||||
if (from_tty)
|
||||
fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename);
|
||||
xfree (saved_filename);
|
||||
saved_filename = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_logging_command (char *args, int from_tty)
|
||||
{
|
||||
printf_unfiltered ("\"set logging\" lets you log output to a file.\n");
|
||||
printf_unfiltered ("Usage: set logging on [FILENAME]\n");
|
||||
printf_unfiltered (" set logging off\n");
|
||||
printf_unfiltered (" set logging file FILENAME\n");
|
||||
printf_unfiltered (" set logging overwrite [on|off]\n");
|
||||
printf_unfiltered (" set logging redirect [on|off]\n");
|
||||
}
|
||||
|
||||
void
|
||||
show_logging_command (char *args, int from_tty)
|
||||
{
|
||||
if (saved_filename)
|
||||
printf_unfiltered ("Currently logging to \"%s\".\n", saved_filename);
|
||||
if (saved_filename == NULL
|
||||
|| strcmp (logging_filename, saved_filename) != 0)
|
||||
printf_unfiltered ("Future logs will be written to %s.\n",
|
||||
logging_filename);
|
||||
|
||||
if (logging_overwrite)
|
||||
printf_unfiltered ("Logs will overwrite the log file.\n");
|
||||
else
|
||||
printf_unfiltered ("Logs will be appended to the log file.\n");
|
||||
|
||||
if (logging_redirect)
|
||||
printf_unfiltered ("Output will be sent only to the log file.\n");
|
||||
else
|
||||
printf_unfiltered ("Output will be logged and displayed.\n");
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_cli_logging (void)
|
||||
{
|
||||
static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
|
||||
|
||||
|
||||
add_prefix_cmd ("logging", class_support, set_logging_command,
|
||||
"Set logging options", &set_logging_cmdlist,
|
||||
"set logging ", 0, &setlist);
|
||||
add_prefix_cmd ("logging", class_support, show_logging_command,
|
||||
"Show logging options", &show_logging_cmdlist,
|
||||
"show logging ", 0, &showlist);
|
||||
add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite,
|
||||
"Set whether logging overwrites or appends "
|
||||
"to the log file.\n",
|
||||
"Show whether logging overwrites or appends "
|
||||
"to the log file.\n",
|
||||
NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
|
||||
add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect,
|
||||
"Set the logging output mode.\n"
|
||||
"If redirect is off, output will go to both the "
|
||||
"screen and the log file.\n"
|
||||
"If redirect is on, output will go only to the log "
|
||||
"file.",
|
||||
"Show the logging output mode.\n"
|
||||
"If redirect is off, output will go to both the "
|
||||
"screen and the log file.\n"
|
||||
"If redirect is on, output will go only to the log "
|
||||
"file.",
|
||||
NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
|
||||
add_setshow_cmd ("file", class_support, var_filename, &logging_filename,
|
||||
"Set the current logfile.", "Show the current logfile.",
|
||||
NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist);
|
||||
add_cmd ("on", class_support, set_logging_on,
|
||||
"Enable logging.", &set_logging_cmdlist);
|
||||
add_cmd ("off", class_support, set_logging_off,
|
||||
"Disable logging.", &set_logging_cmdlist);
|
||||
|
||||
logging_filename = xstrdup ("gdb.txt");
|
||||
}
|
||||
|
|
@ -27,23 +27,15 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "ui-out.h"
|
||||
#include "gdb_string.h"
|
||||
|
||||
#include "top.h"
|
||||
#include "cli/cli-cmds.h"
|
||||
#include "cli/cli-decode.h"
|
||||
#include "cli/cli-script.h"
|
||||
|
||||
/* From gdb/top.c */
|
||||
|
||||
extern void dont_repeat (void);
|
||||
|
||||
extern void do_restore_instream_cleanup (void *stream);
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static struct cleanup *
|
||||
make_cleanup_free_command_lines (struct command_line **arg);
|
||||
|
||||
static enum command_control_type
|
||||
recurse_read_control_structure (struct command_line *current_cmd);
|
||||
|
||||
|
|
@ -213,14 +205,58 @@ print_command_lines (struct ui_out *uiout, struct command_line *cmd,
|
|||
} /* while (list) */
|
||||
}
|
||||
|
||||
/* Handle pre-post hooks. */
|
||||
|
||||
static void
|
||||
clear_hook_in_cleanup (void *data)
|
||||
{
|
||||
struct cmd_list_element *c = data;
|
||||
c->hook_in = 0; /* Allow hook to work again once it is complete */
|
||||
}
|
||||
|
||||
void
|
||||
execute_cmd_pre_hook (struct cmd_list_element *c)
|
||||
{
|
||||
if ((c->hook_pre) && (!c->hook_in))
|
||||
{
|
||||
struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c);
|
||||
c->hook_in = 1; /* Prevent recursive hooking */
|
||||
execute_user_command (c->hook_pre, (char *) 0);
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
execute_cmd_post_hook (struct cmd_list_element *c)
|
||||
{
|
||||
if ((c->hook_post) && (!c->hook_in))
|
||||
{
|
||||
struct cleanup *cleanups = make_cleanup (clear_hook_in_cleanup, c);
|
||||
c->hook_in = 1; /* Prevent recursive hooking */
|
||||
execute_user_command (c->hook_post, (char *) 0);
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute the command in CMD. */
|
||||
static void
|
||||
do_restore_user_call_depth (void * call_depth)
|
||||
{
|
||||
int * depth = call_depth;
|
||||
/* We will be returning_to_top_level() at this point, so we want to
|
||||
reset our depth. */
|
||||
(*depth) = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
execute_user_command (struct cmd_list_element *c, char *args)
|
||||
{
|
||||
register struct command_line *cmdlines;
|
||||
struct command_line *cmdlines;
|
||||
struct cleanup *old_chain;
|
||||
enum command_control_type ret;
|
||||
static int user_call_depth = 0;
|
||||
extern int max_user_call_depth;
|
||||
|
||||
old_chain = setup_user_args (args);
|
||||
|
||||
|
|
@ -229,6 +265,11 @@ execute_user_command (struct cmd_list_element *c, char *args)
|
|||
/* Null command */
|
||||
return;
|
||||
|
||||
if (++user_call_depth > max_user_call_depth)
|
||||
error ("Max user call depth exceeded -- command aborted\n");
|
||||
|
||||
old_chain = make_cleanup (do_restore_user_call_depth, &user_call_depth);
|
||||
|
||||
/* Set the instream to 0, indicating execution of a
|
||||
user-defined function. */
|
||||
old_chain = make_cleanup (do_restore_instream_cleanup, instream);
|
||||
|
|
@ -244,6 +285,8 @@ execute_user_command (struct cmd_list_element *c, char *args)
|
|||
cmdlines = cmdlines->next;
|
||||
}
|
||||
do_cleanups (old_chain);
|
||||
|
||||
user_call_depth--;
|
||||
}
|
||||
|
||||
enum command_control_type
|
||||
|
|
@ -251,21 +294,25 @@ execute_control_command (struct command_line *cmd)
|
|||
{
|
||||
struct expression *expr;
|
||||
struct command_line *current;
|
||||
struct cleanup *old_chain = 0;
|
||||
struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
|
||||
struct value *val;
|
||||
struct value *val_mark;
|
||||
int loop;
|
||||
enum command_control_type ret;
|
||||
char *new_line;
|
||||
|
||||
/* Start by assuming failure, if a problem is detected, the code
|
||||
below will simply "break" out of the switch. */
|
||||
ret = invalid_control;
|
||||
|
||||
switch (cmd->control_type)
|
||||
{
|
||||
case simple_control:
|
||||
/* A simple command, execute it and return. */
|
||||
new_line = insert_args (cmd->line);
|
||||
if (!new_line)
|
||||
return invalid_control;
|
||||
old_chain = make_cleanup (free_current_contents, &new_line);
|
||||
break;
|
||||
make_cleanup (free_current_contents, &new_line);
|
||||
execute_command (new_line, 0);
|
||||
ret = cmd->control_type;
|
||||
break;
|
||||
|
|
@ -282,8 +329,8 @@ execute_control_command (struct command_line *cmd)
|
|||
/* Parse the loop control expression for the while statement. */
|
||||
new_line = insert_args (cmd->line);
|
||||
if (!new_line)
|
||||
return invalid_control;
|
||||
old_chain = make_cleanup (free_current_contents, &new_line);
|
||||
break;
|
||||
make_cleanup (free_current_contents, &new_line);
|
||||
expr = parse_expression (new_line);
|
||||
make_cleanup (free_current_contents, &expr);
|
||||
|
||||
|
|
@ -342,8 +389,8 @@ execute_control_command (struct command_line *cmd)
|
|||
{
|
||||
new_line = insert_args (cmd->line);
|
||||
if (!new_line)
|
||||
return invalid_control;
|
||||
old_chain = make_cleanup (free_current_contents, &new_line);
|
||||
break;
|
||||
make_cleanup (free_current_contents, &new_line);
|
||||
/* Parse the conditional for the if statement. */
|
||||
expr = parse_expression (new_line);
|
||||
make_cleanup (free_current_contents, &expr);
|
||||
|
|
@ -381,11 +428,10 @@ execute_control_command (struct command_line *cmd)
|
|||
|
||||
default:
|
||||
warning ("Invalid control type in command structure.");
|
||||
return invalid_control;
|
||||
break;
|
||||
}
|
||||
|
||||
if (old_chain)
|
||||
do_cleanups (old_chain);
|
||||
do_cleanups (old_chain);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -928,8 +974,8 @@ read_command_lines (char *prompt_arg, int from_tty)
|
|||
void
|
||||
free_command_lines (struct command_line **lptr)
|
||||
{
|
||||
register struct command_line *l = *lptr;
|
||||
register struct command_line *next;
|
||||
struct command_line *l = *lptr;
|
||||
struct command_line *next;
|
||||
struct command_line **blist;
|
||||
int i;
|
||||
|
||||
|
|
@ -955,16 +1001,46 @@ do_free_command_lines_cleanup (void *arg)
|
|||
free_command_lines (arg);
|
||||
}
|
||||
|
||||
static struct cleanup *
|
||||
struct cleanup *
|
||||
make_cleanup_free_command_lines (struct command_line **arg)
|
||||
{
|
||||
return make_cleanup (do_free_command_lines_cleanup, arg);
|
||||
}
|
||||
|
||||
struct command_line *
|
||||
copy_command_lines (struct command_line *cmds)
|
||||
{
|
||||
struct command_line *result = NULL;
|
||||
|
||||
if (cmds)
|
||||
{
|
||||
result = (struct command_line *) xmalloc (sizeof (struct command_line));
|
||||
|
||||
result->next = copy_command_lines (cmds->next);
|
||||
result->line = xstrdup (cmds->line);
|
||||
result->control_type = cmds->control_type;
|
||||
result->body_count = cmds->body_count;
|
||||
if (cmds->body_count > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
result->body_list = (struct command_line **)
|
||||
xmalloc (sizeof (struct command_line *) * cmds->body_count);
|
||||
|
||||
for (i = 0; i < cmds->body_count; i++)
|
||||
result->body_list[i] = copy_command_lines (cmds->body_list[i]);
|
||||
}
|
||||
else
|
||||
result->body_list = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
validate_comname (char *comname)
|
||||
{
|
||||
register char *p;
|
||||
char *p;
|
||||
|
||||
if (comname == 0)
|
||||
error_no_arg ("name of command to define");
|
||||
|
|
@ -994,8 +1070,8 @@ define_command (char *comname, int from_tty)
|
|||
CMD_PRE_HOOK,
|
||||
CMD_POST_HOOK
|
||||
};
|
||||
register struct command_line *cmds;
|
||||
register struct cmd_list_element *c, *newc, *oldc, *hookc = 0;
|
||||
struct command_line *cmds;
|
||||
struct cmd_list_element *c, *newc, *oldc, *hookc = 0;
|
||||
char *tem = comname;
|
||||
char *tem2;
|
||||
char tmpbuf[MAX_TMPBUF];
|
||||
|
|
@ -1011,16 +1087,17 @@ define_command (char *comname, int from_tty)
|
|||
|
||||
/* Look it up, and verify that we got an exact match. */
|
||||
c = lookup_cmd (&tem, cmdlist, "", -1, 1);
|
||||
if (c && !STREQ (comname, c->name))
|
||||
if (c && strcmp (comname, c->name) != 0)
|
||||
c = 0;
|
||||
|
||||
if (c)
|
||||
{
|
||||
int q;
|
||||
if (c->class == class_user || c->class == class_alias)
|
||||
tem = "Redefine command \"%s\"? ";
|
||||
q = query ("Redefine command \"%s\"? ", c->name);
|
||||
else
|
||||
tem = "Really redefine built-in command \"%s\"? ";
|
||||
if (!query (tem, c->name))
|
||||
q = query ("Really redefine built-in command \"%s\"? ", c->name);
|
||||
if (!q)
|
||||
error ("Command \"%s\" not redefined.", c->name);
|
||||
}
|
||||
|
||||
|
|
@ -1044,7 +1121,7 @@ define_command (char *comname, int from_tty)
|
|||
/* Look up cmd it hooks, and verify that we got an exact match. */
|
||||
tem = comname + hook_name_size;
|
||||
hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
|
||||
if (hookc && !STREQ (comname + hook_name_size, hookc->name))
|
||||
if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0)
|
||||
hookc = 0;
|
||||
if (!hookc)
|
||||
{
|
||||
|
|
@ -1099,7 +1176,7 @@ void
|
|||
document_command (char *comname, int from_tty)
|
||||
{
|
||||
struct command_line *doclines;
|
||||
register struct cmd_list_element *c;
|
||||
struct cmd_list_element *c;
|
||||
char *tem = comname;
|
||||
char tmpbuf[128];
|
||||
|
||||
|
|
@ -1117,8 +1194,8 @@ document_command (char *comname, int from_tty)
|
|||
xfree (c->doc);
|
||||
|
||||
{
|
||||
register struct command_line *cl1;
|
||||
register int len = 0;
|
||||
struct command_line *cl1;
|
||||
int len = 0;
|
||||
|
||||
for (cl1 = doclines; cl1; cl1 = cl1->next)
|
||||
len += strlen (cl1->line) + 1;
|
||||
|
|
@ -1146,7 +1223,7 @@ struct source_cleanup_lines_args
|
|||
};
|
||||
|
||||
static void
|
||||
source_cleanup_lines (PTR args)
|
||||
source_cleanup_lines (void *args)
|
||||
{
|
||||
struct source_cleanup_lines_args *p =
|
||||
(struct source_cleanup_lines_args *) args;
|
||||
|
|
@ -1156,7 +1233,6 @@ source_cleanup_lines (PTR args)
|
|||
error_pre_print = p->old_error_pre_print;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
do_fclose_cleanup (void *stream)
|
||||
{
|
||||
|
|
@ -1213,7 +1289,7 @@ script_from_file (FILE *stream, char *file)
|
|||
void
|
||||
show_user_1 (struct cmd_list_element *c, struct ui_file *stream)
|
||||
{
|
||||
register struct command_line *cmdlines;
|
||||
struct command_line *cmdlines;
|
||||
|
||||
cmdlines = c->user_commands;
|
||||
if (!cmdlines)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
#if !defined (CLI_SCRIPT_H)
|
||||
#define CLI_SCRIPT_H 1
|
||||
|
||||
struct ui_file;
|
||||
struct command_line;
|
||||
struct cmd_list_element;
|
||||
|
||||
/* Exported to cli/cli-cmds.c */
|
||||
|
||||
extern void script_from_file (FILE *stream, char *file);
|
||||
|
|
@ -41,6 +45,10 @@ extern enum command_control_type
|
|||
extern void print_command_lines (struct ui_out *,
|
||||
struct command_line *, unsigned int);
|
||||
|
||||
extern struct command_line * copy_command_lines (struct command_line *cmds);
|
||||
|
||||
struct cleanup *make_cleanup_free_command_lines (struct command_line **arg);
|
||||
|
||||
/* Exported to gdb/infrun.c */
|
||||
|
||||
extern void execute_user_command (struct cmd_list_element *c, char *args);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* Handle set and show GDB commands.
|
||||
|
||||
Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
|
|
@ -18,11 +18,10 @@
|
|||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "readline/tilde.h"
|
||||
#include "value.h"
|
||||
#include <ctype.h>
|
||||
#if 0
|
||||
#include "gdb_string.h"
|
||||
#endif
|
||||
|
||||
#include "ui-out.h"
|
||||
|
||||
|
|
@ -34,9 +33,8 @@
|
|||
|
||||
static int parse_binary_operation (char *);
|
||||
|
||||
static enum cmd_auto_boolean parse_auto_binary_operation (const char *arg);
|
||||
|
||||
static enum cmd_auto_boolean
|
||||
static enum auto_boolean
|
||||
parse_auto_binary_operation (const char *arg)
|
||||
{
|
||||
if (arg != NULL && *arg != '\0')
|
||||
|
|
@ -48,18 +46,18 @@ parse_auto_binary_operation (const char *arg)
|
|||
|| strncmp (arg, "1", length) == 0
|
||||
|| strncmp (arg, "yes", length) == 0
|
||||
|| strncmp (arg, "enable", length) == 0)
|
||||
return CMD_AUTO_BOOLEAN_TRUE;
|
||||
return AUTO_BOOLEAN_TRUE;
|
||||
else if (strncmp (arg, "off", length) == 0
|
||||
|| strncmp (arg, "0", length) == 0
|
||||
|| strncmp (arg, "no", length) == 0
|
||||
|| strncmp (arg, "disable", length) == 0)
|
||||
return CMD_AUTO_BOOLEAN_FALSE;
|
||||
return AUTO_BOOLEAN_FALSE;
|
||||
else if (strncmp (arg, "auto", length) == 0
|
||||
|| (strncmp (arg, "-1", length) == 0 && length > 1))
|
||||
return CMD_AUTO_BOOLEAN_AUTO;
|
||||
return AUTO_BOOLEAN_AUTO;
|
||||
}
|
||||
error ("\"on\", \"off\" or \"auto\" expected.");
|
||||
return CMD_AUTO_BOOLEAN_AUTO; /* pacify GCC */
|
||||
return AUTO_BOOLEAN_AUTO; /* pacify GCC */
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -167,7 +165,7 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
|||
*(int *) c->var = parse_binary_operation (arg);
|
||||
break;
|
||||
case var_auto_boolean:
|
||||
*(enum cmd_auto_boolean *) c->var = parse_auto_binary_operation (arg);
|
||||
*(enum auto_boolean *) c->var = parse_auto_binary_operation (arg);
|
||||
break;
|
||||
case var_uinteger:
|
||||
if (arg == NULL)
|
||||
|
|
@ -215,7 +213,7 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
|||
strcat (msg, c->enums[i]);
|
||||
}
|
||||
strcat (msg, ".");
|
||||
error (msg);
|
||||
error ("%s", msg);
|
||||
}
|
||||
|
||||
p = strchr (arg, ' ');
|
||||
|
|
@ -296,15 +294,15 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
|||
fputs_filtered (*(int *) c->var ? "on" : "off", stb->stream);
|
||||
break;
|
||||
case var_auto_boolean:
|
||||
switch (*(enum cmd_auto_boolean*) c->var)
|
||||
switch (*(enum auto_boolean*) c->var)
|
||||
{
|
||||
case CMD_AUTO_BOOLEAN_TRUE:
|
||||
case AUTO_BOOLEAN_TRUE:
|
||||
fputs_filtered ("on", stb->stream);
|
||||
break;
|
||||
case CMD_AUTO_BOOLEAN_FALSE:
|
||||
case AUTO_BOOLEAN_FALSE:
|
||||
fputs_filtered ("off", stb->stream);
|
||||
break;
|
||||
case CMD_AUTO_BOOLEAN_AUTO:
|
||||
case AUTO_BOOLEAN_AUTO:
|
||||
fputs_filtered ("auto", stb->stream);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -355,28 +353,35 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
|
|||
void
|
||||
cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "showlist");
|
||||
struct cleanup *showlist_chain;
|
||||
|
||||
showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist");
|
||||
for (; list != NULL; list = list->next)
|
||||
{
|
||||
/* If we find a prefix, run its list, prefixing our output by its
|
||||
prefix (with "show " skipped). */
|
||||
if (list->prefixlist && !list->abbrev_flag)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "optionlist");
|
||||
struct cleanup *optionlist_chain
|
||||
= make_cleanup_ui_out_tuple_begin_end (uiout, "optionlist");
|
||||
ui_out_field_string (uiout, "prefix", list->prefixname + 5);
|
||||
cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
|
||||
ui_out_tuple_end (uiout);
|
||||
/* Close the tuple. */
|
||||
do_cleanups (optionlist_chain);
|
||||
}
|
||||
if (list->type == show_cmd)
|
||||
{
|
||||
ui_out_tuple_begin (uiout, "option");
|
||||
struct cleanup *option_chain
|
||||
= make_cleanup_ui_out_tuple_begin_end (uiout, "option");
|
||||
ui_out_text (uiout, prefix);
|
||||
ui_out_field_string (uiout, "name", list->name);
|
||||
ui_out_text (uiout, ": ");
|
||||
do_setshow_command ((char *) NULL, from_tty, list);
|
||||
ui_out_tuple_end (uiout);
|
||||
/* Close the tuple. */
|
||||
do_cleanups (option_chain);
|
||||
}
|
||||
}
|
||||
ui_out_tuple_end (uiout);
|
||||
/* Close the tuple. */
|
||||
do_cleanups (showlist_chain);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#if !defined (CLI_SETSHOW_H)
|
||||
#define CLI_SETSHOW_H 1
|
||||
|
||||
struct cmd_list_element;
|
||||
|
||||
/* Exported to cli/cli-cmds.c and gdb/top.c */
|
||||
|
||||
/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
|
||||
|
|
|
|||
346
contrib/gdb/gdb/coff-pe-read.c
Normal file
346
contrib/gdb/gdb/coff-pe-read.c
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
/* Read the export table symbols from a portable executable and
|
||||
convert to internal format, for GDB. Used as a last resort if no
|
||||
debugging symbols recognized.
|
||||
|
||||
Copyright 2003 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.
|
||||
|
||||
Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
|
||||
|
||||
#include "coff-pe-read.h"
|
||||
|
||||
#include "bfd.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbtypes.h"
|
||||
|
||||
#include "symtab.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
|
||||
/* Internal section information */
|
||||
|
||||
struct read_pe_section_data
|
||||
{
|
||||
CORE_ADDR vma_offset; /* Offset to loaded address of section. */
|
||||
unsigned long rva_start; /* Start offset within the pe. */
|
||||
unsigned long rva_end; /* End offset within the pe. */
|
||||
enum minimal_symbol_type ms_type; /* Type to assign symbols in section. */
|
||||
};
|
||||
|
||||
#define PE_SECTION_INDEX_TEXT 0
|
||||
#define PE_SECTION_INDEX_DATA 1
|
||||
#define PE_SECTION_INDEX_BSS 2
|
||||
#define PE_SECTION_TABLE_SIZE 3
|
||||
#define PE_SECTION_INDEX_INVALID -1
|
||||
|
||||
/* Get the index of the named section in our own array, which contains
|
||||
text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
|
||||
if passed an unrecognised section name. */
|
||||
|
||||
static int
|
||||
read_pe_section_index (const char *section_name)
|
||||
{
|
||||
if (strcmp (section_name, ".text") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_TEXT;
|
||||
}
|
||||
|
||||
else if (strcmp (section_name, ".data") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_DATA;
|
||||
}
|
||||
|
||||
else if (strcmp (section_name, ".bss") == 0)
|
||||
{
|
||||
return PE_SECTION_INDEX_BSS;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return PE_SECTION_INDEX_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Record the virtual memory address of a section. */
|
||||
|
||||
static void
|
||||
get_section_vmas (bfd *abfd, asection *sectp, void *context)
|
||||
{
|
||||
struct read_pe_section_data *sections = context;
|
||||
int sectix = read_pe_section_index (sectp->name);
|
||||
|
||||
if (sectix != PE_SECTION_INDEX_INVALID)
|
||||
{
|
||||
/* Data within the section start at rva_start in the pe and at
|
||||
bfd_get_section_vma() within memory. Store the offset. */
|
||||
|
||||
sections[sectix].vma_offset
|
||||
= bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a minimal symbol entry for an exported symbol. */
|
||||
|
||||
static void
|
||||
add_pe_exported_sym (char *sym_name,
|
||||
unsigned long func_rva,
|
||||
const struct read_pe_section_data *section_data,
|
||||
const char *dll_name, struct objfile *objfile)
|
||||
{
|
||||
/* Add the stored offset to get the loaded address of the symbol. */
|
||||
|
||||
CORE_ADDR vma = func_rva + section_data->vma_offset;
|
||||
|
||||
char *qualified_name = 0;
|
||||
int dll_name_len = strlen (dll_name);
|
||||
int count;
|
||||
|
||||
/* Generate a (hopefully unique) qualified name using the first part
|
||||
of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
|
||||
used by windbg from the "Microsoft Debugging Tools for Windows". */
|
||||
|
||||
qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2);
|
||||
|
||||
strncpy (qualified_name, dll_name, dll_name_len);
|
||||
qualified_name[dll_name_len] = '!';
|
||||
strcpy (qualified_name + dll_name_len + 1, sym_name);
|
||||
|
||||
prim_record_minimal_symbol (qualified_name,
|
||||
vma, section_data->ms_type, objfile);
|
||||
|
||||
xfree (qualified_name);
|
||||
|
||||
/* Enter the plain name as well, which might not be unique. */
|
||||
prim_record_minimal_symbol (sym_name, vma, section_data->ms_type, objfile);
|
||||
}
|
||||
|
||||
/* Truncate a dll_name at the first dot character. */
|
||||
|
||||
static void
|
||||
read_pe_truncate_name (char *dll_name)
|
||||
{
|
||||
while (*dll_name)
|
||||
{
|
||||
if ((*dll_name) == '.')
|
||||
{
|
||||
*dll_name = '\0'; /* truncates and causes loop exit. */
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
++dll_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Low-level support functions, direct from the ld module pe-dll.c. */
|
||||
static unsigned int
|
||||
pe_get16 (bfd *abfd, int where)
|
||||
{
|
||||
unsigned char b[2];
|
||||
|
||||
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
|
||||
bfd_bread (b, (bfd_size_type) 2, abfd);
|
||||
return b[0] + (b[1] << 8);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pe_get32 (bfd *abfd, int where)
|
||||
{
|
||||
unsigned char b[4];
|
||||
|
||||
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
|
||||
bfd_bread (b, (bfd_size_type) 4, abfd);
|
||||
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
pe_as32 (void *ptr)
|
||||
{
|
||||
unsigned char *b = ptr;
|
||||
|
||||
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
|
||||
}
|
||||
|
||||
/* Read the (non-debug) export symbol table from a portable
|
||||
executable. Code originally lifted from the ld function
|
||||
pe_implied_import_dll in pe-dll.c. */
|
||||
|
||||
void
|
||||
read_pe_exported_syms (struct objfile *objfile)
|
||||
{
|
||||
bfd *dll = objfile->obfd;
|
||||
unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
|
||||
unsigned long export_rva, export_size, nsections, secptr, expptr;
|
||||
unsigned long exp_funcbase;
|
||||
unsigned char *expdata, *erva;
|
||||
unsigned long name_rvas, ordinals, nexp, ordbase;
|
||||
char *dll_name;
|
||||
|
||||
/* Array elements are for text, data and bss in that order
|
||||
Initialization with start_rva > end_rva guarantees that
|
||||
unused sections won't be matched. */
|
||||
struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
|
||||
= { {0, 1, 0, mst_text},
|
||||
{0, 1, 0, mst_data},
|
||||
{0, 1, 0, mst_bss}
|
||||
};
|
||||
|
||||
struct cleanup *back_to = 0;
|
||||
|
||||
char const *target = bfd_get_target (objfile->obfd);
|
||||
|
||||
if ((strcmp (target, "pe-i386") != 0) && (strcmp (target, "pei-i386") != 0))
|
||||
{
|
||||
/* This is not an i386 format file. Abort now, because the code
|
||||
is untested on anything else. *FIXME* test on further
|
||||
architectures and loosen or remove this test. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get pe_header, optional header and numbers of export entries. */
|
||||
pe_header_offset = pe_get32 (dll, 0x3c);
|
||||
opthdr_ofs = pe_header_offset + 4 + 20;
|
||||
num_entries = pe_get32 (dll, opthdr_ofs + 92);
|
||||
|
||||
if (num_entries < 1) /* No exports. */
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
export_rva = pe_get32 (dll, opthdr_ofs + 96);
|
||||
export_size = pe_get32 (dll, opthdr_ofs + 100);
|
||||
nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
|
||||
secptr = (pe_header_offset + 4 + 20 +
|
||||
pe_get16 (dll, pe_header_offset + 4 + 16));
|
||||
expptr = 0;
|
||||
|
||||
/* Get the rva and size of the export section. */
|
||||
for (i = 0; i < nsections; i++)
|
||||
{
|
||||
char sname[8];
|
||||
unsigned long secptr1 = secptr + 40 * i;
|
||||
unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
|
||||
unsigned long vsize = pe_get32 (dll, secptr1 + 16);
|
||||
unsigned long fptr = pe_get32 (dll, secptr1 + 20);
|
||||
|
||||
bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
|
||||
bfd_bread (sname, (bfd_size_type) 8, dll);
|
||||
|
||||
if (vaddr <= export_rva && vaddr + vsize > export_rva)
|
||||
{
|
||||
expptr = fptr + (export_rva - vaddr);
|
||||
if (export_rva + export_size > vaddr + vsize)
|
||||
export_size = vsize - (export_rva - vaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (export_size == 0)
|
||||
{
|
||||
/* Empty export table. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan sections and store the base and size of the relevant sections. */
|
||||
for (i = 0; i < nsections; i++)
|
||||
{
|
||||
unsigned long secptr1 = secptr + 40 * i;
|
||||
unsigned long vsize = pe_get32 (dll, secptr1 + 8);
|
||||
unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
|
||||
unsigned long flags = pe_get32 (dll, secptr1 + 36);
|
||||
char sec_name[9];
|
||||
int sectix;
|
||||
|
||||
sec_name[8] = '\0';
|
||||
bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
|
||||
bfd_bread (sec_name, (bfd_size_type) 8, dll);
|
||||
|
||||
sectix = read_pe_section_index (sec_name);
|
||||
|
||||
if (sectix != PE_SECTION_INDEX_INVALID)
|
||||
{
|
||||
section_data[sectix].rva_start = vaddr;
|
||||
section_data[sectix].rva_end = vaddr + vsize;
|
||||
}
|
||||
}
|
||||
|
||||
expdata = (unsigned char *) xmalloc (export_size);
|
||||
back_to = make_cleanup (xfree, expdata);
|
||||
|
||||
bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
|
||||
bfd_bread (expdata, (bfd_size_type) export_size, dll);
|
||||
erva = expdata - export_rva;
|
||||
|
||||
nexp = pe_as32 (expdata + 24);
|
||||
name_rvas = pe_as32 (expdata + 32);
|
||||
ordinals = pe_as32 (expdata + 36);
|
||||
ordbase = pe_as32 (expdata + 16);
|
||||
exp_funcbase = pe_as32 (expdata + 28);
|
||||
|
||||
/* Use internal dll name instead of full pathname. */
|
||||
dll_name = pe_as32 (expdata + 12) + erva;
|
||||
|
||||
bfd_map_over_sections (dll, get_section_vmas, section_data);
|
||||
|
||||
/* Adjust the vma_offsets in case this PE got relocated. This
|
||||
assumes that *all* sections share the same relocation offset
|
||||
as the text section. */
|
||||
for (i = 0; i < PE_SECTION_TABLE_SIZE; i++)
|
||||
{
|
||||
section_data[i].vma_offset
|
||||
+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
||||
}
|
||||
|
||||
printf_filtered ("Minimal symbols from %s...", dll_name);
|
||||
wrap_here ("");
|
||||
|
||||
/* Truncate name at first dot. Should maybe also convert to all
|
||||
lower case for convenience on Windows. */
|
||||
read_pe_truncate_name (dll_name);
|
||||
|
||||
/* Iterate through the list of symbols. */
|
||||
for (i = 0; i < nexp; i++)
|
||||
{
|
||||
/* Pointer to the names vector. */
|
||||
unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
|
||||
|
||||
/* Pointer to the function address vector. */
|
||||
unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
|
||||
|
||||
/* Find this symbol's section in our own array. */
|
||||
int sectix = 0;
|
||||
|
||||
for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix)
|
||||
{
|
||||
if ((func_rva >= section_data[sectix].rva_start)
|
||||
&& (func_rva < section_data[sectix].rva_end))
|
||||
{
|
||||
add_pe_exported_sym (erva + name_rva,
|
||||
func_rva,
|
||||
section_data + sectix, dll_name, objfile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* discard expdata. */
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
32
contrib/gdb/gdb/coff-pe-read.h
Normal file
32
contrib/gdb/gdb/coff-pe-read.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* Interface to coff-pe-read.c (portable-executable-specific symbol reader).
|
||||
|
||||
Copyright 2003 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.
|
||||
|
||||
Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
|
||||
|
||||
#if !defined (COFF_PE_READ_H)
|
||||
#define COFF_PE_READ_H
|
||||
|
||||
struct objfile;
|
||||
|
||||
/* Read the export table and convert it to minimal symbol table entries */
|
||||
extern void read_pe_exported_syms (struct objfile *objfile);
|
||||
|
||||
#endif /* !defined (COFF_PE_READ_H) */
|
||||
|
|
@ -1,13 +1,7 @@
|
|||
/* ***DEPRECATED*** The gdblib files must not be calling/using things in any
|
||||
of the possible command languages. If necessary, a hook (that may be
|
||||
present or not) must be used and set to the appropriate routine by any
|
||||
command language that cares about it. If you are having to include this
|
||||
file you are possibly doing things the old way. This file will disapear.
|
||||
2000-12-01 fnasser@redhat.com */
|
||||
|
||||
/* Header file for command-reading library command.c.
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1999,
|
||||
2000, 2002 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
|
|
@ -44,6 +38,8 @@ enum command_class
|
|||
class_pseudo, class_tui, class_xdb
|
||||
};
|
||||
|
||||
/* FIXME: cagney/2002-03-17: Once cmd_type() has been removed, ``enum
|
||||
cmd_types'' can be moved from "command.h" to "cli-decode.h". */
|
||||
/* Not a set/show command. Note that some commands which begin with
|
||||
"set" or "show" might be in this category, if their syntax does
|
||||
not fall into one of the following categories. */
|
||||
|
|
@ -55,14 +51,6 @@ typedef enum cmd_types
|
|||
}
|
||||
cmd_types;
|
||||
|
||||
/* Reasonable values for an AUTO_BOOLEAN variable. */
|
||||
enum cmd_auto_boolean
|
||||
{
|
||||
CMD_AUTO_BOOLEAN_TRUE,
|
||||
CMD_AUTO_BOOLEAN_FALSE,
|
||||
CMD_AUTO_BOOLEAN_AUTO
|
||||
};
|
||||
|
||||
/* Types of "set" or "show" command. */
|
||||
typedef enum var_types
|
||||
{
|
||||
|
|
@ -71,9 +59,9 @@ typedef enum var_types
|
|||
var_boolean,
|
||||
|
||||
/* "on" / "true" / "enable" or "off" / "false" / "disable" or
|
||||
"auto. *VAR is an ``enum cmd_auto_boolean''. NOTE: In general
|
||||
a custom show command will need to be implemented - one that
|
||||
for "auto" prints both the "auto" and the current auto-selected
|
||||
"auto. *VAR is an ``enum auto_boolean''. NOTE: In general a
|
||||
custom show command will need to be implemented - one that for
|
||||
"auto" prints both the "auto" and the current auto-selected
|
||||
value. */
|
||||
var_auto_boolean,
|
||||
|
||||
|
|
@ -105,156 +93,7 @@ typedef enum var_types
|
|||
var_types;
|
||||
|
||||
/* This structure records one command'd definition. */
|
||||
|
||||
|
||||
/* This flag is used by the code executing commands to warn the user
|
||||
the first time a deprecated command is used, see the 'flags' field in
|
||||
the following struct.
|
||||
*/
|
||||
#define CMD_DEPRECATED 0x1
|
||||
#define DEPRECATED_WARN_USER 0x2
|
||||
#define MALLOCED_REPLACEMENT 0x4
|
||||
|
||||
struct cmd_list_element
|
||||
{
|
||||
/* Points to next command in this list. */
|
||||
struct cmd_list_element *next;
|
||||
|
||||
/* Name of this command. */
|
||||
char *name;
|
||||
|
||||
/* Command class; class values are chosen by application program. */
|
||||
enum command_class class;
|
||||
|
||||
/* Function definition of this command. NULL for command class
|
||||
names and for help topics that are not really commands. NOTE:
|
||||
cagney/2002-02-02: This function signature is evolving. For
|
||||
the moment suggest sticking with either set_cmd_cfunc() or
|
||||
set_cmd_sfunc(). */
|
||||
void (*func) (struct cmd_list_element *c, char *args, int from_tty);
|
||||
/* The command's real callback. At present func() bounces through
|
||||
to one of the below. */
|
||||
union
|
||||
{
|
||||
/* If type is not_set_cmd, call it like this: */
|
||||
void (*cfunc) (char *args, int from_tty);
|
||||
|
||||
/* If type is set_cmd or show_cmd, first set the variables, and
|
||||
then call this. */
|
||||
void (*sfunc) (char *args, int from_tty, struct cmd_list_element * c);
|
||||
}
|
||||
function;
|
||||
|
||||
/* Documentation of this command (or help topic).
|
||||
First line is brief documentation; remaining lines form, with it,
|
||||
the full documentation. First line should end with a period.
|
||||
Entire string should also end with a period, not a newline. */
|
||||
char *doc;
|
||||
|
||||
/* flags : a bitfield
|
||||
|
||||
bit 0: (LSB) CMD_DEPRECATED, when 1 indicated that this command
|
||||
is deprecated. It may be removed from gdb's command set in the
|
||||
future.
|
||||
|
||||
bit 1: DEPRECATED_WARN_USER, the user needs to be warned that
|
||||
this is a deprecated command. The user should only be warned
|
||||
the first time a command is used.
|
||||
|
||||
bit 2: MALLOCED_REPLACEMENT, when functions are deprecated at
|
||||
compile time (this is the way it should, in general, be done)
|
||||
the memory containing the replacement string is statically
|
||||
allocated. In some cases it makes sense to deprecate commands
|
||||
at runtime (the testsuite is one example). In this case the
|
||||
memory for replacement is malloc'ed. When a command is
|
||||
undeprecated or re-deprecated at runtime we don't want to risk
|
||||
calling free on statically allocated memory, so we check this
|
||||
flag.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/* if this command is deprecated, this is the replacement name */
|
||||
char *replacement;
|
||||
|
||||
/* If this command represents a show command, then this function
|
||||
is called before the variable's value is examined. */
|
||||
void (*pre_show_hook) (struct cmd_list_element *c);
|
||||
|
||||
/* Hook for another command to be executed before this command. */
|
||||
struct cmd_list_element *hook_pre;
|
||||
|
||||
/* Hook for another command to be executed after this command. */
|
||||
struct cmd_list_element *hook_post;
|
||||
|
||||
/* Flag that specifies if this command is already running it's hook. */
|
||||
/* Prevents the possibility of hook recursion. */
|
||||
int hook_in;
|
||||
|
||||
/* Nonzero identifies a prefix command. For them, the address
|
||||
of the variable containing the list of subcommands. */
|
||||
struct cmd_list_element **prefixlist;
|
||||
|
||||
/* For prefix commands only:
|
||||
String containing prefix commands to get here: this one
|
||||
plus any others needed to get to it. Should end in a space.
|
||||
It is used before the word "command" in describing the
|
||||
commands reached through this prefix. */
|
||||
char *prefixname;
|
||||
|
||||
/* For prefix commands only:
|
||||
nonzero means do not get an error if subcommand is not
|
||||
recognized; call the prefix's own function in that case. */
|
||||
char allow_unknown;
|
||||
|
||||
/* Nonzero says this is an abbreviation, and should not
|
||||
be mentioned in lists of commands.
|
||||
This allows "br<tab>" to complete to "break", which it
|
||||
otherwise wouldn't. */
|
||||
char abbrev_flag;
|
||||
|
||||
/* Completion routine for this command. TEXT is the text beyond
|
||||
what was matched for the command itself (leading whitespace is
|
||||
skipped). It stops where we are supposed to stop completing
|
||||
(rl_point) and is '\0' terminated.
|
||||
|
||||
Return value is a malloc'd vector of pointers to possible completions
|
||||
terminated with NULL. If there are no completions, returning a pointer
|
||||
to a NULL would work but returning NULL itself is also valid.
|
||||
WORD points in the same buffer as TEXT, and completions should be
|
||||
returned relative to this position. For example, suppose TEXT is "foo"
|
||||
and we want to complete to "foobar". If WORD is "oo", return
|
||||
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
|
||||
char **(*completer) (char *text, char *word);
|
||||
|
||||
/* Type of "set" or "show" command (or SET_NOT_SET if not "set"
|
||||
or "show"). */
|
||||
cmd_types type;
|
||||
|
||||
/* Pointer to variable affected by "set" and "show". Doesn't matter
|
||||
if type is not_set. */
|
||||
void *var;
|
||||
|
||||
/* What kind of variable is *VAR? */
|
||||
var_types var_type;
|
||||
|
||||
/* Pointer to NULL terminated list of enumerated values (like argv). */
|
||||
const char **enums;
|
||||
|
||||
/* Pointer to command strings of user-defined commands */
|
||||
struct command_line *user_commands;
|
||||
|
||||
/* Pointer to command that is hooked by this one, (by hook_pre)
|
||||
so the hook can be removed when this one is deleted. */
|
||||
struct cmd_list_element *hookee_pre;
|
||||
|
||||
/* Pointer to command that is hooked by this one, (by hook_post)
|
||||
so the hook can be removed when this one is deleted. */
|
||||
struct cmd_list_element *hookee_post;
|
||||
|
||||
/* Pointer to command that is aliased by this one, so the
|
||||
aliased command can be located in case it has been hooked. */
|
||||
struct cmd_list_element *cmd_pointer;
|
||||
};
|
||||
struct cmd_list_element;
|
||||
|
||||
/* Forward-declarations of the entry-points of cli/cli-decode.c. */
|
||||
|
||||
|
|
@ -285,18 +124,46 @@ extern struct cmd_list_element *add_abbrev_prefix_cmd (char *,
|
|||
|
||||
/* Set the commands corresponding callback. */
|
||||
|
||||
typedef void cmd_cfunc_ftype (char *args, int from_tty);
|
||||
extern void set_cmd_cfunc (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
cmd_cfunc_ftype *cfunc);
|
||||
|
||||
typedef void cmd_sfunc_ftype (char *args, int from_tty,
|
||||
struct cmd_list_element *c);
|
||||
extern void set_cmd_sfunc (struct cmd_list_element *cmd,
|
||||
void (*sfunc) (char *args, int from_tty,
|
||||
struct cmd_list_element * c));
|
||||
cmd_sfunc_ftype *sfunc);
|
||||
|
||||
extern void set_cmd_completer (struct cmd_list_element *cmd,
|
||||
char **(*completer) (char *text, char *word));
|
||||
|
||||
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
|
||||
around in cmd objects to test the value of the commands sfunc(). */
|
||||
extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
|
||||
void (*cfunc) (char *args, int from_tty));
|
||||
|
||||
/* Each command object has a local context attached to it. . */
|
||||
extern void set_cmd_context (struct cmd_list_element *cmd, void *context);
|
||||
extern void *get_cmd_context (struct cmd_list_element *cmd);
|
||||
|
||||
|
||||
/* Execute CMD's pre/post hook. Throw an error if the command fails.
|
||||
If already executing this pre/post hook, or there is no pre/post
|
||||
hook, the call is silently ignored. */
|
||||
extern void execute_cmd_pre_hook (struct cmd_list_element *cmd);
|
||||
extern void execute_cmd_post_hook (struct cmd_list_element *cmd);
|
||||
|
||||
/* Return the type of the command. */
|
||||
/* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
|
||||
the set command passed as a parameter. The clone operation will
|
||||
include (BUG?) any ``set'' command callback, if present. Commands
|
||||
like ``info set'' call all the ``show'' command callbacks.
|
||||
Unfortunately, for ``show'' commands cloned from ``set'', this
|
||||
includes callbacks belonging to ``set'' commands. Making this
|
||||
worse, this only occures if add_show_from_set() is called after
|
||||
add_cmd_sfunc() (BUG?). */
|
||||
extern enum cmd_types cmd_type (struct cmd_list_element *cmd);
|
||||
|
||||
|
||||
extern struct cmd_list_element *lookup_cmd (char **,
|
||||
struct cmd_list_element *, char *,
|
||||
int, int);
|
||||
|
|
@ -343,6 +210,26 @@ extern void help_list (struct cmd_list_element *, char *,
|
|||
extern void help_cmd_list (struct cmd_list_element *, enum command_class,
|
||||
char *, int, struct ui_file *);
|
||||
|
||||
extern void add_setshow_cmd (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern void add_setshow_cmd_full (char *name,
|
||||
enum command_class class,
|
||||
var_types var_type, void *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list,
|
||||
struct cmd_list_element **set_result,
|
||||
struct cmd_list_element **show_result);
|
||||
|
||||
extern struct cmd_list_element *add_set_cmd (char *name, enum
|
||||
command_class class,
|
||||
var_types var_type, void *var,
|
||||
|
|
@ -356,17 +243,34 @@ extern struct cmd_list_element *add_set_enum_cmd (char *name,
|
|||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
|
||||
extern struct cmd_list_element *add_set_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum cmd_auto_boolean *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
extern void add_setshow_auto_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
enum auto_boolean *var,
|
||||
char *set_doc, char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern struct cmd_list_element *add_set_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var,
|
||||
char *doc,
|
||||
struct cmd_list_element **list);
|
||||
extern void add_setshow_boolean_cmd (char *name,
|
||||
enum command_class class,
|
||||
int *var,
|
||||
char *set_doc,
|
||||
char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern void add_setshow_uinteger_cmd (char *name,
|
||||
enum command_class class,
|
||||
unsigned int *var,
|
||||
char *set_doc,
|
||||
char *show_doc,
|
||||
cmd_sfunc_ftype *set_func,
|
||||
cmd_sfunc_ftype *show_func,
|
||||
struct cmd_list_element **set_list,
|
||||
struct cmd_list_element **show_list);
|
||||
|
||||
extern struct cmd_list_element *add_show_from_set (struct cmd_list_element *,
|
||||
struct cmd_list_element
|
||||
|
|
@ -386,4 +290,10 @@ extern void dont_repeat (void);
|
|||
|
||||
extern void not_just_help_class_command (char *, int);
|
||||
|
||||
/* check function pointer */
|
||||
extern int cmd_func_p (struct cmd_list_element *cmd);
|
||||
|
||||
/* call the command function */
|
||||
extern void cmd_func (struct cmd_list_element *cmd, char *args, int from_tty);
|
||||
|
||||
#endif /* !defined (COMMAND_H) */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* Support for complaint handling during symbol reading in GDB.
|
||||
Copyright 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000, 2002 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -21,148 +22,300 @@
|
|||
|
||||
#include "defs.h"
|
||||
#include "complaints.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
|
||||
extern void _initialize_complaints (void);
|
||||
|
||||
/* Structure to manage complaints about symbol file contents. */
|
||||
/* Should each complaint message be self explanatory, or should we assume that
|
||||
a series of complaints is being produced? */
|
||||
|
||||
struct complaint complaint_root[1] =
|
||||
{
|
||||
{
|
||||
(char *) NULL, /* Complaint message */
|
||||
0, /* Complaint counter */
|
||||
complaint_root /* Next complaint. */
|
||||
}
|
||||
/* case 1: First message of a series that must
|
||||
start off with explanation. case 2: Subsequent message of a series
|
||||
that needs no explanation (the user already knows we have a problem
|
||||
so we can just state our piece). */
|
||||
enum complaint_series {
|
||||
/* Isolated self explanatory message. */
|
||||
ISOLATED_MESSAGE,
|
||||
/* First message of a series, includes an explanation. */
|
||||
FIRST_MESSAGE,
|
||||
/* First message of a series, but does not need to include any sort
|
||||
of explanation. */
|
||||
SHORT_FIRST_MESSAGE,
|
||||
/* Subsequent message of a series that needs no explanation (the
|
||||
user already knows we have a problem so we can just state our
|
||||
piece). */
|
||||
SUBSEQUENT_MESSAGE
|
||||
};
|
||||
|
||||
/* How many complaints about a particular thing should be printed before
|
||||
we stop whining about it? Default is no whining at all, since so many
|
||||
systems have ill-constructed symbol files. */
|
||||
/* Structure to manage complaints about symbol file contents. */
|
||||
|
||||
struct complain
|
||||
{
|
||||
const char *file;
|
||||
int line;
|
||||
const char *fmt;
|
||||
int counter;
|
||||
struct complain *next;
|
||||
};
|
||||
|
||||
/* The explanatory message that should accompany the complaint. The
|
||||
message is in two parts - pre and post - that are printed around
|
||||
the complaint text. */
|
||||
struct explanation
|
||||
{
|
||||
const char *prefix;
|
||||
const char *postfix;
|
||||
};
|
||||
|
||||
struct complaints
|
||||
{
|
||||
struct complain *root;
|
||||
|
||||
/* Should each complaint be self explanatory, or should we assume
|
||||
that a series of complaints is being produced? case 0: Isolated
|
||||
self explanatory message. case 1: First message of a series that
|
||||
must start off with explanation. case 2: Subsequent message of a
|
||||
series that needs no explanation (the user already knows we have
|
||||
a problem so we can just state our piece). */
|
||||
int series;
|
||||
|
||||
/* The explanatory messages that should accompany the complaint.
|
||||
NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely
|
||||
i18n friendly, this is an array of two messages. When present,
|
||||
the PRE and POST EXPLANATION[SERIES] are used to wrap the
|
||||
message. */
|
||||
const struct explanation *explanation;
|
||||
};
|
||||
|
||||
static struct complain complaint_sentinel;
|
||||
|
||||
/* The symbol table complaint table. */
|
||||
|
||||
static struct explanation symfile_explanations[] = {
|
||||
{ "During symbol reading, ", "." },
|
||||
{ "During symbol reading...", "..."},
|
||||
{ "", "..."},
|
||||
{ "", "..."},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static struct complaints symfile_complaint_book = {
|
||||
&complaint_sentinel,
|
||||
0,
|
||||
symfile_explanations
|
||||
};
|
||||
struct complaints *symfile_complaints = &symfile_complaint_book;
|
||||
|
||||
/* Wrapper function to, on-demand, fill in a complaints object. */
|
||||
|
||||
static struct complaints *
|
||||
get_complaints (struct complaints **c)
|
||||
{
|
||||
if ((*c) != NULL)
|
||||
return (*c);
|
||||
(*c) = XMALLOC (struct complaints);
|
||||
(*c)->root = &complaint_sentinel;
|
||||
(*c)->series = ISOLATED_MESSAGE;
|
||||
(*c)->explanation = NULL;
|
||||
return (*c);
|
||||
}
|
||||
|
||||
static struct complain *
|
||||
find_complaint (struct complaints *complaints, const char *file,
|
||||
int line, const char *fmt)
|
||||
{
|
||||
struct complain *complaint;
|
||||
|
||||
/* Find the complaint in the table. A more efficient search
|
||||
algorithm (based on hash table or something) could be used. But
|
||||
that can wait until someone shows evidence that this lookup is
|
||||
a real bottle neck. */
|
||||
for (complaint = complaints->root;
|
||||
complaint != NULL;
|
||||
complaint = complaint->next)
|
||||
{
|
||||
if (complaint->fmt == fmt
|
||||
&& complaint->file == file
|
||||
&& complaint->line == line)
|
||||
return complaint;
|
||||
}
|
||||
|
||||
/* Oops not seen before, fill in a new complaint. */
|
||||
complaint = XMALLOC (struct complain);
|
||||
complaint->fmt = fmt;
|
||||
complaint->file = file;
|
||||
complaint->line = line;
|
||||
complaint->counter = 0;
|
||||
complaint->next = NULL;
|
||||
|
||||
/* File it, return it. */
|
||||
complaint->next = complaints->root;
|
||||
complaints->root = complaint;
|
||||
return complaint;
|
||||
}
|
||||
|
||||
|
||||
/* How many complaints about a particular thing should be printed
|
||||
before we stop whining about it? Default is no whining at all,
|
||||
since so many systems have ill-constructed symbol files. */
|
||||
|
||||
static unsigned int stop_whining = 0;
|
||||
|
||||
/* Should each complaint be self explanatory, or should we assume that
|
||||
a series of complaints is being produced?
|
||||
case 0: self explanatory message.
|
||||
case 1: First message of a series that must start off with explanation.
|
||||
case 2: Subsequent message, when user already knows we are reading
|
||||
symbols and we can just state our piece. */
|
||||
/* Print a complaint, and link the complaint block into a chain for
|
||||
later handling. */
|
||||
|
||||
static int complaint_series = 0;
|
||||
|
||||
|
||||
|
||||
/* Functions to handle complaints during symbol reading. */
|
||||
|
||||
/* Print a complaint about the input symbols, and link the complaint block
|
||||
into a chain for later handling. */
|
||||
|
||||
void
|
||||
complain (struct complaint *complaint,...)
|
||||
static void
|
||||
vcomplaint (struct complaints **c, const char *file, int line, const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, complaint);
|
||||
struct complaints *complaints = get_complaints (c);
|
||||
struct complain *complaint = find_complaint (complaints, file, line, fmt);
|
||||
enum complaint_series series;
|
||||
gdb_assert (complaints != NULL);
|
||||
|
||||
complaint->counter++;
|
||||
if (complaint->next == NULL)
|
||||
{
|
||||
complaint->next = complaint_root->next;
|
||||
complaint_root->next = complaint;
|
||||
}
|
||||
if (complaint->counter > stop_whining)
|
||||
return;
|
||||
|
||||
if (info_verbose)
|
||||
series = SUBSEQUENT_MESSAGE;
|
||||
else
|
||||
series = complaints->series;
|
||||
|
||||
if (complaint->file != NULL)
|
||||
internal_vwarning (complaint->file, complaint->line, complaint->fmt, args);
|
||||
else if (warning_hook)
|
||||
(*warning_hook) (complaint->fmt, args);
|
||||
else
|
||||
{
|
||||
return;
|
||||
if (complaints->explanation == NULL)
|
||||
/* A [v]warning() call always appends a newline. */
|
||||
vwarning (complaint->fmt, args);
|
||||
else
|
||||
{
|
||||
char *msg;
|
||||
struct cleanup *cleanups;
|
||||
xvasprintf (&msg, complaint->fmt, args);
|
||||
cleanups = make_cleanup (xfree, msg);
|
||||
wrap_here ("");
|
||||
if (series != SUBSEQUENT_MESSAGE)
|
||||
begin_line ();
|
||||
fprintf_filtered (gdb_stderr, "%s%s%s",
|
||||
complaints->explanation[series].prefix, msg,
|
||||
complaints->explanation[series].postfix);
|
||||
/* Force a line-break after any isolated message. For the
|
||||
other cases, clear_complaints() takes care of any missing
|
||||
trailing newline, the wrap_here() is just a hint. */
|
||||
if (series == ISOLATED_MESSAGE)
|
||||
/* It would be really nice to use begin_line() here.
|
||||
Unfortunately that function doesn't track GDB_STDERR and
|
||||
consequently will sometimes supress a line when it
|
||||
shouldn't. */
|
||||
fputs_filtered ("\n", gdb_stderr);
|
||||
else
|
||||
wrap_here ("");
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
}
|
||||
wrap_here ("");
|
||||
|
||||
switch (complaint_series + (info_verbose << 1))
|
||||
switch (series)
|
||||
{
|
||||
|
||||
/* Isolated messages, must be self-explanatory. */
|
||||
case 0:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
begin_line ();
|
||||
fputs_filtered ("During symbol reading, ", gdb_stderr);
|
||||
wrap_here ("");
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered (".\n", gdb_stderr);
|
||||
}
|
||||
case ISOLATED_MESSAGE:
|
||||
break;
|
||||
|
||||
/* First of a series, without `set verbose'. */
|
||||
case 1:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
begin_line ();
|
||||
fputs_filtered ("During symbol reading...", gdb_stderr);
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered ("...", gdb_stderr);
|
||||
wrap_here ("");
|
||||
complaint_series++;
|
||||
}
|
||||
case FIRST_MESSAGE:
|
||||
complaints->series = SUBSEQUENT_MESSAGE;
|
||||
break;
|
||||
case SUBSEQUENT_MESSAGE:
|
||||
case SHORT_FIRST_MESSAGE:
|
||||
complaints->series = SUBSEQUENT_MESSAGE;
|
||||
break;
|
||||
|
||||
/* Subsequent messages of a series, or messages under `set verbose'.
|
||||
(We'll already have produced a "Reading in symbols for XXX..."
|
||||
message and will clean up at the end with a newline.) */
|
||||
default:
|
||||
if (warning_hook)
|
||||
(*warning_hook) (complaint->message, args);
|
||||
else
|
||||
{
|
||||
vfprintf_filtered (gdb_stderr, complaint->message, args);
|
||||
fputs_filtered ("...", gdb_stderr);
|
||||
wrap_here ("");
|
||||
}
|
||||
}
|
||||
/* If GDB dumps core, we'd like to see the complaints first. Presumably
|
||||
GDB will not be sending so many complaints that this becomes a
|
||||
performance hog. */
|
||||
|
||||
/* If GDB dumps core, we'd like to see the complaints first.
|
||||
Presumably GDB will not be sending so many complaints that this
|
||||
becomes a performance hog. */
|
||||
|
||||
gdb_flush (gdb_stderr);
|
||||
}
|
||||
|
||||
void
|
||||
complaint (struct complaints **complaints, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* Clear out all complaint counters that have ever been incremented.
|
||||
If sym_reading is 1, be less verbose about successive complaints,
|
||||
since the messages are appearing all together during a command that
|
||||
reads symbols (rather than scattered around as psymtabs get fleshed
|
||||
out into symtabs at random times). If noisy is 1, we are in a
|
||||
noisy symbol reading command, and our caller will print enough
|
||||
context for the user to figure it out. */
|
||||
void
|
||||
internal_complaint (struct complaints **complaints, const char *file,
|
||||
int line, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
vcomplaint (complaints, file, line, fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
/* Clear out / initialize all complaint counters that have ever been
|
||||
incremented. If LESS_VERBOSE is 1, be less verbose about
|
||||
successive complaints, since the messages are appearing all
|
||||
together during a command that is reporting a contiguous block of
|
||||
complaints (rather than being interleaved with other messages). If
|
||||
noisy is 1, we are in a noisy command, and our caller will print
|
||||
enough context for the user to figure it out. */
|
||||
|
||||
void
|
||||
clear_complaints (int sym_reading, int noisy)
|
||||
clear_complaints (struct complaints **c, int less_verbose, int noisy)
|
||||
{
|
||||
struct complaint *p;
|
||||
struct complaints *complaints = get_complaints (c);
|
||||
struct complain *p;
|
||||
|
||||
for (p = complaint_root->next; p != complaint_root; p = p->next)
|
||||
for (p = complaints->root; p != NULL; p = p->next)
|
||||
{
|
||||
p->counter = 0;
|
||||
}
|
||||
|
||||
if (!sym_reading && !noisy && complaint_series > 1 && !warning_hook)
|
||||
switch (complaints->series)
|
||||
{
|
||||
/* Terminate previous series, since caller won't. */
|
||||
puts_filtered ("\n");
|
||||
case FIRST_MESSAGE:
|
||||
/* Haven't yet printed anything. */
|
||||
break;
|
||||
case SHORT_FIRST_MESSAGE:
|
||||
/* Haven't yet printed anything. */
|
||||
break;
|
||||
case ISOLATED_MESSAGE:
|
||||
/* The code above, always forces a line-break. No need to do it
|
||||
here. */
|
||||
break;
|
||||
case SUBSEQUENT_MESSAGE:
|
||||
/* It would be really nice to use begin_line() here.
|
||||
Unfortunately that function doesn't track GDB_STDERR and
|
||||
consequently will sometimes supress a line when it shouldn't. */
|
||||
fputs_unfiltered ("\n", gdb_stderr);
|
||||
break;
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__, "bad switch");
|
||||
}
|
||||
|
||||
complaint_series = sym_reading ? 1 + noisy : 0;
|
||||
if (!less_verbose)
|
||||
complaints->series = ISOLATED_MESSAGE;
|
||||
else if (!noisy)
|
||||
complaints->series = FIRST_MESSAGE;
|
||||
else
|
||||
complaints->series = SHORT_FIRST_MESSAGE;
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_complaints (void)
|
||||
{
|
||||
add_show_from_set
|
||||
(add_set_cmd ("complaints", class_support, var_zinteger,
|
||||
(char *) &stop_whining,
|
||||
"Set max number of complaints about incorrect symbols.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
add_setshow_cmd ("complaints", class_support, var_zinteger,
|
||||
&stop_whining,
|
||||
"Set max number of complaints about incorrect symbols.",
|
||||
"Show max number of complaints about incorrect symbols.",
|
||||
NULL, NULL,
|
||||
&setlist, &showlist);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* Definitions for complaint handling during symbol reading in GDB.
|
||||
Copyright 1990, 1991, 1992, 1995, 1998, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1990, 1991, 1992, 1995, 1998, 2000, 2002 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -23,31 +24,30 @@
|
|||
#if !defined (COMPLAINTS_H)
|
||||
#define COMPLAINTS_H
|
||||
|
||||
/* Opaque object used to track the number of complaints of a
|
||||
particular category. */
|
||||
struct complaints;
|
||||
|
||||
/* Support for complaining about things in the symbol file that aren't
|
||||
catastrophic.
|
||||
/* Predefined categories. */
|
||||
extern struct complaints *symfile_complaints;
|
||||
|
||||
Each such thing gets a counter. The first time we have the problem,
|
||||
during a symbol read, we report it. At the end of symbol reading,
|
||||
if verbose, we report how many of each problem we had. */
|
||||
/* Register a complaint. */
|
||||
extern void complaint (struct complaints **complaints, const char *fmt,
|
||||
...) ATTR_FORMAT (printf, 2, 3);
|
||||
extern void internal_complaint (struct complaints **complaints,
|
||||
const char *file, int line, const char *fmt,
|
||||
...) ATTR_FORMAT (printf, 4, 5);
|
||||
|
||||
struct complaint
|
||||
{
|
||||
char *message;
|
||||
unsigned counter;
|
||||
struct complaint *next;
|
||||
};
|
||||
/* Clear out / initialize all complaint counters that have ever been
|
||||
incremented. If LESS_VERBOSE is 1, be less verbose about
|
||||
successive complaints, since the messages are appearing all
|
||||
together during a command that is reporting a contiguous block of
|
||||
complaints (rather than being interleaved with other messages). If
|
||||
noisy is 1, we are in a noisy command, and our caller will print
|
||||
enough context for the user to figure it out. */
|
||||
|
||||
/* Root of the chain of complaints that have at some point been issued.
|
||||
This is used to reset the counters, and/or report the total counts. */
|
||||
|
||||
extern struct complaint complaint_root[1];
|
||||
|
||||
/* Functions that handle complaints. (in complaints.c) */
|
||||
|
||||
extern void complain (struct complaint *, ...);
|
||||
|
||||
extern void clear_complaints (int, int);
|
||||
extern void clear_complaints (struct complaints **complaints,
|
||||
int less_verbose, int noisy);
|
||||
|
||||
|
||||
#endif /* !defined (COMPLAINTS_H) */
|
||||
|
|
|
|||
|
|
@ -23,14 +23,17 @@
|
|||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "filenames.h" /* for DOSish file names */
|
||||
#include "language.h"
|
||||
|
||||
#include "cli/cli-decode.h"
|
||||
|
||||
/* FIXME: This is needed because of lookup_cmd_1().
|
||||
We should be calling a hook instead so we eliminate the CLI dependency. */
|
||||
#include "gdbcmd.h"
|
||||
|
||||
/* Needed for rl_completer_word_break_characters() and for
|
||||
filename_completion_function. */
|
||||
#include <readline/readline.h>
|
||||
rl_filename_completion_function. */
|
||||
#include "readline/readline.h"
|
||||
|
||||
/* readline defines this. */
|
||||
#undef savestring
|
||||
|
|
@ -38,7 +41,8 @@
|
|||
#include "completer.h"
|
||||
|
||||
/* Prototypes for local functions */
|
||||
char *line_completion_function (char *text, int matches, char *line_buffer,
|
||||
static
|
||||
char *line_completion_function (const char *text, int matches, char *line_buffer,
|
||||
int point);
|
||||
|
||||
/* readline uses the word breaks for two things:
|
||||
|
|
@ -48,13 +52,11 @@ char *line_completion_function (char *text, int matches, char *line_buffer,
|
|||
it does affect how much stuff M-? lists.
|
||||
(2) If one of the matches contains a word break character, readline
|
||||
will quote it. That's why we switch between
|
||||
gdb_completer_word_break_characters and
|
||||
current_language->la_word_break_characters() and
|
||||
gdb_completer_command_word_break_characters. I'm not sure when
|
||||
we need this behavior (perhaps for funky characters in C++ symbols?). */
|
||||
|
||||
/* Variables which are necessary for fancy command line editing. */
|
||||
static char *gdb_completer_word_break_characters =
|
||||
" \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-";
|
||||
|
||||
/* When completing on command names, we remove '-' from the list of
|
||||
word break characters, since we use it in command names. If the
|
||||
|
|
@ -87,12 +89,6 @@ static char *gdb_completer_quote_characters = "'";
|
|||
|
||||
/* Accessor for some completer data that may interest other files. */
|
||||
|
||||
char *
|
||||
get_gdb_completer_word_break_characters (void)
|
||||
{
|
||||
return gdb_completer_word_break_characters;
|
||||
}
|
||||
|
||||
char *
|
||||
get_gdb_completer_quote_characters (void)
|
||||
{
|
||||
|
|
@ -102,7 +98,7 @@ get_gdb_completer_quote_characters (void)
|
|||
/* Line completion interface function for readline. */
|
||||
|
||||
char *
|
||||
readline_line_completion_function (char *text, int matches)
|
||||
readline_line_completion_function (const char *text, int matches)
|
||||
{
|
||||
return line_completion_function (text, matches, rl_line_buffer, rl_point);
|
||||
}
|
||||
|
|
@ -133,7 +129,7 @@ filename_completer (char *text, char *word)
|
|||
while (1)
|
||||
{
|
||||
char *p;
|
||||
p = filename_completion_function (text, subsequent_name);
|
||||
p = rl_filename_completion_function (text, subsequent_name);
|
||||
if (return_val_used >= return_val_alloced)
|
||||
{
|
||||
return_val_alloced *= 2;
|
||||
|
|
@ -248,7 +244,7 @@ location_completer (char *text, char *word)
|
|||
colon = p;
|
||||
symbol_start = p + 1;
|
||||
}
|
||||
else if (strchr (gdb_completer_word_break_characters, *p))
|
||||
else if (strchr (current_language->la_word_break_characters(), *p))
|
||||
symbol_start = p + 1;
|
||||
}
|
||||
|
||||
|
|
@ -380,7 +376,7 @@ command_completer (char *text, char *word)
|
|||
should pretend that the line ends at POINT. */
|
||||
|
||||
char **
|
||||
complete_line (char *text, char *line_buffer, int point)
|
||||
complete_line (const char *text, char *line_buffer, int point)
|
||||
{
|
||||
char **list = NULL;
|
||||
char *tmp_command, *p;
|
||||
|
|
@ -396,7 +392,7 @@ complete_line (char *text, char *line_buffer, int point)
|
|||
'-' character used in some commands. */
|
||||
|
||||
rl_completer_word_break_characters =
|
||||
gdb_completer_word_break_characters;
|
||||
current_language->la_word_break_characters();
|
||||
|
||||
/* Decide whether to complete on a list of gdb commands or on symbols. */
|
||||
tmp_command = (char *) alloca (point + 1);
|
||||
|
|
@ -626,8 +622,8 @@ complete_line (char *text, char *line_buffer, int point)
|
|||
which is a possible completion, it is the caller's responsibility to
|
||||
free the string. */
|
||||
|
||||
char *
|
||||
line_completion_function (char *text, int matches, char *line_buffer, int point)
|
||||
static char *
|
||||
line_completion_function (const char *text, int matches, char *line_buffer, int point)
|
||||
{
|
||||
static char **list = (char **) NULL; /* Cache of completions */
|
||||
static int index; /* Next cached completion */
|
||||
|
|
@ -671,21 +667,30 @@ line_completion_function (char *text, int matches, char *line_buffer, int point)
|
|||
/* Make sure the word break characters are set back to normal for the
|
||||
next time that readline tries to complete something. */
|
||||
rl_completer_word_break_characters =
|
||||
gdb_completer_word_break_characters;
|
||||
current_language->la_word_break_characters();
|
||||
#endif
|
||||
|
||||
return (output);
|
||||
}
|
||||
/* Skip over a possibly quoted word (as defined by the quote characters
|
||||
and word break characters the completer uses). Returns pointer to the
|
||||
location after the "word". */
|
||||
|
||||
/* Skip over the possibly quoted word STR (as defined by the quote
|
||||
characters QUOTECHARS and the the word break characters
|
||||
BREAKCHARS). Returns pointer to the location after the "word". If
|
||||
either QUOTECHARS or BREAKCHARS is NULL, use the same values used
|
||||
by the completer. */
|
||||
|
||||
char *
|
||||
skip_quoted (char *str)
|
||||
skip_quoted_chars (char *str, char *quotechars, char *breakchars)
|
||||
{
|
||||
char quote_char = '\0';
|
||||
char *scan;
|
||||
|
||||
if (quotechars == NULL)
|
||||
quotechars = gdb_completer_quote_characters;
|
||||
|
||||
if (breakchars == NULL)
|
||||
breakchars = current_language->la_word_break_characters();
|
||||
|
||||
for (scan = str; *scan != '\0'; scan++)
|
||||
{
|
||||
if (quote_char != '\0')
|
||||
|
|
@ -698,16 +703,26 @@ skip_quoted (char *str)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (strchr (gdb_completer_quote_characters, *scan))
|
||||
else if (strchr (quotechars, *scan))
|
||||
{
|
||||
/* Found start of a quoted string. */
|
||||
quote_char = *scan;
|
||||
}
|
||||
else if (strchr (gdb_completer_word_break_characters, *scan))
|
||||
else if (strchr (breakchars, *scan))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (scan);
|
||||
}
|
||||
|
||||
/* Skip over the possibly quoted word STR (as defined by the quote
|
||||
characters and word break characters used by the completer).
|
||||
Returns pointer to the location after the "word". */
|
||||
|
||||
char *
|
||||
skip_quoted (char *str)
|
||||
{
|
||||
return skip_quoted_chars (str, NULL, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,11 +19,9 @@
|
|||
#if !defined (COMPLETER_H)
|
||||
#define COMPLETER_H 1
|
||||
|
||||
extern char **complete_line (char *text, char *line_buffer, int point);
|
||||
extern char **complete_line (const char *text, char *line_buffer, int point);
|
||||
|
||||
extern char *line_completion_function (char *, int, char *, int);
|
||||
|
||||
extern char *readline_line_completion_function (char *text, int matches);
|
||||
extern char *readline_line_completion_function (const char *text, int matches);
|
||||
|
||||
extern char **noop_completer (char *, char *);
|
||||
|
||||
|
|
@ -33,12 +31,12 @@ extern char **location_completer (char *, char *);
|
|||
|
||||
extern char **command_completer (char *, char *);
|
||||
|
||||
extern char *get_gdb_completer_word_break_characters (void);
|
||||
|
||||
extern char *get_gdb_completer_quote_characters (void);
|
||||
|
||||
/* Exported to linespec.c */
|
||||
|
||||
extern char *skip_quoted (char *str);
|
||||
extern char *skip_quoted_chars (char *, char *, char *);
|
||||
|
||||
extern char *skip_quoted (char *);
|
||||
|
||||
#endif /* defined (COMPLETER_H) */
|
||||
|
|
|
|||
2
contrib/gdb/gdb/config/alpha/alpha.mt
Normal file
2
contrib/gdb/gdb/config/alpha/alpha.mt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
TDEPFILES= alpha-tdep.o
|
||||
TM_FILE= tm-alpha.h
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Target: FreeBSD/Alpha
|
||||
TDEPFILES= alpha-tdep.o alphafbsd-tdep.o
|
||||
TDEPFILES= alpha-tdep.o alpha-mdebug-tdep.o alphabsd-tdep.o alphafbsd-tdep.o
|
||||
TM_FILE= tm-fbsd.h
|
||||
|
|
|
|||
4
contrib/gdb/gdb/config/alpha/nbsd.mh
Normal file
4
contrib/gdb/gdb/config/alpha/nbsd.mh
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Host: Alpha running NetBSD
|
||||
NAT_CLIBS=
|
||||
NATDEPFILES= infptrace.o inftarg.o fork-child.o alphabsd-nat.o
|
||||
NAT_FILE= nm-nbsd.h
|
||||
4
contrib/gdb/gdb/config/alpha/nbsd.mt
Normal file
4
contrib/gdb/gdb/config/alpha/nbsd.mt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Target: Alpha running NetBSD
|
||||
TDEPFILES= alpha-tdep.o alpha-mdebug-tdep.o alphabsd-tdep.o alphanbsd-tdep.o \
|
||||
corelow.o nbsd-tdep.o solib.o solib-svr4.o
|
||||
TM_FILE= tm-nbsd.h
|
||||
|
|
@ -32,13 +32,11 @@
|
|||
#define ATTACH_DETACH
|
||||
|
||||
/* The Alpha does not step over a breakpoint. */
|
||||
#define CANNOT_STEP_BREAKPOINT
|
||||
#define CANNOT_STEP_BREAKPOINT 1
|
||||
|
||||
|
||||
/* Shared library support. */
|
||||
|
||||
#define SVR4_SHARED_LIBS
|
||||
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#include "elf/common.h" /* Additional ELF shared library info. */
|
||||
|
||||
|
|
|
|||
31
contrib/gdb/gdb/config/alpha/nm-nbsd.h
Normal file
31
contrib/gdb/gdb/config/alpha/nm-nbsd.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* Native-dependent definitions for Alpha running NetBSD, for GDB.
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
Contributed by Wasabi Systems, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef NM_NBSD_H
|
||||
#define NM_NBSD_H
|
||||
|
||||
/* Get generic NetBSD native definitions. */
|
||||
#include "config/nm-nbsd.h"
|
||||
|
||||
/* The Alpha does not step over a breakpoint. */
|
||||
#define CANNOT_STEP_BREAKPOINT 1
|
||||
|
||||
#endif /* NM_NBSD_H */
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
/* Native definitions for alpha running OSF/1.
|
||||
Copyright 1993, 1994, 1995, 1998, 2000 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 1993, 1994, 1995, 1998, 2000, 2004 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -18,14 +20,10 @@
|
|||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Figure out where the longjmp will land. We expect that we have just entered
|
||||
longjmp and haven't yet setup the stack frame, so the args are still in the
|
||||
argument regs. A0_REGNUM points at the jmp_buf structure from which we
|
||||
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
|
||||
This routine returns true on success */
|
||||
|
||||
#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
|
||||
extern int get_longjmp_target (CORE_ADDR *);
|
||||
/* Number of traps that happen between exec'ing the shell
|
||||
to run an inferior, and when we finally get to
|
||||
the inferior code. This is 2 on most implementations. */
|
||||
#define START_INFERIOR_TRAPS_EXPECTED 3
|
||||
|
||||
/* ptrace register ``addresses'' are absolute. */
|
||||
|
||||
|
|
@ -41,11 +39,7 @@ extern int get_longjmp_target (CORE_ADDR *);
|
|||
|
||||
/* The alpha does not step over a breakpoint, the manpage is lying again. */
|
||||
|
||||
#define CANNOT_STEP_BREAKPOINT
|
||||
|
||||
/* OSF/1 has shared libraries. */
|
||||
|
||||
#define GDB_TARGET_HAS_SHARED_LIBS
|
||||
#define CANNOT_STEP_BREAKPOINT 1
|
||||
|
||||
/* Support for shared libraries. */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@
|
|||
#define USE_PROC_FS
|
||||
#define HAVE_OPTIONAL_PROC_FS
|
||||
|
||||
/* OSF/1 doesn't provide the standard fault definitions, so don't use them. */
|
||||
#define FAULTED_USE_SIGINFO
|
||||
|
||||
/* Don't trace faults under OSF/1, rely on the posting of the appropriate
|
||||
signal if fault tracing is disabled.
|
||||
Tracing T_IFAULT under Alpha OSF/1 causes a `floating point enable'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/* Target-dependent definitions for FreeBSD/Alpha.
|
||||
Copyright 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
|
@ -23,23 +24,4 @@
|
|||
|
||||
#include "alpha/tm-alpha.h"
|
||||
|
||||
/* FreeBSD uses the old gcc convention for struct returns. */
|
||||
|
||||
#undef USE_STRUCT_CONVENTION
|
||||
#define USE_STRUCT_CONVENTION(gcc_p, type) \
|
||||
alphafbsd_use_struct_convention (gcc_p, type)
|
||||
|
||||
/* FreeBSD doesn't mark the outermost frame. While some FreeBSD/Alpha
|
||||
releases include (a minimal amount of) debugging info in its
|
||||
startup code (crt1.o), the safest thing is to consider the user
|
||||
code entry point as the outermost frame. */
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
func_frame_chain_valid(chain, thisframe)
|
||||
|
||||
/* Number of traps that happen between exec'ing the shell to run an
|
||||
inferior, and when we finally get to the inferior code. The
|
||||
default is right for FreeBSD. */
|
||||
|
||||
#undef START_INFERIOR_TRAPS_EXPECTED
|
||||
|
||||
#endif /* TM_FBSD_H */
|
||||
|
|
|
|||
28
contrib/gdb/gdb/config/alpha/tm-nbsd.h
Normal file
28
contrib/gdb/gdb/config/alpha/tm-nbsd.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Target-dependent definitions for NetBSD/Alpha.
|
||||
|
||||
Copyright 2002, 2004 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_NBSD_H
|
||||
#define TM_NBSD_H
|
||||
|
||||
#include "alpha/tm-alpha.h"
|
||||
#include "solib.h"
|
||||
|
||||
#endif /* TM_NBSD_H */
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
# Target: ARM running NetBSD
|
||||
TDEPFILES= arm-tdep.o armnbsd-tdep.o solib.o solib-svr4.o solib-sunos.o
|
||||
TDEPFILES= arm-tdep.o armnbsd-tdep.o solib.o solib-svr4.o nbsd-tdep.o
|
||||
TM_FILE=tm-nbsd.h
|
||||
|
|
|
|||
5
contrib/gdb/gdb/config/arm/nbsdaout.mh
Normal file
5
contrib/gdb/gdb/config/arm/nbsdaout.mh
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Host ARM running NetBSD
|
||||
NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o armnbsd-nat.o \
|
||||
solib-sunos.o
|
||||
XM_FILE=xm-nbsd.h
|
||||
NAT_FILE=nm-nbsdaout.h
|
||||
4
contrib/gdb/gdb/config/arm/nbsdelf.mh
Normal file
4
contrib/gdb/gdb/config/arm/nbsdelf.mh
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Host ARM running NetBSD
|
||||
NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o armnbsd-nat.o
|
||||
XM_FILE=xm-nbsd.h
|
||||
NAT_FILE=nm-nbsd.h
|
||||
|
|
@ -22,12 +22,6 @@
|
|||
#define NM_NBSD_H
|
||||
|
||||
/* Get generic NetBSD native definitions. */
|
||||
#include "nm-nbsd.h"
|
||||
|
||||
#define REGISTER_U_ADDR(addr, blockend, regno) \
|
||||
(addr) = arm_register_u_addr ((blockend),(regno));
|
||||
|
||||
extern int
|
||||
arm_register_u_addr (int, int);
|
||||
#include "config/nm-nbsd.h"
|
||||
|
||||
#endif /* NM_NBSD_H */
|
||||
|
|
|
|||
29
contrib/gdb/gdb/config/arm/nm-nbsdaout.h
Normal file
29
contrib/gdb/gdb/config/arm/nm-nbsdaout.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/* Native-dependent definitions for ARM running NetBSD, for GDB.
|
||||
Copyright 1986, 1987, 1989, 1992, 1994, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef NM_NBSDAOUT_H
|
||||
#define NM_NBSDAOUT_H
|
||||
|
||||
#include "arm/nm-nbsd.h"
|
||||
|
||||
/* Get generic NetBSD a.out native definitions. */
|
||||
#include "config/nm-nbsdaout.h"
|
||||
|
||||
#endif /* NM_NBSDAOUT_H */
|
||||
|
|
@ -22,9 +22,7 @@
|
|||
#ifndef TM_ARM_H
|
||||
#define TM_ARM_H
|
||||
|
||||
#ifndef GDB_MULTI_ARCH
|
||||
#define GDB_MULTI_ARCH 1
|
||||
#endif
|
||||
|
||||
/* Specify that for the native compiler variables for a particular
|
||||
lexical context are listed after the beginning LBRAC instead of
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue