mirror of
https://github.com/beego/bee.git
synced 2025-07-07 21:50:18 +00:00
Update vendors
This commit is contained in:
156
vendor/github.com/derekparker/delve/pkg/proc/mem.go
generated
vendored
Normal file
156
vendor/github.com/derekparker/delve/pkg/proc/mem.go
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/derekparker/delve/pkg/dwarf/op"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// MemoryReadWriter is an interface for reading or writing to
|
||||
// the targets memory. This allows us to read from the actual
|
||||
// target memory or possibly a cache.
|
||||
type MemoryReadWriter interface {
|
||||
MemoryReader
|
||||
WriteMemory(addr uintptr, data []byte) (written int, err error)
|
||||
}
|
||||
|
||||
type memCache struct {
|
||||
loaded bool
|
||||
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)) {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
switch cacheMem := mem.(type) {
|
||||
case *memCache:
|
||||
if cacheMem.contains(addr, size) {
|
||||
return mem
|
||||
}
|
||||
case *compositeMemory:
|
||||
return mem
|
||||
}
|
||||
return &memCache{false, addr, make([]byte, size), mem}
|
||||
}
|
||||
|
||||
// fakeAddress used by extractVarInfoFromEntry for variables that do not
|
||||
// have a memory address, we can't use 0 because a lot of code (likely
|
||||
// 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
|
||||
pieces []op.Piece
|
||||
data []byte
|
||||
}
|
||||
|
||||
func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []op.Piece) *compositeMemory {
|
||||
cmem := &compositeMemory{realmem: mem, regs: regs, pieces: pieces, data: []byte{}}
|
||||
for _, piece := range pieces {
|
||||
if piece.IsRegister {
|
||||
reg := regs.Bytes(piece.RegNum)
|
||||
sz := piece.Size
|
||||
if sz == 0 && len(pieces) == 1 {
|
||||
sz = len(reg)
|
||||
}
|
||||
cmem.data = append(cmem.data, reg[:sz]...)
|
||||
} else {
|
||||
buf := make([]byte, piece.Size)
|
||||
mem.ReadMemory(buf, uintptr(piece.Addr))
|
||||
cmem.data = append(cmem.data, buf...)
|
||||
}
|
||||
}
|
||||
return cmem
|
||||
}
|
||||
|
||||
func (mem *compositeMemory) ReadMemory(data []byte, addr uintptr) (int, error) {
|
||||
addr -= fakeAddress
|
||||
if addr >= uintptr(len(mem.data)) || addr+uintptr(len(data)) > uintptr(len(mem.data)) {
|
||||
return 0, errors.New("read out of bounds")
|
||||
}
|
||||
copy(data, mem.data[addr:addr+uintptr(len(data))])
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (mem *compositeMemory) WriteMemory(addr uintptr, data []byte) (int, error) {
|
||||
//TODO(aarzilli): implement
|
||||
return 0, errors.New("can't write composite memory")
|
||||
}
|
||||
|
||||
// DereferenceMemory returns a MemoryReadWriter that can read and write the
|
||||
// memory pointed to by pointers in this memory.
|
||||
// Normally mem and mem.Dereference are the same object, they are different
|
||||
// only if this MemoryReadWriter is used to access memory outside of the
|
||||
// normal address space of the inferior process (such as data contained in
|
||||
// registers, or composite memory).
|
||||
func DereferenceMemory(mem MemoryReadWriter) MemoryReadWriter {
|
||||
switch mem := mem.(type) {
|
||||
case *compositeMemory:
|
||||
return mem.realmem
|
||||
}
|
||||
return mem
|
||||
}
|
||||
|
||||
// bufferMemoryReadWriter is dummy a MemoryReadWriter backed by a []byte.
|
||||
type bufferMemoryReadWriter struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (mem *bufferMemoryReadWriter) ReadMemory(buf []byte, addr uintptr) (n int, err error) {
|
||||
copy(buf, mem.buf[addr-fakeAddress:][:len(buf)])
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
func (mem *bufferMemoryReadWriter) WriteMemory(addr uintptr, data []byte) (written int, err error) {
|
||||
copy(mem.buf[addr-fakeAddress:], data)
|
||||
return len(data), nil
|
||||
}
|
Reference in New Issue
Block a user