proc: change memCache to delay reading

Change memCache so that the preloaded memory is not read immediately
but only after the actual read to the preloaded range.

This allows us to request caching the entire stack frame every time we
create an eval scope and no unnecessary reads will be made even if the
user is just trying to evaluate a global variable.
This commit is contained in:
aarzilli 2018-04-14 14:57:35 +02:00 committed by Derek Parker
parent 35622fd667
commit a5574bcdc7
3 changed files with 15 additions and 15 deletions

@ -23,6 +23,7 @@ type MemoryReadWriter interface {
}
type memCache struct {
loaded bool
cacheAddr uintptr
cache []byte
mem MemoryReadWriter
@ -34,6 +35,13 @@ func (m *memCache) contains(addr uintptr, size int) bool {
func (m *memCache) ReadMemory(data []byte, addr uintptr) (n int, err error) {
if m.contains(addr, len(data)) {
if !m.loaded {
_, err := m.mem.ReadMemory(m.cache, m.cacheAddr)
if err != nil {
return 0, err
}
m.loaded = true
}
copy(data, m.cache[addr-m.cacheAddr:])
return len(data), nil
}
@ -56,23 +64,11 @@ func cacheMemory(mem MemoryReadWriter, addr uintptr, size int) MemoryReadWriter
case *memCache:
if cacheMem.contains(addr, size) {
return mem
} else {
cache := make([]byte, size)
_, err := cacheMem.mem.ReadMemory(cache, addr)
if err != nil {
return mem
}
return &memCache{addr, cache, mem}
}
case *compositeMemory:
return mem
}
cache := make([]byte, size)
_, err := mem.ReadMemory(cache, addr)
if err != nil {
return mem
}
return &memCache{addr, cache, mem}
return &memCache{false, addr, make([]byte, size), mem}
}
// fakeAddress used by extractVarInfoFromEntry for variables that do not

@ -511,7 +511,11 @@ func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) {
return FrameToScope(dbp.BinInfo(), thread, g, locs[frame]), nil
}
// FrameToScope returns a new EvalScope for this frame
// FrameToScope returns a new EvalScope for frames[0].
// If frames has at least two elements all memory between
// frames[0].Regs.SP() and frames[1].Regs.CFA will be cached.
// Otherwise all memory between frames[0].Regs.SP() and frames[0].Regs.CFA
// will be cached.
func FrameToScope(bi *BinaryInfo, thread MemoryReadWriter, g *G, frame Stackframe) *EvalScope {
var gvar *Variable
if g != nil {

@ -7,7 +7,7 @@ import (
func TestIssue554(t *testing.T) {
// unsigned integer overflow in proc.(*memCache).contains was
// causing it to always return true for address 0xffffffffffffffff
mem := memCache{0x20, make([]byte, 100), nil}
mem := memCache{true, 0x20, make([]byte, 100), nil}
if mem.contains(0xffffffffffffffff, 40) {
t.Fatalf("should be false")
}