This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On Fri, Jun 30, 2017 at 12:37 PM, Pedro Alves <palves@redhat.com> wrote:
> On 06/30/2017 01:28 AM, Zack Weinberg wrote:
>> 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?

The _primary_ goal of the glibc patches is to trigger a pretty-printer
when someone does

(gdb) p errno

with no further adornment. Since pretty-printers are keyed by type
(and since people do store errno codes in other places than errno),
this involves a type 'error_t' (and its implementation-namespace alias
'__error_t'), but if we can't get 'p errno' to work, we're probably
not going to bother.

In all currently-supported configurations, this is glibc's definition of errno:

extern int *__errno_location (void) __THROW __attribute__ ((__const__));
#define errno (*__errno_location ())

(__THROW is a macro expanding to 'throw ()' when compiling C++.)

The patches change that to

extern __error_t *__errno_location (void) __THROW __attribute__ ((__const__));

which should be sufficient to get the pretty-printing happening.  But
obviously that's only going to work if GDB actually knows that the
return type of __errno_location is __error_t*, and it doesn't seem to,
*even when debug information for the definition is available*:

 $ gdb /lib/x86_64-linux-gnu/libc.so.6
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
...

Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols
from /usr/lib/debug/.build-id/cc/80584889db7a969292959a46c718a2b1500702.debug...done.
done.
(gdb) ptype __errno_location
type = int ()
(gdb) p __errno_location
$1 = {<text variable, no debug info>} 0x20590 <__GI___errno_location>

... a suspicion occurs...

(gdb) ptype __GI___errno_location
type = int *(void)
(gdb) p __GI___errno_location
$2 = {int *(void)} 0x20590 <__GI___errno_location>

... so I guess this is a problem with the __GI_ indirection, which
*may* be a thing we can resolve on our end.  I don't fully understand
that stuff.

Still, It Would Be Nice™ if you _didn't_ have to have the debug
symbols for libc.so installed for this to work.  Probably a lot of
people think you only need those if you are debugging libc itself.

> 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.)

Probably because that's the pre-C89 legacy default function signature?

> 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.

Hmm.  How would one do that from inside Python?

zw


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]