delve/pkg/proc/mem.go

68 lines
1.6 KiB
Go
Raw Normal View History

package proc
const cacheEnabled = true
// MemoryReader is like io.ReaderAt, but the offset is a uintptr so that it
// can address all of 64-bit memory.
// Redundant with memoryReadWriter but more easily suited to working with
// the standard io package.
type MemoryReader interface {
// ReadMemory is just like io.ReaderAt.ReadAt.
ReadMemory(buf []byte, addr uintptr) (n int, err error)
}
type memoryReadWriter interface {
MemoryReader
writeMemory(addr uintptr, data []byte) (written int, err error)
}
type memCache struct {
cacheAddr uintptr
cache []byte
mem memoryReadWriter
}
func (m *memCache) contains(addr uintptr, size int) bool {
return addr >= m.cacheAddr && addr <= (m.cacheAddr+uintptr(len(m.cache)-size))
}
func (m *memCache) ReadMemory(data []byte, addr uintptr) (n int, err error) {
if m.contains(addr, len(data)) {
copy(data, m.cache[addr-m.cacheAddr:])
return len(data), nil
}
return m.mem.ReadMemory(data, addr)
}
func (m *memCache) writeMemory(addr uintptr, data []byte) (written int, err error) {
return m.mem.writeMemory(addr, data)
}
func cacheMemory(mem memoryReadWriter, addr uintptr, size int) memoryReadWriter {
if !cacheEnabled {
return mem
}
if size <= 0 {
return mem
}
if cacheMem, isCache := mem.(*memCache); isCache {
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}
}
}
cache := make([]byte, size)
_, err := mem.ReadMemory(cache, addr)
if err != nil {
return mem
}
return &memCache{addr, cache, mem}
}