This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils 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: Difficulties while adding local init_regs support to libebl


Mark Wielaard <mjw@redhat.com> writes:

> Hi Ben,
>
> [Maybe read it all first before trying anything. At the end I think I
> got the correct solution, I start with some more cumbersome
> workarounds...]
>
Thanks again for your response!

> On Thu, 2015-09-03 at 22:10 +0200, Ben Gamari wrote:
>> I now have a few patches [1] adding support for collecting initial
>> register values from the current thread. While I believe the initial
>> register collection logic works (it works for GHC), I have encountered
>> an unfortunate issue while folding this code into libebl. Namely, it
>> seems that libebl backends are dynamically loaded.
>> 
>> To see why this is problematic, consider this example,
>>
>>   void test() {
>>     Dwfl *dwfl = dwfl_begin (&proc_callbacks);
>> 
>>     // Figure out what modules are loaded
>>     dwfl_linux_proc_report(dwfl, getpid());
>>     dwfl_report_end (dwfl, NULL, NULL);
>> 
>>     // but the ebl backend, libebl_x86_64.so, only gets loaded here
>>     dwfl_linux_local_attach(dwfl);
>> 
>>     // therefore when we begin to unwind we have no debug information
>>     // for libebl, which is where PC sits when we collect the initial
>>     // register values. Unwinding consequently fails
>>     dwfl_getthread_frames (dwfl, getpid(), frame_cb, dwfl) != 0;
>>   }
>> 
>> The issue here is that debug information is not reported to libdwfl as
>> it is not loaded at the time we report the loaded modules.
>
> Ah, interesting case indeed. I think the easiest workaround for now
> would just be to cheat and force the load of the native ebl backend in
> some initial setup/initialization function:
>
...
>
> You could even cheat a bit more and just call ebl_openbackend ()
> directly yourself. But that isn't officially supported.
>
Indeed I could cheat but I'd really like to avoid this if possible.

>> At this point I'm a bit unsure of how to proceed. I can think of a few
>> options,
>> 
>>   * teach dwfl_linux_local_attach to report libebl when it gets
>>     loaded. This would be rather ugly as we would either need to
>>     re-read the /proc map data or somehow extract the necessary
>>     information from the dynamic linker
>
> It might be interesting to have a Dwfl *dwfl_linux_local_report () that
> creates a Dwfl using the dynamic linker structures. It could come with a
> _refresh function or keep things automagically up to date (although that
> might be tricky with threading). But that seems a but more work than
> what you signed up for right now.
>
That might be the best option although I'm not entirely sure what
(reasonably portable) interfaces exist for this task.

>>   * Expose an entirely different interface from dwfl_getthread_frames
>>     for local unwinding such that PC doesn't sit within libebl when
>>     initial register values are collected.
>> [...[
>>     Unfortunately this is quite a departure from the current interface
>>     and seems to break the nice separation between libebl and the
>>     libdwfl.
>
> Yeah, that seems not great.
>
Agreed.

>>   * Something I haven't yet thought of...
>
> Maybe you could just do:
>
>   dwfl_report_begin (dwfl);
>   dwfl_linux_proc_report(dwfl, getpid());
>   dwfl_report_end (dwfl, NULL, NULL);
>
> after dwfl_linux_local_attach (), but before dwfl_getthread_frames ().
>
> That is supported to simply refreshes the Dwfl_Modules into the Dwfl.
> The only downside is that you reparse the /proc/pid/maps again, so it
> isn't as efficient as it could be.
>
Yeah, the reparsing is unfortunate but it might be acceptable.

Unfortunately it seems that libebl_x86_64.so doesn't even appear in
/proc/$PID/maps, so dwfl_linux_proc_report doesn't find it. I have no
idea why considering that gdb knows about it. Perhaps the reason is that
it is loaded with dlopen?

This makes me think that your suggestion of building up the module list
From the dynamic linker's structures might be necessary.

It's unfortunate that things get so complicated when you try to put the
initial register code in libebl. It all works so nicely in GHC.

> O, I should have thought of this at the start. Maybe you could just
> start with an empty Dwfl. Do you need to call dwfl_linux_proc_report ()
> before dwfl_linux_local_attach () at all? dwfl_linux_local_attach ()
> should be able to figure out the ebl backend it needs on its own. Then
> you could just report the modules as above after you called
> dwfl_linux_local_attach ().
>
That's a good question. The only reason I report first is that I thought
this was what the library expected. If this isn't the case then I
suppose this is all a moot point.

Unfortunately, when I do try to move the dwfl_linux_local_attach call
before dwfl_linux_proc_report the attach call fails in
dwfl_attach_state, which tries to traverse the loaded modules, I believe
to identify the architecture. The error message it returns is 

    linux_local_attach failed: Couldn't find architecture of any ELF

Thanks again for your help,

Cheers,

- Ben

Attachment: signature.asc
Description: PGP signature


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