Re: [RFC PATCH 0/3] Pretty-printing for errno

Pedro Alves
2017-06-30T16:38:15Z

On 06/30/2017 01:28 AM, Zack Weinberg wrote:
> On Thu, Jun 29, 2017 at 1:28 PM, Pedro Alves <palves@redhat.com> wrote:
>> With this code:
>>
>> typedef int zzz;
>> zzz z;
>>
>> gdb:
>>
>> (gdb) whatis z
>> type = zzz
>> (gdb) whatis (zzz)0
>> type = zzz
>> (gdb) whatis zzz
>> type = int
>

I've now sent the patch to gdb-patches:

https://sourceware.org/ml/gdb-patches/2017-06/msg00827.html

Could one of you check whether the type printer kicks in with that,
in the problematic cast case?

Phil, might it be a good idea to convert what you were
using to a real gdb testsuite test?

> For the glibc patch to go through, this case also needs to work:
>
> typedef int error_t;
> error_t var;
> extern error_t *errloc(void);
>
> int main(void)
> {
> return *errloc();
> }
>
> (compiled to .o file)
>
> (gdb) ptype errloc
> No symbol "errloc" in current context.
>
> This might be a problem with inadequate debugging information
> generated by the compiler

Debug info is generated for function definitions, not declarations.
I.e., that declaration for "errloc" alone produces no debug info
at all. Try 'readelf -dw' on the .o file.

But why is this a valid scenario? Even if you have no debug info,
GDB should be able to find the function's address in the elf dynamic
symbol table?

I'm not sure what you mean by "glibc patch to go through".
If you mean acceptance upstream, then I'd consider this a separate
issue, because now you're talking about being able to print the
"errno" variable in the first place, even as a plain int with no
printer? That is related, but orthogonal from the error_t type printer?
Otherwise, can you clarify?

-- it does work correctly if a function
> *definition* is visible. But we need it to work given only the above,
> possibly with no debug symbols in the shared library defining
> "errloc".

Won't __errno_location be always present in the dynamic symbol table?
If you strip everything from libc.so.6 / libpthread.so.0 including
dynamic symbols, leaving gdb with no clue about "__errno_location",
let alone its address, there's no way that gdb can call it.
(Unless you call it by address manually.)

The next problem is that without debug info for __errno_location,
gdb has no clue of its prototype, only that its a function, and so
it assumes that it has type "int()", i.e., that it returns int,
while in reality it returns int * / __error_t *. (Falling back
to assuming "int" is IMO not the best idea, but I don't know
the history behind it.)

I.e., with your example .o + a separate .o file defining
errloc (with no debug info), we now get:

(gdb) ptype errloc
type = int ()

and then calling "p *errloc()" (the equivalent of
'#define errno (*__errno_location ())' silently subtly does
the wrong thing.

One dirty way around it would be for the printer to
re-define the errno macro (using to cast __errno_location to
the correct type before calling it, I guess:

(gdb) macro define errno *(*(__error_t *(*) (void)) __errno_location) ()

That's make "errno" available when you compile with levels
lower than -g3, too.

Fedora gdb has a morally equivalent hack in the source code
directly.

Ideally, we'd find a clean way to make this all Just Work.

Thanks,
Pedro Alves