proc/*,service: replace uses of uintptr with uint64 (#2163)
Since proc is supposed to work independently from the target architecture it shouldn't use architecture-dependent types, like uintptr. For example when reading a 64bit core file on a 32bit architecture, uintptr will be 32bit but the addresses proc needs to represent will be 64bit.
This commit is contained in:
parent
e07bfd3180
commit
12009e9833
@ -142,7 +142,7 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
|
|||||||
// switches from the goroutine stack to the system stack.
|
// switches from the goroutine stack to the system stack.
|
||||||
// Since we are unwinding the stack from callee to caller we have to switch
|
// Since we are unwinding the stack from callee to caller we have to switch
|
||||||
// from the system stack to the goroutine stack.
|
// from the system stack to the goroutine stack.
|
||||||
off, _ := readIntRaw(it.mem, uintptr(it.regs.SP()+amd64cgocallSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize())) // reads "offset of SP from StackHi" from where runtime.asmcgocall saved it
|
off, _ := readIntRaw(it.mem, uint64(it.regs.SP()+amd64cgocallSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize())) // reads "offset of SP from StackHi" from where runtime.asmcgocall saved it
|
||||||
oldsp := it.regs.SP()
|
oldsp := it.regs.SP()
|
||||||
it.regs.Reg(it.regs.SPRegNum).Uint64Val = uint64(int64(it.stackhi) - off)
|
it.regs.Reg(it.regs.SPRegNum).Uint64Val = uint64(int64(it.stackhi) - off)
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
|
|||||||
|
|
||||||
// advances to the next frame in the call stack
|
// advances to the next frame in the call stack
|
||||||
it.frame.addrret = uint64(int64(it.regs.SP()) + int64(it.bi.Arch.PtrSize()))
|
it.frame.addrret = uint64(int64(it.regs.SP()) + int64(it.bi.Arch.PtrSize()))
|
||||||
it.frame.Ret, _ = readUintRaw(it.mem, uintptr(it.frame.addrret), int64(it.bi.Arch.PtrSize()))
|
it.frame.Ret, _ = readUintRaw(it.mem, it.frame.addrret, int64(it.bi.Arch.PtrSize()))
|
||||||
it.pc = it.frame.Ret
|
it.pc = it.frame.Ret
|
||||||
|
|
||||||
it.top = false
|
it.top = false
|
||||||
@ -183,7 +183,7 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
|
|||||||
// entering the system stack
|
// entering the system stack
|
||||||
it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g0_sched_sp
|
it.regs.Reg(it.regs.SPRegNum).Uint64Val = it.g0_sched_sp
|
||||||
// reads the previous value of g0.sched.sp that runtime.cgocallback_gofunc saved on the stack
|
// reads the previous value of g0.sched.sp that runtime.cgocallback_gofunc saved on the stack
|
||||||
it.g0_sched_sp, _ = readUintRaw(it.mem, uintptr(it.regs.SP()), int64(it.bi.Arch.PtrSize()))
|
it.g0_sched_sp, _ = readUintRaw(it.mem, uint64(it.regs.SP()), int64(it.bi.Arch.PtrSize()))
|
||||||
it.top = false
|
it.top = false
|
||||||
callFrameRegs, ret, retaddr := it.advanceRegs()
|
callFrameRegs, ret, retaddr := it.advanceRegs()
|
||||||
frameOnSystemStack := it.newStackframe(ret, retaddr)
|
frameOnSystemStack := it.newStackframe(ret, retaddr)
|
||||||
|
|||||||
@ -146,9 +146,9 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
|
|||||||
return true
|
return true
|
||||||
case "crosscall2":
|
case "crosscall2":
|
||||||
//The offsets get from runtime/cgo/asm_arm64.s:10
|
//The offsets get from runtime/cgo/asm_arm64.s:10
|
||||||
newsp, _ := readUintRaw(it.mem, uintptr(it.regs.SP()+8*24), int64(it.bi.Arch.PtrSize()))
|
newsp, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*24), int64(it.bi.Arch.PtrSize()))
|
||||||
newbp, _ := readUintRaw(it.mem, uintptr(it.regs.SP()+8*14), int64(it.bi.Arch.PtrSize()))
|
newbp, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*14), int64(it.bi.Arch.PtrSize()))
|
||||||
newlr, _ := readUintRaw(it.mem, uintptr(it.regs.SP()+8*15), int64(it.bi.Arch.PtrSize()))
|
newlr, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*15), int64(it.bi.Arch.PtrSize()))
|
||||||
if it.regs.Reg(it.regs.BPRegNum) != nil {
|
if it.regs.Reg(it.regs.BPRegNum) != nil {
|
||||||
it.regs.Reg(it.regs.BPRegNum).Uint64Val = uint64(newbp)
|
it.regs.Reg(it.regs.BPRegNum).Uint64Val = uint64(newbp)
|
||||||
} else {
|
} else {
|
||||||
@ -188,7 +188,7 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
|
|||||||
// switches from the goroutine stack to the system stack.
|
// switches from the goroutine stack to the system stack.
|
||||||
// Since we are unwinding the stack from callee to caller we have to switch
|
// Since we are unwinding the stack from callee to caller we have to switch
|
||||||
// from the system stack to the goroutine stack.
|
// from the system stack to the goroutine stack.
|
||||||
off, _ := readIntRaw(it.mem, uintptr(callFrameRegs.SP()+arm64cgocallSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize()))
|
off, _ := readIntRaw(it.mem, uint64(callFrameRegs.SP()+arm64cgocallSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize()))
|
||||||
oldsp := callFrameRegs.SP()
|
oldsp := callFrameRegs.SP()
|
||||||
newsp := uint64(int64(it.stackhi) - off)
|
newsp := uint64(int64(it.stackhi) - off)
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
|
|||||||
callFrameRegs.Reg(callFrameRegs.SPRegNum).Uint64Val = it.g0_sched_sp
|
callFrameRegs.Reg(callFrameRegs.SPRegNum).Uint64Val = it.g0_sched_sp
|
||||||
// reads the previous value of g0.sched.sp that runtime.cgocallback_gofunc saved on the stack
|
// reads the previous value of g0.sched.sp that runtime.cgocallback_gofunc saved on the stack
|
||||||
|
|
||||||
it.g0_sched_sp, _ = readUintRaw(it.mem, uintptr(callFrameRegs.SP()+prevG0schedSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize()))
|
it.g0_sched_sp, _ = readUintRaw(it.mem, uint64(callFrameRegs.SP()+prevG0schedSPOffsetSaveSlot), int64(it.bi.Arch.PtrSize()))
|
||||||
it.systemstack = true
|
it.systemstack = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ type BinaryInfo struct {
|
|||||||
// nameOfRuntimeType maps an address of a runtime._type struct to its
|
// nameOfRuntimeType maps an address of a runtime._type struct to its
|
||||||
// decoded name. Used with versions of Go <= 1.10 to figure out the DIE of
|
// decoded name. Used with versions of Go <= 1.10 to figure out the DIE of
|
||||||
// the concrete type of interfaces.
|
// the concrete type of interfaces.
|
||||||
nameOfRuntimeType map[uintptr]nameOfRuntimeTypeEntry
|
nameOfRuntimeType map[uint64]nameOfRuntimeTypeEntry
|
||||||
|
|
||||||
// consts[off] lists all the constants with the type defined at offset off.
|
// consts[off] lists all the constants with the type defined at offset off.
|
||||||
consts constantsMap
|
consts constantsMap
|
||||||
@ -425,7 +425,7 @@ type ElfDynamicSection struct {
|
|||||||
|
|
||||||
// NewBinaryInfo returns an initialized but unloaded BinaryInfo struct.
|
// NewBinaryInfo returns an initialized but unloaded BinaryInfo struct.
|
||||||
func NewBinaryInfo(goos, goarch string) *BinaryInfo {
|
func NewBinaryInfo(goos, goarch string) *BinaryInfo {
|
||||||
r := &BinaryInfo{GOOS: goos, nameOfRuntimeType: make(map[uintptr]nameOfRuntimeTypeEntry), logger: logflags.DebuggerLogger()}
|
r := &BinaryInfo{GOOS: goos, nameOfRuntimeType: make(map[uint64]nameOfRuntimeTypeEntry), logger: logflags.DebuggerLogger()}
|
||||||
|
|
||||||
// TODO: find better way to determine proc arch (perhaps use executable file info).
|
// TODO: find better way to determine proc arch (perhaps use executable file info).
|
||||||
switch goarch {
|
switch goarch {
|
||||||
|
|||||||
@ -26,13 +26,13 @@ type splicedMemory struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type readerEntry struct {
|
type readerEntry struct {
|
||||||
offset uintptr
|
offset uint64
|
||||||
length uintptr
|
length uint64
|
||||||
reader proc.MemoryReader
|
reader proc.MemoryReader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a new region to the SplicedMemory, which may override existing regions.
|
// Add adds a new region to the SplicedMemory, which may override existing regions.
|
||||||
func (r *splicedMemory) Add(reader proc.MemoryReader, off, length uintptr) {
|
func (r *splicedMemory) Add(reader proc.MemoryReader, off, length uint64) {
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ func (r *splicedMemory) Add(reader proc.MemoryReader, off, length uintptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadMemory implements MemoryReader.ReadMemory.
|
// ReadMemory implements MemoryReader.ReadMemory.
|
||||||
func (r *splicedMemory) ReadMemory(buf []byte, addr uintptr) (n int, err error) {
|
func (r *splicedMemory) ReadMemory(buf []byte, addr uint64) (n int, err error) {
|
||||||
started := false
|
started := false
|
||||||
for _, entry := range r.readers {
|
for _, entry := range r.readers {
|
||||||
if entry.offset+entry.length < addr {
|
if entry.offset+entry.length < addr {
|
||||||
@ -107,7 +107,7 @@ func (r *splicedMemory) ReadMemory(buf []byte, addr uintptr) (n int, err error)
|
|||||||
|
|
||||||
// Don't go past the region.
|
// Don't go past the region.
|
||||||
pb := buf
|
pb := buf
|
||||||
if addr+uintptr(len(buf)) > entry.offset+entry.length {
|
if addr+uint64(len(buf)) > entry.offset+entry.length {
|
||||||
pb = pb[:entry.offset+entry.length-addr]
|
pb = pb[:entry.offset+entry.length-addr]
|
||||||
}
|
}
|
||||||
pn, err := entry.reader.ReadMemory(pb, addr)
|
pn, err := entry.reader.ReadMemory(pb, addr)
|
||||||
@ -119,7 +119,7 @@ func (r *splicedMemory) ReadMemory(buf []byte, addr uintptr) (n int, err error)
|
|||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
buf = buf[pn:]
|
buf = buf[pn:]
|
||||||
addr += uintptr(pn)
|
addr += uint64(pn)
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
// Done, don't bother scanning the rest.
|
// Done, don't bother scanning the rest.
|
||||||
return n, nil
|
return n, nil
|
||||||
@ -138,11 +138,11 @@ func (r *splicedMemory) ReadMemory(buf []byte, addr uintptr) (n int, err error)
|
|||||||
// to return the results of a read in that part of the address space.
|
// to return the results of a read in that part of the address space.
|
||||||
type offsetReaderAt struct {
|
type offsetReaderAt struct {
|
||||||
reader io.ReaderAt
|
reader io.ReaderAt
|
||||||
offset uintptr
|
offset uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadMemory will read the memory at addr-offset.
|
// ReadMemory will read the memory at addr-offset.
|
||||||
func (r *offsetReaderAt) ReadMemory(buf []byte, addr uintptr) (n int, err error) {
|
func (r *offsetReaderAt) ReadMemory(buf []byte, addr uint64) (n int, err error) {
|
||||||
return r.reader.ReadAt(buf, int64(addr-r.offset))
|
return r.reader.ReadAt(buf, int64(addr-r.offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +262,7 @@ func (p *process) ClearCheckpoint(int) error { return errors.New("checkpoint not
|
|||||||
// ReadMemory will return memory from the core file at the specified location and put the
|
// ReadMemory will return memory from the core file at the specified location and put the
|
||||||
// read memory into `data`, returning the length read, and returning an error if
|
// read memory into `data`, returning the length read, and returning an error if
|
||||||
// the length read is shorter than the length of the `data` buffer.
|
// the length read is shorter than the length of the `data` buffer.
|
||||||
func (t *thread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
func (t *thread) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
||||||
n, err = t.p.mem.ReadMemory(data, addr)
|
n, err = t.p.mem.ReadMemory(data, addr)
|
||||||
if err == nil && n != len(data) {
|
if err == nil && n != len(data) {
|
||||||
err = ErrShortRead
|
err = ErrShortRead
|
||||||
@ -272,7 +272,7 @@ func (t *thread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
|||||||
|
|
||||||
// WriteMemory will only return an error for core files, you cannot write
|
// WriteMemory will only return an error for core files, you cannot write
|
||||||
// to the memory of a core process.
|
// to the memory of a core process.
|
||||||
func (t *thread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
func (t *thread) WriteMemory(addr uint64, data []byte) (int, error) {
|
||||||
return 0, ErrWriteCore
|
return 0, ErrWriteCore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,13 +50,13 @@ func TestSplicedReader(t *testing.T) {
|
|||||||
|
|
||||||
type region struct {
|
type region struct {
|
||||||
data []byte
|
data []byte
|
||||||
off uintptr
|
off uint64
|
||||||
length uintptr
|
length uint64
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
regions []region
|
regions []region
|
||||||
readAddr uintptr
|
readAddr uint64
|
||||||
readLen int
|
readLen int
|
||||||
want []byte
|
want []byte
|
||||||
}{
|
}{
|
||||||
|
|||||||
@ -326,9 +326,9 @@ func buildMemory(core, exeELF *elf.File, exe io.ReaderAt, notes []*note) proc.Me
|
|||||||
for _, entry := range fileNote.entries {
|
for _, entry := range fileNote.entries {
|
||||||
r := &offsetReaderAt{
|
r := &offsetReaderAt{
|
||||||
reader: exe,
|
reader: exe,
|
||||||
offset: uintptr(entry.Start - (entry.FileOfs * fileNote.PageSize)),
|
offset: entry.Start - (entry.FileOfs * fileNote.PageSize),
|
||||||
}
|
}
|
||||||
memory.Add(r, uintptr(entry.Start), uintptr(entry.End-entry.Start))
|
memory.Add(r, entry.Start, entry.End-entry.Start)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -344,9 +344,9 @@ func buildMemory(core, exeELF *elf.File, exe io.ReaderAt, notes []*note) proc.Me
|
|||||||
}
|
}
|
||||||
r := &offsetReaderAt{
|
r := &offsetReaderAt{
|
||||||
reader: prog.ReaderAt,
|
reader: prog.ReaderAt,
|
||||||
offset: uintptr(prog.Vaddr),
|
offset: prog.Vaddr,
|
||||||
}
|
}
|
||||||
memory.Add(r, uintptr(prog.Vaddr), uintptr(prog.Filesz))
|
memory.Add(r, prog.Vaddr, prog.Filesz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -182,7 +182,7 @@ type MemoryRange struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadMemory reads len(buf) bytes of memory starting at addr into buf from this memory region.
|
// ReadMemory reads len(buf) bytes of memory starting at addr into buf from this memory region.
|
||||||
func (m *MemoryRange) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
func (m *MemoryRange) ReadMemory(buf []byte, addr uint64) (int, error) {
|
||||||
if len(buf) == 0 {
|
if len(buf) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ func readAMD64Minidump(minidumpPath, exePath string) (*process, error) {
|
|||||||
|
|
||||||
for i := range mdmp.MemoryRanges {
|
for i := range mdmp.MemoryRanges {
|
||||||
m := &mdmp.MemoryRanges[i]
|
m := &mdmp.MemoryRanges[i]
|
||||||
memory.Add(m, uintptr(m.Addr), uintptr(len(m.Data)))
|
memory.Add(m, m.Addr, uint64(len(m.Data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
entryPoint := uint64(0)
|
entryPoint := uint64(0)
|
||||||
|
|||||||
@ -125,7 +125,7 @@ func Disassemble(mem MemoryReadWriter, regs Registers, breakpoints *BreakpointMa
|
|||||||
|
|
||||||
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64, singleInstr bool) ([]AsmInstruction, error) {
|
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64, singleInstr bool) ([]AsmInstruction, error) {
|
||||||
mem := make([]byte, int(endAddr-startAddr))
|
mem := make([]byte, int(endAddr-startAddr))
|
||||||
_, err := memrw.ReadMemory(mem, uintptr(startAddr))
|
_, err := memrw.ReadMemory(mem, startAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,7 @@ func newFakeMemory(base uint64, contents ...interface{}) *fakeMemory {
|
|||||||
return mem
|
return mem
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *fakeMemory) ReadMemory(data []byte, addr uintptr) (int, error) {
|
func (mem *fakeMemory) ReadMemory(data []byte, addr uint64) (int, error) {
|
||||||
if uint64(addr) < mem.base {
|
if uint64(addr) < mem.base {
|
||||||
return 0, fmt.Errorf("read out of bounds %d %#x", len(data), addr)
|
return 0, fmt.Errorf("read out of bounds %d %#x", len(data), addr)
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ func (mem *fakeMemory) ReadMemory(data []byte, addr uintptr) (int, error) {
|
|||||||
return len(data), nil
|
return len(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *fakeMemory) WriteMemory(uintptr, []byte) (int, error) {
|
func (mem *fakeMemory) WriteMemory(uint64, []byte) (int, error) {
|
||||||
return 0, fmt.Errorf("not implemented")
|
return 0, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,7 @@ func FrameToScope(bi *BinaryInfo, thread MemoryReadWriter, g *G, frames ...Stack
|
|||||||
maxaddr = uint64(frames[0].Regs.CFA)
|
maxaddr = uint64(frames[0].Regs.CFA)
|
||||||
}
|
}
|
||||||
if maxaddr > minaddr && maxaddr-minaddr < maxFramePrefetchSize {
|
if maxaddr > minaddr && maxaddr-minaddr < maxFramePrefetchSize {
|
||||||
thread = cacheMemory(thread, uintptr(minaddr), int(maxaddr-minaddr))
|
thread = cacheMemory(thread, minaddr, int(maxaddr-minaddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &EvalScope{Location: frames[0].Call, Regs: frames[0].Regs, Mem: thread, g: g, BinInfo: bi, frameOffset: frames[0].FrameOffset()}
|
s := &EvalScope{Location: frames[0].Call, Regs: frames[0].Regs, Mem: thread, g: g, BinInfo: bi, frameOffset: frames[0].FrameOffset()}
|
||||||
@ -232,9 +232,9 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
|
|||||||
if trustArgOrder && ((val.Unreadable != nil && val.Addr == 0) || val.Flags&VariableFakeAddress != 0) && entry.Tag == dwarf.TagFormalParameter {
|
if trustArgOrder && ((val.Unreadable != nil && val.Addr == 0) || val.Flags&VariableFakeAddress != 0) && entry.Tag == dwarf.TagFormalParameter {
|
||||||
addr := afterLastArgAddr(vars)
|
addr := afterLastArgAddr(vars)
|
||||||
if addr == 0 {
|
if addr == 0 {
|
||||||
addr = uintptr(scope.Regs.CFA)
|
addr = uint64(scope.Regs.CFA)
|
||||||
}
|
}
|
||||||
addr = uintptr(alignAddr(int64(addr), val.DwarfType.Align()))
|
addr = uint64(alignAddr(int64(addr), val.DwarfType.Align()))
|
||||||
val = newVariable(val.Name, addr, val.DwarfType, scope.BinInfo, scope.Mem)
|
val = newVariable(val.Name, addr, val.DwarfType, scope.BinInfo, scope.Mem)
|
||||||
}
|
}
|
||||||
vars = append(vars, val)
|
vars = append(vars, val)
|
||||||
@ -288,11 +288,11 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
|
|||||||
return vars, nil
|
return vars, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func afterLastArgAddr(vars []*Variable) uintptr {
|
func afterLastArgAddr(vars []*Variable) uint64 {
|
||||||
for i := len(vars) - 1; i >= 0; i-- {
|
for i := len(vars) - 1; i >= 0; i-- {
|
||||||
v := vars[i]
|
v := vars[i]
|
||||||
if (v.Flags&VariableArgument != 0) || (v.Flags&VariableReturnArgument != 0) {
|
if (v.Flags&VariableArgument != 0) || (v.Flags&VariableReturnArgument != 0) {
|
||||||
return v.Addr + uintptr(v.DwarfType.Size())
|
return v.Addr + uint64(v.DwarfType.Size())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@ -520,9 +520,9 @@ func (scope *EvalScope) findGlobalInternal(name string) (*Variable, error) {
|
|||||||
for _, fn := range scope.BinInfo.Functions {
|
for _, fn := range scope.BinInfo.Functions {
|
||||||
if fn.Name == name || strings.HasSuffix(fn.Name, "/"+name) {
|
if fn.Name == name || strings.HasSuffix(fn.Name, "/"+name) {
|
||||||
//TODO(aarzilli): convert function entry into a function type?
|
//TODO(aarzilli): convert function entry into a function type?
|
||||||
r := newVariable(fn.Name, uintptr(fn.Entry), &godwarf.FuncType{}, scope.BinInfo, scope.Mem)
|
r := newVariable(fn.Name, fn.Entry, &godwarf.FuncType{}, scope.BinInfo, scope.Mem)
|
||||||
r.Value = constant.MakeString(fn.Name)
|
r.Value = constant.MakeString(fn.Name)
|
||||||
r.Base = uintptr(fn.Entry)
|
r.Base = fn.Entry
|
||||||
r.loaded = true
|
r.loaded = true
|
||||||
if fn.Entry == 0 {
|
if fn.Entry == 0 {
|
||||||
r.Unreadable = fmt.Errorf("function %s is inlined", fn.Name)
|
r.Unreadable = fmt.Errorf("function %s is inlined", fn.Name)
|
||||||
@ -626,7 +626,7 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia
|
|||||||
return nil, converr
|
return nil, converr
|
||||||
}
|
}
|
||||||
for i, ch := range []byte(constant.StringVal(argv.Value)) {
|
for i, ch := range []byte(constant.StringVal(argv.Value)) {
|
||||||
e := newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem)
|
e := newVariable("", argv.Addr+uint64(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem)
|
||||||
e.loaded = true
|
e.loaded = true
|
||||||
e.Value = constant.MakeInt64(int64(ch))
|
e.Value = constant.MakeInt64(int64(ch))
|
||||||
v.Children = append(v.Children, *e)
|
v.Children = append(v.Children, *e)
|
||||||
@ -640,7 +640,7 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia
|
|||||||
return nil, converr
|
return nil, converr
|
||||||
}
|
}
|
||||||
for i, ch := range constant.StringVal(argv.Value) {
|
for i, ch := range constant.StringVal(argv.Value) {
|
||||||
e := newVariable("", argv.Addr+uintptr(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem)
|
e := newVariable("", argv.Addr+uint64(i), targetType.(*godwarf.SliceType).ElemType, scope.BinInfo, argv.mem)
|
||||||
e.loaded = true
|
e.loaded = true
|
||||||
e.Value = constant.MakeInt64(int64(ch))
|
e.Value = constant.MakeInt64(int64(ch))
|
||||||
v.Children = append(v.Children, *e)
|
v.Children = append(v.Children, *e)
|
||||||
@ -854,7 +854,7 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) {
|
|||||||
|
|
||||||
n, _ := constant.Int64Val(argv.Value)
|
n, _ := constant.Int64Val(argv.Value)
|
||||||
|
|
||||||
v.Children = []Variable{*(newVariable("", uintptr(n), ttyp.Type, scope.BinInfo, scope.Mem))}
|
v.Children = []Variable{*(newVariable("", uint64(n), ttyp.Type, scope.BinInfo, scope.Mem))}
|
||||||
v.Children[0].OnlyAddr = true
|
v.Children[0].OnlyAddr = true
|
||||||
return v, nil
|
return v, nil
|
||||||
|
|
||||||
@ -1885,7 +1885,7 @@ func (v *Variable) sliceAccess(idx int) (*Variable, error) {
|
|||||||
if v.Kind != reflect.Array {
|
if v.Kind != reflect.Array {
|
||||||
mem = DereferenceMemory(mem)
|
mem = DereferenceMemory(mem)
|
||||||
}
|
}
|
||||||
return v.newVariable("", v.Base+uintptr(int64(idx)*v.stride), v.fieldType, mem), nil
|
return v.newVariable("", v.Base+uint64(int64(idx)*v.stride), v.fieldType, mem), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Variable) mapAccess(idx *Variable) (*Variable, error) {
|
func (v *Variable) mapAccess(idx *Variable) (*Variable, error) {
|
||||||
@ -1938,7 +1938,7 @@ func (v *Variable) reslice(low int64, high int64) (*Variable, error) {
|
|||||||
return nil, fmt.Errorf("index out of bounds")
|
return nil, fmt.Errorf("index out of bounds")
|
||||||
}
|
}
|
||||||
|
|
||||||
base := v.Base + uintptr(int64(low)*v.stride)
|
base := v.Base + uint64(int64(low)*v.stride)
|
||||||
len := high - low
|
len := high - low
|
||||||
|
|
||||||
if high-low < 0 {
|
if high-low < 0 {
|
||||||
@ -2053,7 +2053,7 @@ func functionToVariable(fn *Function, bi *BinaryInfo, mem MemoryReadWriter) (*Va
|
|||||||
v := newVariable(fn.Name, 0, typ, bi, mem)
|
v := newVariable(fn.Name, 0, typ, bi, mem)
|
||||||
v.Value = constant.MakeString(fn.Name)
|
v.Value = constant.MakeString(fn.Name)
|
||||||
v.loaded = true
|
v.loaded = true
|
||||||
v.Base = uintptr(fn.Entry)
|
v.Base = fn.Entry
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -407,7 +407,7 @@ func writePointer(bi *BinaryInfo, mem MemoryReadWriter, addr, val uint64) error
|
|||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unsupported pointer size %d", len(ptrbuf)))
|
panic(fmt.Errorf("unsupported pointer size %d", len(ptrbuf)))
|
||||||
}
|
}
|
||||||
_, err := mem.WriteMemory(uintptr(addr), ptrbuf)
|
_, err := mem.WriteMemory(addr, ptrbuf)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +555,7 @@ func funcCallCopyOneArg(scope *EvalScope, fncall *functionCallState, actualArg *
|
|||||||
//TODO(aarzilli): autmoatic wrapping in interfaces for cases not handled
|
//TODO(aarzilli): autmoatic wrapping in interfaces for cases not handled
|
||||||
// by convertToEface.
|
// by convertToEface.
|
||||||
|
|
||||||
formalArgVar := newVariable(formalArg.name, uintptr(formalArg.off+int64(argFrameAddr)), formalArg.typ, scope.BinInfo, scope.Mem)
|
formalArgVar := newVariable(formalArg.name, uint64(formalArg.off+int64(argFrameAddr)), formalArg.typ, scope.BinInfo, scope.Mem)
|
||||||
if err := scope.setValue(formalArgVar, actualArg, actualArg.Name); err != nil {
|
if err := scope.setValue(formalArgVar, actualArg, actualArg.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -671,7 +671,7 @@ func escapeCheck(v *Variable, name string, stack stack) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Func:
|
case reflect.Func:
|
||||||
if err := escapeCheckPointer(uintptr(v.funcvalAddr()), name, stack); err != nil {
|
if err := escapeCheckPointer(v.funcvalAddr(), name, stack); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,7 +679,7 @@ func escapeCheck(v *Variable, name string, stack stack) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func escapeCheckPointer(addr uintptr, name string, stack stack) error {
|
func escapeCheckPointer(addr uint64, name string, stack stack) error {
|
||||||
if uint64(addr) >= stack.lo && uint64(addr) < stack.hi {
|
if uint64(addr) >= stack.lo && uint64(addr) < stack.hi {
|
||||||
return fmt.Errorf("stack object passed to escaping pointer: %s", name)
|
return fmt.Errorf("stack object passed to escaping pointer: %s", name)
|
||||||
}
|
}
|
||||||
@ -856,7 +856,7 @@ func readTopstackVariable(thread Thread, regs Registers, typename string, loadCf
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
v := newVariable("", uintptr(regs.SP()), typ, scope.BinInfo, scope.Mem)
|
v := newVariable("", regs.SP(), typ, scope.BinInfo, scope.Mem)
|
||||||
v.loadValue(loadCfg)
|
v.loadValue(loadCfg)
|
||||||
if v.Unreadable != nil {
|
if v.Unreadable != nil {
|
||||||
return nil, v.Unreadable
|
return nil, v.Unreadable
|
||||||
@ -932,7 +932,7 @@ func allocString(scope *EvalScope, v *Variable) error {
|
|||||||
if len(mallocv.Children) != 1 {
|
if len(mallocv.Children) != 1 {
|
||||||
return errors.New("internal error, could not interpret return value of mallocgc call")
|
return errors.New("internal error, could not interpret return value of mallocgc call")
|
||||||
}
|
}
|
||||||
v.Base = uintptr(mallocv.Children[0].Addr)
|
v.Base = mallocv.Children[0].Addr
|
||||||
_, err = scope.Mem.WriteMemory(v.Base, []byte(constant.StringVal(v.Value)))
|
_, err = scope.Mem.WriteMemory(v.Base, []byte(constant.StringVal(v.Value)))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -281,7 +281,7 @@ func (p *gdbProcess) Connect(conn net.Conn, path string, pid int, debugInfoDirs
|
|||||||
// If the stub doesn't support memory allocation reloadRegisters will
|
// If the stub doesn't support memory allocation reloadRegisters will
|
||||||
// overwrite some existing memory to store the MOV.
|
// overwrite some existing memory to store the MOV.
|
||||||
if addr, err := p.conn.allocMemory(256); err == nil {
|
if addr, err := p.conn.allocMemory(256); err == nil {
|
||||||
if _, err := p.conn.writeMemory(uintptr(addr), p.loadGInstr()); err == nil {
|
if _, err := p.conn.writeMemory(addr, p.loadGInstr()); err == nil {
|
||||||
p.loadGInstrAddr = addr
|
p.loadGInstrAddr = addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1260,7 +1260,7 @@ func (p *gdbProcess) setCurrentBreakpoints() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadMemory will read into 'data' memory at the address provided.
|
// ReadMemory will read into 'data' memory at the address provided.
|
||||||
func (t *gdbThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
func (t *gdbThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
||||||
err = t.p.conn.readMemory(data, addr)
|
err = t.p.conn.readMemory(data, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -1269,7 +1269,7 @@ func (t *gdbThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteMemory will write into the memory at 'addr' the data provided.
|
// WriteMemory will write into the memory at 'addr' the data provided.
|
||||||
func (t *gdbThread) WriteMemory(addr uintptr, data []byte) (written int, err error) {
|
func (t *gdbThread) WriteMemory(addr uint64, data []byte) (written int, err error) {
|
||||||
return t.p.conn.writeMemory(addr, data)
|
return t.p.conn.writeMemory(addr, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1517,18 +1517,18 @@ func (t *gdbThread) reloadGAtPC() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
savedcode := make([]byte, len(movinstr))
|
savedcode := make([]byte, len(movinstr))
|
||||||
_, err := t.ReadMemory(savedcode, uintptr(pc))
|
_, err := t.ReadMemory(savedcode, pc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = t.WriteMemory(uintptr(pc), movinstr)
|
_, err = t.WriteMemory(pc, movinstr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
_, err0 := t.WriteMemory(uintptr(pc), savedcode)
|
_, err0 := t.WriteMemory(pc, savedcode)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = err0
|
err = err0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -880,7 +880,7 @@ func (conn *gdbConn) appendThreadSelector(threadID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// executes 'm' (read memory) command
|
// executes 'm' (read memory) command
|
||||||
func (conn *gdbConn) readMemory(data []byte, addr uintptr) error {
|
func (conn *gdbConn) readMemory(data []byte, addr uint64) error {
|
||||||
size := len(data)
|
size := len(data)
|
||||||
data = data[:0]
|
data = data[:0]
|
||||||
|
|
||||||
@ -894,7 +894,7 @@ func (conn *gdbConn) readMemory(data []byte, addr uintptr) error {
|
|||||||
}
|
}
|
||||||
size = size - sz
|
size = size - sz
|
||||||
|
|
||||||
fmt.Fprintf(&conn.outbuf, "$m%x,%x", addr+uintptr(len(data)), sz)
|
fmt.Fprintf(&conn.outbuf, "$m%x,%x", addr+uint64(len(data)), sz)
|
||||||
resp, err := conn.exec(conn.outbuf.Bytes(), "memory read")
|
resp, err := conn.exec(conn.outbuf.Bytes(), "memory read")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -915,7 +915,7 @@ func writeAsciiBytes(w io.Writer, data []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// executes 'M' (write memory) command
|
// executes 'M' (write memory) command
|
||||||
func (conn *gdbConn) writeMemory(addr uintptr, data []byte) (written int, err error) {
|
func (conn *gdbConn) writeMemory(addr uint64, data []byte) (written int, err error) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
// LLDB can't parse requests for 0-length writes and hangs if we emit them
|
// LLDB can't parse requests for 0-length writes and hangs if we emit them
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
|||||||
@ -27,12 +27,12 @@ func (gcache *goroutineCache) getRuntimeAllg(bi *BinaryInfo, mem MemoryReadWrite
|
|||||||
if gcache.allglenAddr == 0 || gcache.allgentryAddr == 0 {
|
if gcache.allglenAddr == 0 || gcache.allgentryAddr == 0 {
|
||||||
return 0, 0, ErrNoRuntimeAllG
|
return 0, 0, ErrNoRuntimeAllG
|
||||||
}
|
}
|
||||||
allglen, err := readUintRaw(mem, uintptr(gcache.allglenAddr), int64(bi.Arch.PtrSize()))
|
allglen, err := readUintRaw(mem, gcache.allglenAddr, int64(bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
allgptr, err := readUintRaw(mem, uintptr(gcache.allgentryAddr), int64(bi.Arch.PtrSize()))
|
allgptr, err := readUintRaw(mem, gcache.allgentryAddr, int64(bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ func dynamicSearchDebug(p proc.Process) (uint64, error) {
|
|||||||
mem := p.CurrentThread()
|
mem := p.CurrentThread()
|
||||||
|
|
||||||
dynbuf := make([]byte, bi.ElfDynamicSection.Size)
|
dynbuf := make([]byte, bi.ElfDynamicSection.Size)
|
||||||
_, err := mem.ReadMemory(dynbuf, uintptr(bi.ElfDynamicSection.Addr))
|
_, err := mem.ReadMemory(dynbuf, bi.ElfDynamicSection.Addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ func dynamicSearchDebug(p proc.Process) (uint64, error) {
|
|||||||
|
|
||||||
func readPtr(p proc.Process, addr uint64) (uint64, error) {
|
func readPtr(p proc.Process, addr uint64) (uint64, error) {
|
||||||
ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize())
|
ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize())
|
||||||
_, err := p.CurrentThread().ReadMemory(ptrbuf, uintptr(addr))
|
_, err := p.CurrentThread().ReadMemory(ptrbuf, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ func readCString(p proc.Process, addr uint64) (string, error) {
|
|||||||
if len(r) > maxLibraryPathLength {
|
if len(r) > maxLibraryPathLength {
|
||||||
return "", fmt.Errorf("error reading libraries: string too long (%d)", len(r))
|
return "", fmt.Errorf("error reading libraries: string too long (%d)", len(r))
|
||||||
}
|
}
|
||||||
_, err := mem.ReadMemory(buf, uintptr(addr))
|
_, err := mem.ReadMemory(buf, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,13 +9,13 @@ import (
|
|||||||
|
|
||||||
const cacheEnabled = true
|
const cacheEnabled = true
|
||||||
|
|
||||||
// MemoryReader is like io.ReaderAt, but the offset is a uintptr so that it
|
// MemoryReader is like io.ReaderAt, but the offset is a uint64 so that it
|
||||||
// can address all of 64-bit memory.
|
// can address all of 64-bit memory.
|
||||||
// Redundant with memoryReadWriter but more easily suited to working with
|
// Redundant with memoryReadWriter but more easily suited to working with
|
||||||
// the standard io package.
|
// the standard io package.
|
||||||
type MemoryReader interface {
|
type MemoryReader interface {
|
||||||
// ReadMemory is just like io.ReaderAt.ReadAt.
|
// ReadMemory is just like io.ReaderAt.ReadAt.
|
||||||
ReadMemory(buf []byte, addr uintptr) (n int, err error)
|
ReadMemory(buf []byte, addr uint64) (n int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MemoryReadWriter is an interface for reading or writing to
|
// MemoryReadWriter is an interface for reading or writing to
|
||||||
@ -23,21 +23,21 @@ type MemoryReader interface {
|
|||||||
// target memory or possibly a cache.
|
// target memory or possibly a cache.
|
||||||
type MemoryReadWriter interface {
|
type MemoryReadWriter interface {
|
||||||
MemoryReader
|
MemoryReader
|
||||||
WriteMemory(addr uintptr, data []byte) (written int, err error)
|
WriteMemory(addr uint64, data []byte) (written int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type memCache struct {
|
type memCache struct {
|
||||||
loaded bool
|
loaded bool
|
||||||
cacheAddr uintptr
|
cacheAddr uint64
|
||||||
cache []byte
|
cache []byte
|
||||||
mem MemoryReadWriter
|
mem MemoryReadWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memCache) contains(addr uintptr, size int) bool {
|
func (m *memCache) contains(addr uint64, size int) bool {
|
||||||
return addr >= m.cacheAddr && addr <= (m.cacheAddr+uintptr(len(m.cache)-size))
|
return addr >= m.cacheAddr && addr <= (m.cacheAddr+uint64(len(m.cache)-size))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memCache) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
func (m *memCache) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
||||||
if m.contains(addr, len(data)) {
|
if m.contains(addr, len(data)) {
|
||||||
if !m.loaded {
|
if !m.loaded {
|
||||||
_, err := m.mem.ReadMemory(m.cache, m.cacheAddr)
|
_, err := m.mem.ReadMemory(m.cache, m.cacheAddr)
|
||||||
@ -53,11 +53,11 @@ func (m *memCache) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
|||||||
return m.mem.ReadMemory(data, addr)
|
return m.mem.ReadMemory(data, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memCache) WriteMemory(addr uintptr, data []byte) (written int, err error) {
|
func (m *memCache) WriteMemory(addr uint64, data []byte) (written int, err error) {
|
||||||
return m.mem.WriteMemory(addr, data)
|
return m.mem.WriteMemory(addr, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cacheMemory(mem MemoryReadWriter, addr uintptr, size int) MemoryReadWriter {
|
func cacheMemory(mem MemoryReadWriter, addr uint64, size int) MemoryReadWriter {
|
||||||
if !cacheEnabled {
|
if !cacheEnabled {
|
||||||
return mem
|
return mem
|
||||||
}
|
}
|
||||||
@ -112,23 +112,23 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o
|
|||||||
cmem.data = append(cmem.data, reg[:sz]...)
|
cmem.data = append(cmem.data, reg[:sz]...)
|
||||||
} else {
|
} else {
|
||||||
buf := make([]byte, piece.Size)
|
buf := make([]byte, piece.Size)
|
||||||
mem.ReadMemory(buf, uintptr(piece.Addr))
|
mem.ReadMemory(buf, uint64(piece.Addr))
|
||||||
cmem.data = append(cmem.data, buf...)
|
cmem.data = append(cmem.data, buf...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cmem, nil
|
return cmem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *compositeMemory) ReadMemory(data []byte, addr uintptr) (int, error) {
|
func (mem *compositeMemory) ReadMemory(data []byte, addr uint64) (int, error) {
|
||||||
addr -= fakeAddress
|
addr -= fakeAddress
|
||||||
if addr >= uintptr(len(mem.data)) || addr+uintptr(len(data)) > uintptr(len(mem.data)) {
|
if addr >= uint64(len(mem.data)) || addr+uint64(len(data)) > uint64(len(mem.data)) {
|
||||||
return 0, errors.New("read out of bounds")
|
return 0, errors.New("read out of bounds")
|
||||||
}
|
}
|
||||||
copy(data, mem.data[addr:addr+uintptr(len(data))])
|
copy(data, mem.data[addr:addr+uint64(len(data))])
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *compositeMemory) WriteMemory(addr uintptr, data []byte) (int, error) {
|
func (mem *compositeMemory) WriteMemory(addr uint64, data []byte) (int, error) {
|
||||||
//TODO(aarzilli): implement
|
//TODO(aarzilli): implement
|
||||||
return 0, errors.New("can't write composite memory")
|
return 0, errors.New("can't write composite memory")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
// delve counterpart to runtime.moduledata
|
// delve counterpart to runtime.moduledata
|
||||||
type moduleData struct {
|
type moduleData struct {
|
||||||
text, etext uintptr
|
text, etext uint64
|
||||||
types, etypes uintptr
|
types, etypes uint64
|
||||||
typemapVar *Variable
|
typemapVar *Variable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,11 +44,11 @@ func loadModuleData(bi *BinaryInfo, mem MemoryReadWriter) ([]moduleData, error)
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
touint := func(name string) (ret uintptr) {
|
touint := func(name string) (ret uint64) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var n uint64
|
var n uint64
|
||||||
n, err = vars[name].asUint()
|
n, err = vars[name].asUint()
|
||||||
ret = uintptr(n)
|
ret = n
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ func loadModuleData(bi *BinaryInfo, mem MemoryReadWriter) ([]moduleData, error)
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findModuleDataForType(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, mem MemoryReadWriter) *moduleData {
|
func findModuleDataForType(bi *BinaryInfo, mds []moduleData, typeAddr uint64, mem MemoryReadWriter) *moduleData {
|
||||||
for i := range mds {
|
for i := range mds {
|
||||||
if typeAddr >= mds[i].types && typeAddr < mds[i].etypes {
|
if typeAddr >= mds[i].types && typeAddr < mds[i].etypes {
|
||||||
return &mds[i]
|
return &mds[i]
|
||||||
@ -80,7 +80,7 @@ func findModuleDataForType(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, m
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveTypeOff(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, off uintptr, mem MemoryReadWriter) (*Variable, error) {
|
func resolveTypeOff(bi *BinaryInfo, mds []moduleData, typeAddr, off uint64, mem MemoryReadWriter) (*Variable, error) {
|
||||||
// See runtime.(*_type).typeOff in $GOROOT/src/runtime/type.go
|
// See runtime.(*_type).typeOff in $GOROOT/src/runtime/type.go
|
||||||
md := findModuleDataForType(bi, mds, typeAddr, mem)
|
md := findModuleDataForType(bi, mds, typeAddr, mem)
|
||||||
|
|
||||||
@ -96,19 +96,19 @@ func resolveTypeOff(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, off uint
|
|||||||
}
|
}
|
||||||
v.loadValue(LoadConfig{false, 1, 0, 0, -1, 0})
|
v.loadValue(LoadConfig{false, 1, 0, 0, -1, 0})
|
||||||
addr, _ := constant.Int64Val(v.Value)
|
addr, _ := constant.Int64Val(v.Value)
|
||||||
return v.newVariable(v.Name, uintptr(addr), rtyp, mem), nil
|
return v.newVariable(v.Name, uint64(addr), rtyp, mem), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), mem)); t != nil {
|
if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), mem)); t != nil {
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
res := md.types + uintptr(off)
|
res := md.types + off
|
||||||
|
|
||||||
return newVariable("", res, rtyp, bi, mem), nil
|
return newVariable("", uint64(res), rtyp, bi, mem), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveNameOff(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, off uintptr, mem MemoryReadWriter) (name, tag string, pkgpathoff int32, err error) {
|
func resolveNameOff(bi *BinaryInfo, mds []moduleData, typeAddr, off uint64, mem MemoryReadWriter) (name, tag string, pkgpathoff int32, err error) {
|
||||||
// See runtime.resolveNameOff in $GOROOT/src/runtime/type.go
|
// See runtime.resolveNameOff in $GOROOT/src/runtime/type.go
|
||||||
for _, md := range mds {
|
for _, md := range mds {
|
||||||
if typeAddr >= md.types && typeAddr < md.etypes {
|
if typeAddr >= md.types && typeAddr < md.etypes {
|
||||||
@ -129,7 +129,7 @@ func resolveNameOff(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, off uint
|
|||||||
return loadName(bi, resv.Addr, mem)
|
return loadName(bi, resv.Addr, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflectOffsMapAccess(bi *BinaryInfo, off uintptr, mem MemoryReadWriter) (*Variable, error) {
|
func reflectOffsMapAccess(bi *BinaryInfo, off uint64, mem MemoryReadWriter) (*Variable, error) {
|
||||||
scope := globalScope(bi, bi.Images[0], mem)
|
scope := globalScope(bi, bi.Images[0], mem)
|
||||||
reflectOffs, err := scope.findGlobal("runtime", "reflectOffs")
|
reflectOffs, err := scope.findGlobal("runtime", "reflectOffs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,7 +151,7 @@ const (
|
|||||||
nameflagHasPkg = 1 << 2
|
nameflagHasPkg = 1 << 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func loadName(bi *BinaryInfo, addr uintptr, mem MemoryReadWriter) (name, tag string, pkgpathoff int32, err error) {
|
func loadName(bi *BinaryInfo, addr uint64, mem MemoryReadWriter) (name, tag string, pkgpathoff int32, err error) {
|
||||||
off := addr
|
off := addr
|
||||||
namedata := make([]byte, 3)
|
namedata := make([]byte, 3)
|
||||||
_, err = mem.ReadMemory(namedata, off)
|
_, err = mem.ReadMemory(namedata, off)
|
||||||
@ -164,7 +164,7 @@ func loadName(bi *BinaryInfo, addr uintptr, mem MemoryReadWriter) (name, tag str
|
|||||||
|
|
||||||
rawstr := make([]byte, int(namelen))
|
rawstr := make([]byte, int(namelen))
|
||||||
_, err = mem.ReadMemory(rawstr, off)
|
_, err = mem.ReadMemory(rawstr, off)
|
||||||
off += uintptr(namelen)
|
off += uint64(namelen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", 0, err
|
return "", "", 0, err
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ func loadName(bi *BinaryInfo, addr uintptr, mem MemoryReadWriter) (name, tag str
|
|||||||
|
|
||||||
rawstr := make([]byte, int(taglen))
|
rawstr := make([]byte, int(taglen))
|
||||||
_, err = mem.ReadMemory(rawstr, off)
|
_, err = mem.ReadMemory(rawstr, off)
|
||||||
off += uintptr(taglen)
|
off += uint64(taglen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", 0, err
|
return "", "", 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,12 +102,12 @@ func (t *nativeThread) SetDX(dx uint64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadMemory reads len(buf) bytes at addr into buf.
|
// ReadMemory reads len(buf) bytes at addr into buf.
|
||||||
func (t *nativeThread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) {
|
||||||
panic(ErrNativeBackendDisabled)
|
panic(ErrNativeBackendDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMemory writes the contents of data at addr.
|
// WriteMemory writes the contents of data at addr.
|
||||||
func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
func (t *nativeThread) WriteMemory(addr uint64, data []byte) (int, error) {
|
||||||
panic(ErrNativeBackendDisabled)
|
panic(ErrNativeBackendDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -209,7 +209,7 @@ func (dbp *nativeProcess) WriteBreakpoint(addr uint64) (string, int, *proc.Funct
|
|||||||
f, l, fn := dbp.bi.PCToLine(uint64(addr))
|
f, l, fn := dbp.bi.PCToLine(uint64(addr))
|
||||||
|
|
||||||
originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
|
originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
|
||||||
_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
|
_, err := dbp.currentThread.ReadMemory(originalData, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, nil, nil, err
|
return "", 0, nil, nil, err
|
||||||
}
|
}
|
||||||
@ -317,7 +317,7 @@ func (dbp *nativeProcess) postExit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *nativeProcess) writeSoftwareBreakpoint(thread *nativeThread, addr uint64) error {
|
func (dbp *nativeProcess) writeSoftwareBreakpoint(thread *nativeThread, addr uint64) error {
|
||||||
_, err := thread.WriteMemory(uintptr(addr), dbp.bi.Arch.BreakpointInstruction())
|
_, err := thread.WriteMemory(addr, dbp.bi.Arch.BreakpointInstruction())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -310,7 +310,7 @@ func (dbp *nativeProcess) waitForDebugEvent(flags waitForDebugEventFlags) (threa
|
|||||||
atbp := true
|
atbp := true
|
||||||
if thread, found := dbp.threads[tid]; found {
|
if thread, found := dbp.threads[tid]; found {
|
||||||
data := make([]byte, dbp.bi.Arch.BreakpointSize())
|
data := make([]byte, dbp.bi.Arch.BreakpointSize())
|
||||||
if _, err := thread.ReadMemory(data, exception.ExceptionRecord.ExceptionAddress); err == nil {
|
if _, err := thread.ReadMemory(data, uint64(exception.ExceptionRecord.ExceptionAddress)); err == nil {
|
||||||
instr := dbp.bi.Arch.BreakpointInstruction()
|
instr := dbp.bi.Arch.BreakpointInstruction()
|
||||||
for i := range instr {
|
for i := range instr {
|
||||||
if data[i] != instr[i] {
|
if data[i] != instr[i] {
|
||||||
|
|||||||
@ -150,7 +150,7 @@ func (t *nativeThread) ThreadID() int {
|
|||||||
|
|
||||||
// ClearBreakpoint clears the specified breakpoint.
|
// ClearBreakpoint clears the specified breakpoint.
|
||||||
func (t *nativeThread) ClearBreakpoint(bp *proc.Breakpoint) error {
|
func (t *nativeThread) ClearBreakpoint(bp *proc.Breakpoint) error {
|
||||||
if _, err := t.WriteMemory(uintptr(bp.Addr), bp.OriginalData); err != nil {
|
if _, err := t.WriteMemory(bp.Addr, bp.OriginalData); err != nil {
|
||||||
return fmt.Errorf("could not clear breakpoint %s", err)
|
return fmt.Errorf("could not clear breakpoint %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -110,7 +110,7 @@ func (t *nativeThread) Stopped() bool {
|
|||||||
return C.thread_blocked(t.os.threadAct) > C.int(0)
|
return C.thread_blocked(t.os.threadAct) > C.int(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
func (t *nativeThread) WriteMemory(addr uint64, data []byte) (int, error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
|||||||
return len(data), nil
|
return len(data), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,24 +110,24 @@ func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
|
|||||||
return restoreRegistersErr
|
return restoreRegistersErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (written int, err error) {
|
func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
t.dbp.execPtraceFunc(func() { written, err = ptraceWriteData(t.ID, addr, data) })
|
t.dbp.execPtraceFunc(func() { written, err = ptraceWriteData(t.ID, uintptr(addr), data) })
|
||||||
return written, err
|
return written, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
t.dbp.execPtraceFunc(func() { n, err = ptraceReadData(t.ID, addr, data) })
|
t.dbp.execPtraceFunc(func() { n, err = ptraceReadData(t.ID, uintptr(addr), data) })
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,7 +84,7 @@ func (t *nativeThread) Blocked() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (written int, err error) {
|
func (t *nativeThread) WriteMemory(addr uint64, data []byte) (written int, err error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
@ -94,24 +94,24 @@ func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (written int, err
|
|||||||
// ProcessVmWrite can't poke read-only memory like ptrace, so don't
|
// ProcessVmWrite can't poke read-only memory like ptrace, so don't
|
||||||
// even bother for small writes -- likely breakpoints and such.
|
// even bother for small writes -- likely breakpoints and such.
|
||||||
if len(data) > sys.SizeofPtr {
|
if len(data) > sys.SizeofPtr {
|
||||||
written, _ = processVmWrite(t.ID, addr, data)
|
written, _ = processVmWrite(t.ID, uintptr(addr), data)
|
||||||
}
|
}
|
||||||
if written == 0 {
|
if written == 0 {
|
||||||
t.dbp.execPtraceFunc(func() { written, err = sys.PtracePokeData(t.ID, addr, data) })
|
t.dbp.execPtraceFunc(func() { written, err = sys.PtracePokeData(t.ID, uintptr(addr), data) })
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) ReadMemory(data []byte, addr uintptr) (n int, err error) {
|
func (t *nativeThread) ReadMemory(data []byte, addr uint64) (n int, err error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, _ = processVmRead(t.ID, addr, data)
|
n, _ = processVmRead(t.ID, uintptr(addr), data)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
t.dbp.execPtraceFunc(func() { n, err = sys.PtracePeekData(t.ID, addr, data) })
|
t.dbp.execPtraceFunc(func() { n, err = sys.PtracePeekData(t.ID, uintptr(addr), data) })
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,7 +137,7 @@ func (t *nativeThread) Stopped() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
func (t *nativeThread) WriteMemory(addr uint64, data []byte) (int, error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
var count uintptr
|
var count uintptr
|
||||||
err := _WriteProcessMemory(t.dbp.os.hProcess, addr, &data[0], uintptr(len(data)), &count)
|
err := _WriteProcessMemory(t.dbp.os.hProcess, uintptr(addr), &data[0], uintptr(len(data)), &count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
|
|||||||
|
|
||||||
var ErrShortRead = errors.New("short read")
|
var ErrShortRead = errors.New("short read")
|
||||||
|
|
||||||
func (t *nativeThread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) {
|
||||||
if t.dbp.exited {
|
if t.dbp.exited {
|
||||||
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ func (t *nativeThread) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
var count uintptr
|
var count uintptr
|
||||||
err := _ReadProcessMemory(t.dbp.os.hProcess, addr, &buf[0], uintptr(len(buf)), &count)
|
err := _ReadProcessMemory(t.dbp.os.hProcess, uintptr(addr), &buf[0], uintptr(len(buf)), &count)
|
||||||
if err == nil && count != uintptr(len(buf)) {
|
if err == nil && count != uintptr(len(buf)) {
|
||||||
err = ErrShortRead
|
err = ErrShortRead
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ func TestIssue554(t *testing.T) {
|
|||||||
case 8:
|
case 8:
|
||||||
addr = 0xffffffffffffffff
|
addr = 0xffffffffffffffff
|
||||||
}
|
}
|
||||||
if mem.contains(uintptr(addr), 40) {
|
if mem.contains(addr, 40) {
|
||||||
t.Fatalf("should be false")
|
t.Fatalf("should be false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ type memRead struct {
|
|||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dm *dummyMem) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
func (dm *dummyMem) ReadMemory(buf []byte, addr uint64) (int, error) {
|
||||||
dm.t.Logf("read addr=%#x size=%#x\n", addr, len(buf))
|
dm.t.Logf("read addr=%#x size=%#x\n", addr, len(buf))
|
||||||
dm.reads = append(dm.reads, memRead{uint64(addr), len(buf)})
|
dm.reads = append(dm.reads, memRead{uint64(addr), len(buf)})
|
||||||
a := int64(addr) - int64(dm.base)
|
a := int64(addr) - int64(dm.base)
|
||||||
@ -55,7 +55,7 @@ func (dm *dummyMem) ReadMemory(buf []byte, addr uintptr) (int, error) {
|
|||||||
return len(buf), nil
|
return len(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dm *dummyMem) WriteMemory(uintptr, []byte) (int, error) {
|
func (dm *dummyMem) WriteMemory(uint64, []byte) (int, error) {
|
||||||
panic("not supported")
|
panic("not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ func TestReadCStringValue(t *testing.T) {
|
|||||||
t.Logf("base is %#x\n", tc.base)
|
t.Logf("base is %#x\n", tc.base)
|
||||||
dm.base = tc.base
|
dm.base = tc.base
|
||||||
dm.reads = dm.reads[:0]
|
dm.reads = dm.reads[:0]
|
||||||
out, done, err := readCStringValue(dm, uintptr(tc.base), LoadConfig{MaxStringLen: maxstrlen})
|
out, done, err := readCStringValue(dm, tc.base, LoadConfig{MaxStringLen: maxstrlen})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("base=%#x readCStringValue: %v", tc.base, err)
|
t.Errorf("base=%#x readCStringValue: %v", tc.base, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,7 @@ func getRegisters(p *proc.Target, t *testing.T) proc.Registers {
|
|||||||
|
|
||||||
func dataAtAddr(thread proc.MemoryReadWriter, addr uint64) ([]byte, error) {
|
func dataAtAddr(thread proc.MemoryReadWriter, addr uint64) ([]byte, error) {
|
||||||
data := make([]byte, 1)
|
data := make([]byte, 1)
|
||||||
_, err := thread.ReadMemory(data, uintptr(addr))
|
_, err := thread.ReadMemory(data, addr)
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -516,7 +516,7 @@ func (it *stackIterator) executeFrameRegRule(regnum uint64, rule frame.DWRule, c
|
|||||||
|
|
||||||
func (it *stackIterator) readRegisterAt(regnum uint64, addr uint64) (*op.DwarfRegister, error) {
|
func (it *stackIterator) readRegisterAt(regnum uint64, addr uint64) (*op.DwarfRegister, error) {
|
||||||
buf := make([]byte, it.bi.Arch.regSize(regnum))
|
buf := make([]byte, it.bi.Arch.regSize(regnum))
|
||||||
_, err := it.mem.ReadMemory(buf, uintptr(addr))
|
_, err := it.mem.ReadMemory(buf, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -675,7 +675,7 @@ func (d *Defer) EvalScope(thread Thread) (*EvalScope, error) {
|
|||||||
return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
|
return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
|
||||||
}
|
}
|
||||||
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)
|
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)
|
||||||
scope.Mem = cacheMemory(scope.Mem, uintptr(scope.Regs.CFA), int(d.argSz))
|
scope.Mem = cacheMemory(scope.Mem, uint64(scope.Regs.CFA), int(d.argSz))
|
||||||
|
|
||||||
return scope, nil
|
return scope, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,7 +142,7 @@ func (dbp *Target) Continue() error {
|
|||||||
if !arch.BreakInstrMovesPC() {
|
if !arch.BreakInstrMovesPC() {
|
||||||
bpsize := arch.BreakpointSize()
|
bpsize := arch.BreakpointSize()
|
||||||
bp := make([]byte, bpsize)
|
bp := make([]byte, bpsize)
|
||||||
_, err = dbp.CurrentThread().ReadMemory(bp, uintptr(loc.PC))
|
_, err = dbp.CurrentThread().ReadMemory(bp, loc.PC)
|
||||||
if bytes.Equal(bp, arch.BreakpointInstruction()) {
|
if bytes.Equal(bp, arch.BreakpointInstruction()) {
|
||||||
curthread.SetPC(loc.PC + uint64(bpsize))
|
curthread.SetPC(loc.PC + uint64(bpsize))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,7 +107,7 @@ func newLoadDebugInfoMapsContext(bi *BinaryInfo, image *Image, offsetToVersion m
|
|||||||
// debug_info
|
// debug_info
|
||||||
// * After go1.11 the runtimeTypeToDIE map is used to look up the address of
|
// * After go1.11 the runtimeTypeToDIE map is used to look up the address of
|
||||||
// the type and map it drectly to a DIE.
|
// the type and map it drectly to a DIE.
|
||||||
func runtimeTypeToDIE(_type *Variable, dataAddr uintptr) (typ godwarf.Type, kind int64, err error) {
|
func runtimeTypeToDIE(_type *Variable, dataAddr uint64) (typ godwarf.Type, kind int64, err error) {
|
||||||
bi := _type.bi
|
bi := _type.bi
|
||||||
|
|
||||||
_type = _type.maybeDereference()
|
_type = _type.maybeDereference()
|
||||||
@ -218,7 +218,7 @@ func nameOfNamedRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64
|
|||||||
// For a description of how memory is organized for type names read
|
// For a description of how memory is organized for type names read
|
||||||
// the comment to 'type name struct' in $GOROOT/src/reflect/type.go
|
// the comment to 'type name struct' in $GOROOT/src/reflect/type.go
|
||||||
|
|
||||||
typename, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uintptr(strOff), _type.mem)
|
typename, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uint64(strOff), _type.mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -244,7 +244,7 @@ func nameOfNamedRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64
|
|||||||
if ut := uncommon(_type, tflag); ut != nil {
|
if ut := uncommon(_type, tflag); ut != nil {
|
||||||
if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil {
|
if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil {
|
||||||
pkgPathOff, _ := constant.Int64Val(pkgPathField.Value)
|
pkgPathOff, _ := constant.Int64Val(pkgPathField.Value)
|
||||||
pkgPath, _, _, err := resolveNameOff(_type.bi, mds, _type.Addr, uintptr(pkgPathOff), _type.mem)
|
pkgPath, _, _, err := resolveNameOff(_type.bi, mds, _type.Addr, uint64(pkgPathOff), _type.mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -344,7 +344,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
|
|||||||
outCount = outCount & (1<<15 - 1)
|
outCount = outCount & (1<<15 - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cursortyp := _type.newVariable("", _type.Addr+uintptr(uadd), prtyp, _type.mem)
|
cursortyp := _type.newVariable("", _type.Addr+uint64(uadd), prtyp, _type.mem)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if anonymous {
|
if anonymous {
|
||||||
buf.WriteString("func(")
|
buf.WriteString("func(")
|
||||||
@ -354,7 +354,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
|
|||||||
|
|
||||||
for i := int64(0); i < inCount; i++ {
|
for i := int64(0); i < inCount; i++ {
|
||||||
argtype := cursortyp.maybeDereference()
|
argtype := cursortyp.maybeDereference()
|
||||||
cursortyp.Addr += uintptr(_type.bi.Arch.PtrSize())
|
cursortyp.Addr += uint64(_type.bi.Arch.PtrSize())
|
||||||
argtypename, _, err := nameOfRuntimeType(mds, argtype)
|
argtypename, _, err := nameOfRuntimeType(mds, argtype)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -381,7 +381,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
|
|||||||
buf.WriteString(" (")
|
buf.WriteString(" (")
|
||||||
for i := int64(0); i < outCount; i++ {
|
for i := int64(0); i < outCount; i++ {
|
||||||
argtype := cursortyp.maybeDereference()
|
argtype := cursortyp.maybeDereference()
|
||||||
cursortyp.Addr += uintptr(_type.bi.Arch.PtrSize())
|
cursortyp.Addr += uint64(_type.bi.Arch.PtrSize())
|
||||||
argtypename, _, err := nameOfRuntimeType(mds, argtype)
|
argtypename, _, err := nameOfRuntimeType(mds, argtype)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -419,14 +419,14 @@ func nameOfInterfaceRuntimeType(mds []moduleData, _type *Variable, kind, tflag i
|
|||||||
case imethodFieldName:
|
case imethodFieldName:
|
||||||
nameoff, _ := constant.Int64Val(im.Children[i].Value)
|
nameoff, _ := constant.Int64Val(im.Children[i].Value)
|
||||||
var err error
|
var err error
|
||||||
methodname, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uintptr(nameoff), _type.mem)
|
methodname, _, _, err = resolveNameOff(_type.bi, mds, _type.Addr, uint64(nameoff), _type.mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
case imethodFieldItyp:
|
case imethodFieldItyp:
|
||||||
typeoff, _ := constant.Int64Val(im.Children[i].Value)
|
typeoff, _ := constant.Int64Val(im.Children[i].Value)
|
||||||
typ, err := resolveTypeOff(_type.bi, mds, _type.Addr, uintptr(typeoff), _type.mem)
|
typ, err := resolveTypeOff(_type.bi, mds, _type.Addr, uint64(typeoff), _type.mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -489,7 +489,7 @@ func nameOfStructRuntimeType(mds []moduleData, _type *Variable, kind, tflag int6
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
fieldname, _, _, err = loadName(_type.bi, uintptr(nameoff), _type.mem)
|
fieldname, _, _, err = loadName(_type.bi, uint64(nameoff), _type.mem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -564,7 +564,7 @@ func uncommon(_type *Variable, tflag int64) *Variable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return _type.newVariable(_type.Name, _type.Addr+uintptr(_type.RealType.Size()), typ, _type.mem)
|
return _type.newVariable(_type.Name, _type.Addr+uint64(_type.RealType.Size()), typ, _type.mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
var kindToRuntimeTypeName = map[reflect.Kind]string{
|
var kindToRuntimeTypeName = map[reflect.Kind]string{
|
||||||
@ -627,7 +627,7 @@ func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, false, err
|
return 0, 0, false, err
|
||||||
}
|
}
|
||||||
_type := newVariable("", uintptr(typeAddr), rtyp, bi, mem)
|
_type := newVariable("", typeAddr, rtyp, bi, mem)
|
||||||
kindv := _type.loadFieldNamed("kind")
|
kindv := _type.loadFieldNamed("kind")
|
||||||
if kindv.Unreadable != nil || kindv.Kind != reflect.Uint {
|
if kindv.Unreadable != nil || kindv.Kind != reflect.Uint {
|
||||||
return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable)
|
return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable)
|
||||||
|
|||||||
@ -86,7 +86,7 @@ const (
|
|||||||
// and the memory of the debugged process.
|
// and the memory of the debugged process.
|
||||||
// If OnlyAddr is true, the variables value has not been loaded.
|
// If OnlyAddr is true, the variables value has not been loaded.
|
||||||
type Variable struct {
|
type Variable struct {
|
||||||
Addr uintptr
|
Addr uint64
|
||||||
OnlyAddr bool
|
OnlyAddr bool
|
||||||
Name string
|
Name string
|
||||||
DwarfType godwarf.Type
|
DwarfType godwarf.Type
|
||||||
@ -107,7 +107,7 @@ type Variable struct {
|
|||||||
// Base address of the backing byte array for strings
|
// Base address of the backing byte array for strings
|
||||||
// address of the struct backing chan and map variables
|
// address of the struct backing chan and map variables
|
||||||
// address of the function entry point for function variables (0 for nil function pointers)
|
// address of the function entry point for function variables (0 for nil function pointers)
|
||||||
Base uintptr
|
Base uint64
|
||||||
stride int64
|
stride int64
|
||||||
fieldType godwarf.Type
|
fieldType godwarf.Type
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ func GoroutinesInfo(dbp *Target, start, count int) ([]*G, int, error) {
|
|||||||
if count != 0 && len(allg) >= count {
|
if count != 0 && len(allg) >= count {
|
||||||
return allg, int(i), nil
|
return allg, int(i), nil
|
||||||
}
|
}
|
||||||
gvar, err := newGVariable(dbp.CurrentThread(), uintptr(allgptr+(i*uint64(dbp.BinInfo().Arch.PtrSize()))), true)
|
gvar, err := newGVariable(dbp.CurrentThread(), allgptr+(i*uint64(dbp.BinInfo().Arch.PtrSize())), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allg = append(allg, &G{Unreadable: err})
|
allg = append(allg, &G{Unreadable: err})
|
||||||
continue
|
continue
|
||||||
@ -434,16 +434,16 @@ func getGVariable(thread Thread) (*Variable, error) {
|
|||||||
gaddr, hasgaddr := regs.GAddr()
|
gaddr, hasgaddr := regs.GAddr()
|
||||||
if !hasgaddr {
|
if !hasgaddr {
|
||||||
var err error
|
var err error
|
||||||
gaddr, err = readUintRaw(thread, uintptr(regs.TLS()+thread.BinInfo().GStructOffset()), int64(thread.BinInfo().Arch.PtrSize()))
|
gaddr, err = readUintRaw(thread, regs.TLS()+thread.BinInfo().GStructOffset(), int64(thread.BinInfo().Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newGVariable(thread, uintptr(gaddr), thread.BinInfo().Arch.DerefTLS())
|
return newGVariable(thread, gaddr, thread.BinInfo().Arch.DerefTLS())
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
|
func newGVariable(thread Thread, gaddr uint64, deref bool) (*Variable, error) {
|
||||||
typ, err := thread.BinInfo().findType("runtime.g")
|
typ, err := thread.BinInfo().findType("runtime.g")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -567,15 +567,15 @@ func globalScope(bi *BinaryInfo, image *Image, mem MemoryReadWriter) *EvalScope
|
|||||||
return &EvalScope{Location: Location{}, Regs: op.DwarfRegisters{StaticBase: image.StaticBase}, Mem: mem, g: nil, BinInfo: bi, frameOffset: 0}
|
return &EvalScope{Location: Location{}, Regs: op.DwarfRegisters{StaticBase: image.StaticBase}, Mem: mem, g: nil, BinInfo: bi, frameOffset: 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVariableFromThread(t Thread, name string, addr uintptr, dwarfType godwarf.Type) *Variable {
|
func newVariableFromThread(t Thread, name string, addr uint64, dwarfType godwarf.Type) *Variable {
|
||||||
return newVariable(name, addr, dwarfType, t.BinInfo(), t)
|
return newVariable(name, addr, dwarfType, t.BinInfo(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Variable) newVariable(name string, addr uintptr, dwarfType godwarf.Type, mem MemoryReadWriter) *Variable {
|
func (v *Variable) newVariable(name string, addr uint64, dwarfType godwarf.Type, mem MemoryReadWriter) *Variable {
|
||||||
return newVariable(name, addr, dwarfType, v.bi, mem)
|
return newVariable(name, addr, dwarfType, v.bi, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVariable(name string, addr uintptr, dwarfType godwarf.Type, bi *BinaryInfo, mem MemoryReadWriter) *Variable {
|
func newVariable(name string, addr uint64, dwarfType godwarf.Type, bi *BinaryInfo, mem MemoryReadWriter) *Variable {
|
||||||
if styp, isstruct := dwarfType.(*godwarf.StructType); isstruct && !strings.Contains(styp.Name, "<") && !strings.Contains(styp.Name, "{") {
|
if styp, isstruct := dwarfType.(*godwarf.StructType); isstruct && !strings.Contains(styp.Name, "<") && !strings.Contains(styp.Name, "{") {
|
||||||
// For named structs the compiler will emit a DW_TAG_structure_type entry
|
// For named structs the compiler will emit a DW_TAG_structure_type entry
|
||||||
// and a DW_TAG_typedef entry.
|
// and a DW_TAG_typedef entry.
|
||||||
@ -625,8 +625,7 @@ func newVariable(name string, addr uintptr, dwarfType godwarf.Type, bi *BinaryIn
|
|||||||
v.Kind = reflect.String
|
v.Kind = reflect.String
|
||||||
}
|
}
|
||||||
if v.Addr != 0 {
|
if v.Addr != 0 {
|
||||||
n, err := readUintRaw(v.mem, v.Addr, int64(v.bi.Arch.PtrSize()))
|
v.Base, v.Unreadable = readUintRaw(v.mem, v.Addr, int64(v.bi.Arch.PtrSize()))
|
||||||
v.Base, v.Unreadable = uintptr(n), err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *godwarf.ChanType:
|
case *godwarf.ChanType:
|
||||||
@ -778,7 +777,7 @@ func (v *Variable) toField(field *godwarf.StructField) (*Variable, error) {
|
|||||||
name = fmt.Sprintf("%s.%s", v.Name, field.Name)
|
name = fmt.Sprintf("%s.%s", v.Name, field.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return v.newVariable(name, uintptr(int64(v.Addr)+field.ByteOffset), field.Type, v.mem), nil
|
return v.newVariable(name, uint64(int64(v.Addr)+field.ByteOffset), field.Type, v.mem), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrNoGoroutine returned when a G could not be found
|
// ErrNoGoroutine returned when a G could not be found
|
||||||
@ -800,7 +799,7 @@ func (v *Variable) parseG() (*G, error) {
|
|||||||
|
|
||||||
if deref {
|
if deref {
|
||||||
var err error
|
var err error
|
||||||
gaddr, err = readUintRaw(mem, uintptr(gaddr), int64(v.bi.Arch.PtrSize()))
|
gaddr, err = readUintRaw(mem, gaddr, int64(v.bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error derefing *G %s", err)
|
return nil, fmt.Errorf("error derefing *G %s", err)
|
||||||
}
|
}
|
||||||
@ -1148,7 +1147,7 @@ func extractVarInfoFromEntry(bi *BinaryInfo, image *Image, regs op.DwarfRegister
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v := newVariable(n, uintptr(addr), t, bi, mem)
|
v := newVariable(n, uint64(addr), t, bi, mem)
|
||||||
if pieces != nil {
|
if pieces != nil {
|
||||||
v.Flags |= VariableFakeAddress
|
v.Flags |= VariableFakeAddress
|
||||||
}
|
}
|
||||||
@ -1172,8 +1171,8 @@ func (v *Variable) maybeDereference() *Variable {
|
|||||||
// fake pointer variable constructed by casting an integer to a pointer type
|
// fake pointer variable constructed by casting an integer to a pointer type
|
||||||
return &v.Children[0]
|
return &v.Children[0]
|
||||||
}
|
}
|
||||||
ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize)
|
ptrval, err := readUintRaw(v.mem, v.Addr, t.ByteSize)
|
||||||
r := v.newVariable("", uintptr(ptrval), t.Type, DereferenceMemory(v.mem))
|
r := v.newVariable("", ptrval, t.Type, DereferenceMemory(v.mem))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Unreadable = err
|
r.Unreadable = err
|
||||||
}
|
}
|
||||||
@ -1341,14 +1340,14 @@ func convertToEface(srcv, dstv *Variable) error {
|
|||||||
return dstv.writeEmptyInterface(typeAddr, srcv)
|
return dstv.writeEmptyInterface(typeAddr, srcv)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readStringInfo(mem MemoryReadWriter, arch *Arch, addr uintptr) (uintptr, int64, error) {
|
func readStringInfo(mem MemoryReadWriter, arch *Arch, addr uint64) (uint64, int64, error) {
|
||||||
// string data structure is always two ptrs in size. Addr, followed by len
|
// string data structure is always two ptrs in size. Addr, followed by len
|
||||||
// http://research.swtch.com/godata
|
// http://research.swtch.com/godata
|
||||||
|
|
||||||
mem = cacheMemory(mem, addr, arch.PtrSize()*2)
|
mem = cacheMemory(mem, addr, arch.PtrSize()*2)
|
||||||
|
|
||||||
// read len
|
// read len
|
||||||
strlen, err := readIntRaw(mem, addr+uintptr(arch.PtrSize()), int64(arch.PtrSize()))
|
strlen, err := readIntRaw(mem, addr+uint64(arch.PtrSize()), int64(arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, fmt.Errorf("could not read string len %s", err)
|
return 0, 0, fmt.Errorf("could not read string len %s", err)
|
||||||
}
|
}
|
||||||
@ -1357,18 +1356,17 @@ func readStringInfo(mem MemoryReadWriter, arch *Arch, addr uintptr) (uintptr, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read addr
|
// read addr
|
||||||
val, err := readUintRaw(mem, addr, int64(arch.PtrSize()))
|
addr, err = readUintRaw(mem, addr, int64(arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, fmt.Errorf("could not read string pointer %s", err)
|
return 0, 0, fmt.Errorf("could not read string pointer %s", err)
|
||||||
}
|
}
|
||||||
addr = uintptr(val)
|
|
||||||
if addr == 0 {
|
if addr == 0 {
|
||||||
return 0, 0, nil
|
return 0, 0, nil
|
||||||
}
|
}
|
||||||
return addr, strlen, nil
|
return addr, strlen, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readStringValue(mem MemoryReadWriter, addr uintptr, strlen int64, cfg LoadConfig) (string, error) {
|
func readStringValue(mem MemoryReadWriter, addr uint64, strlen int64, cfg LoadConfig) (string, error) {
|
||||||
if strlen == 0 {
|
if strlen == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@ -1387,7 +1385,7 @@ func readStringValue(mem MemoryReadWriter, addr uintptr, strlen int64, cfg LoadC
|
|||||||
return string(val), nil
|
return string(val), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readCStringValue(mem MemoryReadWriter, addr uintptr, cfg LoadConfig) (string, bool, error) {
|
func readCStringValue(mem MemoryReadWriter, addr uint64, cfg LoadConfig) (string, bool, error) {
|
||||||
buf := make([]byte, cfg.MaxStringLen) //
|
buf := make([]byte, cfg.MaxStringLen) //
|
||||||
val := buf[:0] // part of the string we've already read
|
val := buf[:0] // part of the string we've already read
|
||||||
|
|
||||||
@ -1399,7 +1397,7 @@ func readCStringValue(mem MemoryReadWriter, addr uintptr, cfg LoadConfig) (strin
|
|||||||
// memory we don't even need.
|
// memory we don't even need.
|
||||||
// We don't know how big a page is but 1024 is a reasonable minimum common
|
// We don't know how big a page is but 1024 is a reasonable minimum common
|
||||||
// divisor for all architectures.
|
// divisor for all architectures.
|
||||||
curaddr := addr + uintptr(len(val))
|
curaddr := addr + uint64(len(val))
|
||||||
maxsize := int(alignAddr(int64(curaddr+1), 1024) - int64(curaddr))
|
maxsize := int(alignAddr(int64(curaddr+1), 1024) - int64(curaddr))
|
||||||
size := len(buf)
|
size := len(buf)
|
||||||
if size > maxsize {
|
if size > maxsize {
|
||||||
@ -1444,9 +1442,9 @@ func (v *Variable) loadSliceInfo(t *godwarf.SliceType) {
|
|||||||
switch f.Name {
|
switch f.Name {
|
||||||
case sliceArrayFieldName:
|
case sliceArrayFieldName:
|
||||||
var base uint64
|
var base uint64
|
||||||
base, err = readUintRaw(v.mem, uintptr(int64(v.Addr)+f.ByteOffset), f.Type.Size())
|
base, err = readUintRaw(v.mem, uint64(int64(v.Addr)+f.ByteOffset), f.Type.Size())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
v.Base = uintptr(base)
|
v.Base = base
|
||||||
// Dereference array type to get value type
|
// Dereference array type to get value type
|
||||||
ptrType, ok := f.Type.(*godwarf.PtrType)
|
ptrType, ok := f.Type.(*godwarf.PtrType)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -1560,7 +1558,7 @@ func (v *Variable) loadArrayValues(recurseLevel int, cfg LoadConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := int64(0); i < count; i++ {
|
for i := int64(0); i < count; i++ {
|
||||||
fieldvar := v.newVariable("", uintptr(int64(v.Base)+(i*v.stride)), v.fieldType, mem)
|
fieldvar := v.newVariable("", uint64(int64(v.Base)+(i*v.stride)), v.fieldType, mem)
|
||||||
fieldvar.loadValueInternal(recurseLevel+1, cfg)
|
fieldvar.loadValueInternal(recurseLevel+1, cfg)
|
||||||
|
|
||||||
if fieldvar.Unreadable != nil {
|
if fieldvar.Unreadable != nil {
|
||||||
@ -1589,7 +1587,7 @@ func (v *Variable) readComplex(size int64) {
|
|||||||
ftyp := &godwarf.FloatType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: fs, Name: fmt.Sprintf("float%d", fs)}, BitSize: fs * 8, BitOffset: 0}}
|
ftyp := &godwarf.FloatType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: fs, Name: fmt.Sprintf("float%d", fs)}, BitSize: fs * 8, BitOffset: 0}}
|
||||||
|
|
||||||
realvar := v.newVariable("real", v.Addr, ftyp, v.mem)
|
realvar := v.newVariable("real", v.Addr, ftyp, v.mem)
|
||||||
imagvar := v.newVariable("imaginary", v.Addr+uintptr(fs), ftyp, v.mem)
|
imagvar := v.newVariable("imaginary", v.Addr+uint64(fs), ftyp, v.mem)
|
||||||
realvar.loadValue(loadSingleValue)
|
realvar.loadValue(loadSingleValue)
|
||||||
imagvar.loadValue(loadSingleValue)
|
imagvar.loadValue(loadSingleValue)
|
||||||
v.Value = constant.BinaryOp(realvar.Value, token.ADD, constant.MakeImag(imagvar.Value))
|
v.Value = constant.BinaryOp(realvar.Value, token.ADD, constant.MakeImag(imagvar.Value))
|
||||||
@ -1601,11 +1599,11 @@ func (v *Variable) writeComplex(real, imag float64, size int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
imagaddr := *v
|
imagaddr := *v
|
||||||
imagaddr.Addr += uintptr(size / 2)
|
imagaddr.Addr += uint64(size / 2)
|
||||||
return imagaddr.writeFloatRaw(imag, int64(size/2))
|
return imagaddr.writeFloatRaw(imag, int64(size/2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func readIntRaw(mem MemoryReadWriter, addr uintptr, size int64) (int64, error) {
|
func readIntRaw(mem MemoryReadWriter, addr uint64, size int64) (int64, error) {
|
||||||
var n int64
|
var n int64
|
||||||
|
|
||||||
val := make([]byte, int(size))
|
val := make([]byte, int(size))
|
||||||
@ -1646,7 +1644,7 @@ func (v *Variable) writeUint(value uint64, size int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func readUintRaw(mem MemoryReadWriter, addr uintptr, size int64) (uint64, error) {
|
func readUintRaw(mem MemoryReadWriter, addr uint64, size int64) (uint64, error) {
|
||||||
var n uint64
|
var n uint64
|
||||||
|
|
||||||
val := make([]byte, int(size))
|
val := make([]byte, int(size))
|
||||||
@ -1731,7 +1729,7 @@ func (v *Variable) writeEmptyInterface(typeAddr uint64, data *Variable) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Variable) writeSlice(len, cap int64, base uintptr) error {
|
func (v *Variable) writeSlice(len, cap int64, base uint64) error {
|
||||||
for _, f := range v.RealType.(*godwarf.SliceType).Field {
|
for _, f := range v.RealType.(*godwarf.SliceType).Field {
|
||||||
switch f.Name {
|
switch f.Name {
|
||||||
case sliceArrayFieldName:
|
case sliceArrayFieldName:
|
||||||
@ -1782,13 +1780,13 @@ func (v *Variable) readFunctionPtr() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val, err := readUintRaw(v.mem, uintptr(v.closureAddr), int64(v.bi.Arch.PtrSize()))
|
val, err := readUintRaw(v.mem, v.closureAddr, int64(v.bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.Unreadable = err
|
v.Unreadable = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Base = uintptr(val)
|
v.Base = val
|
||||||
fn := v.bi.PCToFunc(uint64(v.Base))
|
fn := v.bi.PCToFunc(uint64(v.Base))
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
v.Unreadable = fmt.Errorf("could not find function for %#v", v.Base)
|
v.Unreadable = fmt.Errorf("could not find function for %#v", v.Base)
|
||||||
@ -1949,7 +1947,7 @@ func (it *mapIterator) nextBucket() bool {
|
|||||||
|
|
||||||
for it.bidx < it.numbuckets {
|
for it.bidx < it.numbuckets {
|
||||||
it.b = it.buckets.clone()
|
it.b = it.buckets.clone()
|
||||||
it.b.Addr += uintptr(uint64(it.buckets.DwarfType.Size()) * it.bidx)
|
it.b.Addr += uint64(it.buckets.DwarfType.Size()) * it.bidx
|
||||||
|
|
||||||
if it.oldbuckets.Addr <= 0 {
|
if it.oldbuckets.Addr <= 0 {
|
||||||
break
|
break
|
||||||
@ -1965,7 +1963,7 @@ func (it *mapIterator) nextBucket() bool {
|
|||||||
|
|
||||||
oldbidx := it.bidx & it.oldmask
|
oldbidx := it.bidx & it.oldmask
|
||||||
oldb := it.oldbuckets.clone()
|
oldb := it.oldbuckets.clone()
|
||||||
oldb.Addr += uintptr(uint64(it.oldbuckets.DwarfType.Size()) * oldbidx)
|
oldb.Addr += uint64(it.oldbuckets.DwarfType.Size()) * oldbidx
|
||||||
|
|
||||||
if it.mapEvacuated(oldb) {
|
if it.mapEvacuated(oldb) {
|
||||||
break
|
break
|
||||||
|
|||||||
@ -110,7 +110,7 @@ func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool
|
|||||||
if err1 != nil || err2 != nil {
|
if err1 != nil || err2 != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
addr := uintptr(int64(base) + int64(index*uint64(arg.Scale)) + arg.Disp)
|
addr := uint64(int64(base) + int64(index*uint64(arg.Scale)) + arg.Disp)
|
||||||
pc, err = readUintRaw(mem, addr, int64(inst.MemBytes))
|
pc, err = readUintRaw(mem, addr, int64(inst.MemBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -1555,7 +1555,7 @@ func examineMemoryCmd(t *Term, ctx callContext, args string) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
var (
|
var (
|
||||||
address int64
|
address uint64
|
||||||
err error
|
err error
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
@ -1604,7 +1604,7 @@ func examineMemoryCmd(t *Term, ctx callContext, args string) error {
|
|||||||
return fmt.Errorf("unknown option %q", v[i])
|
return fmt.Errorf("unknown option %q", v[i])
|
||||||
}
|
}
|
||||||
// TODO, maybe we can support expression.
|
// TODO, maybe we can support expression.
|
||||||
address, err = strconv.ParseInt(v[len(v)-1], 0, 64)
|
address, err = strconv.ParseUint(v[len(v)-1], 0, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("convert address into uintptr type failed, %s", err)
|
return fmt.Errorf("convert address into uintptr type failed, %s", err)
|
||||||
}
|
}
|
||||||
@ -1615,7 +1615,7 @@ func examineMemoryCmd(t *Term, ctx callContext, args string) error {
|
|||||||
return fmt.Errorf("no address specified")
|
return fmt.Errorf("no address specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
memArea, err := t.client.ExamineMemory(uintptr(address), length)
|
memArea, err := t.client.ExamineMemory(address, length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -240,7 +240,7 @@ type Variable struct {
|
|||||||
// Name of the variable or struct member
|
// Name of the variable or struct member
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Address of the variable or struct member
|
// Address of the variable or struct member
|
||||||
Addr uintptr `json:"addr"`
|
Addr uint64 `json:"addr"`
|
||||||
// Only the address field is filled (result of evaluating expressions like &<expr>)
|
// Only the address field is filled (result of evaluating expressions like &<expr>)
|
||||||
OnlyAddr bool `json:"onlyAddr"`
|
OnlyAddr bool `json:"onlyAddr"`
|
||||||
// Go type of the variable
|
// Go type of the variable
|
||||||
@ -272,7 +272,7 @@ type Variable struct {
|
|||||||
// Base address of the backing byte array for strings
|
// Base address of the backing byte array for strings
|
||||||
// address of the struct backing chan and map variables
|
// address of the struct backing chan and map variables
|
||||||
// address of the function entry point for function variables (0 for nil function pointers)
|
// address of the function entry point for function variables (0 for nil function pointers)
|
||||||
Base uintptr `json:"base"`
|
Base uint64 `json:"base"`
|
||||||
|
|
||||||
// Unreadable addresses will have this field set
|
// Unreadable addresses will have this field set
|
||||||
Unreadable string `json:"unreadable"`
|
Unreadable string `json:"unreadable"`
|
||||||
|
|||||||
@ -160,7 +160,7 @@ type Client interface {
|
|||||||
// ExamineMemory returns the raw memory stored at the given address.
|
// ExamineMemory returns the raw memory stored at the given address.
|
||||||
// The amount of data to be read is specified by length which must be less than or equal to 1000.
|
// The amount of data to be read is specified by length which must be less than or equal to 1000.
|
||||||
// This function will return an error if it reads less than `length` bytes.
|
// This function will return an error if it reads less than `length` bytes.
|
||||||
ExamineMemory(address uintptr, length int) ([]byte, error)
|
ExamineMemory(address uint64, length int) ([]byte, error)
|
||||||
|
|
||||||
// StopRecording stops a recording if one is in progress.
|
// StopRecording stops a recording if one is in progress.
|
||||||
StopRecording() error
|
StopRecording() error
|
||||||
|
|||||||
@ -1604,7 +1604,7 @@ func (d *Debugger) ListDynamicLibraries() []api.Image {
|
|||||||
// ExamineMemory returns the raw memory stored at the given address.
|
// ExamineMemory returns the raw memory stored at the given address.
|
||||||
// The amount of data to be read is specified by length.
|
// The amount of data to be read is specified by length.
|
||||||
// This function will return an error if it reads less than `length` bytes.
|
// This function will return an error if it reads less than `length` bytes.
|
||||||
func (d *Debugger) ExamineMemory(address uintptr, length int) ([]byte, error) {
|
func (d *Debugger) ExamineMemory(address uint64, length int) ([]byte, error) {
|
||||||
d.targetMutex.Lock()
|
d.targetMutex.Lock()
|
||||||
defer d.targetMutex.Unlock()
|
defer d.targetMutex.Unlock()
|
||||||
|
|
||||||
|
|||||||
@ -441,7 +441,7 @@ func (c *RPCClient) ListDynamicLibraries() ([]api.Image, error) {
|
|||||||
return out.List, nil
|
return out.List, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RPCClient) ExamineMemory(address uintptr, count int) ([]byte, error) {
|
func (c *RPCClient) ExamineMemory(address uint64, count int) ([]byte, error) {
|
||||||
out := &ExaminedMemoryOut{}
|
out := &ExaminedMemoryOut{}
|
||||||
|
|
||||||
err := c.call("ExamineMemory", ExamineMemoryIn{Length: count, Address: address}, out)
|
err := c.call("ExamineMemory", ExamineMemoryIn{Length: count, Address: address}, out)
|
||||||
|
|||||||
@ -766,7 +766,7 @@ func (s *RPCServer) ListPackagesBuildInfo(in ListPackagesBuildInfoIn, out *ListP
|
|||||||
|
|
||||||
// ExamineMemoryIn holds the arguments of ExamineMemory
|
// ExamineMemoryIn holds the arguments of ExamineMemory
|
||||||
type ExamineMemoryIn struct {
|
type ExamineMemoryIn struct {
|
||||||
Address uintptr
|
Address uint64
|
||||||
Length int
|
Length int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user