From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23155 invoked by alias); 9 Aug 2012 18:19:07 -0000 Received: (qmail 23141 invoked by uid 22791); 9 Aug 2012 18:19:03 -0000 X-SWARE-Spam-Status: No, hits=-5.1 required=5.0 tests=AWL,BAYES_00,FROM_12LTRDOM,KHOP_PGP_SIGNED,KHOP_RCVD_UNTRUST,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; Thu, 09 Aug 2012 18:18:43 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1SzXJi-0004LP-GM from Thomas_Schwinge@mentor.com for gdb@sourceware.org; Thu, 09 Aug 2012 11:18:42 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Thu, 9 Aug 2012 11:18:42 -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; Thu, 9 Aug 2012 19:18:40 +0100 From: Thomas Schwinge To: Subject: Memory corruption for host double format different from target double format User-Agent: Notmuch/0.9-101-g81dad07 (http://notmuchmail.org) Emacs/23.3.1 (x86_64-pc-linux-gnu) Date: Thu, 09 Aug 2012 18:19:00 -0000 Message-ID: <87r4rgrkss.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/msg00028.txt.bz2 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Content-length: 8247 Hi! 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. As I'm not sufficiently experienced with GDB's expressions and type system, I'd like some help here. $ install/bin/*-gdb -q -ex 'file [...]/gdb.cp/misc' -ex 'show architect= ure' -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 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). sh-tdep.c:sh_gdbarch_init: case bfd_mach_sh2a_or_sh3e: /* doubles on sh2e and sh3e are actually 4 byte. */ set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT); 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? Our friend Valgrind is able to confirm this memory corruption issue, and -- as so often -- gives a clue where to begin looking: $ valgrind -v -- install/bin/*-gdb -q -ex 'file [...]/gdb.cp/misc' -ex = '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:881) =3D=3D6509=3D=3D by 0x81023DA: value_from_double (value.c:3170) =3D=3D6509=3D=3D by 0x810424F: evaluate_subexp_standard (eval.c:846) =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:2713) =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:695) =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:846) =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:2713) =3D=3D6509=3D=3D by 0x82020E3: evaluate_subexp_c (c-lang.c:719) =3D=3D6509=3D=3D by 0x8102975: evaluate_subexp (eval.c:73) [...] Here is what is happening, in value.c:value_from_double: 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 if (code =3D=3D TYPE_CODE_FLT) { store_typed_floating (value_contents_raw (val), base_type, num); [...] 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 0x852c3= 88, 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_prototype= d =3D 0, flag_incomplete =3D 0, flag_varargs =3D 0, flag_vector =3D 0, flag= _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_field= =3D TYPE_SPECIFIC_NONE, nfields =3D 0, vptr_fieldno =3D -1, name =3D 0x852= c408 "double", tag_name =3D 0x0,=20 owner =3D {objfile =3D 0x8512f80, gdbarch =3D 0x8512f80}, target_type= =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 0x8476d8= c, 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 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. Stepping further, allocate_value, allocate_value_contents: 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->e= nclosing_type)); (gdb)=20 xzalloc (size=3D4) at [...]/gdb/common/common-utils.c:100 100 return xcalloc (1, size); So indeed we allocate 32 bits. Back in value_from_double, on to doublest.c:store_typed_floating: void store_typed_floating (void *addr, const struct type *type, DOUBLEST val) { const struct floatformat *fmt =3D floatformat_from_type (type); [...] floatformat_from_doublest (fmt, &val, addr); } store_typed_floating (addr=3D0x850a570, type=3D0x852c388, val=3D17.93) = at [...]/gdb/doublest.c:859 859 const struct floatformat *fmt =3D floatformat_from_type (type= ); [...] 881 floatformat_from_doublest (fmt, &val, addr); (gdb) s floatformat_from_doublest (fmt=3D0x8461f40, in=3D0xffffbfd8, out=3D0x85= 0a570) at [...]/gdb/doublest.c:757 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: (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)); We have host_double_format, =C2=BBsizeof val=C2=AB is 64 bits, but we only allocated 32 bits, thus memcpy corrupts the memory. Looking at doublest:floatformat_from_type: const struct floatformat * floatformat_from_type (const struct type *type) { struct gdbarch *gdbarch =3D get_type_arch (type); =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)); } 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. So, my understanding is that =C2=BBTYPE_FLOATFORMAT (type)=C2=AB is set incorrectly -- but where and why is this happening? Gr=C3=BC=C3=9Fe, Thomas --=-=-= Content-Type: application/pgp-signature Content-length: 489 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAEBAgAGBQJQI/7zAAoJENuKOtuXzphJb28H/RkYdVlA449uXFfIneoFUy2E 25a33WuZ6JOe+E+P8g6P5uR7KFrnLstDrziQsAc92rIRb0C7ILSH9hxloxjoP3U5 RXfC4/x4yxpuGWlE+IokFeSFz4/ibkxCFySXScVGfIqRvvnBeiay3CMyMsI5TnEI nnCTG+swkwWleAbX+/1/Sh5mT4bEjD4LYWHEad+ha9bEcYUysdkpQfoEHhAfY7UR We+phccjKMODnomfeef4V9ZIQz4iw2/oV7MA/kqtxIl7DQPjkcnkujRftFY9Ce9n YGV59OBTVJCYKfb/u0ap56ZiBR6rZYoMa/zogGwP1wArcbwmCym1LUMARf2ZbNk= =nTm6 -----END PGP SIGNATURE----- --=-=-=--