diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1de35843e2..5dfb83168b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +Sun May 3 15:47:45 1992 Fred Fish (fnf@cygnus.com) + + * Makefile.in (VERSION): Bump to 4.5.2. + * Makefile.in (DEMANGLE_OPTS): Add, default to -Dnounderscore. + * configure.in: Simplify ncr3000 gdb_host logic, add gdb_target. + * dwarfread.c (struct_type): Apply fix from Peggy Fieland for + proper handling of bit fields. + * gdbtypes.h (struct type): Clarify use of field.bitpos. + * symtab.h: Fix couple of misspellings in comments. + * value.h (struct value): Clarify use of bitpos. + * value.h (unpack_field_as_long): Change prototype, returns + LONGEST. + * values.c (unpack_field_as_long): Change return type to LONGEST, + sign extend unpacked fields that are signed, other rewriting. + * config/ncr3000.mt: New target config file. + Fri May 1 01:53:26 1992 John Gilmore (gnu at cygnus.com) * utils.c (printchar): Print 0x7F and 0x80-0x9F in \nnn notation diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 62f00e501d..467aa9d83b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -165,12 +165,19 @@ CDEPS = ${XM_CDEPS} ${TM_CDEPS} ${BFD_LIB} ${MMALLOC_LIB} ${LIBIBERTY} \ ADD_FILES = ${REGEX} ${ALLOCA} ${XM_ADD_FILES} ${TM_ADD_FILES} ADD_DEPS = ${REGEX1} ${ALLOCA1} ${XM_ADD_FILES} ${TM_ADD_FILES} -VERSION = 4.5.1 +VERSION = 4.5.2 DIST=gdb LINT=/usr/5bin/lint LINTFLAGS= -I${BFD_DIR} +# Select options to use when compiling cplus-dem.c. The default is to +# use -Dnounderscore, which is correct for most targets, and also +# defaults to g++ style demangling. For other demangling styles, such +# as the Annotated C++ Reference Manual (section 7.2.1c) style, set +# this define in the target-dependent makefile fragment. +DEMANGLE_OPTS=-Dnounderscore + # Host and target-dependent makefile fragments come in here. #### # End of host and target-dependent makefile fragments @@ -721,7 +728,7 @@ force_update: # -Dnounderscore. cplus-dem.o: cplus-dem.c - ${CC} -c ${INTERNAL_CFLAGS} -Dnounderscore \ + ${CC} -c ${INTERNAL_CFLAGS} ${DEMANGLE_OPTS} \ `echo ${srcdir}/cplus-dem.c | sed 's,^\./,,'` # GNU Make has an annoying habit of putting *all* the Makefile variables diff --git a/gdb/configure.in b/gdb/configure.in index 000578a3dc..e6b87c0199 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -99,11 +99,7 @@ i386) sun) gdb_host=sun386 ;; sco) gdb_host=i386sco ;; sequent) gdb_host=symmetry ;; - ncr) - case "${host_os}" in - sysv4*) gdb_host=ncr3000 ;; - esac - ;; + ncr) gdb_host=ncr3000 ;; *) case "${host_os}" in sysv32) gdb_host=i386v32 ;; @@ -283,6 +279,7 @@ i386) sco) gdb_target=i386sco ;; sun) gdb_target=sun386 ;; sequent) gdb_target=symmetry ;; + ncr) gdb_target=ncr3000 ;; *) case "${target_os}" in sysv32) gdb_target=i386v32 ;; diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 2e52295686..1cd34cd3c3 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -856,7 +856,27 @@ struct_type (dip, thisdie, enddie, objfile) list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name)); list -> field.type = decode_die_type (&mbr); list -> field.bitpos = 8 * locval (mbr.at_location); - list -> field.bitsize = 0; + /* Handle bit fields. */ + list -> field.bitsize = mbr.at_bit_size; +#if BITS_BIG_ENDIAN + /* For big endian bits, the at_bit_offset gives the additional + bit offset from the MSB of the containing anonymous object to + the MSB of the field. We don't have to do anything special + since we don't need to know the size of the anonymous object. */ + list -> field.bitpos += mbr.at_bit_offset; +#else + /* For little endian bits, we need to have a non-zero at_bit_size, + so that we know we are in fact dealing with a bitfield. Compute + the bit offset to the MSB of the anonymous object, subtract off + the number of bits from the MSB of the field to the MSB of the + object, and then subtract off the number of bits of the field + itself. The result is the bit offset of the LSB of the field. */ + if (mbr.at_bit_size > 0) + { + list -> field.bitpos += + mbr.at_byte_size * 8 - mbr.at_bit_offset - mbr.at_bit_size; + } +#endif nfields++; break; default: diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 7578b446c2..7e51e458ac 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -183,7 +183,9 @@ struct type /* Position of this field, counting in bits from start of containing structure. For a function type, this is the position in the argument list of this argument. - For a range bound or enum value, this is the value itself. */ + For a range bound or enum value, this is the value itself. + For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB. + For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB. */ int bitpos; diff --git a/gdb/values.c b/gdb/values.c index 895df77e30..c7ab7b77cc 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1190,29 +1190,60 @@ baseclass_addr (type, index, valaddr, valuep, errp) return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8; } -long +/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at + VALADDR. + + Extracting bits depends on endianness of the machine. Compute the + number of least significant bits to discard. For big endian machines, + we compute the total number of bits in the anonymous object, subtract + off the bit count from the MSB of the object to the MSB of the + bitfield, then the size of the bitfield, which leaves the LSB discard + count. For little endian machines, the discard count is simply the + number of bits from the LSB of the anonymous object to the LSB of the + bitfield. + + If the field is signed, we also do sign extension. */ + +LONGEST unpack_field_as_long (type, valaddr, fieldno) struct type *type; char *valaddr; int fieldno; { - unsigned long val; + unsigned LONGEST val; + unsigned LONGEST valmask; int bitpos = TYPE_FIELD_BITPOS (type, fieldno); int bitsize = TYPE_FIELD_BITSIZE (type, fieldno); + int lsbcount; - bcopy (valaddr + bitpos / 8, &val, sizeof val); - SWAP_TARGET_AND_HOST (&val, sizeof val); + bcopy (valaddr + bitpos / 8, &val, sizeof (val)); + SWAP_TARGET_AND_HOST (&val, sizeof (val)); + + /* Extract bits. See comment above. */ - /* Extracting bits depends on endianness of the machine. */ #if BITS_BIG_ENDIAN - val = val >> (sizeof val * 8 - bitpos % 8 - bitsize); + lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize); #else - val = val >> (bitpos % 8); + lsbcount = (bitpos % 8); #endif + val >>= lsbcount; - if (bitsize < 8 * sizeof (val)) - val &= (((unsigned long)1) << bitsize) - 1; - return val; + /* If the field does not entirely fill a LONGEST, then zero the sign bits. + If the field is signed, and is negative, then sign extend. */ + + if ((bitsize > 0) && (bitsize < 8 * sizeof (val))) + { + valmask = (((unsigned LONGEST) 1) << bitsize) - 1; + val &= valmask; + if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno))) + { + if (val & (valmask ^ (valmask >> 1))) + { + val |= ~valmask; + } + } + } + return (val); } /* Modify the value of a bitfield. ADDR points to a block of memory in