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:
parent
35622fd667
commit
a5574bcdc7
@ -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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user