unwind non-PC registers using elfutils

Jacob Burkholder jake.burkholder2@gmail.com
Thu Nov 11 06:23:21 GMT 2021


Hi Mark, thanks for your mail.

On Wed, Nov 10, 2021 at 6:09 AM Mark Wielaard <mark@klomp.org> wrote:
>
> Hi Jacob,
>
> On Sun, 2021-10-03 at 09:38 -0700, Jacob Burkholder via Elfutils-devel wrote:
> > Hi, I'm trying to figure out how to unwind registers other than the PC
> > using elfutils.  I can use dwfl_module_register_names to get the register
> > names, and then I'm trying to use dwarf_frame_register to get the register
> > values for a given frame.  I looked at the code in __libdwfl_frame_unwind
> > and there's another example in addrcfi.c.   dwarf_frame_register seems
> > quite a low level dwarf API, I'm not sure how to use the ops that are
> > returned, also the code used by __libdwfl_frame_unwind to evaluate the ops
> > is all static or internal so not callable.  Any guidance?  Do I need to
> > basically interpret the dwarf atoms in the ops returned by
> > dwarf_frame_register?  Any plans to make code like
> > frame_unwind.c:expr_eval() used by frame_unwind.c:handle_cfi externally
> > accessible?
>
> Sorry for the late reply. I missed this message earlier. As you
> correctly observe the public API only supports unwinding of threads for
> backtraces with just the PC. Internally most of the logic of unwinding
> other registers is there, but we don't have a public API for it. We
> really should. I filed:
> https://sourceware.org/bugzilla/show_bug.cgi?id=28579
>
> Could you add some requirements there?
> The hard part is making sure the interface is actually useful.
> What information do you have and what information do you want to get
> out?

I developed a patch against elfutils-0.185 which adds some APIs I use that
do what I want, it also includes some bug fixes.  It is just a proof of concept
at this point.

I exported __libdwfl_frame_reg_get and __libdwfl_frame_reg_set and I also
added an exported wrapper function for expr_eval.

I added dwfl_module_getebl as a convenience, any code that uses the disasm
functions needs an ebl pointer, Dwfl_Module has one but there's no way to get
at it and creating a new ebl instance just to disassemble can be error prone.

Getting the unwound register values was easy, they're already unwound there's
just no way to read them from the Dwfl_Frame.

Unwinding function parameters and local variables was a bit harder and I needed
to be able to call expr_eval.  The basic usage model is pretty much the same as
expr_eval is used inside of elfutils:

1. Call dwarf_getscopes with the pc of the frame of interest.
2. Find the enclosing DW_TAG_subprogram or DW_TAG_inlined_subroutine.
3. For each DW_TAG_formal_parameter or DW_TAG_variable child, find the
DW_AT_location, then call dwarf_getlocations and find the location that
corresponds to the pc.
4. Call __libdwfl_expr_eval and pass in the ops and nops, the value is returned.

I currently always pass NULL for the Dwarf_Frame, it doesn't look that
complicated
to get the Dwarf_Frame to pass in but I'm not sure in which cases it is needed.

There's some header mess adding these functions to libdwfl.h because the Dwarf
types are defined in libdw.h.

>
> Thanks,
>
> Mark
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0-libdwfl.h
Type: text/x-chdr
Size: 5718 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/elfutils-devel/attachments/20211110/8ad83784/attachment.bin>


More information about the Elfutils-devel mailing list