This is the mail archive of the
mailing list for the elfutils project.
Re: overflows in Dwfl_Thread_Callbacks::memory_read callback
- From: Mark Wielaard <mark at klomp dot org>
- To: Milian Wolff <mail at milianw dot de>
- Cc: elfutils-devel at sourceware dot org
- Date: Wed, 14 Jun 2017 20:50:08 +0200
- Subject: Re: overflows in Dwfl_Thread_Callbacks::memory_read callback
- Authentication-results: sourceware.org; auth=none
- References: <2117244.RMs6e62TRU@agathebauer> <email@example.com> <1553274.yb8VYApAHh@agathebauer>
On Tue, 2017-06-13 at 18:15 +0200, Milian Wolff wrote:
> > I am not following the above trace completely, but what is going on
> > seems to be that we have CFI and want to get a register value. So we
> > call dwarf_frame_register to determine the DWARF expression operations
> > that we need to execute to get the register value. dwarf_frame_register
> > determines that that the register is described by a register offset
> > value rule, so it generates operations saying see an the CFA
> > (DW_OP_call_frame_cfa) plus some offset (DW_OP_plus_uconst) as a value
> > (so read the value from cfa + offset, which is somewhere on the stack).
> > But then the cfa comes out as 15? That is obviously bogus. But I don't
> > really understand how that happened. It should be a value somewhere near
> > the current stack. Then reading 15 - offset (16) clearly fails.
> Right, so that cfa value - is that in the DWARF info? So is the dso "broken"?
> Or is this some runtime value that we returned earlier in our register or
> memory callback implementation?
This is how DWARF defines the CFA:
An area of memory that is allocated on a stack called a “call
frame.” The call frame is identified by an address on the stack.
We refer to this address as the Canonical Frame Address or CFA.
Typically, the CFA is defined to be the value of the stack
pointer at the call site in the previous frame (which may be
different from its value on entry to the current frame).
So in practice it points inside the stack where the previous stack
pointer was when this function was called. Various things can often be
found as offset of the CFA, the return address, saved register values,
arguments to the current function etc. You start unwinding by first
calculating the CFA. I cannot immediately see why that went wrong in
this case. But either we picked the wrong CFI (Call Frame Information)
for the current pc and are just calculating something bogus. Or one of
the needed values to calculate the CFA was garbage (either a bad
register value or a bad stack value).