Re: runtime validation of DT_SYMTAB lookups - why is there no DT_SYMSZ?

2022-08-27 Thread Jacob Burkholder via Elfutils-devel
I've always used the fact that the symbol table and string table are
present in the binary in that order and adjacent to each other to find
the number of symbol table entries., ie (strtab - (char *)symtab) /
sizeof(*symtab), although clearly this is not required and may just be
gnu ld convention.  DT_SYMSZ would be a useful addition to the ELF
standard IMO.


unwind non-PC registers using elfutils

2021-10-03 Thread Jacob Burkholder via Elfutils-devel
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?


Re: unwind non-PC registers using elfutils

2021-11-10 Thread Jacob Burkholder via Elfutils-devel
Hi Mark, thanks for your mail.

On Wed, Nov 10, 2021 at 6:09 AM Mark Wielaard  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
diff -Nru elfutils-0.185.orig/backends/x86_64_init.c elfutils-0.185/backends/x86_64_init.c
--- elfutils-0.185.orig/backends/x86_64_init.c	2021-05-22 11:25:24.0 -0700
+++ elfutils-0.185/backends/x86_64_init.c	2021-10-03 22:11:47.050651661 -0700
@@ -60,7 +60,7 @@
   HOOK (eh, disasm);
   HOOK (eh, abi_cfi);
   /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
-  eh->frame_nregs = 17;
+  eh->frame_nregs = 67;
   HOOK (eh, set_initial_registers_tid);
   HOOK (eh, unwind);
   HOOK (eh, check_reloc_target_type);
diff -Nru elfutils-0.185.orig/backends/x86_64_initreg.c elfutils-0.185/backends/x86_64_initreg.c
--- elfutils-0.185.orig/backends/x86_64_initreg.c	2021-05-22 11:25:24.0 -0700
+++ elfutils-0.185/backends/x86_64_initreg.c	2021-10-03 21:52:42.251129764 -0700
@@ -68,6 +68,21 @@
   dwarf_regs[14] = user_regs.r14;
   dwarf_regs[15] = user_regs.r15;
   dwarf_regs[16] = user_regs.rip;
-  return setfunc (0, 17, dwarf_regs, arg);
+  if (!setfunc (0, 17, dwarf_regs, arg))
+return false;
+  dwarf_regs[0] = user_regs.eflags;
+  dwarf_regs[1] = user_regs.es;
+  dwarf_regs[2] = user_regs.cs;
+  dwarf_regs[3] = user_regs.ss;
+  dwarf_regs[4] = user_regs.ds;
+  dwarf_regs[5] = user_regs.fs;
+  dwarf_regs[6] = user_regs.gs;
+  if (!setfunc (49, 7, dwarf_regs, arg))
+return false;
+  dwarf_regs[0] = user_regs.fs_base;
+  dwarf_regs[1] = user_regs.gs_base;
+  if (!setfunc (58, 2, dwarf_regs, arg))
+return false;
+  return true;
 #endif /* __x86_64__ */
 }
diff -Nru elfutils-0.185.orig/libasm/disasm_str.c elfutils-0.185/libasm/disasm_str.c
--- elfutils-0.185.orig/libasm/disasm_str.c	2021-05-22 11:25:24.0 -0700
+++ elfutils-0.185/libasm/disasm_str.c	2021-10-10 12:11