From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 38772 invoked by alias); 15 Nov 2017 12:17:07 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 38138 invoked by uid 89); 15 Nov 2017 12:17:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=BAYES_00,KB_WAM_FROM_NAME_SINGLEWORD,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=no version=3.3.2 spammy=debate, Hopefully, Joel X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 15 Nov 2017 12:17:05 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD4D4C0587F7; Wed, 15 Nov 2017 12:17:03 +0000 (UTC) Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1912B32B3; Wed, 15 Nov 2017 12:17:02 +0000 (UTC) Subject: Re: RFC: problems with minimal symbols (without a type) To: Joel Brobecker References: <20171109012540.ds5ixw4pq6rclhgc@adacore.com> <4bca71af-2877-2adf-9f54-e51d7e6b5b8b@redhat.com> <20171115013531.cwj5pzjttrihofhl@adacore.com> Cc: gdb-patches@sourceware.org From: Pedro Alves Message-ID: Date: Wed, 15 Nov 2017 12:17:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <20171115013531.cwj5pzjttrihofhl@adacore.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-SW-Source: 2017-11/txt/msg00278.txt.bz2 On 11/15/2017 01:35 AM, Joel Brobecker wrote: >>> And unfortunately, the Ada equivalent of casting does not work either: >>> >>> (gdb) print integer(constraint_error) >>> 'constraint_error' has unknown type; cast it to its declared type >> >> Shouldn't we just make that work, like it works for C? > > Of course. It's at the top of my list, and independent in my mind > of the discussion about forcing the cast. It was a convenient > work-around, however, allowing me to reduce the urgency to fix > this issue with casting. Sorry, it wasn't clear to me that this was intended as a workaround as opposed to a proposal to make Ada always assume int. I'm not seeing this as independent -- if GDB assumes unknown types are integers, then we won't need to support casting from unknown types to anything else in the first place, it just falls out of supporting conversion from integer to anything else. Unless, gdb assumed int if there's no cast, and used the cast-to type if there's a cast. I don't think that's a good idea, because it'd still lead to surprising results. You could even get very hard-to-explain-by-users results, like: int64_t global = 0xffffffff00000000; (gdb) p global -1 -1 looks reasonable, the program sets global to -1 some times. I.e., there's no reason for a user to suspect gdb here, even though -1 was actually the incorrect value. And then with a cast, you'd get these conflicting results: (gdb) p /x global 0xffffffff (gdb) p /x (int64_t) (int) global 0xffffffffffffffff (gdb) p /x (int64_t) global 0xffffffff00000000 Notice that this isn't just about printing the values directly. You can get hard-to-diagnose problems if if you pass the value directly to some function. extern void function (unsigned long long); (gdb) p function (global) Above old GDB passes 0xffffffffffffffff, incorrectly. > That being said... > >> Let me quote a conversation that happened on IRC just last week >> (user name anonymized): > [...] >> you have to cast malloc to the right function pointer type, and then call that. >> something like: p ((void * (*) (size_t )) malloc) (128) >> in master, the simpler 'p (void*)malloc (128)' does the right thing. >> (it infers the prototype from the type of the passed in arguments + the cast-to type) > > I understand why GDB now behaves more naturally when using the casting > information to infer the symbol's type and how this is an improvement. > But wouldn't that part be orthogonal to the question whether GDB should > make this case mandatory or not? I actually pasted that part just for completeness. The point I was really trying to convey is in the unquoted part. I.e, that this is really a FAQ, that frequently users show up on IRC confused by GDB showing incorrect results they can't explain. IMHO, it's also very common to have globals that are pointers, which tend to be 64-bit nowadays, while integers are 32-bit, leading to problems with incorrect slicing and sign extending, similar to that user's issue with the return type of malloc. > > This is probably a judgement call. And since I didn't comment on > the patch when it was proposed, I suppose it's fair that I try it > for Ada users as well, and see how they react. It'll keep the languages > consistent too, which is an advantage. > > Just to answer some of your questions (therefore not in the spirit > of continuing a debate): > >> At least an Ada conversion/cast is Ada syntax. >> The "print {my_type} minsym'address" syntax above looks like >> the GDB syntax/extension that works with C too? > > Yes, this part is documented in the Ada section of the GDB manual. > OK. When involving "minsym" in a more complicated expression, it seems to me that the Ada conversion syntax would be a bit more convenient / natural: (gdb) print foo + long_integer (minsym) + bar (gdb) print foo + {long_integer} minsym'address + bar But then again, I'm clueless on most things Ada. :-) >> How do users discover that that gdb syntax extension is available >> and that they need to use it? >> For non-integer types, users must already do some casting to get at >> the real data. Why treat integers differently? > > For me, this is because those minimal symbols are typically integral > types. So, for a non-trivial part of the times I use this feature, > it actually gives me the right answer. Therefore, for me, GDB lost > a small feature that didn't always work, but still did work for a good > chunk of the scenarios I was involved in. > > I'll work on fixing the casting whenever I find some time... Thanks! Hopefully it'll be a simple change to ada_evaluate_subexp's UNOP_CAST handling, mirroring the evaluate_subexp_for_cast in eval.c. Let me know if you run into something odd. > > That got me to one piece of code in evaluate_subexp_for_cast: > > /* Don't allow e.g. '&(int)var_with_no_debug_info'. */ > if (VALUE_LVAL (val) == lval_memory) > { > if (value_lazy (val)) > value_fetch_lazy (val); > VALUE_LVAL (val) = not_lval; > } > > I was wondering why do we not want to allow someone get its > address? I checked the commit that introduced this change, > and it doesn't say. This is to follow usual language rules. A cast expression isn't an lvalue, so you can't take its address: int global; void foo () { int *p = & (int) global; } $ gcc cast-address.c -o cast-address -g3 -O0 cast-address.c: In function ‘foo’: cast-address.c:5:12: error: lvalue required as unary ‘&’ operand int *p = & (int) global; ^ So accordingly, taking the address of the lvalue in GDB does work: (gdb) p &dataglobal $1 = ( *) 0x601040 But taking the address of the rvalue doesn't: (gdb) p &(int) dataglobal Attempt to take address of value not located in memory. (gdb) p *& (int) dataglobal Attempt to take address of value not located in memory. Just like what you'd get if you had debug info for "dataglobal". The correct way is to cast the resulting pointer instead: (gdb) p (int *) &dataglobal $2 = (int *) 0x601040 (gdb) p *(int *) &dataglobal $3 = 3 which works the same whether you have debug info for dataglobal or not. This is covered by the tests in gdb.base/nodebug.exp, in the loop right after "We can't rely on uintXX_t". About the exception catchpoints, to answer my own question about which expression is GDB trying to evaluate, I was able to reproduce the issue with catchpoints using the gdb.ada/mi_exc_info.exp testcase, btw, using 'strip -g' on the testcase's binary. (gdb) set language ada (gdb) catch exception const__aint_global_gdb_e warning: failed to reevaluate internal exception condition for catchpoint 0: 'const.aint_global_gdb_e' has unknown type; cast it to its declared type Catchpoint 2: `const__aint_global_gdb_e' Ada exception Setting a breakpoint on 'warning' reveals: (top-gdb) p s $1 = 0x1ec6d00 "long_integer (e) = long_integer (&const__aint_global_gdb_e)" Curious, I didn't know that "&" worked in Ada too. Thanks, Pedro Alves