How does Delve get addresses & values of variables?

64 views
Skip to first unread message

vaastav anand

unread,
Oct 21, 2019, 8:09:46 PM10/21/19
to delve-dev
Hi,

I was looking through the delve source code but I couldn't wrap my head around as to how Delve was getting the addresses and values of variables during runtime.
I know that Delve is parsing the Dwarf info which has offsets for variables and parameters, but I was wondering how
does Delve put these offsets in context with the absolute addresses.
If someone could please explain this to me, I would greatly appreciate it.

vaastav anand

unread,
Oct 21, 2019, 8:33:51 PM10/21/19
to delve-dev
Just to be more specific, my question is what all information from the go-runtime do I need to be able to
get the address/values of the variables.
I am working with a modified version of go-runtime where I can get access to the stacks of all the goroutines.
What I need in addition is to be able to get the values of the variables for which I need to find the address for that specific variable.

I have been able to parse the DWARF debugging information to get some sort of relative address but I am not sure if that
is correct or what it is relative to. Do I just need to look at the stack pointer or base pointer of the goroutine?

Alessandro Arzilli

unread,
Oct 22, 2019, 6:37:29 AM10/22/19
to vaastav anand, delve-dev
You probably already know that variable entries in debug_info have a
DW_AT_location that's supposed to tell you where they are in memory. This is
either a DWARF location expression or a reference to debug_loc.
If it is the latter you have to scan the referenced list looking for the
current value of your PC register and get the location expression from
there.

Location expressions are little programs for a stack based VM. The
implementation of that for delve is in pkg/dwarf/op/op.go. If you are
debugging unoptimized go programs almost all variables will have a location
that looks like this:

DW_OP_fbreg <a constant>

This gives you the offset of the varible from the "frame base". To find the
frame base which means that you have to get the DW_AT_frame_base of the
subroutine containing your variable, which happens to be an expression, and
evaluate it.
For all go programs this expression is simply 'DW_OP_call_frame_cfa'.

The problem with executing those expression is that first you have to unwind
the stack using debug_frame which is very complicated. We do this in
pkg/proc/stack.go with assistence from pkg/dwarf/frame. In particular
advanceRegs in stack.go. This will get you the value of 'CFA' (which is a
special pseudo-register that DWARF uses) to use to resolve the address of a
stack variable.

For go programs then CFA is just the value of SP just before the CALL
instruction that created the current frame was executed and the size of the
current frame is always described with a constant (all IIRC).
So you can cheat and just implement enough debug_frame stuff that you can
just get CFA in those circumstances and you'll be fine. Very old versions of
delve did this. You could look at stack.go in, a ~2016 version of delve.
> --
> You received this message because you are subscribed to the Google Groups "delve-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to delve-dev+...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/delve-dev/9f88cbdb-994d-4e03-bb52-69ba7139c90d%40googlegroups.com.

chainhelen

unread,
Jan 1, 2020, 9:40:49 PM1/1/20
to delve-dev
Also appreciate it. it always make me confused for the different of cfa and sp. 
 `Typically, the CFA is defined to be the value of the stack pointer at the call site in the previous frame` that found on website.  

So I hava more one queustion. for example on x86_64,  when I use `PtraceGetRegs`, I can get `rsp` and `rbp`, and `%rbp + 8` is last call frame ret address (last `rsp`).   
Maybe I can get all `rsp`s recursively instead of computing the expression by `DW_OP_call_frame_cfa` or others.    
And then `cfa == rsp`, so I can use thoses fake `cfa`s ? 

在 2019年10月22日星期二 UTC+8下午6:37:29,alessandro.arzilli写道:
> To unsubscribe from this group and stop receiving emails from it, send an email to delv...@googlegroups.com.

Alessandro Arzilli

unread,
Jan 2, 2020, 5:20:41 AM1/2/20
to chainhelen, delve-dev
On Wed, Jan 01, 2020 at 06:40:48PM -0800, chainhelen wrote:
> Also appreciate it. it always make me confused for the different of cfa and
> sp.
> `Typically, the CFA is defined to be the value of the stack pointer at the
> call site in the previous frame` that found on website.
>
> So I hava more one queustion. for example on x86_64, when I use
> `PtraceGetRegs`, I can get `rsp` and `rbp`, and `%rbp + 8` is last call
> frame ret address (last `rsp`).
> Maybe I can get all `rsp`s recursively instead of computing the expression
> by `DW_OP_call_frame_cfa` or others.
> And then `cfa == rsp`, so I can use thoses fake `cfa`s ?

Yes, if the program you are debugging updates keeps a frame pointer (rbp)
then you can just use that.
Reply all
Reply to author
Forward
0 new messages