question about why gdb needs executable's binary

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

question about why gdb needs executable's binary

Jirka Koutný
Hello,

If we assume debugging a core file generated by an excutable with stripped
symbols (that gdb is able to find and load correctly in my case),
I was wondering why does gdb still need the executable's binary as well? Is
there some additional information retrieved from the executable? It does
seem the stack trace does not get resolved if the executable file is not
specified, but if I understand it right, PT_NOTE contains address ranges
and shared libraries names as well, so the information to build the strack
trace is there already. So say if I only start gdb and then core-file
<corefilename>, why does 'where' return a list of question marks?
What is the missing bit of information there?

I'm not questioning correctness or anything, if it's like that from
historical reasons I'm cool with that, I'm just trying to understand the
thing.

Thank you,
Jirka
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Andreas Schwab
On Mär 13 2019, Jirka Koutný <[hidden email]> wrote:

> If we assume debugging a core file generated by an excutable with stripped
> symbols (that gdb is able to find and load correctly in my case),
> I was wondering why does gdb still need the executable's binary as
> well?

A core file only contains data from modified mappings.  Any data from
read-only mappings needs to be read from the original files.

Andreas.

--
Andreas Schwab, SUSE Labs, [hidden email]
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jirka Koutný
Thanks Andreas! Aha that's interesting.. hmm so, is there some read-only
segment, that would contain information necessary for the output of 'where'?

Den ons. 13. mar. 2019 kl. 14:34 skrev Andreas Schwab <[hidden email]>:

> On Mär 13 2019, Jirka Koutný <[hidden email]> wrote:
>
> > If we assume debugging a core file generated by an excutable with
> stripped
> > symbols (that gdb is able to find and load correctly in my case),
> > I was wondering why does gdb still need the executable's binary as
> > well?
>
> A core file only contains data from modified mappings.  Any data from
> read-only mappings needs to be read from the original files.
>
> Andreas.
>
> --
> Andreas Schwab, SUSE Labs, [hidden email]
> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
> "And now for something completely different."
>
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

John Baldwin
On 3/13/19 8:41 AM, Jirka Koutný wrote:
> Thanks Andreas! Aha that's interesting.. hmm so, is there some read-only
> segment, that would contain information necessary for the output of 'where'?

The .text section containing the instructions being executed is often needed
for unwinding if there is no debug info.  On some architectures with a fixed
frame layout like 32-bit x86 you can get by without decoding instructions, but
on other architectures like 64-bit x86, an unwinder has to try to decode
instructions to determine frame layouts in the absence of debug info.

> Den ons. 13. mar. 2019 kl. 14:34 skrev Andreas Schwab <[hidden email]>:
>
>> On Mär 13 2019, Jirka Koutný <[hidden email]> wrote:
>>
>>> If we assume debugging a core file generated by an excutable with
>> stripped
>>> symbols (that gdb is able to find and load correctly in my case),
>>> I was wondering why does gdb still need the executable's binary as
>>> well?
>>
>> A core file only contains data from modified mappings.  Any data from
>> read-only mappings needs to be read from the original files.
>>
>> Andreas.
>>
>> --
>> Andreas Schwab, SUSE Labs, [hidden email]
>> GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
>> "And now for something completely different."
>>


--
John Baldwin
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jan Kratochvil-2
In reply to this post by Jirka Koutný
On Wed, 13 Mar 2019 15:24:50 +0100, Jirka Koutný wrote:
> I was wondering why does gdb still need the executable's binary as well?
> Is there some additional information retrieved from the executable?

Yes, without the main executable GDB cannot find the list of shared libraries.


> PT_NOTE contains address ranges and shared libraries names as well,

NT_FILE is a recent feature and GDB can only produce it, GDB cannot read it.
GDB also cannot read /proc/PID/maps to recognize the list of shared libraries.


> What is the missing bit of information there?

To find the list of mapped shared libraries GDB needs to read DT_DEBUG which
is located in DYNAMIC segment of the main executable.

GDB can read also "_r_debug" but for that it needs to know ld.so which is
a mapped shared library so that is a chicked-and-egg problem.


eu-stack can do these:

With main executable:
$ eu-stack --core=sleep.core
PID 1886638 - core
TID 1886638:
#0  0x00007f37e04707f8 __nanosleep
#1  0x000055a9557f28d7 rpl_nanosleep
#2  0x000055a9557f26b0 xnanosleep
#3  0x000055a9557ef7c8 main
#4  0x00007f37e03cb413 __libc_start_main
#5  0x000055a9557ef89e _start

Without main executable:
$ eu-stack --core=sleep.core2
PID 1886638 - core
TID 1886638:
#0  0x00007f37e04707f8 __nanosleep
#1  0x000055a9557f28d7
eu-stack: dwfl_thread_getframes tid 1886638 at 0x55a9557f28d6 in /usr/bin/sleep: Callback returned failure

Just that eu-stack does not contain heuristics for unwinding frames with
missing unwind information (.eh_frame/.debug_frame) and so if a frame is
generated from the main executable it gives up for further unwinding.


Jan
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jirka Koutný
Sorry for the delay, I needed some time to read up on DT_DEBUG and r_debug.
It makes a little bit more sense now, so thanks a lot. If you find time,
I'd still like to ask a few more questions:

PT_NOTE can't be read by gdb, that settles it, thanks *thumb up*. That
being said, how about dlopen()? How do these get in the trace? Surely not
from the executable.

For what I found out about DT_DEBUG this section gets initialized by ld as
you said. Do I understand you correctly, this is an alternative to the
first option, that in fact doesn't require the executable?

Thank you
Jirka

Den tor. 14. mar. 2019 kl. 21:45 skrev Jan Kratochvil <
[hidden email]>:

> On Wed, 13 Mar 2019 15:24:50 +0100, Jirka Koutný wrote:
> > I was wondering why does gdb still need the executable's binary as well?
> > Is there some additional information retrieved from the executable?
>
> Yes, without the main executable GDB cannot find the list of shared
> libraries.
>
>
> > PT_NOTE contains address ranges and shared libraries names as well,
>
> NT_FILE is a recent feature and GDB can only produce it, GDB cannot read
> it.
> GDB also cannot read /proc/PID/maps to recognize the list of shared
> libraries.
>
>
> > What is the missing bit of information there?
>
> To find the list of mapped shared libraries GDB needs to read DT_DEBUG
> which
> is located in DYNAMIC segment of the main executable.
>
> GDB can read also "_r_debug" but for that it needs to know ld.so which is
> a mapped shared library so that is a chicked-and-egg problem.
>
>
> eu-stack can do these:
>
> With main executable:
> $ eu-stack --core=sleep.core
> PID 1886638 - core
> TID 1886638:
> #0  0x00007f37e04707f8 __nanosleep
> #1  0x000055a9557f28d7 rpl_nanosleep
> #2  0x000055a9557f26b0 xnanosleep
> #3  0x000055a9557ef7c8 main
> #4  0x00007f37e03cb413 __libc_start_main
> #5  0x000055a9557ef89e _start
>
> Without main executable:
> $ eu-stack --core=sleep.core2
> PID 1886638 - core
> TID 1886638:
> #0  0x00007f37e04707f8 __nanosleep
> #1  0x000055a9557f28d7
> eu-stack: dwfl_thread_getframes tid 1886638 at 0x55a9557f28d6 in
> /usr/bin/sleep: Callback returned failure
>
> Just that eu-stack does not contain heuristics for unwinding frames with
> missing unwind information (.eh_frame/.debug_frame) and so if a frame is
> generated from the main executable it gives up for further unwinding.
>
>
> Jan
>
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jan Kratochvil-2
On Tue, 19 Mar 2019 15:25:15 +0100, Jirka Koutný wrote:
> PT_NOTE can't be read by gdb,

Various PT_NOTESs are read by GDB but not PT_NOTE of type NT_FILE.


> That being said, how about dlopen()?

That does not matter, both initially-loaded libraries and dlopen()ed libraries
are present in DT_DEBUG/_r_debug/r_debug the same way.

"initially-loaded library" (which is linked automatically, during compilation
specified by -lNAME) are present in DT_NEEDED but that is for ld.so
(/lib64/ld-linux-x86-64.so.2) and GDB does not care about those.
It would be nice if GDB did but that is an unrelated RFE:
        RFE: preload DT_NEEDED library list
        https://sourceware.org/bugzilla/show_bug.cgi?id=12249


> For what I found out about DT_DEBUG this section gets initialized by ld as

by ld.so (/lib64/ld-linux-x86-64.so.2), not /usr/bin/ld.


> you said. Do I understand you correctly, this is an alternative to the
> first option, that in fact doesn't require the executable?

yes, sort of alternative.  But NT_FILE is generated by kernel so there can
appear even shared libraries mmap()ed as data files while in
DT_DEBUG/_r_debug/r_debug can be found only libraries really opened by
DT_NEEDED or dlopen()ed.  So there is a subtle difference what those two
sources of information mean.

Also NT_FILE is generated only by Linux kernel (or GDB) while
DT_DEBUG/_r_debug/r_debug are present even on non-Linux UNIXes
(if one thinks there still exist some).


Jan
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jirka Koutný
I see, just to make sure - DT_DEBUG gets dumped into the corefile, is that
correct?

Den tir. 19. mar. 2019 kl. 14:35 skrev Jan Kratochvil <
[hidden email]>:

> On Tue, 19 Mar 2019 15:25:15 +0100, Jirka Koutný wrote:
> > PT_NOTE can't be read by gdb,
>
> Various PT_NOTESs are read by GDB but not PT_NOTE of type NT_FILE.
>
>
> > That being said, how about dlopen()?
>
> That does not matter, both initially-loaded libraries and dlopen()ed
> libraries
> are present in DT_DEBUG/_r_debug/r_debug the same way.
>
> "initially-loaded library" (which is linked automatically, during
> compilation
> specified by -lNAME) are present in DT_NEEDED but that is for ld.so
> (/lib64/ld-linux-x86-64.so.2) and GDB does not care about those.
> It would be nice if GDB did but that is an unrelated RFE:
>         RFE: preload DT_NEEDED library list
>         https://sourceware.org/bugzilla/show_bug.cgi?id=12249
>
>
> > For what I found out about DT_DEBUG this section gets initialized by ld
> as
>
> by ld.so (/lib64/ld-linux-x86-64.so.2), not /usr/bin/ld.
>
>
> > you said. Do I understand you correctly, this is an alternative to the
> > first option, that in fact doesn't require the executable?
>
> yes, sort of alternative.  But NT_FILE is generated by kernel so there can
> appear even shared libraries mmap()ed as data files while in
> DT_DEBUG/_r_debug/r_debug can be found only libraries really opened by
> DT_NEEDED or dlopen()ed.  So there is a subtle difference what those two
> sources of information mean.
>
> Also NT_FILE is generated only by Linux kernel (or GDB) while
> DT_DEBUG/_r_debug/r_debug are present even on non-Linux UNIXes
> (if one thinks there still exist some).
>
>
> Jan
>
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jan Kratochvil-2
On Tue, 19 Mar 2019 16:25:30 +0100, Jirka Koutný wrote:
> I see, just to make sure - DT_DEBUG gets dumped into the corefile, is that
> correct?

The PT_DYNAMIC segment containing the DT_DEBUG pointer (pointing to
r_debug/_r_debug) normally gets dumped into the core file. The problem is that
without having the main executable one cannot much find where is the DT_DEBUG
pointer located in the core file. Core file has for example NT_AUXV where is
AT_PHDR and from program headers one could find PT_DYNAMIC where is DT_DEBUG.
But core file does not have to contain the program headers as those may be in
a read-only page of the main executable. Nowadays with dumping of the first
page of any ELF (even if it is read-only, for its NT_GNU_BUILD_ID) one can
probably find the program headers there. But then one can also just read
NT_FILE nowadays.


Jan
Reply | Threaded
Open this post in threaded view
|

Re: question about why gdb needs executable's binary

Jirka Koutný
Aha, perfect, now it makes sense, thank you very much for your patience :)

Den tir. 19. mar. 2019 kl. 15:41 skrev Jan Kratochvil <
[hidden email]>:

> On Tue, 19 Mar 2019 16:25:30 +0100, Jirka Koutný wrote:
> > I see, just to make sure - DT_DEBUG gets dumped into the corefile, is
> that
> > correct?
>
> The PT_DYNAMIC segment containing the DT_DEBUG pointer (pointing to
> r_debug/_r_debug) normally gets dumped into the core file. The problem is
> that
> without having the main executable one cannot much find where is the
> DT_DEBUG
> pointer located in the core file. Core file has for example NT_AUXV where
> is
> AT_PHDR and from program headers one could find PT_DYNAMIC where is
> DT_DEBUG.
> But core file does not have to contain the program headers as those may be
> in
> a read-only page of the main executable. Nowadays with dumping of the first
> page of any ELF (even if it is read-only, for its NT_GNU_BUILD_ID) one can
> probably find the program headers there. But then one can also just read
> NT_FILE nowadays.
>
>
> Jan
>