Any way to print a 'struct g' within delve/gdb

897 views
Skip to first unread message

Xiangdong JI

unread,
Nov 11, 2019, 2:58:24 AM11/11/19
to golang-nuts
Given a valid goroutine structure's pointer, say retrieving from the register 'g', how can I convert it to 'struct g' in delve or gdb?

gdb usually reports "A syntax error in expression ...", and delve issues various "Command failed" message (failed to figure the proper way of converting a literal, I guess).

Thanks.

Derek Parker

unread,
Nov 11, 2019, 1:28:12 PM11/11/19
to golang-nuts
Can you reply with a gist showing the exact Delve commands you are attempting to use and what errors are being returned?

There is some more information on the expression parser here. You can also open an issue on the Delve Github repo and we can help you out over there as well.
Message has been deleted

Xiangdong JI

unread,
Nov 12, 2019, 2:29:42 AM11/12/19
to golang-nuts
Hi Derek,

Say I have the pointer value of a specific G struct, how to convert it to 'struct g' (or any other form) in delve so that I can check 
the details of its fields?

For example (simply utilized runtime.m0.curg to get a pointer value here)

(dlv) p &runtime.m0.curg
(**runtime.g)(0x56a140)

Just tried a few commands to convert the value back to 'struct g' or a pointer to 'struct g'

(dlv) p (runtime.g*)(0x56b140)
Command failed: 1:12: expected operand, found ')'
(dlv) p ('runtime.g'*)(0x56b140)
Command failed: 1:2: illegal rune literal
(dlv) p ("runtime.g"*)(0x56b140)
Command failed: 1:14: expected operand, found ')'
(dlv) p ("runtime".g*)(0x56b140)
Command failed: 1:14: expected operand, found ')'

Thanks.

Max

unread,
Nov 12, 2019, 5:29:29 AM11/12/19
to golang-nuts
I just tried with latest delve, and 'p runtime.m0.curg' is enough:

(dlv) p runtime.m0.curg
*runtime.g nil
(dlv) break main.main
(dlv) continue
[...]
(dlv) p runtime.m0.curg
*runtime.g {
    stack: runtime.stack {lo: 824635269120, hi: 824635285504},
    stackguard0: 824635270000,
    stackguard1: 18446744073709551615,
    _panic: *runtime._panic nil,
    _defer: *runtime._defer {
        siz: 8,
        started: false,
        sp: 824635285400,
        pc: 4406401,
        fn: *(*runtime.funcval)(0xd49398),
        _panic: *runtime._panic nil,
        link: *runtime._defer nil,},
    m: *runtime.m {
        g0: *(*runtime.g)(0x1493020),
        morebuf: (*runtime.gobuf)(0x1493b08),
        divmod: 0,
        procid: 8426,
        gsignal: *(*runtime.g)(0xc000000000),
        goSigStack: (*runtime.gsignalStack)(0x1493b58),
        sigmask: runtime.sigset [0,0],
        tls: [6]uintptr [0,0,0,0,0,0],
        mstartfn: nil,
        curg: *(*runtime.g)(0xc000000180),
        caughtsig: 0,
        p: 824633933824,
        nextp: 0,
        oldp: 0,
        id: 0,
        mallocing: 0,
        throwing: 0,
        preemptoff: "",
        locks: 0,
        dying: 0,
        profilehz: 0,
        spinning: false,
        blocked: false,
        inwb: false,
        newSigstack: true,
        printlock: 0,
        incgo: false,
        freeWait: 0,
        fastrand: [2]uint32 [1474176035,2600743942],
        needextram: false,
        traceback: 0,
        ncgocall: 1,
        ncgo: 0,
        cgoCallersUse: 0,
        cgoCallers: *runtime.cgoCallers [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        park: (*runtime.note)(0x1493c48),
        alllink: *runtime.m nil,
        schedlink: 0,
        mcache: *(*runtime.mcache)(0x7fc8210fe008),
        lockedg: 0,
        createstack: [32]uintptr [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
        lockedExt: 0,
        lockedInt: 0,
        nextwaitm: 0,
        waitunlockf: unsafe.Pointer(0x0),
        waitlock: unsafe.Pointer(0x0),
        waittraceev: 23,
        waittraceskip: 3,
        startingtrace: false,
        syscalltick: 4,
        thread: 0,
        freelink: *runtime.m nil,
        libcall: (*runtime.libcall)(0x1493db8),
        libcallpc: 0,
        libcallsp: 0,
        libcallg: 0,
        syscall: (*runtime.libcall)(0x1493e00),
        vdsoSP: 0,
        vdsoPC: 5077558,
        mOS: runtime.mOS {},},
    sched: runtime.gobuf {sp: 0, pc: 4586608, g: 824633721216, ctxt: unsafe.Pointer(0x0), ret: 0, lr: 0, bp: 824635273744},
    syscallsp: 0,
    syscallpc: 5004501,
    stktopsp: 824635285472,
    param: unsafe.Pointer(0x0),
    atomicstatus: 2,
    stackLock: 0,
    goid: 1,
    schedlink: 0,
    waitsince: 0,
    waitreason: waitReasonChanReceive (13),
    preempt: false,
    paniconfault: false,
    preemptscan: false,
    gcscandone: false,
    gcscanvalid: false,
    throwsplit: false,
    raceignore: 0,
    sysblocktraced: true,
    sysexitticks: 0,
    traceseq: 0,
    tracelastp: 0,
    lockedm: 0,
    sig: 0,
    writebuf: []uint8 len: 0, cap: 0, nil,
    sigcode0: 0,
    sigcode1: 0,
    sigpc: 0,
    gopc: 4586345,
    ancestors: *[]runtime.ancestorInfo nil,
    startpc: 4406160,
    racectx: 0,
    waiting: *runtime.sudog nil,
    cgoCtxt: []uintptr len: 0, cap: 0, nil,
    labels: unsafe.Pointer(0x0),
    timer: *runtime.timer nil,
    selectDone: 0,
    gcAssistBytes: 0,}

Derek Parker

unread,
Nov 12, 2019, 9:52:58 AM11/12/19
to golang-nuts
If you look at the output of your first command you see the result `(**runtime.g)(<addr>)`, however you're trying to cast to `(runtime.g*)(<addr>)`. The correct syntax you're looking for is ` *(*runtime.g)(<addr>)`. Hope that helps!

Xiangdong JI

unread,
Nov 12, 2019, 11:55:02 AM11/12/19
to golang-nuts
Thank your Derek, that's really helpful. 
Reply all
Reply to author
Forward
0 new messages