From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16694 invoked by alias); 10 Aug 2012 09:33:27 -0000 Received: (qmail 16677 invoked by uid 22791); 10 Aug 2012 09:33:25 -0000 X-SWARE-Spam-Status: No, hits=-7.6 required=5.0 tests=AWL,BAYES_00,KHOP_PGP_SIGNED,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_BJ,TW_CP,TW_VP,TW_XZ X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 10 Aug 2012 09:33:09 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1Szlaf-0001IK-BB from Thomas_Schwinge@mentor.com ; Fri, 10 Aug 2012 02:33:09 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Fri, 10 Aug 2012 02:33:09 -0700 Received: from feldtkeller.schwinge.homeip.net (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Fri, 10 Aug 2012 10:33:06 +0100 From: Thomas Schwinge To: CC: Subject: Re: Memory corruption for host double format different from target double format In-Reply-To: <87r4rgrkss.fsf@schwinge.name> References: <87r4rgrkss.fsf@schwinge.name> User-Agent: Notmuch/0.9-101-g81dad07 (http://notmuchmail.org) Emacs/23.3.1 (x86_64-pc-linux-gnu) Date: Fri, 10 Aug 2012 09:33:00 -0000 Message-ID: <87ipcrrt16.fsf@schwinge.name> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha1; protocol="application/pgp-signature" Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2012-08/txt/msg00029.txt.bz2 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Content-length: 11657 Hi! On Thu, 09 Aug 2012 20:18:27 +0200, I wrote: > Thanks to the recent memory checking instrastructure (well, it's been > some weeks already...), a memory corruption issue has been uncovered for > configurations where the host double format is not equal to target double > format. I have seen this for SH, but don't believe it really is specific > to SH, it's just that the very most of all GDB targets have host double > format match the target double format. >=20 > As I'm not sufficiently experienced with GDB's expressions and type > system, I'd like some help here. >=20 > $ install/bin/*-gdb -q -ex 'file [...]/gdb.cp/misc' -ex 'show archite= cture' -ex 'print (bool)17.93' > Reading symbols from [...]/gdb.cp/misc...done. > The target architecture is set automatically (currently sh2a-or-sh3e) > $1 =3D true > memory clobbered past end of allocated block > Aborted >=20 > sh2a-or-sh3e configures for a 32-bit double format, as opposed to the > "normal" 64-bit double format (which also is the x86_64 host's double > format). >=20 > sh-tdep.c:sh_gdbarch_init: >=20 > case bfd_mach_sh2a_or_sh3e: > /* doubles on sh2e and sh3e are actually 4 byte. */ > set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); Turns out it -- somewhat -- is an issue in sh-tdep.c. With the following patch, everything is fine. Index: sh-tdep.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/sh-tdep.c,v retrieving revision 1.246 diff -u -p -r1.246 sh-tdep.c --- sh-tdep.c 22 Jul 2012 16:52:41 -0000 1.246 +++ sh-tdep.c 10 Aug 2012 09:15:04 -0000 @@ -2299,6 +2299,7 @@ sh_gdbarch_init (struct gdbarch_info inf case bfd_mach_sh2e: /* doubles on sh2e and sh3e are actually 4 byte. */ set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); + set_gdbarch_double_format (gdbarch, floatformats_ieee_single); =20 set_gdbarch_register_name (gdbarch, sh_sh2e_register_name); set_gdbarch_register_type (gdbarch, sh_sh3e_register_type); @@ -2344,6 +2345,7 @@ sh_gdbarch_init (struct gdbarch_info inf case bfd_mach_sh2a_or_sh3e: /* doubles on sh2e and sh3e are actually 4 byte. */ set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); + set_gdbarch_double_format (gdbarch, floatformats_ieee_single); =20 set_gdbarch_register_name (gdbarch, sh_sh3e_register_name); set_gdbarch_register_type (gdbarch, sh_sh3e_register_type); The testresults speak for themselves: =3D=3D=3D gdb Summary =3D=3D=3D =20=20=20=20=20 -# of expected passes 14953 -# of unexpected failures 154 +# of expected passes 15760 +# of unexpected failures 100 # of unexpected successes 2 # of expected failures 42 # of known failures 59 -# of unresolved testcases 797 # of untested testcases 45 # of unsupported tests 172 However, it seems there are other targets where a similar patching would be needed. And, to begin with, why does GDB allow for letting this mismatch happen? Quoting my yesterday's analysis: > First and foremost -- is my understanding correct that given this > configuration the expression =C2=BB(bool) 17.93=C2=AB then indeed is to be > evaluated in a 32-bit double format, and not in the host's 64-bit double > format? >=20 > Our friend Valgrind is able to confirm this memory corruption issue, and > -- as so often -- gives a clue where to begin looking: >=20 > $ valgrind -v -- install/bin/*-gdb -q -ex 'file [...]/gdb.cp/misc' -e= x 'print (bool)17.93' > [...] > =3D=3D6509=3D=3D Invalid write of size 1 > =3D=3D6509=3D=3D at 0x47FB974: memcpy (mc_replace_strmem.c:497) > =3D=3D6509=3D=3D by 0x824D487: floatformat_from_doublest (doublest= .c:768) > =3D=3D6509=3D=3D by 0x824D78D: store_typed_floating (doublest.c:88= 1) > =3D=3D6509=3D=3D by 0x81023DA: value_from_double (value.c:3170) > =3D=3D6509=3D=3D by 0x810424F: evaluate_subexp_standard (eval.c:84= 6) > =3D=3D6509=3D=3D by 0x82020E3: evaluate_subexp_c (c-lang.c:719) > =3D=3D6509=3D=3D by 0x8102975: evaluate_subexp (eval.c:73) > =3D=3D6509=3D=3D by 0x810A157: evaluate_subexp_standard (eval.c:27= 13) > =3D=3D6509=3D=3D by 0x82020E3: evaluate_subexp_c (c-lang.c:719) > =3D=3D6509=3D=3D by 0x8102975: evaluate_subexp (eval.c:73) > =3D=3D6509=3D=3D by 0x8102B02: evaluate_expression (eval.c:148) > =3D=3D6509=3D=3D by 0x811EE31: print_command_1 (printcmd.c:966) > =3D=3D6509=3D=3D Address 0x8e83bbc is 0 bytes after a block of size = 4 alloc'd > =3D=3D6509=3D=3D at 0x47F925F: calloc (vg_replace_malloc.c:467) > =3D=3D6509=3D=3D by 0x82725B4: xcalloc (common-utils.c:90) > =3D=3D6509=3D=3D by 0x82725EA: xzalloc (common-utils.c:100) > =3D=3D6509=3D=3D by 0x80FE7AB: allocate_value_contents (value.c:69= 5) > =3D=3D6509=3D=3D by 0x80FE7D4: allocate_value (value.c:705) > =3D=3D6509=3D=3D by 0x8102383: value_from_double (value.c:3164) > =3D=3D6509=3D=3D by 0x810424F: evaluate_subexp_standard (eval.c:84= 6) > =3D=3D6509=3D=3D by 0x82020E3: evaluate_subexp_c (c-lang.c:719) > =3D=3D6509=3D=3D by 0x8102975: evaluate_subexp (eval.c:73) > =3D=3D6509=3D=3D by 0x810A157: evaluate_subexp_standard (eval.c:27= 13) > =3D=3D6509=3D=3D by 0x82020E3: evaluate_subexp_c (c-lang.c:719) > =3D=3D6509=3D=3D by 0x8102975: evaluate_subexp (eval.c:73) > [...] >=20 > Here is what is happening, in value.c:value_from_double: >=20 > struct value * > value_from_double (struct type *type, DOUBLEST num) > { > struct value *val =3D allocate_value (type); > struct type *base_type =3D check_typedef (type); > enum type_code code =3D TYPE_CODE (base_type); >=20=20=20=20=20 > if (code =3D=3D TYPE_CODE_FLT) > { > store_typed_floating (value_contents_raw (val), base_type, num); > [...] >=20 > Breakpoint 1, value_from_double (type=3D0x852c388, num=3D17.93) at [.= ..]/gdb/value.c:3164 > 3164 struct value *val =3D allocate_value (type); > (gdb) print *type > $2 =3D {pointer_type =3D 0x0, reference_type =3D 0x0, chain =3D 0x852= c388, instance_flags =3D 0, length =3D 4, main_type =3D 0x852c3c0} > (gdb) print *type->main_type > $3 =3D {code =3D TYPE_CODE_FLT, flag_unsigned =3D 0, flag_nosign =3D = 0, flag_stub =3D 0, flag_target_stub =3D 0, flag_static =3D 0, flag_prototy= ped =3D 0, flag_incomplete =3D 0, flag_varargs =3D 0, flag_vector =3D 0, fl= ag_stub_supported =3D 0,=20 > flag_gnu_ifunc =3D 0, flag_fixed_instance =3D 0, flag_objfile_owned= =3D 0, flag_declared_class =3D 0, flag_flag_enum =3D 0, type_specific_fiel= d =3D TYPE_SPECIFIC_NONE, nfields =3D 0, vptr_fieldno =3D -1, name =3D 0x85= 2c408 "double", tag_name =3D 0x0,=20 > owner =3D {objfile =3D 0x8512f80, gdbarch =3D 0x8512f80}, target_ty= pe =3D 0x0, flds_bnds =3D {fields =3D 0x0, bounds =3D 0x0}, vptr_basetype = =3D 0x0, type_specific =3D {cplus_stuff =3D 0x8476d8c, gnat_stuff =3D 0x847= 6d8c, floatformat =3D 0x8476d8c,=20 > func_stuff =3D 0x8476d8c}} > (gdb) print type->main_type->type_specific->floatformat[1] > $36 =3D (const struct floatformat *) 0x8461f40 > (gdb) print host_float_format=20 > $31 =3D (const struct floatformat *) 0x8461e80 > (gdb) print host_double_format=20 > $35 =3D (const struct floatformat *) 0x8461f40 >=20 > Here we can already see that, TYPE's floatformat is host_double_format, > which is 64-bit double format. However, in my understanding, TYPE is > meant to be a 32-bit double type, having a 32-bit double format. >=20 > Stepping further, allocate_value, allocate_value_contents: >=20 > allocate_value (type=3D0x852c388) at [...]/gdb/value.c:705 > 705 allocate_value_contents (val); > (gdb)=20 > allocate_value_contents (val=3D0x8522508) at [...]/gdb/value.c:694 > 694 if (!val->contents) > (gdb)=20 > 695 val->contents =3D (gdb_byte *) xzalloc (TYPE_LENGTH (val-= >enclosing_type)); > (gdb)=20 > xzalloc (size=3D4) at [...]/gdb/common/common-utils.c:100 > 100 return xcalloc (1, size); >=20 > So indeed we allocate 32 bits. >=20 > Back in value_from_double, on to doublest.c:store_typed_floating: >=20 > void > store_typed_floating (void *addr, const struct type *type, DOUBLEST v= al) > { > const struct floatformat *fmt =3D floatformat_from_type (type); > [...] > floatformat_from_doublest (fmt, &val, addr); > } >=20 > store_typed_floating (addr=3D0x850a570, type=3D0x852c388, val=3D17.93= ) at [...]/gdb/doublest.c:859 > 859 const struct floatformat *fmt =3D floatformat_from_type (ty= pe); > [...] > 881 floatformat_from_doublest (fmt, &val, addr); > (gdb) s > floatformat_from_doublest (fmt=3D0x8461f40, in=3D0xffffbfd8, out=3D0x= 850a570) at [...]/gdb/doublest.c:757 >=20 > Here we indeed see floatformat fmt 0x8461f40 being passed, which is > host_double_format, the 64-bit double format (see Bearkpoint 1 above). > In the following, things break: >=20 > (gdb) s > 758 if (fmt =3D=3D host_float_format) > (gdb)=20 > 764 else if (fmt =3D=3D host_double_format) > (gdb)=20 > 766 double val =3D *in; > (gdb)=20 > 768 memcpy (out, &val, sizeof (val)); >=20 > We have host_double_format, =C2=BBsizeof val=C2=AB is 64 bits, but we only > allocated 32 bits, thus memcpy corrupts the memory. >=20 > Looking at doublest:floatformat_from_type: >=20 > const struct floatformat * > floatformat_from_type (const struct type *type) > { > struct gdbarch *gdbarch =3D get_type_arch (type); >=20=20=20=20=20 > gdb_assert (TYPE_CODE (type) =3D=3D TYPE_CODE_FLT); > if (TYPE_FLOATFORMAT (type) !=3D NULL) > return TYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)]; > else > return floatformat_from_length (gdbarch, TYPE_LENGTH (type)); > } >=20 > In our case, =C2=BBTYPE_FLOATFORMAT (type)[gdbarch_byte_order (gdbarch)]= =C2=AB is > host_double_format (see Breakpoint 1 above). If I instead make that take > the floatformat_from_length route, it correctly returns the 32-bit > host_float_type, and everything works as expected. >=20 > So, my understanding is that =C2=BBTYPE_FLOATFORMAT (type)=C2=AB is set > incorrectly -- but where and why is this happening? It is here: gdbarch.c:verify_gdbarch: [...] /* Skip verify of float_bit, invalid_p =3D=3D 0 */ if (gdbarch->float_format =3D=3D 0) gdbarch->float_format =3D floatformats_ieee_single; /* Skip verify of double_bit, invalid_p =3D=3D 0 */ if (gdbarch->double_format =3D=3D 0) gdbarch->double_format =3D floatformats_ieee_double; /* Skip verify of long_double_bit, invalid_p =3D=3D 0 */ if (gdbarch->long_double_format =3D=3D 0) gdbarch->long_double_format =3D floatformats_ieee_double; [...] That is, if set_gdbarch_double_format has not been called, it will default to floatformats_ieee_double -- even though set_gdbarch_double_bit may have been called setting it unequal to the 64-bit double format. Hmm, and gdbarch.c:verify_gdbarch has the following comment on top of it: =C2=BBEnsure that all values in a GDBARCH are reasonable.=C2=AB ;-) Gr=C3=BC=C3=9Fe, Thomas --=-=-= Content-Type: application/pgp-signature Content-length: 489 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAEBAgAGBQJQJNVFAAoJENuKOtuXzphJV2QIAMG45XhG4+AvJgbGGJdnnZci URLOQ7dF0mZdFITyM6sPFCa6lFPBisflYK2zUXOUg3bctcB+N6iTseIEMHjNQnhw gC3HSQmsZit9oqSrq01VAQ0nFEP2R/ANoH39B6dvnl674k3hSye+4Ngg75vDjrky HIMq6A7aMEEDrAZepTdp4ic+jt0Tiqtk6m15HGBYRgGTlI+Omw8/IcWBtyvghSPo I12LW59msiZqOixczJ7MGiLggIQEi5T+zTX44iLmDN2CNYqr9OuklzU1LiNwaAI9 LO19zRF+ZWuAWFtVQ0Fm9Z2/7QCwZvAJDQj0fNrEq0lEPgYZVt1xrBF+423RNLs= =oRjt -----END PGP SIGNATURE----- --=-=-=--