From 62fe792bfdf6599ad06c084096efd96a01246ab8 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Jan 2018 16:50:18 +0100 Subject: [PATCH] proc: disable caching for variables with an extended location Our current frame caching strategy doesn't handle extended locations expressions correctly, disable it on variables that don't have a simple address. --- pkg/proc/dwarf_expr_test.go | 3 +++ pkg/proc/mem.go | 7 +++++++ pkg/proc/variables.go | 12 ++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/proc/dwarf_expr_test.go b/pkg/proc/dwarf_expr_test.go index 8d7568ce..8342d8c6 100644 --- a/pkg/proc/dwarf_expr_test.go +++ b/pkg/proc/dwarf_expr_test.go @@ -128,6 +128,7 @@ func TestDwarfExprComposite(t *testing.T) { testCases := map[string]uint16{ "pair.k": 0x8765, "pair.v": 0x5678, + "n": 42, } const stringVal = "this is a string" @@ -163,6 +164,7 @@ func TestDwarfExprComposite(t *testing.T) { dwb.AddVariable("s", stringoff, dwarfbuilder.LocationBlock( op.DW_OP_reg1, op.DW_OP_piece, uint(8), op.DW_OP_reg0, op.DW_OP_piece, uint(8))) + dwb.AddVariable("n", intoff, dwarfbuilder.LocationBlock(op.DW_OP_reg3)) dwb.TagClose() bi := fakeBinaryInfo(t, dwb) @@ -173,6 +175,7 @@ func TestDwarfExprComposite(t *testing.T) { regs.Rax = uint64(len(stringVal)) regs.Rdx = defaultCFA + 18 regs.Rcx = uint64(testCases["pair.k"]) + regs.Rbx = uint64(testCases["n"]) scope := dwarfExprCheck(t, mem, dwarfRegisters(®s), bi, testCases) diff --git a/pkg/proc/mem.go b/pkg/proc/mem.go index c49e4e20..b81e15e6 100644 --- a/pkg/proc/mem.go +++ b/pkg/proc/mem.go @@ -80,6 +80,13 @@ func cacheMemory(mem MemoryReadWriter, addr uintptr, size int) MemoryReadWriter // including client code) assumes that addr == 0 is nil const fakeAddress = 0xbeef0000 +// compositeMemory represents a chunk of memory that is stored in CPU +// registers or non-contiguously. +// +// When optimizations are enabled the compiler will store some variables +// into registers and sometimes it will also store structs non-contiguously +// with some fields stored into CPU registers and other fields stored in +// memory. type compositeMemory struct { realmem MemoryReadWriter regs op.DwarfRegisters diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go index c559c7ec..51b4b6ee 100644 --- a/pkg/proc/variables.go +++ b/pkg/proc/variables.go @@ -1897,13 +1897,19 @@ func (scope *EvalScope) variablesByTag(tag dwarf.Tag, cfg *LoadConfig) ([]*Varia sort.Stable(&variablesByDepth{vars, depths}) } - // prefetch the whole chunk of memory relative to these variables + // Prefetch the whole chunk of memory relative to these variables. + // Variables that are not stored contiguously in memory (i.e. the ones that + // read from a compositeMemory) will be ignored. minaddr := vars[0].Addr var maxaddr uintptr var size int64 for _, v := range vars { + if _, extloc := v.mem.(*compositeMemory); extloc { + continue + } + if v.Addr < minaddr { minaddr = v.Addr } @@ -1923,7 +1929,9 @@ func (scope *EvalScope) variablesByTag(tag dwarf.Tag, cfg *LoadConfig) ([]*Varia mem := cacheMemory(vars[0].mem, minaddr, int(maxaddr-minaddr)) for _, v := range vars { - v.mem = mem + if _, extloc := v.mem.(*compositeMemory); !extloc { + v.mem = mem + } } }