From patchwork Thu Aug 25 15:08:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 14934 Received: (qmail 52106 invoked by alias); 25 Aug 2016 15:08:28 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 51631 invoked by uid 89); 25 Aug 2016 15:08:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 spammy=stru, 7708 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 25 Aug 2016 15:08:18 +0000 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u7PF4I58054891 for ; Thu, 25 Aug 2016 11:08:16 -0400 Received: from e06smtp15.uk.ibm.com (e06smtp15.uk.ibm.com [195.75.94.111]) by mx0a-001b2d01.pphosted.com with ESMTP id 251ff5m9vj-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 25 Aug 2016 11:08:15 -0400 Received: from localhost by e06smtp15.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 25 Aug 2016 16:08:13 +0100 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp15.uk.ibm.com (192.168.101.145) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 25 Aug 2016 16:08:11 +0100 X-IBM-Helo: d06dlp01.portsmouth.uk.ibm.com X-IBM-MailFrom: uweigand@de.ibm.com X-IBM-RcptTo: gdb-patches@sourceware.org Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 951E217D8056 for ; Thu, 25 Aug 2016 16:09:57 +0100 (BST) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u7PF8BnR2163176 for ; Thu, 25 Aug 2016 15:08:11 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u7PF8A2x011809 for ; Thu, 25 Aug 2016 11:08:10 -0400 Received: from oc7340732750.ibm.com (icon-9-164-148-136.megacenter.de.ibm.com [9.164.148.136]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u7PF8Aqw011791 for ; Thu, 25 Aug 2016 11:08:10 -0400 Received: by oc7340732750.ibm.com (Postfix, from userid 500) id A7B5FC9FB; Thu, 25 Aug 2016 17:08:09 +0200 (CEST) Subject: [8/9] Add gdbarch callback to provide formats for debug info float types To: gdb-patches@sourceware.org Date: Thu, 25 Aug 2016 17:08:09 +0200 (CEST) From: "Ulrich Weigand" MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16082515-0020-0000-0000-00000237EC29 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16082515-0021-0000-0000-00003DC35C94 Message-Id: <20160825150809.A7B5FC9FB@oc7340732750.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-08-25_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1608250181 Hello, at this point, all TYPE_CODE_FLT types carry their floating-point format, except for those creating from reading DWARF or stabs debug info. Those will be addressed by this patch. The main issue here is that we actually have to determine which floating- point format to use. Currently, we only have the type length as input to this decision. In the future, we may hopefully get --at least in DWARF-- additional information to help disambiguate multiple different formats of the same length. For now, we can still look at the type name as a hint. This decision logic is encapsulated in a gdbarch callback to allow platform-specific overrides. The default implementation use the same logic (compare type length against the various gdbarch_..._bit sizes) that is currently implemented in floatformat_from_length. With this patch, all platforms still use the default logic, so there should be no actual change in behavior. A follow-on patch will add support for __float128 on Intel and Power. Once dwarf2read.c and stabsread.c make use of the new callback to determine floating-point formats, we're now sure every TYPE_CODE_FLT type will always carry its format. The patch therefore adds asserts to verify_floatformat to ensure new code will continue to always provide formats, and removes the code in floatformat_from_type that used to handle types with a NULL TYPE_FLOATFORMAT. Bye, Ulrich ChangeLog: * gdbarch.sh (floatformat_for_type): New gdbarch callback. * gdbarch.h, gdbarch.c: Re-generate. * arch-utils.h (default_floatformat_for_type): New prototype. * arch-utils.c (default_floatformat_for_type): New function. * doublest.c (floatformat_from_length): Remove. (floatformat_from_type): Assume TYPE_FLOATFORMAT is non-NULL. * gdbtypes.c (verify_floatformat): Require non-NULL format. * dwarf2read.c (dwarf2_init_float_type): New function. (read_base_type): Use it. * stabsread.c (dbx_init_float_type): New function. (read_sun_floating_type): Use it. (read_range_type): Likewise. Index: binutils-gdb/gdb/gdbarch.sh =================================================================== --- binutils-gdb.orig/gdb/gdbarch.sh 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/gdbarch.sh 2016-08-25 13:11:52.524850596 +0200 @@ -383,6 +383,11 @@ v:const struct floatformat **:double_for v:int:long_double_bit:::8 * sizeof (long double):8*TARGET_CHAR_BIT::0 v:const struct floatformat **:long_double_format:::::floatformats_ieee_double::pformat (gdbarch->long_double_format) +# Returns the floating-point format to be used for values of length LENGTH. +# NAME, if non-NULL, is the type name, which may be used to distinguish +# different target formats of the same length. +m:const struct floatformat **:floatformat_for_type:const char *name, int length:name, length:0:default_floatformat_for_type::0 + # For most targets, a pointer on the target and its representation as an # address in GDB have the same size and "look the same". For such a # target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit Index: binutils-gdb/gdb/gdbarch.h =================================================================== --- binutils-gdb.orig/gdb/gdbarch.h 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/gdbarch.h 2016-08-25 13:11:52.527850608 +0200 @@ -187,6 +187,14 @@ extern void set_gdbarch_long_double_bit extern const struct floatformat ** gdbarch_long_double_format (struct gdbarch *gdbarch); extern void set_gdbarch_long_double_format (struct gdbarch *gdbarch, const struct floatformat ** long_double_format); +/* Returns the floating-point format to be used for values of length LENGTH. + NAME, if non-NULL, is the type name, which may be used to distinguish + different target formats of the same length. */ + +typedef const struct floatformat ** (gdbarch_floatformat_for_type_ftype) (struct gdbarch *gdbarch, const char *name, int length); +extern const struct floatformat ** gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length); +extern void set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch, gdbarch_floatformat_for_type_ftype *floatformat_for_type); + /* For most targets, a pointer on the target and its representation as an address in GDB have the same size and "look the same". For such a target, you need only set gdbarch_ptr_bit and gdbarch_addr_bit Index: binutils-gdb/gdb/gdbarch.c =================================================================== --- binutils-gdb.orig/gdb/gdbarch.c 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/gdbarch.c 2016-08-25 13:11:52.529850616 +0200 @@ -176,6 +176,7 @@ struct gdbarch const struct floatformat ** double_format; int long_double_bit; const struct floatformat ** long_double_format; + gdbarch_floatformat_for_type_ftype *floatformat_for_type; int ptr_bit; int addr_bit; int dwarf2_addr_size; @@ -376,6 +377,7 @@ gdbarch_alloc (const struct gdbarch_info gdbarch->float_bit = 4*TARGET_CHAR_BIT; gdbarch->double_bit = 8*TARGET_CHAR_BIT; gdbarch->long_double_bit = 8*TARGET_CHAR_BIT; + gdbarch->floatformat_for_type = default_floatformat_for_type; gdbarch->ptr_bit = gdbarch->int_bit; gdbarch->char_signed = -1; gdbarch->virtual_frame_pointer = legacy_virtual_frame_pointer; @@ -522,6 +524,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of long_double_bit, invalid_p == 0 */ if (gdbarch->long_double_format == 0) gdbarch->long_double_format = floatformats_ieee_double; + /* Skip verify of floatformat_for_type, invalid_p == 0 */ /* Skip verify of ptr_bit, invalid_p == 0 */ if (gdbarch->addr_bit == 0) gdbarch->addr_bit = gdbarch_ptr_bit (gdbarch); @@ -973,6 +976,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: float_format = %s\n", pformat (gdbarch->float_format)); fprintf_unfiltered (file, + "gdbarch_dump: floatformat_for_type = <%s>\n", + host_address_to_string (gdbarch->floatformat_for_type)); + fprintf_unfiltered (file, "gdbarch_dump: fp0_regnum = %s\n", plongest (gdbarch->fp0_regnum)); fprintf_unfiltered (file, @@ -1729,6 +1735,23 @@ set_gdbarch_long_double_format (struct g gdbarch->long_double_format = long_double_format; } +const struct floatformat ** +gdbarch_floatformat_for_type (struct gdbarch *gdbarch, const char *name, int length) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->floatformat_for_type != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_floatformat_for_type called\n"); + return gdbarch->floatformat_for_type (gdbarch, name, length); +} + +void +set_gdbarch_floatformat_for_type (struct gdbarch *gdbarch, + gdbarch_floatformat_for_type_ftype floatformat_for_type) +{ + gdbarch->floatformat_for_type = floatformat_for_type; +} + int gdbarch_ptr_bit (struct gdbarch *gdbarch) { Index: binutils-gdb/gdb/arch-utils.h =================================================================== --- binutils-gdb.orig/gdb/arch-utils.h 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/arch-utils.h 2016-08-25 13:11:52.533850634 +0200 @@ -95,6 +95,11 @@ int cannot_register_not (struct gdbarch extern gdbarch_virtual_frame_pointer_ftype legacy_virtual_frame_pointer; +/* Default implementation of gdbarch_floatformat_for_type. */ +extern const struct floatformat ** + default_floatformat_for_type (struct gdbarch *gdbarch, + const char *name, int len); + extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc); Index: binutils-gdb/gdb/arch-utils.c =================================================================== --- binutils-gdb.orig/gdb/arch-utils.c 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/arch-utils.c 2016-08-25 13:11:52.537850652 +0200 @@ -241,6 +241,34 @@ legacy_virtual_frame_pointer (struct gdb *frame_offset = 0; } +/* Return a floating-point format for a floating-point variable of + length LEN in bits. If non-NULL, NAME is the name of its type. + If no suitable type is found, return NULL. */ + +const struct floatformat ** +default_floatformat_for_type (struct gdbarch *gdbarch, + const char *name, int len) +{ + const struct floatformat **format = NULL; + + if (len == gdbarch_half_bit (gdbarch)) + format = gdbarch_half_format (gdbarch); + else if (len == gdbarch_float_bit (gdbarch)) + format = gdbarch_float_format (gdbarch); + else if (len == gdbarch_double_bit (gdbarch)) + format = gdbarch_double_format (gdbarch); + else if (len == gdbarch_long_double_bit (gdbarch)) + format = gdbarch_long_double_format (gdbarch); + /* On i386 the 'long double' type takes 96 bits, + while the real number of used bits is only 80, + both in processor and in memory. + The code below accepts the real bit size. */ + else if (gdbarch_long_double_format (gdbarch) != NULL + && len == gdbarch_long_double_format (gdbarch)[0]->totalsize) + format = gdbarch_long_double_format (gdbarch); + + return format; +} int generic_convert_register_p (struct gdbarch *gdbarch, int regnum, Index: binutils-gdb/gdb/doublest.c =================================================================== --- binutils-gdb.orig/gdb/doublest.c 2016-08-25 13:11:36.762781562 +0200 +++ binutils-gdb/gdb/doublest.c 2016-08-25 13:11:52.541850668 +0200 @@ -770,52 +770,8 @@ floatformat_from_doublest (const struct } -/* Return a floating-point format for a floating-point variable of - length LEN. If no suitable floating-point format is found, an - error is thrown. - - We need this functionality since information about the - floating-point format of a type is not always available to GDB; the - debug information typically only tells us the size of a - floating-point type. - - FIXME: kettenis/2001-10-28: In many places, particularly in - target-dependent code, the format of floating-point types is known, - but not passed on by GDB. This should be fixed. */ - -static const struct floatformat * -floatformat_from_length (struct gdbarch *gdbarch, int len) -{ - const struct floatformat *format; - - if (len * TARGET_CHAR_BIT == gdbarch_half_bit (gdbarch)) - format = gdbarch_half_format (gdbarch) - [gdbarch_byte_order (gdbarch)]; - else if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch)) - format = gdbarch_float_format (gdbarch) - [gdbarch_byte_order (gdbarch)]; - else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (gdbarch)) - format = gdbarch_double_format (gdbarch) - [gdbarch_byte_order (gdbarch)]; - else if (len * TARGET_CHAR_BIT == gdbarch_long_double_bit (gdbarch)) - format = gdbarch_long_double_format (gdbarch) - [gdbarch_byte_order (gdbarch)]; - /* On i386 the 'long double' type takes 96 bits, - while the real number of used bits is only 80, - both in processor and in memory. - The code below accepts the real bit size. */ - else if ((gdbarch_long_double_format (gdbarch) != NULL) - && (len * TARGET_CHAR_BIT - == gdbarch_long_double_format (gdbarch)[0]->totalsize)) - format = gdbarch_long_double_format (gdbarch) - [gdbarch_byte_order (gdbarch)]; - else - format = NULL; - if (format == NULL) - error (_("Unrecognized %d-bit floating-point type."), - len * TARGET_CHAR_BIT); - return format; -} +/* Return the floating-point format for a floating-point variable of + type TYPE. */ const struct floatformat * floatformat_from_type (const struct type *type) @@ -824,11 +780,8 @@ floatformat_from_type (const struct type const struct floatformat *fmt; gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT); - if (TYPE_FLOATFORMAT (type) != NULL) - fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)]; - else - fmt = floatformat_from_length (gdbarch, TYPE_LENGTH (type)); - + gdb_assert (TYPE_FLOATFORMAT (type)); + fmt = TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)]; gdb_assert (TYPE_LENGTH (type) >= floatformat_totalsize_bytes (fmt)); return fmt; } Index: binutils-gdb/gdb/gdbtypes.c =================================================================== --- binutils-gdb.orig/gdb/gdbtypes.c 2016-08-25 13:11:50.766842886 +0200 +++ binutils-gdb/gdb/gdbtypes.c 2016-08-25 13:11:52.546850692 +0200 @@ -2712,21 +2712,16 @@ set_type_code (struct type *type, enum t static int verify_floatformat (int bit, const struct floatformat **floatformats) { + gdb_assert (floatformats != NULL); + gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL); + if (bit == -1) - { - gdb_assert (floatformats != NULL); - gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL); - bit = floatformats[0]->totalsize; - } + bit = floatformats[0]->totalsize; gdb_assert (bit >= 0); - if (floatformats != NULL) - { - size_t len = bit / TARGET_CHAR_BIT; - - gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0])); - gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1])); - } + size_t len = bit / TARGET_CHAR_BIT; + gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0])); + gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1])); return bit; } Index: binutils-gdb/gdb/dwarf2read.c =================================================================== --- binutils-gdb.orig/gdb/dwarf2read.c 2016-08-25 13:11:49.268836321 +0200 +++ binutils-gdb/gdb/dwarf2read.c 2016-08-25 13:11:52.556850735 +0200 @@ -14757,6 +14757,27 @@ read_typedef (struct die_info *die, stru return this_type; } +/* Allocate a floating-point type of size BITS and name NAME. Pass NAME_HINT + (which may be different from NAME) to the architecture back-end to allow + it to guess the correct format if necessary. */ + +static struct type * +dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name, + const char *name_hint) +{ + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const struct floatformat **format; + struct type *type; + + format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits); + if (format) + type = init_float_type (objfile, bits, name, format); + else + type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, name); + + return type; +} + /* Find a representation of a given base type and install it in the TYPE field of the die. */ @@ -14797,14 +14818,14 @@ read_base_type (struct die_info *die, st type = init_boolean_type (objfile, bits, 1, name); break; case DW_ATE_complex_float: - type = init_float_type (objfile, bits / 2, NULL, NULL); + type = dwarf2_init_float_type (objfile, bits / 2, NULL, name); type = init_complex_type (objfile, name, type); break; case DW_ATE_decimal_float: type = init_decfloat_type (objfile, bits, name); break; case DW_ATE_float: - type = init_float_type (objfile, bits, name, NULL); + type = dwarf2_init_float_type (objfile, bits, name, name); break; case DW_ATE_signed: type = init_integer_type (objfile, bits, 0, name); Index: binutils-gdb/gdb/stabsread.c =================================================================== --- binutils-gdb.orig/gdb/stabsread.c 2016-08-25 13:11:51.623846644 +0200 +++ binutils-gdb/gdb/stabsread.c 2016-08-25 13:11:52.562850760 +0200 @@ -353,6 +353,24 @@ dbx_alloc_type (int typenums[2], struct return (*type_addr); } +/* Allocate a floating-point type of size BITS. */ + +static struct type * +dbx_init_float_type (struct objfile *objfile, int bits) +{ + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const struct floatformat **format; + struct type *type; + + format = gdbarch_floatformat_for_type (gdbarch, NULL, bits); + if (format) + type = init_float_type (objfile, bits, NULL, format); + else + type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, NULL); + + return type; +} + /* for all the stabs in a given stab vector, build appropriate types and fix their symbols in given symbol vector. */ @@ -3847,11 +3865,11 @@ read_sun_floating_type (char **pp, int t if (details == NF_COMPLEX || details == NF_COMPLEX16 || details == NF_COMPLEX32) { - rettype = init_float_type (objfile, nbits / 2, NULL, NULL); + rettype = dbx_init_float_type (objfile, nbits / 2); return init_complex_type (objfile, NULL, rettype); } - return init_float_type (objfile, nbits, NULL, NULL); + return dbx_init_float_type (objfile, nbits); } /* Read a number from the string pointed to by *PP. @@ -4138,7 +4156,7 @@ read_range_type (char **pp, int typenums if (n3 == 0 && n2 > 0) { struct type *float_type - = init_float_type (objfile, n2 * TARGET_CHAR_BIT, NULL, NULL); + = dbx_init_float_type (objfile, n2 * TARGET_CHAR_BIT); if (self_subrange) return init_complex_type (objfile, NULL, float_type);