proc: Use MemoryReader inside memoryReadWriter
This commit is contained in:
parent
329bc7e69d
commit
182f805094
@ -9,15 +9,6 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// A SplicedMemory represents a memory space formed from multiple regions,
|
||||
// each of which may override previously regions. For example, in the following
|
||||
// core, the program text was loaded at 0x400000:
|
||||
@ -203,13 +194,12 @@ func (p *CoreProcess) BinInfo() *BinaryInfo {
|
||||
return &p.bi
|
||||
}
|
||||
|
||||
func (thread *CoreThread) readMemory(addr uintptr, size int) (data []byte, err error) {
|
||||
data = make([]byte, size)
|
||||
n, err := thread.p.core.ReadMemory(data, addr)
|
||||
func (thread *CoreThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
||||
n, err = thread.p.core.ReadMemory(data, addr)
|
||||
if err == nil && n != len(data) {
|
||||
err = ErrShortRead
|
||||
}
|
||||
return data, err
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (thread *CoreThread) writeMemory(addr uintptr, data []byte) (int, error) {
|
||||
|
@ -45,7 +45,8 @@ func Disassemble(dbp DisassembleInfo, g *G, startPC, endPC uint64) ([]AsmInstruc
|
||||
}
|
||||
|
||||
func disassemble(memrw memoryReadWriter, regs Registers, breakpoints map[uint64]*Breakpoint, bi *BinaryInfo, startPC, endPC uint64) ([]AsmInstruction, error) {
|
||||
mem, err := memrw.readMemory(uintptr(startPC), int(endPC-startPC))
|
||||
mem := make([]byte, int(endPC-startPC))
|
||||
_, err := memrw.ReadMemory(mem, uintptr(startPC))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -96,7 +96,8 @@ func resolveCallArg(inst *ArchInst, currentGoroutine bool, regs Registers, mem m
|
||||
}
|
||||
addr := uintptr(int64(base) + int64(index*uint64(arg.Scale)) + arg.Disp)
|
||||
//TODO: should this always be 64 bits instead of inst.MemBytes?
|
||||
pcbytes, err := mem.readMemory(addr, inst.MemBytes)
|
||||
pcbytes := make([]byte, inst.MemBytes)
|
||||
_, err := mem.ReadMemory(pcbytes, addr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -841,8 +841,12 @@ func (p *GdbserverProcess) setCurrentBreakpoints() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *GdbserverThread) readMemory(addr uintptr, size int) (data []byte, err error) {
|
||||
return t.p.conn.readMemory(addr, size)
|
||||
func (t *GdbserverThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
||||
err = t.p.conn.readMemory(data, addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (t *GdbserverThread) writeMemory(addr uintptr, data []byte) (written int, err error) {
|
||||
@ -1028,7 +1032,8 @@ func (t *GdbserverThread) reloadGAtPC() error {
|
||||
}
|
||||
}
|
||||
|
||||
savedcode, err := t.readMemory(uintptr(pc), len(movinstr))
|
||||
savedcode := make([]byte, len(movinstr))
|
||||
_, err := t.ReadMemory(savedcode, uintptr(pc))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -778,8 +778,9 @@ func (conn *gdbConn) appendThreadSelector(threadID string) {
|
||||
}
|
||||
|
||||
// executes 'm' (read memory) command
|
||||
func (conn *gdbConn) readMemory(addr uintptr, size int) (data []byte, err error) {
|
||||
data = make([]byte, 0, size)
|
||||
func (conn *gdbConn) readMemory(data []byte, addr uintptr) error {
|
||||
size := len(data)
|
||||
data = data[:0]
|
||||
|
||||
for size > 0 {
|
||||
conn.outbuf.Reset()
|
||||
@ -794,7 +795,7 @@ func (conn *gdbConn) readMemory(addr uintptr, size int) (data []byte, err error)
|
||||
fmt.Fprintf(&conn.outbuf, "$m%x,%x", addr+uintptr(len(data)), sz)
|
||||
resp, err := conn.exec(conn.outbuf.Bytes(), "memory read")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(resp); i += 2 {
|
||||
@ -802,7 +803,7 @@ func (conn *gdbConn) readMemory(addr uintptr, size int) (data []byte, err error)
|
||||
data = append(data, uint8(n))
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// executes 'M' (write memory) command
|
||||
|
@ -2,8 +2,17 @@ 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 {
|
||||
readMemory(addr uintptr, size int) (data []byte, err error)
|
||||
MemoryReader
|
||||
writeMemory(addr uintptr, data []byte) (written int, err error)
|
||||
}
|
||||
|
||||
@ -17,14 +26,13 @@ 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(addr uintptr, size int) (data []byte, err error) {
|
||||
if m.contains(addr, size) {
|
||||
d := make([]byte, size)
|
||||
copy(d, m.cache[addr-m.cacheAddr:])
|
||||
return d, nil
|
||||
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(addr, size)
|
||||
return m.mem.ReadMemory(data, addr)
|
||||
}
|
||||
|
||||
func (m *memCache) writeMemory(addr uintptr, data []byte) (written int, err error) {
|
||||
@ -42,14 +50,16 @@ func cacheMemory(mem memoryReadWriter, addr uintptr, size int) memoryReadWriter
|
||||
if cacheMem.contains(addr, size) {
|
||||
return mem
|
||||
} else {
|
||||
cache, err := cacheMem.mem.readMemory(addr, size)
|
||||
cache := make([]byte, size)
|
||||
_, err := cacheMem.mem.ReadMemory(cache, addr)
|
||||
if err != nil {
|
||||
return mem
|
||||
}
|
||||
return &memCache{addr, cache, mem}
|
||||
}
|
||||
}
|
||||
cache, err := mem.readMemory(addr, size)
|
||||
cache := make([]byte, size)
|
||||
_, err := mem.ReadMemory(cache, addr)
|
||||
if err != nil {
|
||||
return mem
|
||||
}
|
||||
|
@ -142,7 +142,8 @@ const (
|
||||
|
||||
func loadName(bi *BinaryInfo, addr uintptr, mem memoryReadWriter) (name, tag string, pkgpathoff int32, err error) {
|
||||
off := addr
|
||||
namedata, err := mem.readMemory(off, 3)
|
||||
namedata := make([]byte, 3)
|
||||
_, err = mem.ReadMemory(namedata, off)
|
||||
off += 3
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
@ -150,7 +151,8 @@ func loadName(bi *BinaryInfo, addr uintptr, mem memoryReadWriter) (name, tag str
|
||||
|
||||
namelen := uint16(namedata[1]<<8) | uint16(namedata[2])
|
||||
|
||||
rawstr, err := mem.readMemory(off, int(namelen))
|
||||
rawstr := make([]byte, int(namelen))
|
||||
_, err = mem.ReadMemory(rawstr, off)
|
||||
off += uintptr(namelen)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
@ -159,14 +161,16 @@ func loadName(bi *BinaryInfo, addr uintptr, mem memoryReadWriter) (name, tag str
|
||||
name = string(rawstr)
|
||||
|
||||
if namedata[0]&nameflagHasTag != 0 {
|
||||
taglendata, err := mem.readMemory(off, 2)
|
||||
taglendata := make([]byte, 2)
|
||||
_, err = mem.ReadMemory(taglendata, off)
|
||||
off += 2
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
taglen := uint16(taglendata[0]<<8) | uint16(taglendata[1])
|
||||
|
||||
rawstr, err := mem.readMemory(off, int(taglen))
|
||||
rawstr := make([]byte, int(taglen))
|
||||
_, err = mem.ReadMemory(rawstr, off)
|
||||
off += uintptr(taglen)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
@ -176,7 +180,8 @@ func loadName(bi *BinaryInfo, addr uintptr, mem memoryReadWriter) (name, tag str
|
||||
}
|
||||
|
||||
if namedata[0]&nameflagHasPkg != 0 {
|
||||
pkgdata, err := mem.readMemory(off, 4)
|
||||
pkgdata := make([]byte, 4)
|
||||
_, err = mem.ReadMemory(pkgdata, off)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
@ -282,7 +282,8 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Exp
|
||||
}
|
||||
|
||||
thread := dbp.threads[tid]
|
||||
originalData, err := thread.readMemory(uintptr(addr), dbp.bi.arch.BreakpointSize())
|
||||
originalData := make([]byte, dbp.bi.arch.BreakpointSize())
|
||||
_, err := thread.ReadMemory(originalData, uintptr(addr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -707,7 +708,8 @@ func GoroutinesInfo(dbp EvalScopeConvertible) ([]*G, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allglenBytes, err := dbp.CurrentThread().readMemory(uintptr(addr), 8)
|
||||
allglenBytes := make([]byte, 8)
|
||||
_, err = dbp.CurrentThread().ReadMemory(allglenBytes, uintptr(addr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -722,7 +724,8 @@ func GoroutinesInfo(dbp EvalScopeConvertible) ([]*G, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
faddr, err := dbp.CurrentThread().readMemory(uintptr(allgentryaddr), dbp.BinInfo().arch.PtrSize())
|
||||
faddr := make([]byte, dbp.BinInfo().arch.PtrSize())
|
||||
_, err = dbp.CurrentThread().ReadMemory(faddr, uintptr(allgentryaddr))
|
||||
allgptr := binary.LittleEndian.Uint64(faddr)
|
||||
|
||||
for i := uint64(0); i < allglen; i++ {
|
||||
|
@ -135,7 +135,9 @@ func getRegisters(p IProcess, t *testing.T) Registers {
|
||||
}
|
||||
|
||||
func dataAtAddr(thread memoryReadWriter, addr uint64) ([]byte, error) {
|
||||
return thread.readMemory(uintptr(addr), 1)
|
||||
data := make([]byte, 1)
|
||||
_, err := thread.ReadMemory(data, uintptr(addr))
|
||||
return data, err
|
||||
}
|
||||
|
||||
func assertNoError(err error, t testing.TB, s string) {
|
||||
|
@ -330,7 +330,8 @@ func (dbp *Process) waitForDebugEvent(flags waitForDebugEventFlags) (threadID, e
|
||||
// this exception anymore.
|
||||
atbp := true
|
||||
if thread, found := dbp.threads[tid]; found {
|
||||
if data, err := thread.readMemory(exception.ExceptionRecord.ExceptionAddress, dbp.bi.arch.BreakpointSize()); err == nil {
|
||||
data := make([]byte, dbp.bi.arch.BreakpointSize())
|
||||
if _, err := thread.ReadMemory(data, exception.ExceptionRecord.ExceptionAddress); err == nil {
|
||||
instr := dbp.bi.arch.BreakpointInstruction()
|
||||
for i := range instr {
|
||||
if data[i] != instr[i] {
|
||||
|
@ -385,7 +385,8 @@ func getGVariable(thread IThread) (*Variable, error) {
|
||||
|
||||
gaddr, hasgaddr := regs.GAddr()
|
||||
if !hasgaddr {
|
||||
gaddrbs, err := thread.readMemory(uintptr(regs.TLS()+arch.GStructOffset()), arch.PtrSize())
|
||||
gaddrbs := make([]byte, arch.PtrSize())
|
||||
_, err := thread.ReadMemory(gaddrbs, uintptr(regs.TLS()+arch.GStructOffset()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -119,20 +119,19 @@ func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) {
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) {
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
func (t *Thread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
||||
if len(buf) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
var (
|
||||
buf = make([]byte, size)
|
||||
vmData = unsafe.Pointer(&buf[0])
|
||||
vmAddr = C.mach_vm_address_t(addr)
|
||||
length = C.mach_msg_type_number_t(size)
|
||||
length = C.mach_msg_type_number_t(len(buf))
|
||||
)
|
||||
|
||||
ret := C.read_memory(t.dbp.os.task, vmAddr, vmData, length)
|
||||
if ret < 0 {
|
||||
return nil, fmt.Errorf("could not read memory")
|
||||
return 0, fmt.Errorf("could not read memory")
|
||||
}
|
||||
return buf, nil
|
||||
return len(buf), nil
|
||||
}
|
||||
|
@ -102,11 +102,10 @@ func (t *Thread) writeMemory(addr uintptr, data []byte) (written int, err error)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Thread) readMemory(addr uintptr, size int) (data []byte, err error) {
|
||||
if size == 0 {
|
||||
func (t *Thread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
||||
if len(data) == 0 {
|
||||
return
|
||||
}
|
||||
data = make([]byte, size)
|
||||
t.dbp.execPtraceFunc(func() { _, err = sys.PtracePeekData(t.ID, addr, data) })
|
||||
return
|
||||
}
|
||||
|
@ -138,15 +138,14 @@ func (t *Thread) writeMemory(addr uintptr, data []byte) (int, error) {
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (t *Thread) readMemory(addr uintptr, size int) ([]byte, error) {
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
func (t *Thread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
||||
if len(buf) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
var count uintptr
|
||||
buf := make([]byte, size)
|
||||
err := _ReadProcessMemory(t.dbp.os.hProcess, addr, &buf[0], uintptr(size), &count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
err := _ReadProcessMemory(t.dbp.os.hProcess, addr, &buf[0], uintptr(len(buf)), &count)
|
||||
if err == nil && count != uintptr(len(buf)) {
|
||||
err = ErrShortRead
|
||||
}
|
||||
return buf[:count], nil
|
||||
return int(count), err
|
||||
}
|
||||
|
@ -367,7 +367,8 @@ func (gvar *Variable) parseG() (*G, error) {
|
||||
_, deref := gvar.RealType.(*dwarf.PtrType)
|
||||
|
||||
if deref {
|
||||
gaddrbytes, err := mem.readMemory(uintptr(gaddr), gvar.bi.arch.PtrSize())
|
||||
gaddrbytes := make([]byte, gvar.bi.arch.PtrSize())
|
||||
_, err := mem.ReadMemory(gaddrbytes, uintptr(gaddr))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error derefing *G %s", err)
|
||||
}
|
||||
@ -886,7 +887,8 @@ func (v *Variable) loadValueInternal(recurseLevel int, cfg LoadConfig) {
|
||||
v.Value = constant.MakeUint64(val)
|
||||
|
||||
case reflect.Bool:
|
||||
val, err := v.mem.readMemory(v.Addr, 1)
|
||||
val := make([]byte, 1)
|
||||
_, err := v.mem.ReadMemory(val, v.Addr)
|
||||
v.Unreadable = err
|
||||
if err == nil {
|
||||
v.Value = constant.MakeBool(val[0] != 0)
|
||||
@ -946,7 +948,8 @@ func readStringInfo(mem memoryReadWriter, arch Arch, addr uintptr) (uintptr, int
|
||||
mem = cacheMemory(mem, addr, arch.PtrSize()*2)
|
||||
|
||||
// read len
|
||||
val, err := mem.readMemory(addr+uintptr(arch.PtrSize()), arch.PtrSize())
|
||||
val := make([]byte, arch.PtrSize())
|
||||
_, err := mem.ReadMemory(val, addr+uintptr(arch.PtrSize()))
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("could not read string len %s", err)
|
||||
}
|
||||
@ -956,7 +959,7 @@ func readStringInfo(mem memoryReadWriter, arch Arch, addr uintptr) (uintptr, int
|
||||
}
|
||||
|
||||
// read addr
|
||||
val, err = mem.readMemory(addr, arch.PtrSize())
|
||||
_, err = mem.ReadMemory(val, addr)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("could not read string pointer %s", err)
|
||||
}
|
||||
@ -974,7 +977,8 @@ func readStringValue(mem memoryReadWriter, addr uintptr, strlen int64, cfg LoadC
|
||||
count = int64(cfg.MaxStringLen)
|
||||
}
|
||||
|
||||
val, err := mem.readMemory(addr, int(count))
|
||||
val := make([]byte, int(count))
|
||||
_, err := mem.ReadMemory(val, addr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not read string at %#v due to %s", addr, err)
|
||||
}
|
||||
@ -1102,7 +1106,8 @@ func (v *Variable) writeComplex(real, imag float64, size int64) error {
|
||||
func readIntRaw(mem memoryReadWriter, addr uintptr, size int64) (int64, error) {
|
||||
var n int64
|
||||
|
||||
val, err := mem.readMemory(addr, int(size))
|
||||
val := make([]byte, int(size))
|
||||
_, err := mem.ReadMemory(val, addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1142,7 +1147,8 @@ func (v *Variable) writeUint(value uint64, size int64) error {
|
||||
func readUintRaw(mem memoryReadWriter, addr uintptr, size int64) (uint64, error) {
|
||||
var n uint64
|
||||
|
||||
val, err := mem.readMemory(addr, int(size))
|
||||
val := make([]byte, int(size))
|
||||
_, err := mem.ReadMemory(val, addr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1162,7 +1168,8 @@ func readUintRaw(mem memoryReadWriter, addr uintptr, size int64) (uint64, error)
|
||||
}
|
||||
|
||||
func (v *Variable) readFloatRaw(size int64) (float64, error) {
|
||||
val, err := v.mem.readMemory(v.Addr, int(size))
|
||||
val := make([]byte, int(size))
|
||||
_, err := v.mem.ReadMemory(val, v.Addr)
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
@ -1206,7 +1213,8 @@ func (v *Variable) writeBool(value bool) error {
|
||||
}
|
||||
|
||||
func (v *Variable) readFunctionPtr() {
|
||||
val, err := v.mem.readMemory(v.Addr, v.bi.arch.PtrSize())
|
||||
val := make([]byte, v.bi.arch.PtrSize())
|
||||
_, err := v.mem.ReadMemory(val, v.Addr)
|
||||
if err != nil {
|
||||
v.Unreadable = err
|
||||
return
|
||||
@ -1220,7 +1228,7 @@ func (v *Variable) readFunctionPtr() {
|
||||
return
|
||||
}
|
||||
|
||||
val, err = v.mem.readMemory(fnaddr, v.bi.arch.PtrSize())
|
||||
_, err = v.mem.ReadMemory(val, fnaddr)
|
||||
if err != nil {
|
||||
v.Unreadable = err
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user