Repository: go-delve/delve
Pull request #2167 (2020-09-08 14:28:37)

service/dap: pull in newer version of google/go-dap
Pulls in v0.3.0 of google/go-dap; this version has some fixes and API
improvements which service/dap will be able to leverage to clean up some
code.

Note: I ran `go mod vendor` after changing the version in `go.mod`. I tried running `make vendor` but that command failed with `error executing go [list -mod=vendor ./...]`. 


Patch:
diff --git a/.travis.yml b/.travis.yml
index 496044c8..cb7c8254 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -53,7 +53,7 @@ jobs:
   include:
     -  os: linux
        services: docker
-       env: go_32_version=1.14 # Linux/i386 tests held back to Go1.14 until issue #2134 is fixed
+       env: go_32_version=1.15.2 # Linux/i386 tests will fail on go1.15 prior to 1.15.2 (see issue #2134)
 
 script: >-
     if [ $TRAVIS_OS_NAME = "linux" ] && [ $go_32_version ]; then
diff --git a/Documentation/cli/README.md b/Documentation/cli/README.md
index 89e5691c..1f6022eb 100644
--- a/Documentation/cli/README.md
+++ b/Documentation/cli/README.md
@@ -259,15 +259,15 @@ Aliases: ed
 ## examinemem
 Examine memory:
 
-	examinemem [-fmt <format>] [-len <length>] <address>
+	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
 
-Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
+Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal), addr(address).
 Length is the number of bytes (default 1) and must be less than or equal to 1000.
-Address is the memory location of the target to examine.
+Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'.
 
 For example:
 
-    x -fmt hex -len 20 0xc00008af38
+    x -fmt hex -count 20 -size 1 0xc00008af38
 
 Aliases: x
 
diff --git a/_fixtures/issue2162.go b/_fixtures/issue2162.go
new file mode 100644
index 00000000..5b579031
--- /dev/null
+++ b/_fixtures/issue2162.go
@@ -0,0 +1,7 @@
+package main
+
+import "fmt"
+
+func main() {
+	fmt.Println("test dlv")
+}
diff --git a/_scripts/gen-travis.go b/_scripts/gen-travis.go
index 7e5be0ad..607e8306 100644
--- a/_scripts/gen-travis.go
+++ b/_scripts/gen-travis.go
@@ -112,7 +112,7 @@ jobs:
   include:
     -  os: linux
        services: docker
-       env: go_32_version={{index .GoVersions 1}} # Linux/i386 tests held back to Go1.14 until issue #2134 is fixed
+       env: go_32_version={{index .GoVersions 0}}.2 # Linux/i386 tests will fail on go1.15 prior to 1.15.2 (see issue #2134)
 
 script: >-
     if [ $TRAVIS_OS_NAME = "linux" ] && [ $go_32_version ]; then
diff --git a/go.mod b/go.mod
index f473794e..06b2af29 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
 	github.com/cosiner/argv v0.1.0
 	github.com/cpuguy83/go-md2man v1.0.10 // indirect
 	github.com/creack/pty v1.1.9
-	github.com/google/go-dap v0.2.0
+	github.com/google/go-dap v0.3.0
 	github.com/hashicorp/golang-lru v0.5.4
 	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 	github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561
diff --git a/go.sum b/go.sum
index 6e15ea3d..bc95a8a6 100644
--- a/go.sum
+++ b/go.sum
@@ -14,6 +14,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/google/go-dap v0.2.0 h1:whjIGQRumwbR40qRU7CEKuFLmePUUc2s4Nt9DoXXxWk=
 github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
+github.com/google/go-dap v0.3.0 h1:Dc4izN0u4VhZERYrz80f1PSEoDsVfdVmdM/W82CxzFk=
+github.com/google/go-dap v0.3.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
diff --git a/pkg/proc/amd64_arch.go b/pkg/proc/amd64_arch.go
index 5ac81024..fc914269 100644
--- a/pkg/proc/amd64_arch.go
+++ b/pkg/proc/amd64_arch.go
@@ -142,7 +142,7 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
 		// switches from the goroutine stack to the system stack.
 		// Since we are unwinding the stack from callee to caller we have to switch
 		// 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()
 		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
 		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.top = false
@@ -183,7 +183,7 @@ func amd64SwitchStack(it *stackIterator, _ *op.DwarfRegisters) bool {
 		// entering the system stack
 		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
-		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
 		callFrameRegs, ret, retaddr := it.advanceRegs()
 		frameOnSystemStack := it.newStackframe(ret, retaddr)
diff --git a/pkg/proc/arm64_arch.go b/pkg/proc/arm64_arch.go
index 5f2bb165..efa994ef 100644
--- a/pkg/proc/arm64_arch.go
+++ b/pkg/proc/arm64_arch.go
@@ -146,9 +146,9 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
 			return true
 		case "crosscall2":
 			//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()))
-			newbp, _ := readUintRaw(it.mem, uintptr(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()))
+			newsp, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*24), int64(it.bi.Arch.PtrSize()))
+			newbp, _ := readUintRaw(it.mem, uint64(it.regs.SP()+8*14), 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 {
 				it.regs.Reg(it.regs.BPRegNum).Uint64Val = uint64(newbp)
 			} else {
@@ -188,7 +188,7 @@ func arm64SwitchStack(it *stackIterator, callFrameRegs *op.DwarfRegisters) bool
 		// switches from the goroutine stack to the system stack.
 		// Since we are unwinding the stack from callee to caller we have to switch
 		// 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()
 		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
 		// 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
 		return false
 	}
diff --git a/pkg/proc/bininfo.go b/pkg/proc/bininfo.go
index 1acae9c7..d97251ff 100644
--- a/pkg/proc/bininfo.go
+++ b/pkg/proc/bininfo.go
@@ -93,7 +93,7 @@ type BinaryInfo struct {
 	// 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
 	// 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 constantsMap
@@ -425,7 +425,7 @@ type ElfDynamicSection struct {
 
 // NewBinaryInfo returns an initialized but unloaded BinaryInfo struct.
 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).
 	switch goarch {
diff --git a/pkg/proc/core/core.go b/pkg/proc/core/core.go
index 984ffdf3..abb05b78 100644
--- a/pkg/proc/core/core.go
+++ b/pkg/proc/core/core.go
@@ -26,13 +26,13 @@ type splicedMemory struct {
 }
 
 type readerEntry struct {
-	offset uintptr
-	length uintptr
+	offset uint64
+	length uint64
 	reader proc.MemoryReader
 }
 
 // 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 {
 		return
 	}
@@ -92,7 +92,7 @@ func (r *splicedMemory) Add(reader proc.MemoryReader, off, length uintptr) {
 }
 
 // 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
 	for _, entry := range r.readers {
 		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.
 		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]
 		}
 		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
 		}
 		buf = buf[pn:]
-		addr += uintptr(pn)
+		addr += uint64(pn)
 		if len(buf) == 0 {
 			// Done, don't bother scanning the rest.
 			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.
 type offsetReaderAt struct {
 	reader io.ReaderAt
-	offset uintptr
+	offset uint64
 }
 
 // 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))
 }
 
@@ -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
 // 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.
-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)
 	if err == nil && n != len(data) {
 		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
 // 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
 }
 
diff --git a/pkg/proc/core/linux_core.go b/pkg/proc/core/linux_core.go
index 35f6f6b6..77c5e108 100644
--- a/pkg/proc/core/linux_core.go
+++ b/pkg/proc/core/linux_core.go
@@ -326,9 +326,9 @@ func buildMemory(core, exeELF *elf.File, exe io.ReaderAt, notes []*note) proc.Me
 			for _, entry := range fileNote.entries {
 				r := &offsetReaderAt{
 					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{
 					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)
 			}
 		}
 	}
diff --git a/pkg/proc/core/minidump/minidump.go b/pkg/proc/core/minidump/minidump.go
index b3446741..9348f3cf 100644
--- a/pkg/proc/core/minidump/minidump.go
+++ b/pkg/proc/core/minidump/minidump.go
@@ -182,7 +182,7 @@ type MemoryRange struct {
 }
 
 // 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 {
 		return 0, nil
 	}
diff --git a/pkg/proc/core/windows_amd64_minidump.go b/pkg/proc/core/windows_amd64_minidump.go
index 31879e49..554a66f4 100644
--- a/pkg/proc/core/windows_amd64_minidump.go
+++ b/pkg/proc/core/windows_amd64_minidump.go
@@ -25,7 +25,7 @@ func readAMD64Minidump(minidumpPath, exePath string) (*process, error) {
 
 	for i := range mdmp.MemoryRanges {
 		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)
diff --git a/pkg/proc/disasm.go b/pkg/proc/disasm.go
index 06f4b1ae..94477990 100644
--- a/pkg/proc/disasm.go
+++ b/pkg/proc/disasm.go
@@ -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) {
 	mem := make([]byte, int(endAddr-startAddr))
-	_, err := memrw.ReadMemory(mem, uintptr(startAddr))
+	_, err := memrw.ReadMemory(mem, startAddr)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go
index 74221b95..83a16b10 100644
--- a/pkg/proc/eval.go
+++ b/pkg/proc/eval.go
@@ -123,7 +123,7 @@ func FrameToScope(bi *BinaryInfo, thread MemoryReadWriter, g *G, frames ...Stack
 		maxaddr = uint64(frames[0].Regs.CFA)
 	}
 	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()}
@@ -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 {
 			addr := afterLastArgAddr(vars)
 			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)
 		}
 		vars = append(vars, val)
@@ -288,11 +288,11 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
 	return vars, nil
 }
 
-func afterLastArgAddr(vars []*Variable) uintptr {
+func afterLastArgAddr(vars []*Variable) uint64 {
 	for i := len(vars) - 1; i >= 0; i-- {
 		v := vars[i]
 		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
@@ -520,9 +520,9 @@ func (scope *EvalScope) findGlobalInternal(name string) (*Variable, error) {
 	for _, fn := range scope.BinInfo.Functions {
 		if fn.Name == name || strings.HasSuffix(fn.Name, "/"+name) {
 			//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.Base = uintptr(fn.Entry)
+			r.Base = fn.Entry
 			r.loaded = true
 			if fn.Entry == 0 {
 				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
 		}
 		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.Value = constant.MakeInt64(int64(ch))
 			v.Children = append(v.Children, *e)
@@ -640,7 +640,7 @@ func (scope *EvalScope) evalToplevelTypeCast(t ast.Expr, cfg LoadConfig) (*Varia
 			return nil, converr
 		}
 		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.Value = constant.MakeInt64(int64(ch))
 			v.Children = append(v.Children, *e)
@@ -854,7 +854,7 @@ func (scope *EvalScope) evalTypeCast(node *ast.CallExpr) (*Variable, error) {
 
 		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
 		return v, nil
 
@@ -1885,7 +1885,7 @@ func (v *Variable) sliceAccess(idx int) (*Variable, error) {
 	if v.Kind != reflect.Array {
 		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) {
@@ -1938,7 +1938,7 @@ func (v *Variable) reslice(low int64, high int64) (*Variable, error) {
 		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
 
 	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.Value = constant.MakeString(fn.Name)
 	v.loaded = true
-	v.Base = uintptr(fn.Entry)
+	v.Base = fn.Entry
 	return v, nil
 }
 
diff --git a/pkg/proc/fncall.go b/pkg/proc/fncall.go
index 374549d1..0933f947 100644
--- a/pkg/proc/fncall.go
+++ b/pkg/proc/fncall.go
@@ -407,7 +407,7 @@ func writePointer(bi *BinaryInfo, mem MemoryReadWriter, addr, val uint64) error
 	default:
 		panic(fmt.Errorf("unsupported pointer size %d", len(ptrbuf)))
 	}
-	_, err := mem.WriteMemory(uintptr(addr), ptrbuf)
+	_, err := mem.WriteMemory(addr, ptrbuf)
 	return err
 }
 
@@ -555,7 +555,7 @@ func funcCallCopyOneArg(scope *EvalScope, fncall *functionCallState, actualArg *
 	//TODO(aarzilli): autmoatic wrapping in interfaces for cases not handled
 	// 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 {
 		return err
 	}
@@ -671,7 +671,7 @@ func escapeCheck(v *Variable, name string, stack stack) error {
 			}
 		}
 	case reflect.Func:
-		if err := escapeCheckPointer(uintptr(v.funcvalAddr()), name, stack); err != nil {
+		if err := escapeCheckPointer(v.funcvalAddr(), name, stack); err != nil {
 			return err
 		}
 	}
@@ -679,7 +679,7 @@ func escapeCheck(v *Variable, name string, stack stack) error {
 	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 {
 		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 {
 		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)
 	if v.Unreadable != nil {
 		return nil, v.Unreadable
@@ -932,7 +932,7 @@ func allocString(scope *EvalScope, v *Variable) error {
 	if len(mallocv.Children) != 1 {
 		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)))
 	return err
 }
diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go
index 2ff9bedc..26883047 100644
--- a/pkg/proc/gdbserial/gdbserver.go
+++ b/pkg/proc/gdbserial/gdbserver.go
@@ -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
 	// overwrite some existing memory to store the MOV.
 	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
 		}
 	}
@@ -1260,7 +1260,7 @@ func (p *gdbProcess) setCurrentBreakpoints() error {
 }
 
 // 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)
 	if err != nil {
 		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.
-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)
 }
 
@@ -1517,18 +1517,18 @@ func (t *gdbThread) reloadGAtPC() error {
 	}
 
 	savedcode := make([]byte, len(movinstr))
-	_, err := t.ReadMemory(savedcode, uintptr(pc))
+	_, err := t.ReadMemory(savedcode, pc)
 	if err != nil {
 		return err
 	}
 
-	_, err = t.WriteMemory(uintptr(pc), movinstr)
+	_, err = t.WriteMemory(pc, movinstr)
 	if err != nil {
 		return err
 	}
 
 	defer func() {
-		_, err0 := t.WriteMemory(uintptr(pc), savedcode)
+		_, err0 := t.WriteMemory(pc, savedcode)
 		if err == nil {
 			err = err0
 		}
diff --git a/pkg/proc/gdbserial/gdbserver_conn.go b/pkg/proc/gdbserial/gdbserver_conn.go
index 1186893d..fbd3aea5 100644
--- a/pkg/proc/gdbserial/gdbserver_conn.go
+++ b/pkg/proc/gdbserial/gdbserver_conn.go
@@ -880,7 +880,7 @@ func (conn *gdbConn) appendThreadSelector(threadID string) {
 }
 
 // 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)
 	data = data[:0]
 
@@ -894,7 +894,7 @@ func (conn *gdbConn) readMemory(data []byte, addr uintptr) error {
 		}
 		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")
 		if err != nil {
 			return err
@@ -915,7 +915,7 @@ func writeAsciiBytes(w io.Writer, data []byte) {
 }
 
 // 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 {
 		// LLDB can't parse requests for 0-length writes and hangs if we emit them
 		return 0, nil
@@ -1084,14 +1084,14 @@ func (conn *gdbConn) recv(cmd []byte, context string, binary bool) (resp []byte,
 		}
 
 		// read checksum
-		_, err = conn.rdr.Read(conn.inbuf[:2])
+		_, err = io.ReadFull(conn.rdr, conn.inbuf[:2])
 		if err != nil {
 			return nil, err
 		}
 		if logflags.GdbWire() {
 			out := resp
 			partial := false
-			if idx := bytes.Index(out, []byte{'\n'}); idx >= 0 {
+			if idx := bytes.Index(out, []byte{'\n'}); idx >= 0 && !binary {
 				out = resp[:idx]
 				partial = true
 			}
@@ -1100,9 +1100,17 @@ func (conn *gdbConn) recv(cmd []byte, context string, binary bool) (resp []byte,
 				partial = true
 			}
 			if !partial {
-				conn.log.Debugf("-> %s%s", string(resp), string(conn.inbuf[:2]))
+				if binary {
+					conn.log.Debugf("-> %q%s", string(resp), string(conn.inbuf[:2]))
+				} else {
+					conn.log.Debugf("-> %s%s", string(resp), string(conn.inbuf[:2]))
+				}
 			} else {
-				conn.log.Debugf("-> %s...", string(out))
+				if binary {
+					conn.log.Debugf("-> %q...", string(out))
+				} else {
+					conn.log.Debugf("-> %s...", string(out))
+				}
 			}
 		}
 
@@ -1136,7 +1144,7 @@ func (conn *gdbConn) recv(cmd []byte, context string, binary bool) (resp []byte,
 		conn.inbuf, resp = wiredecode(resp, conn.inbuf)
 	}
 
-	if len(resp) == 0 || resp[0] == 'E' {
+	if len(resp) == 0 || (resp[0] == 'E' && !binary) || (resp[0] == 'E' && len(resp) == 3) {
 		cmdstr := ""
 		if cmd != nil {
 			cmdstr = string(cmd)
diff --git a/pkg/proc/goroutine_cache.go b/pkg/proc/goroutine_cache.go
index e81f4d2b..3e34fad9 100644
--- a/pkg/proc/goroutine_cache.go
+++ b/pkg/proc/goroutine_cache.go
@@ -27,12 +27,12 @@ func (gcache *goroutineCache) getRuntimeAllg(bi *BinaryInfo, mem MemoryReadWrite
 	if gcache.allglenAddr == 0 || gcache.allgentryAddr == 0 {
 		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 {
 		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 {
 		return 0, 0, err
 	}
diff --git a/pkg/proc/linutil/dynamic.go b/pkg/proc/linutil/dynamic.go
index 73fd34dc..46eab4db 100644
--- a/pkg/proc/linutil/dynamic.go
+++ b/pkg/proc/linutil/dynamic.go
@@ -47,7 +47,7 @@ func dynamicSearchDebug(p proc.Process) (uint64, error) {
 	mem := p.CurrentThread()
 
 	dynbuf := make([]byte, bi.ElfDynamicSection.Size)
-	_, err := mem.ReadMemory(dynbuf, uintptr(bi.ElfDynamicSection.Addr))
+	_, err := mem.ReadMemory(dynbuf, bi.ElfDynamicSection.Addr)
 	if err != nil {
 		return 0, err
 	}
@@ -73,7 +73,7 @@ func dynamicSearchDebug(p proc.Process) (uint64, error) {
 
 func readPtr(p proc.Process, addr uint64) (uint64, error) {
 	ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize())
-	_, err := p.CurrentThread().ReadMemory(ptrbuf, uintptr(addr))
+	_, err := p.CurrentThread().ReadMemory(ptrbuf, addr)
 	if err != nil {
 		return 0, err
 	}
@@ -122,7 +122,7 @@ func readCString(p proc.Process, addr uint64) (string, error) {
 		if len(r) > maxLibraryPathLength {
 			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 {
 			return "", err
 		}
diff --git a/pkg/proc/mem.go b/pkg/proc/mem.go
index d7891f48..4a795cbf 100644
--- a/pkg/proc/mem.go
+++ b/pkg/proc/mem.go
@@ -9,13 +9,13 @@ import (
 
 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.
 // 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)
+	ReadMemory(buf []byte, addr uint64) (n int, err error)
 }
 
 // MemoryReadWriter is an interface for reading or writing to
@@ -23,21 +23,21 @@ type MemoryReader interface {
 // target memory or possibly a cache.
 type MemoryReadWriter interface {
 	MemoryReader
-	WriteMemory(addr uintptr, data []byte) (written int, err error)
+	WriteMemory(addr uint64, data []byte) (written int, err error)
 }
 
 type memCache struct {
 	loaded    bool
-	cacheAddr uintptr
+	cacheAddr uint64
 	cache     []byte
 	mem       MemoryReadWriter
 }
 
-func (m *memCache) contains(addr uintptr, size int) bool {
-	return addr >= m.cacheAddr && addr <= (m.cacheAddr+uintptr(len(m.cache)-size))
+func (m *memCache) contains(addr uint64, size int) bool {
+	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.loaded {
 			_, 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)
 }
 
-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)
 }
 
-func cacheMemory(mem MemoryReadWriter, addr uintptr, size int) MemoryReadWriter {
+func cacheMemory(mem MemoryReadWriter, addr uint64, size int) MemoryReadWriter {
 	if !cacheEnabled {
 		return mem
 	}
@@ -112,23 +112,23 @@ func newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters, pieces []o
 			cmem.data = append(cmem.data, reg[:sz]...)
 		} else {
 			buf := make([]byte, piece.Size)
-			mem.ReadMemory(buf, uintptr(piece.Addr))
+			mem.ReadMemory(buf, uint64(piece.Addr))
 			cmem.data = append(cmem.data, buf...)
 		}
 	}
 	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
-	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")
 	}
-	copy(data, mem.data[addr:addr+uintptr(len(data))])
+	copy(data, mem.data[addr:addr+uint64(len(data))])
 	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
 	return 0, errors.New("can't write composite memory")
 }
diff --git a/pkg/proc/moduledata.go b/pkg/proc/moduledata.go
index 90f6e113..3eb28a2e 100644
--- a/pkg/proc/moduledata.go
+++ b/pkg/proc/moduledata.go
@@ -7,8 +7,8 @@ import (
 
 // delve counterpart to runtime.moduledata
 type moduleData struct {
-	text, etext   uintptr
-	types, etypes uintptr
+	text, etext   uint64
+	types, etypes uint64
 	typemapVar    *Variable
 }
 
@@ -44,11 +44,11 @@ func loadModuleData(bi *BinaryInfo, mem MemoryReadWriter) ([]moduleData, error)
 
 		var err error
 
-		touint := func(name string) (ret uintptr) {
+		touint := func(name string) (ret uint64) {
 			if err == nil {
 				var n uint64
 				n, err = vars[name].asUint()
-				ret = uintptr(n)
+				ret = n
 			}
 			return ret
 		}
@@ -71,7 +71,7 @@ func loadModuleData(bi *BinaryInfo, mem MemoryReadWriter) ([]moduleData, error)
 	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 {
 		if typeAddr >= mds[i].types && typeAddr < mds[i].etypes {
 			return &mds[i]
@@ -80,7 +80,7 @@ func findModuleDataForType(bi *BinaryInfo, mds []moduleData, typeAddr uintptr, m
 	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
 	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})
 		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 {
 		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
 	for _, md := range mds {
 		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)
 }
 
-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)
 	reflectOffs, err := scope.findGlobal("runtime", "reflectOffs")
 	if err != nil {
@@ -151,7 +151,7 @@ const (
 	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
 	namedata := make([]byte, 3)
 	_, 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))
 	_, err = mem.ReadMemory(rawstr, off)
-	off += uintptr(namelen)
+	off += uint64(namelen)
 	if err != nil {
 		return "", "", 0, err
 	}
@@ -182,7 +182,7 @@ func loadName(bi *BinaryInfo, addr uintptr, mem MemoryReadWriter) (name, tag str
 
 		rawstr := make([]byte, int(taglen))
 		_, err = mem.ReadMemory(rawstr, off)
-		off += uintptr(taglen)
+		off += uint64(taglen)
 		if err != nil {
 			return "", "", 0, err
 		}
diff --git a/pkg/proc/native/nonative_darwin.go b/pkg/proc/native/nonative_darwin.go
index 30ccb8fa..544b2d73 100644
--- a/pkg/proc/native/nonative_darwin.go
+++ b/pkg/proc/native/nonative_darwin.go
@@ -102,12 +102,12 @@ func (t *nativeThread) SetDX(dx uint64) error {
 }
 
 // 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)
 }
 
 // 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)
 }
 
diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go
index 3a80b86e..a2a8939d 100644
--- a/pkg/proc/native/proc.go
+++ b/pkg/proc/native/proc.go
@@ -209,7 +209,7 @@ func (dbp *nativeProcess) WriteBreakpoint(addr uint64) (string, int, *proc.Funct
 	f, l, fn := dbp.bi.PCToLine(uint64(addr))
 
 	originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
-	_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
+	_, err := dbp.currentThread.ReadMemory(originalData, addr)
 	if err != nil {
 		return "", 0, nil, nil, err
 	}
@@ -317,7 +317,7 @@ func (dbp *nativeProcess) postExit() {
 }
 
 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
 }
 
diff --git a/pkg/proc/native/proc_windows.go b/pkg/proc/native/proc_windows.go
index 133d218f..fa32ebb4 100644
--- a/pkg/proc/native/proc_windows.go
+++ b/pkg/proc/native/proc_windows.go
@@ -310,7 +310,7 @@ func (dbp *nativeProcess) waitForDebugEvent(flags waitForDebugEventFlags) (threa
 				atbp := true
 				if thread, found := dbp.threads[tid]; found {
 					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()
 						for i := range instr {
 							if data[i] != instr[i] {
diff --git a/pkg/proc/native/threads.go b/pkg/proc/native/threads.go
index 780f3bc8..65b5ab75 100644
--- a/pkg/proc/native/threads.go
+++ b/pkg/proc/native/threads.go
@@ -150,7 +150,7 @@ func (t *nativeThread) ThreadID() int {
 
 // ClearBreakpoint clears the specified breakpoint.
 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 nil
diff --git a/pkg/proc/native/threads_darwin.go b/pkg/proc/native/threads_darwin.go
index 1ce8902d..183ddff9 100644
--- a/pkg/proc/native/threads_darwin.go
+++ b/pkg/proc/native/threads_darwin.go
@@ -110,7 +110,7 @@ func (t *nativeThread) Stopped() bool {
 	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 {
 		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
 }
 
-func (t *nativeThread) ReadMemory(buf []byte, addr uintptr) (int, error) {
+func (t *nativeThread) ReadMemory(buf []byte, addr uint64) (int, error) {
 	if t.dbp.exited {
 		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
 	}
diff --git a/pkg/proc/native/threads_freebsd.go b/pkg/proc/native/threads_freebsd.go
index 2c569f6c..6e7cf427 100644
--- a/pkg/proc/native/threads_freebsd.go
+++ b/pkg/proc/native/threads_freebsd.go
@@ -110,24 +110,24 @@ func (t *nativeThread) restoreRegisters(savedRegs proc.Registers) error {
 	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 {
 		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
 	}
 	if len(data) == 0 {
 		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
 }
 
-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 {
 		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
 	}
 	if len(data) == 0 {
 		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
 }
diff --git a/pkg/proc/native/threads_linux.go b/pkg/proc/native/threads_linux.go
index 0f6dfa79..90af3240 100644
--- a/pkg/proc/native/threads_linux.go
+++ b/pkg/proc/native/threads_linux.go
@@ -84,7 +84,7 @@ func (t *nativeThread) Blocked() bool {
 	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 {
 		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
 	// even bother for small writes -- likely breakpoints and such.
 	if len(data) > sys.SizeofPtr {
-		written, _ = processVmWrite(t.ID, addr, data)
+		written, _ = processVmWrite(t.ID, uintptr(addr), data)
 	}
 	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
 }
 
-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 {
 		return 0, proc.ErrProcessExited{Pid: t.dbp.pid}
 	}
 	if len(data) == 0 {
 		return
 	}
-	n, _ = processVmRead(t.ID, addr, data)
+	n, _ = processVmRead(t.ID, uintptr(addr), data)
 	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
 }
diff --git a/pkg/proc/native/threads_windows.go b/pkg/proc/native/threads_windows.go
index fb429377..610b75c4 100644
--- a/pkg/proc/native/threads_windows.go
+++ b/pkg/proc/native/threads_windows.go
@@ -137,7 +137,7 @@ func (t *nativeThread) Stopped() bool {
 	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 {
 		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
 	}
 	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 {
 		return 0, err
 	}
@@ -154,7 +154,7 @@ func (t *nativeThread) WriteMemory(addr uintptr, data []byte) (int, error) {
 
 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 {
 		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
 	}
 	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)) {
 		err = ErrShortRead
 	}
diff --git a/pkg/proc/stack.go b/pkg/proc/stack.go
index 12fc2753..cf7abbb3 100644
--- a/pkg/proc/stack.go
+++ b/pkg/proc/stack.go
@@ -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) {
 	buf := make([]byte, it.bi.Arch.regSize(regnum))
-	_, err := it.mem.ReadMemory(buf, uintptr(addr))
+	_, err := it.mem.ReadMemory(buf, addr)
 	if err != nil {
 		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)
 	}
 	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
 }
diff --git a/pkg/proc/target_exec.go b/pkg/proc/target_exec.go
index 885e4d9c..30102819 100644
--- a/pkg/proc/target_exec.go
+++ b/pkg/proc/target_exec.go
@@ -142,7 +142,7 @@ func (dbp *Target) Continue() error {
 				if !arch.BreakInstrMovesPC() {
 					bpsize := arch.BreakpointSize()
 					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()) {
 						curthread.SetPC(loc.PC + uint64(bpsize))
 					}
@@ -529,7 +529,10 @@ func next(dbp *Target, stepInto, inlinedStepOut bool) error {
 		return err
 	}
 
-	sameFrameCond := astutil.And(sameGCond, frameoffCondition(&topframe))
+	var sameFrameCond ast.Expr
+	if sameGCond != nil {
+		sameFrameCond = astutil.And(sameGCond, frameoffCondition(&topframe))
+	}
 
 	if stepInto && !backward {
 		err := setStepIntoBreakpoints(dbp, topframe.Current.Fn, text, topframe, sameGCond)
diff --git a/pkg/proc/types.go b/pkg/proc/types.go
index 4f8c746e..16d1954e 100644
--- a/pkg/proc/types.go
+++ b/pkg/proc/types.go
@@ -107,7 +107,7 @@ func newLoadDebugInfoMapsContext(bi *BinaryInfo, image *Image, offsetToVersion m
 //   debug_info
 // * After go1.11 the runtimeTypeToDIE map is used to look up the address of
 //   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
 
 	_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
 	// 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 {
 		return "", err
 	}
@@ -244,7 +244,7 @@ func nameOfNamedRuntimeType(mds []moduleData, _type *Variable, kind, tflag int64
 	if ut := uncommon(_type, tflag); ut != nil {
 		if pkgPathField := ut.loadFieldNamed("pkgpath"); pkgPathField != nil && pkgPathField.Value != nil {
 			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 {
 				return "", err
 			}
@@ -344,7 +344,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
 		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
 	if anonymous {
 		buf.WriteString("func(")
@@ -354,7 +354,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
 
 	for i := int64(0); i < inCount; i++ {
 		argtype := cursortyp.maybeDereference()
-		cursortyp.Addr += uintptr(_type.bi.Arch.PtrSize())
+		cursortyp.Addr += uint64(_type.bi.Arch.PtrSize())
 		argtypename, _, err := nameOfRuntimeType(mds, argtype)
 		if err != nil {
 			return "", err
@@ -381,7 +381,7 @@ func nameOfFuncRuntimeType(mds []moduleData, _type *Variable, tflag int64, anony
 		buf.WriteString(" (")
 		for i := int64(0); i < outCount; i++ {
 			argtype := cursortyp.maybeDereference()
-			cursortyp.Addr += uintptr(_type.bi.Arch.PtrSize())
+			cursortyp.Addr += uint64(_type.bi.Arch.PtrSize())
 			argtypename, _, err := nameOfRuntimeType(mds, argtype)
 			if err != nil {
 				return "", err
@@ -419,14 +419,14 @@ func nameOfInterfaceRuntimeType(mds []moduleData, _type *Variable, kind, tflag i
 			case imethodFieldName:
 				nameoff, _ := constant.Int64Val(im.Children[i].Value)
 				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 {
 					return "", err
 				}
 
 			case imethodFieldItyp:
 				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 {
 					return "", err
 				}
@@ -489,7 +489,7 @@ func nameOfStructRuntimeType(mds []moduleData, _type *Variable, kind, tflag int6
 				}
 
 				var err error
-				fieldname, _, _, err = loadName(_type.bi, uintptr(nameoff), _type.mem)
+				fieldname, _, _, err = loadName(_type.bi, uint64(nameoff), _type.mem)
 				if err != nil {
 					return "", err
 				}
@@ -564,7 +564,7 @@ func uncommon(_type *Variable, tflag int64) *Variable {
 		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{
@@ -627,7 +627,7 @@ func dwarfToRuntimeType(bi *BinaryInfo, mem MemoryReadWriter, typ godwarf.Type)
 	if err != nil {
 		return 0, 0, false, err
 	}
-	_type := newVariable("", uintptr(typeAddr), rtyp, bi, mem)
+	_type := newVariable("", typeAddr, rtyp, bi, mem)
 	kindv := _type.loadFieldNamed("kind")
 	if kindv.Unreadable != nil || kindv.Kind != reflect.Uint {
 		return 0, 0, false, fmt.Errorf("unreadable interface type: %v", kindv.Unreadable)
diff --git a/pkg/proc/variables.go b/pkg/proc/variables.go
index 35d01ae9..d6ecd576 100644
--- a/pkg/proc/variables.go
+++ b/pkg/proc/variables.go
@@ -86,7 +86,7 @@ const (
 // and the memory of the debugged process.
 // If OnlyAddr is true, the variables value has not been loaded.
 type Variable struct {
-	Addr      uintptr
+	Addr      uint64
 	OnlyAddr  bool
 	Name      string
 	DwarfType godwarf.Type
@@ -107,7 +107,7 @@ type Variable struct {
 	// Base address of the backing byte array for strings
 	// address of the struct backing chan and map variables
 	// address of the function entry point for function variables (0 for nil function pointers)
-	Base      uintptr
+	Base      uint64
 	stride    int64
 	fieldType godwarf.Type
 
@@ -328,7 +328,7 @@ func GoroutinesInfo(dbp *Target, start, count int) ([]*G, int, error) {
 		if count != 0 && len(allg) >= count {
 			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 {
 			allg = append(allg, &G{Unreadable: err})
 			continue
@@ -434,16 +434,16 @@ func getGVariable(thread Thread) (*Variable, error) {
 	gaddr, hasgaddr := regs.GAddr()
 	if !hasgaddr {
 		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 {
 			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")
 	if err != nil {
 		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}
 }
 
-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)
 }
 
-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)
 }
 
-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, "{") {
 		// For named structs the compiler will emit a DW_TAG_structure_type 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
 			}
 			if v.Addr != 0 {
-				n, err := readUintRaw(v.mem, v.Addr, int64(v.bi.Arch.PtrSize()))
-				v.Base, v.Unreadable = uintptr(n), err
+				v.Base, v.Unreadable = readUintRaw(v.mem, v.Addr, int64(v.bi.Arch.PtrSize()))
 			}
 		}
 	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)
 		}
 	}
-	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
@@ -800,7 +799,7 @@ func (v *Variable) parseG() (*G, error) {
 
 	if deref {
 		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 {
 			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 {
 		v.Flags |= VariableFakeAddress
 	}
@@ -1172,8 +1171,8 @@ func (v *Variable) maybeDereference() *Variable {
 			// fake pointer variable constructed by casting an integer to a pointer type
 			return &v.Children[0]
 		}
-		ptrval, err := readUintRaw(v.mem, uintptr(v.Addr), t.ByteSize)
-		r := v.newVariable("", uintptr(ptrval), t.Type, DereferenceMemory(v.mem))
+		ptrval, err := readUintRaw(v.mem, v.Addr, t.ByteSize)
+		r := v.newVariable("", ptrval, t.Type, DereferenceMemory(v.mem))
 		if err != nil {
 			r.Unreadable = err
 		}
@@ -1341,14 +1340,14 @@ func convertToEface(srcv, dstv *Variable) error {
 	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
 	// http://research.swtch.com/godata
 
 	mem = cacheMemory(mem, addr, arch.PtrSize()*2)
 
 	// 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 {
 		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
-	val, err := readUintRaw(mem, addr, int64(arch.PtrSize()))
+	addr, err = readUintRaw(mem, addr, int64(arch.PtrSize()))
 	if err != nil {
 		return 0, 0, fmt.Errorf("could not read string pointer %s", err)
 	}
-	addr = uintptr(val)
 	if addr == 0 {
 		return 0, 0, 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 {
 		return "", nil
 	}
@@ -1387,7 +1385,7 @@ func readStringValue(mem MemoryReadWriter, addr uintptr, strlen int64, cfg LoadC
 	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) //
 	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.
 		// We don't know how big a page is but 1024 is a reasonable minimum common
 		// divisor for all architectures.
-		curaddr := addr + uintptr(len(val))
+		curaddr := addr + uint64(len(val))
 		maxsize := int(alignAddr(int64(curaddr+1), 1024) - int64(curaddr))
 		size := len(buf)
 		if size > maxsize {
@@ -1444,9 +1442,9 @@ func (v *Variable) loadSliceInfo(t *godwarf.SliceType) {
 		switch f.Name {
 		case sliceArrayFieldName:
 			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 {
-				v.Base = uintptr(base)
+				v.Base = base
 				// Dereference array type to get value type
 				ptrType, ok := f.Type.(*godwarf.PtrType)
 				if !ok {
@@ -1560,7 +1558,7 @@ func (v *Variable) loadArrayValues(recurseLevel int, cfg LoadConfig) {
 	}
 
 	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)
 
 		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}}
 
 	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)
 	imagvar.loadValue(loadSingleValue)
 	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
 	}
 	imagaddr := *v
-	imagaddr.Addr += uintptr(size / 2)
+	imagaddr.Addr += uint64(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
 
 	val := make([]byte, int(size))
@@ -1646,7 +1644,7 @@ func (v *Variable) writeUint(value uint64, size int64) error {
 	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
 
 	val := make([]byte, int(size))
@@ -1731,7 +1729,7 @@ func (v *Variable) writeEmptyInterface(typeAddr uint64, data *Variable) error {
 	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 {
 		switch f.Name {
 		case sliceArrayFieldName:
@@ -1782,13 +1780,13 @@ func (v *Variable) readFunctionPtr() {
 		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 {
 		v.Unreadable = err
 		return
 	}
 
-	v.Base = uintptr(val)
+	v.Base = val
 	fn := v.bi.PCToFunc(uint64(v.Base))
 	if fn == nil {
 		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 {
 			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 {
 				break
@@ -1965,7 +1963,7 @@ func (it *mapIterator) nextBucket() bool {
 
 			oldbidx := it.bidx & it.oldmask
 			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) {
 				break
diff --git a/pkg/proc/x86_disasm.go b/pkg/proc/x86_disasm.go
index ad962bf8..f2ed572d 100644
--- a/pkg/proc/x86_disasm.go
+++ b/pkg/proc/x86_disasm.go
@@ -110,7 +110,7 @@ func resolveCallArgX86(inst *x86asm.Inst, instAddr uint64, currentGoroutine bool
 		if err1 != nil || err2 != 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))
 		if err != nil {
 			return nil
diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go
index 3dcb9c54..25423619 100644
--- a/pkg/terminal/command.go
+++ b/pkg/terminal/command.go
@@ -390,15 +390,15 @@ If locspec is omitted edit will open the current source file in the editor, othe
 
 		{aliases: []string{"examinemem", "x"}, group: dataCmds, cmdFn: examineMemoryCmd, helpMsg: `Examine memory:
 
-	examinemem [-fmt <format>] [-len <length>] <address>
+	examinemem [-fmt <format>] [-count|-len <count>] [-size <size>] <address>
 
-Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
+Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal), addr(address).
 Length is the number of bytes (default 1) and must be less than or equal to 1000.
-Address is the memory location of the target to examine.
+Address is the memory location of the target to examine. Please note '-len' is deprecated by '-count and -size'.
 
 For example:
 
-    x -fmt hex -len 20 0xc00008af38`},
+    x -fmt hex -count 20 -size 1 0xc00008af38`},
 
 		{aliases: []string{"display"}, group: dataCmds, cmdFn: display, helpMsg: `Print value of an expression every time the program stops.
 
@@ -1555,14 +1555,15 @@ func examineMemoryCmd(t *Term, ctx callContext, args string) error {
 	})
 
 	var (
-		address int64
+		address uint64
 		err     error
 		ok      bool
 	)
 
 	// Default value
 	priFmt := byte('x')
-	length := 1
+	count := 1
+	size := 1
 
 	for i := 0; i < len(v); i++ {
 		switch v[i] {
@@ -1585,42 +1586,52 @@ func examineMemoryCmd(t *Term, ctx callContext, args string) error {
 			if !ok {
 				return fmt.Errorf("%q is not a valid format", v[i])
 			}
-		case "-len":
+		case "-count", "-len":
 			i++
 			if i >= len(v) {
-				return fmt.Errorf("expected argument after -len")
+				return fmt.Errorf("expected argument after -count/-len")
 			}
 			var err error
-			length, err = strconv.Atoi(v[i])
-			if err != nil || length <= 0 {
-				return fmt.Errorf("len must be an positive integer")
+			count, err = strconv.Atoi(v[i])
+			if err != nil || count <= 0 {
+				return fmt.Errorf("count/len must be a positive integer")
 			}
-			// TODO, maybe configured by user.
-			if length > 1000 {
-				return fmt.Errorf("len must be less than or equal to 1000")
+		case "-size":
+			i++
+			if i >= len(v) {
+				return fmt.Errorf("expected argument after -size")
+			}
+			var err error
+			size, err = strconv.Atoi(v[i])
+			if err != nil || size <= 0 || size > 8 {
+				return fmt.Errorf("size must be a positive integer (<=8)")
 			}
 		default:
 			if i != len(v)-1 {
 				return fmt.Errorf("unknown option %q", v[i])
 			}
 			// 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 {
 				return fmt.Errorf("convert address into uintptr type failed, %s", err)
 			}
 		}
 	}
 
+	// TODO, maybe configured by user.
+	if count*size > 1000 {
+		return fmt.Errorf("read memory range (count*size) must be less than or equal to 1000 bytes")
+	}
+
 	if address == 0 {
 		return fmt.Errorf("no address specified")
 	}
 
-	memArea, err := t.client.ExamineMemory(uintptr(address), length)
+	memArea, isLittleEndian, err := t.client.ExamineMemory(address, count*size)
 	if err != nil {
 		return err
 	}
-
-	fmt.Print(api.PrettyExamineMemory(uintptr(address), memArea, priFmt))
+	fmt.Print(api.PrettyExamineMemory(uintptr(address), memArea, isLittleEndian, priFmt, size))
 	return nil
 }
 
diff --git a/service/api/conversions.go b/service/api/conversions.go
index c22035e1..ad47d6e0 100644
--- a/service/api/conversions.go
+++ b/service/api/conversions.go
@@ -7,7 +7,9 @@ import (
 	"go/printer"
 	"go/token"
 	"reflect"
+	"sort"
 	"strconv"
+	"strings"
 
 	"github.com/go-delve/delve/pkg/dwarf/godwarf"
 	"github.com/go-delve/delve/pkg/dwarf/op"
@@ -109,7 +111,16 @@ func ConvertThread(th proc.Thread) *Thread {
 	}
 }
 
-func prettyTypeName(typ godwarf.Type) string {
+// ConvertThreads converts a slice of proc.Thread into a slice of api.Thread.
+func ConvertThreads(threads []proc.Thread) []*Thread {
+	r := make([]*Thread, len(threads))
+	for i := range threads {
+		r[i] = ConvertThread(threads[i])
+	}
+	return r
+}
+
+func PrettyTypeName(typ godwarf.Type) string {
 	if typ == nil {
 		return ""
 	}
@@ -152,29 +163,14 @@ func ConvertVar(v *proc.Variable) *Variable {
 		DeclLine:     v.DeclLine,
 	}
 
-	r.Type = prettyTypeName(v.DwarfType)
-	r.RealType = prettyTypeName(v.RealType)
+	r.Type = PrettyTypeName(v.DwarfType)
+	r.RealType = PrettyTypeName(v.RealType)
 
 	if v.Unreadable != nil {
 		r.Unreadable = v.Unreadable.Error()
 	}
 
-	if v.Value != nil {
-		switch v.Kind {
-		case reflect.Float32:
-			r.Value = convertFloatValue(v, 32)
-		case reflect.Float64:
-			r.Value = convertFloatValue(v, 64)
-		case reflect.String, reflect.Func:
-			r.Value = constant.StringVal(v.Value)
-		default:
-			if cd := v.ConstDescr(); cd != "" {
-				r.Value = fmt.Sprintf("%s (%s)", cd, v.Value.String())
-			} else {
-				r.Value = v.Value.String()
-			}
-		}
-	}
+	r.Value = VariableValueAsString(v)
 
 	switch v.Kind {
 	case reflect.Complex64:
@@ -230,6 +226,38 @@ func ConvertVar(v *proc.Variable) *Variable {
 	return &r
 }
 
+func VariableValueAsString(v *proc.Variable) string {
+	if v.Value == nil {
+		return ""
+	}
+	switch v.Kind {
+	case reflect.Float32:
+		return convertFloatValue(v, 32)
+	case reflect.Float64:
+		return convertFloatValue(v, 64)
+	case reflect.String, reflect.Func:
+		return constant.StringVal(v.Value)
+	default:
+		if cd := v.ConstDescr(); cd != "" {
+			return fmt.Sprintf("%s (%s)", cd, v.Value.String())
+		} else {
+			return v.Value.String()
+		}
+	}
+}
+
+// ConvertVars converts from []*proc.Variable to []api.Variable.
+func ConvertVars(pv []*proc.Variable) []Variable {
+	if pv == nil {
+		return nil
+	}
+	vars := make([]Variable, 0, len(pv))
+	for _, v := range pv {
+		vars = append(vars, *ConvertVar(v))
+	}
+	return vars
+}
+
 // ConvertFunction converts from gosym.Func to
 // api.Function.
 func ConvertFunction(fn *proc.Function) *Function {
@@ -271,6 +299,15 @@ func ConvertGoroutine(g *proc.G) *Goroutine {
 	}
 }
 
+// ConvertGoroutines converts from []*proc.G to []*api.Goroutine.
+func ConvertGoroutines(gs []*proc.G) []*Goroutine {
+	goroutines := make([]*Goroutine, len(gs))
+	for i := range gs {
+		goroutines[i] = ConvertGoroutine(gs[i])
+	}
+	return goroutines
+}
+
 // ConvertLocation converts from proc.Location to api.Location.
 func ConvertLocation(loc proc.Location) Location {
 	return Location{
@@ -327,29 +364,55 @@ func LoadConfigFromProc(cfg *proc.LoadConfig) *LoadConfig {
 	}
 }
 
+var canonicalRegisterOrder = map[string]int{
+	// amd64
+	"rip": 0,
+	"rsp": 1,
+	"rax": 2,
+	"rbx": 3,
+	"rcx": 4,
+	"rdx": 5,
+
+	// arm64
+	"pc": 0,
+	"sp": 1,
+}
+
 // ConvertRegisters converts proc.Register to api.Register for a slice.
-func ConvertRegisters(in op.DwarfRegisters, arch *proc.Arch, floatingPoint bool) (out []Register) {
-	if floatingPoint {
-		in.Reg(^uint64(0)) // force loading all registers
-	}
+func ConvertRegisters(in *op.DwarfRegisters, dwarfRegisterToString func(int, *op.DwarfRegister) (string, bool, string), floatingPoint bool) (out []Register) {
 	out = make([]Register, 0, in.CurrentSize())
 	for i := 0; i < in.CurrentSize(); i++ {
 		reg := in.Reg(uint64(i))
 		if reg == nil {
 			continue
 		}
-		name, fp, repr := arch.DwarfRegisterToString(i, reg)
+		name, fp, repr := dwarfRegisterToString(i, reg)
 		if !floatingPoint && fp {
 			continue
 		}
 		out = append(out, Register{name, repr, i})
 	}
-	return
-}
+	// Sort the registers in a canonical order we prefer, this is mostly
+	// because the DWARF register numbering for AMD64 is weird.
+	sort.Slice(out, func(i, j int) bool {
+		a, b := out[i], out[j]
+		an, aok := canonicalRegisterOrder[strings.ToLower(a.Name)]
+		bn, bok := canonicalRegisterOrder[strings.ToLower(b.Name)]
+		// Registers that don't appear in canonicalRegisterOrder sort after registers that do.
+		if !aok {
+			an = 1000
+		}
+		if !bok {
+			bn = 1000
+		}
+		if an == bn {
+			// keep registers that don't appear in canonicalRegisterOrder in DWARF order
+			return a.DwarfNumber < b.DwarfNumber
+		}
+		return an < bn
 
-// ConvertCheckpoint converts proc.Chekcpoint to api.Checkpoint.
-func ConvertCheckpoint(in proc.Checkpoint) (out Checkpoint) {
-	return Checkpoint(in)
+	})
+	return
 }
 
 func ConvertImage(image *proc.Image) Image {
diff --git a/service/api/prettyprint.go b/service/api/prettyprint.go
index 45571def..564bae57 100644
--- a/service/api/prettyprint.go
+++ b/service/api/prettyprint.go
@@ -360,13 +360,19 @@ func (v *Variable) writeSliceOrArrayTo(buf io.Writer, newlines bool, indent stri
 	fmt.Fprint(buf, "]")
 }
 
-func PrettyExamineMemory(address uintptr, memArea []byte, format byte) string {
+// PrettyExamineMemory examine the memory and format data
+//
+// `format` specifies the data format (or data type), `size` specifies size of each data,
+// like 4byte integer, 1byte character, etc. `count` specifies the number of values.
+func PrettyExamineMemory(address uintptr, memArea []byte, isLittleEndian bool, format byte, size int) string {
 
 	var (
 		cols      int
 		colFormat string
-		addrLen   int
-		addrFmt   string
+		colBytes  = size
+
+		addrLen int
+		addrFmt string
 	)
 
 	// Diffrent versions of golang output differently about '#'.
@@ -374,24 +380,24 @@ func PrettyExamineMemory(address uintptr, memArea []byte, format byte) string {
 	switch format {
 	case 'b':
 		cols = 4 // Avoid emitting rows that are too long when using binary format
-		colFormat = "%08b"
+		colFormat = fmt.Sprintf("%%0%db", colBytes*8)
 	case 'o':
 		cols = 8
-		colFormat = "%04o" // Always keep one leading zero for octal.
+		colFormat = fmt.Sprintf("0%%0%do", colBytes*3) // Always keep one leading zero for octal.
 	case 'd':
 		cols = 8
-		colFormat = "%03d"
+		colFormat = fmt.Sprintf("%%0%dd", colBytes*3)
 	case 'x':
 		cols = 8
-		colFormat = "0x%02x" // Always keep one leading '0x' for hex.
+		colFormat = fmt.Sprintf("0x%%0%dx", colBytes*2) // Always keep one leading '0x' for hex.
 	default:
 		return fmt.Sprintf("not supprted format %q\n", string(format))
 	}
 	colFormat += "\t"
 
 	l := len(memArea)
-	rows := l / cols
-	if l%cols != 0 {
+	rows := l / (cols * colBytes)
+	if l%(cols*colBytes) != 0 {
 		rows++
 	}
 
@@ -403,10 +409,16 @@ func PrettyExamineMemory(address uintptr, memArea []byte, format byte) string {
 
 	var b strings.Builder
 	w := tabwriter.NewWriter(&b, 0, 0, 3, ' ', 0)
+
 	for i := 0; i < rows; i++ {
 		fmt.Fprintf(w, addrFmt, address)
-		for j := 0; j < cols && i*cols+j < l; j++ {
-			fmt.Fprintf(w, colFormat, memArea[i*cols+j])
+
+		for j := 0; j < cols; j++ {
+			offset := i*(cols*colBytes) + j*colBytes
+			if offset+colBytes <= len(memArea) {
+				n := byteArrayToUInt64(memArea[offset:offset+colBytes], isLittleEndian)
+				fmt.Fprintf(w, colFormat, n)
+			}
 		}
 		fmt.Fprintln(w, "")
 		address += uintptr(cols)
@@ -414,3 +426,17 @@ func PrettyExamineMemory(address uintptr, memArea []byte, format byte) string {
 	w.Flush()
 	return b.String()
 }
+
+func byteArrayToUInt64(buf []byte, isLittleEndian bool) uint64 {
+	var n uint64
+	if isLittleEndian {
+		for i := len(buf) - 1; i >= 0; i-- {
+			n = n<<8 + uint64(buf[i])
+		}
+	} else {
+		for i := 0; i < len(buf); i++ {
+			n = n<<8 + uint64(buf[i])
+		}
+	}
+	return n
+}
diff --git a/service/api/types.go b/service/api/types.go
index 31ccbbc5..3581c275 100644
--- a/service/api/types.go
+++ b/service/api/types.go
@@ -240,7 +240,7 @@ type Variable struct {
 	// Name of the variable or struct member
 	Name string `json:"name"`
 	// 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>)
 	OnlyAddr bool `json:"onlyAddr"`
 	// Go type of the variable
@@ -272,7 +272,7 @@ type Variable struct {
 	// Base address of the backing byte array for strings
 	// address of the struct backing chan and map variables
 	// 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 string `json:"unreadable"`
diff --git a/service/client.go b/service/client.go
index 7e623179..8fd863b8 100644
--- a/service/client.go
+++ b/service/client.go
@@ -160,7 +160,7 @@ type Client interface {
 	// 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.
 	// 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, bool, error)
 
 	// StopRecording stops a recording if one is in progress.
 	StopRecording() error
diff --git a/service/dap/handles.go b/service/dap/handles.go
index 05bfd3dd..ec9bfe1e 100644
--- a/service/dap/handles.go
+++ b/service/dap/handles.go
@@ -1,5 +1,7 @@
 package dap
 
+import "github.com/go-delve/delve/pkg/proc"
+
 const startHandle = 1000
 
 // handlesMap maps arbitrary values to unique sequential ids.
@@ -32,3 +34,27 @@ func (hs *handlesMap) get(handle int) (interface{}, bool) {
 	v, ok := hs.handleToVal[handle]
 	return v, ok
 }
+
+type variablesHandlesMap struct {
+	m *handlesMap
+}
+
+func newVariablesHandlesMap() *variablesHandlesMap {
+	return &variablesHandlesMap{newHandlesMap()}
+}
+
+func (hs *variablesHandlesMap) create(value *proc.Variable) int {
+	return hs.m.create(value)
+}
+
+func (hs *variablesHandlesMap) get(handle int) (*proc.Variable, bool) {
+	v, ok := hs.m.get(handle)
+	if !ok {
+		return nil, false
+	}
+	return v.(*proc.Variable), true
+}
+
+func (hs *variablesHandlesMap) reset() {
+	hs.m.reset()
+}
diff --git a/service/dap/server.go b/service/dap/server.go
index c87e0946..0669822b 100644
--- a/service/dap/server.go
+++ b/service/dap/server.go
@@ -12,11 +12,13 @@ import (
 	"bufio"
 	"encoding/json"
 	"fmt"
+	"go/constant"
 	"io"
 	"net"
 	"os"
 	"path/filepath"
 	"reflect"
+	"strings"
 
 	"github.com/go-delve/delve/pkg/gobuild"
 	"github.com/go-delve/delve/pkg/logflags"
@@ -59,7 +61,7 @@ type Server struct {
 	stackFrameHandles *handlesMap
 	// variableHandles maps compound variables to unique references within their stack frame.
 	// See also comment for convertVariable.
-	variableHandles *handlesMap
+	variableHandles *variablesHandlesMap
 	// args tracks special settings for handling debug session requests.
 	args launchAttachArgs
 }
@@ -71,12 +73,15 @@ type launchAttachArgs struct {
 	stopOnEntry bool
 	// stackTraceDepth is the maximum length of the returned list of stack frames.
 	stackTraceDepth int
+	// showGlobalVariables indicates if global package variables should be loaded.
+	showGlobalVariables bool
 }
 
 // defaultArgs borrows the defaults for the arguments from the original vscode-go adapter.
 var defaultArgs = launchAttachArgs{
-	stopOnEntry:     false,
-	stackTraceDepth: 50,
+	stopOnEntry:         false,
+	stackTraceDepth:     50,
+	showGlobalVariables: false,
 }
 
 // NewServer creates a new DAP Server. It takes an opened Listener
@@ -93,7 +98,7 @@ func NewServer(config *service.Config) *Server {
 		stopChan:          make(chan struct{}),
 		log:               logger,
 		stackFrameHandles: newHandlesMap(),
-		variableHandles:   newHandlesMap(),
+		variableHandles:   newVariablesHandlesMap(),
 		args:              defaultArgs,
 	}
 }
@@ -456,13 +461,19 @@ func (s *Server) onLaunchRequest(request *dap.LaunchRequest) {
 		return
 	}
 
-	stop, ok := request.Arguments["stopOnEntry"]
-	s.args.stopOnEntry = ok && stop == true
-
+	// If user-specified, overwrite the defaults for optional args.
+	stop, ok := request.Arguments["stopOnEntry"].(bool)
+	if ok {
+		s.args.stopOnEntry = stop
+	}
 	depth, ok := request.Arguments["stackTraceDepth"].(float64)
 	if ok && depth > 0 {
 		s.args.stackTraceDepth = int(depth)
 	}
+	globals, ok := request.Arguments["showGlobalVariables"].(bool)
+	if ok {
+		s.args.showGlobalVariables = globals
+	}
 
 	var targetArgs []string
 	args, ok := request.Arguments["args"]
@@ -593,6 +604,9 @@ func (s *Server) onThreadsRequest(request *dap.ThreadsRequest) {
 		return
 	}
 
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+
 	threads := make([]dap.Thread, len(gs))
 	if len(threads) == 0 {
 		// Depending on the debug session stage, goroutines information
@@ -604,8 +618,9 @@ func (s *Server) onThreadsRequest(request *dap.ThreadsRequest) {
 	} else {
 		for i, g := range gs {
 			threads[i].Id = g.ID
-			if loc := g.UserCurrentLoc; loc.Function != nil {
-				threads[i].Name = loc.Function.Name()
+			loc := g.UserCurrent()
+			if loc.Fn != nil {
+				threads[i].Name = loc.Fn.Name
 			} else {
 				threads[i].Name = fmt.Sprintf("%s@%d", loc.File, loc.Line)
 			}
@@ -668,17 +683,22 @@ type stackFrame struct {
 // This is a mandatory request to support.
 func (s *Server) onStackTraceRequest(request *dap.StackTraceRequest) {
 	goroutineID := request.Arguments.ThreadId
-	locs, err := s.debugger.Stacktrace(goroutineID, s.args.stackTraceDepth, 0, nil /*skip locals & args*/)
+	frames, err := s.debugger.Stacktrace(goroutineID, s.args.stackTraceDepth, 0)
 	if err != nil {
 		s.sendErrorResponse(request.Request, UnableToProduceStackTrace, "Unable to produce stack trace", err.Error())
 		return
 	}
 
-	stackFrames := make([]dap.StackFrame, len(locs))
-	for i, loc := range locs {
+	stackFrames := make([]dap.StackFrame, len(frames))
+	for i, frame := range frames {
+		loc := &frame.Call
 		uniqueStackFrameID := s.stackFrameHandles.create(stackFrame{goroutineID, i})
 		stackFrames[i] = dap.StackFrame{Id: uniqueStackFrameID, Line: loc.Line}
-		stackFrames[i].Name = loc.Function.Name()
+		if loc.Fn == nil {
+			stackFrames[i].Name = "???"
+		} else {
+			stackFrames[i].Name = loc.Fn.Name
+		}
 		if loc.File != "<autogenerated>" {
 			stackFrames[i].Source = dap.Source{Name: filepath.Base(loc.File), Path: loc.File}
 		}
@@ -692,7 +712,7 @@ func (s *Server) onStackTraceRequest(request *dap.StackTraceRequest) {
 	}
 	response := &dap.StackTraceResponse{
 		Response: *newResponse(request.Request),
-		Body:     dap.StackTraceResponseBody{StackFrames: stackFrames, TotalFrames: len(locs)},
+		Body:     dap.StackTraceResponseBody{StackFrames: stackFrames, TotalFrames: len(frames)},
 	}
 	s.send(response)
 }
@@ -706,33 +726,67 @@ func (s *Server) onScopesRequest(request *dap.ScopesRequest) {
 		return
 	}
 
-	scope := api.EvalScope{GoroutineID: sf.(stackFrame).goroutineID, Frame: sf.(stackFrame).frameIndex}
+	goid := sf.(stackFrame).goroutineID
+	frame := sf.(stackFrame).frameIndex
 	// TODO(polina): Support setting config via launch/attach args
 	cfg := proc.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}
 
 	// Retrieve arguments
-	args, err := s.debugger.FunctionArguments(scope, cfg)
+	args, err := s.debugger.FunctionArguments(goid, frame, 0, cfg)
 	if err != nil {
 		s.sendErrorResponse(request.Request, UnableToListArgs, "Unable to list args", err.Error())
 		return
 	}
-	argScope := api.Variable{Name: "Arguments", Children: args}
+	argScope := &proc.Variable{Name: "Arguments", Children: slicePtrVarToSliceVar(args)}
 
 	// Retrieve local variables
-	locals, err := s.debugger.LocalVariables(scope, cfg)
+	locals, err := s.debugger.LocalVariables(goid, frame, 0, cfg)
 	if err != nil {
-		s.sendErrorResponse(request.Request, UnableToListLocals, "Unable to list local vars", err.Error())
+		s.sendErrorResponse(request.Request, UnableToListLocals, "Unable to list locals", err.Error())
 		return
 	}
-	locScope := api.Variable{Name: "Locals", Children: locals}
+	locScope := &proc.Variable{Name: "Locals", Children: slicePtrVarToSliceVar(locals)}
 
 	// TODO(polina): Annotate shadowed variables
-	// TODO(polina): Retrieve global variables
 
 	scopeArgs := dap.Scope{Name: argScope.Name, VariablesReference: s.variableHandles.create(argScope)}
 	scopeLocals := dap.Scope{Name: locScope.Name, VariablesReference: s.variableHandles.create(locScope)}
 	scopes := []dap.Scope{scopeArgs, scopeLocals}
 
+	if s.args.showGlobalVariables {
+		// Limit what global variables we will return to the current package only.
+		// TODO(polina): This is how vscode-go currently does it to make
+		// the amount of the returned data manageable. In fact, this is
+		// considered so expensive even with the package filter, that
+		// the default for showGlobalVariables was recently flipped to
+		// not showing. If we delay loading of the globals until the corresponding
+		// scope is expanded, generating an explicit variable request,
+		// should we consider making all globals accessible with a scope per package?
+		// Or users can just rely on watch variables.
+		currPkg, err := s.debugger.CurrentPackage()
+		if err != nil {
+			s.sendErrorResponse(request.Request, UnableToListGlobals, "Unable to list globals", err.Error())
+			return
+		}
+		currPkgFilter := fmt.Sprintf("^%s\\.", currPkg)
+		globals, err := s.debugger.PackageVariables(s.debugger.CurrentThread().ThreadID(), currPkgFilter, cfg)
+		if err != nil {
+			s.sendErrorResponse(request.Request, UnableToListGlobals, "Unable to list globals", err.Error())
+			return
+		}
+		// Remove package prefix from the fully-qualified variable names.
+		// We will include the package info once in the name of the scope instead.
+		for i, g := range globals {
+			globals[i].Name = strings.TrimPrefix(g.Name, currPkg+".")
+		}
+
+		globScope := &proc.Variable{
+			Name:     fmt.Sprintf("Globals (package %s)", currPkg),
+			Children: slicePtrVarToSliceVar(globals),
+		}
+		scopeGlobals := dap.Scope{Name: globScope.Name, VariablesReference: s.variableHandles.create(globScope)}
+		scopes = append(scopes, scopeGlobals)
+	}
 	response := &dap.ScopesResponse{
 		Response: *newResponse(request.Request),
 		Body:     dap.ScopesResponseBody{Scopes: scopes},
@@ -740,15 +794,22 @@ func (s *Server) onScopesRequest(request *dap.ScopesRequest) {
 	s.send(response)
 }
 
+func slicePtrVarToSliceVar(vars []*proc.Variable) []proc.Variable {
+	r := make([]proc.Variable, len(vars))
+	for i := range vars {
+		r[i] = *vars[i]
+	}
+	return r
+}
+
 // onVariablesRequest handles 'variables' requests.
 // This is a mandatory request to support.
 func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
-	variable, ok := s.variableHandles.get(request.Arguments.VariablesReference)
+	v, ok := s.variableHandles.get(request.Arguments.VariablesReference)
 	if !ok {
 		s.sendErrorResponse(request.Request, UnableToLookupVariable, "Unable to lookup variable", fmt.Sprintf("unknown reference %d", request.Arguments.VariablesReference))
 		return
 	}
-	v := variable.(api.Variable)
 	children := make([]dap.Variable, 0)
 	// TODO(polina): check and handle if variable loaded incompletely
 	// https://github.com/go-delve/delve/blob/master/Documentation/api/ClientHowto.md#looking-into-variables
@@ -759,8 +820,8 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
 			// A map will have twice as many children as there are key-value elements.
 			kvIndex := i / 2
 			// Process children in pairs: even indices are map keys, odd indices are values.
-			key, keyref := s.convertVariable(v.Children[i])
-			val, valref := s.convertVariable(v.Children[i+1])
+			key, keyref := s.convertVariable(&v.Children[i])
+			val, valref := s.convertVariable(&v.Children[i+1])
 			// If key or value or both are scalars, we can use
 			// a single variable to represet key:value format.
 			// Otherwise, we must return separate variables for both.
@@ -792,7 +853,8 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
 		}
 	case reflect.Slice, reflect.Array:
 		children = make([]dap.Variable, len(v.Children))
-		for i, c := range v.Children {
+		for i := range v.Children {
+			c := &v.Children[i]
 			value, varref := s.convertVariable(c)
 			children[i] = dap.Variable{
 				Name:               fmt.Sprintf("[%d]", i),
@@ -802,7 +864,8 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
 		}
 	default:
 		children = make([]dap.Variable, len(v.Children))
-		for i, c := range v.Children {
+		for i := range v.Children {
+			c := &v.Children[i]
 			value, variablesReference := s.convertVariable(c)
 			children[i] = dap.Variable{
 				Name:               c.Name,
@@ -827,11 +890,12 @@ func (s *Server) onVariablesRequest(request *dap.VariablesRequest) {
 // can be issued to get the elements of the compound variable. As a custom, a zero
 // reference, reminiscent of a zero pointer, is used to indicate that a scalar
 // variable cannot be "dereferenced" to get its elements (as there are none).
-func (s *Server) convertVariable(v api.Variable) (value string, variablesReference int) {
-	if v.Unreadable != "" {
-		value = fmt.Sprintf("unreadable <%s>", v.Unreadable)
+func (s *Server) convertVariable(v *proc.Variable) (value string, variablesReference int) {
+	if v.Unreadable != nil {
+		value = fmt.Sprintf("unreadable <%v>", v.Unreadable)
 		return
 	}
+	typeName := api.PrettyTypeName(v.DwarfType)
 	switch v.Kind {
 	case reflect.UnsafePointer:
 		if len(v.Children) == 0 {
@@ -840,65 +904,87 @@ func (s *Server) convertVariable(v api.Variable) (value string, variablesReferen
 			value = fmt.Sprintf("unsafe.Pointer(%#x)", v.Children[0].Addr)
 		}
 	case reflect.Ptr:
-		if v.Type == "" || len(v.Children) == 0 {
+		if v.DwarfType == nil || len(v.Children) == 0 {
 			value = "nil"
 		} else if v.Children[0].Addr == 0 {
-			value = "nil <" + v.Type + ">"
-		} else if v.Children[0].Type == "void" {
+			value = "nil <" + typeName + ">"
+		} else if v.Children[0].Kind == reflect.Invalid {
 			value = "void"
 		} else {
-			value = fmt.Sprintf("<%s>(%#x)", v.Type, v.Children[0].Addr)
+			value = fmt.Sprintf("<%s>(%#x)", typeName, v.Children[0].Addr)
 			variablesReference = s.variableHandles.create(v)
 		}
 	case reflect.Array:
-		value = "<" + v.Type + ">"
+		value = "<" + typeName + ">"
 		if len(v.Children) > 0 {
 			variablesReference = s.variableHandles.create(v)
 		}
 	case reflect.Slice:
 		if v.Base == 0 {
-			value = "nil <" + v.Type + ">"
+			value = "nil <" + typeName + ">"
 		} else {
-			value = fmt.Sprintf("<%s> (length: %d, cap: %d)", v.Type, v.Len, v.Cap)
+			value = fmt.Sprintf("<%s> (length: %d, cap: %d)", typeName, v.Len, v.Cap)
 			if len(v.Children) > 0 {
 				variablesReference = s.variableHandles.create(v)
 			}
 		}
 	case reflect.Map:
 		if v.Base == 0 {
-			value = "nil <" + v.Type + ">"
+			value = "nil <" + typeName + ">"
 		} else {
-			value = fmt.Sprintf("<%s> (length: %d)", v.Type, v.Len)
+			value = fmt.Sprintf("<%s> (length: %d)", typeName, v.Len)
 			if len(v.Children) > 0 {
 				variablesReference = s.variableHandles.create(v)
 			}
 		}
 	case reflect.String:
-		lenNotLoaded := v.Len - int64(len(v.Value))
-		vvalue := v.Value
+		vvalue := constant.StringVal(v.Value)
+		lenNotLoaded := v.Len - int64(len(vvalue))
 		if lenNotLoaded > 0 {
 			vvalue += fmt.Sprintf("...+%d more", lenNotLoaded)
 		}
 		value = fmt.Sprintf("%q", vvalue)
 	case reflect.Chan:
 		if len(v.Children) == 0 {
-			value = "nil <" + v.Type + ">"
+			value = "nil <" + typeName + ">"
 		} else {
-			value = "<" + v.Type + ">"
+			value = "<" + typeName + ">"
 			variablesReference = s.variableHandles.create(v)
 		}
 	case reflect.Interface:
-		if len(v.Children) == 0 || v.Children[0].Kind == reflect.Invalid && v.Children[0].Addr == 0 {
-			value = "nil <" + v.Type + ">"
+		if v.Addr == 0 {
+			// An escaped interface variable that points to nil, this shouldn't
+			// happen in normal code but can happen if the variable is out of scope,
+			// such as if an interface variable has been captured by a
+			// closure and replaced by a pointer to interface, and the pointer
+			// happens to contain 0.
+			value = "nil"
+		} else if len(v.Children) == 0 || v.Children[0].Kind == reflect.Invalid && v.Children[0].Addr == 0 {
+			value = "nil <" + typeName + ">"
 		} else {
-			value = "<" + v.Type + ">"
+			value = "<" + typeName + ">"
 			variablesReference = s.variableHandles.create(v)
 		}
+	case reflect.Complex64, reflect.Complex128:
+		v.Children = make([]proc.Variable, 2)
+		v.Children[0].Name = "real"
+		v.Children[0].Value = constant.Real(v.Value)
+		v.Children[1].Name = "imaginary"
+		v.Children[1].Value = constant.Imag(v.Value)
+		if v.Kind == reflect.Complex64 {
+			v.Children[0].Kind = reflect.Float32
+			v.Children[1].Kind = reflect.Float32
+		} else {
+			v.Children[0].Kind = reflect.Float64
+			v.Children[1].Kind = reflect.Float64
+		}
+		fallthrough
 	default: // Struct, complex, scalar
-		if v.Value != "" {
-			value = v.Value
+		vvalue := api.VariableValueAsString(v)
+		if vvalue != "" {
+			value = vvalue
 		} else {
-			value = "<" + v.Type + ">"
+			value = "<" + typeName + ">"
 		}
 		if len(v.Children) > 0 {
 			variablesReference = s.variableHandles.create(v)
diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go
index 08c465d3..4f48ada9 100644
--- a/service/debugger/debugger.go
+++ b/service/debugger/debugger.go
@@ -552,7 +552,7 @@ func (d *Debugger) state(retLoadCfg *proc.LoadConfig) (*api.DebuggerState, error
 		th := api.ConvertThread(thread)
 
 		if retLoadCfg != nil {
-			th.ReturnValues = convertVars(thread.Common().ReturnValues(*retLoadCfg))
+			th.ReturnValues = api.ConvertVars(thread.Common().ReturnValues(*retLoadCfg))
 		}
 
 		state.Threads = append(state.Threads, th)
@@ -825,7 +825,7 @@ func (d *Debugger) findBreakpointByName(name string) *api.Breakpoint {
 }
 
 // Threads returns the threads of the target process.
-func (d *Debugger) Threads() ([]*api.Thread, error) {
+func (d *Debugger) Threads() ([]proc.Thread, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -833,15 +833,11 @@ func (d *Debugger) Threads() ([]*api.Thread, error) {
 		return nil, err
 	}
 
-	threads := []*api.Thread{}
-	for _, th := range d.target.ThreadList() {
-		threads = append(threads, api.ConvertThread(th))
-	}
-	return threads, nil
+	return d.target.ThreadList(), nil
 }
 
 // FindThread returns the thread for the given 'id'.
-func (d *Debugger) FindThread(id int) (*api.Thread, error) {
+func (d *Debugger) FindThread(id int) (proc.Thread, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -851,7 +847,7 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) {
 
 	for _, th := range d.target.ThreadList() {
 		if th.ThreadID() == id {
-			return api.ConvertThread(th), nil
+			return th, nil
 		}
 	}
 	return nil, nil
@@ -1079,12 +1075,12 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
 		}
 		if bp.LoadArgs != nil {
 			if vars, err := s.FunctionArguments(*api.LoadConfigToProc(bp.LoadArgs)); err == nil {
-				bpi.Arguments = convertVars(vars)
+				bpi.Arguments = api.ConvertVars(vars)
 			}
 		}
 		if bp.LoadLocals != nil {
 			if locals, err := s.LocalVariables(*api.LoadConfigToProc(bp.LoadLocals)); err == nil {
-				bpi.Locals = convertVars(locals)
+				bpi.Locals = api.ConvertVars(locals)
 			}
 		}
 	}
@@ -1157,7 +1153,7 @@ func (d *Debugger) Types(filter string) ([]string, error) {
 
 // PackageVariables returns a list of package variables for the thread,
 // optionally regexp filtered using regexp described in 'filter'.
-func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadConfig) ([]api.Variable, error) {
+func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadConfig) ([]*proc.Variable, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -1166,7 +1162,6 @@ func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadCo
 		return nil, fmt.Errorf("invalid filter argument: %s", err.Error())
 	}
 
-	vars := []api.Variable{}
 	thread, found := d.target.FindThread(threadID)
 	if !found {
 		return nil, fmt.Errorf("couldn't find thread %d", threadID)
@@ -1179,146 +1174,93 @@ func (d *Debugger) PackageVariables(threadID int, filter string, cfg proc.LoadCo
 	if err != nil {
 		return nil, err
 	}
-	for _, v := range pv {
-		if regex.Match([]byte(v.Name)) {
-			vars = append(vars, *api.ConvertVar(v))
+	pvr := pv[:0]
+	for i := range pv {
+		if regex.Match([]byte(pv[i].Name)) {
+			pvr = append(pvr, pv[i])
 		}
 	}
-	return vars, err
+	return pvr, nil
 }
 
-// Registers returns string representation of the CPU registers.
-func (d *Debugger) Registers(threadID int, scope *api.EvalScope, floatingPoint bool) (api.Registers, error) {
+// ThreadRegisters returns registers of the specified thread.
+func (d *Debugger) ThreadRegisters(threadID int, floatingPoint bool) (*op.DwarfRegisters, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
-	var dregs op.DwarfRegisters
-
-	if scope != nil {
-		s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
-		if err != nil {
-			return nil, err
-		}
-		dregs = s.Regs
-	} else {
-		thread, found := d.target.FindThread(threadID)
-		if !found {
-			return nil, fmt.Errorf("couldn't find thread %d", threadID)
-		}
-		regs, err := thread.Registers()
-		if err != nil {
-			return nil, err
-		}
-		dregs = d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
+	thread, found := d.target.FindThread(threadID)
+	if !found {
+		return nil, fmt.Errorf("couldn't find thread %d", threadID)
 	}
-	r := api.ConvertRegisters(dregs, d.target.BinInfo().Arch, floatingPoint)
-	if floatingPoint && dregs.FloatLoadError != nil {
-		return nil, dregs.FloatLoadError
+	regs, err := thread.Registers()
+	if err != nil {
+		return nil, err
 	}
-	// Sort the registers in a canonical order we prefer, this is mostly
-	// because the DWARF register numbering for AMD64 is weird.
-	sort.Slice(r, func(i, j int) bool {
-		a, b := r[i], r[j]
-		an, aok := canonicalRegisterOrder[strings.ToLower(a.Name)]
-		bn, bok := canonicalRegisterOrder[strings.ToLower(b.Name)]
-		// Registers that don't appear in canonicalRegisterOrder sort after registers that do.
-		if !aok {
-			an = 1000
-		}
-		if !bok {
-			bn = 1000
-		}
-		if an == bn {
-			// keep registers that don't appear in canonicalRegisterOrder in DWARF order
-			return a.DwarfNumber < b.DwarfNumber
-		}
-		return an < bn
-
-	})
-	return r, nil
+	dregs := d.target.BinInfo().Arch.RegistersToDwarfRegisters(0, regs)
+	return &dregs, nil
 }
 
-var canonicalRegisterOrder = map[string]int{
-	// amd64
-	"rip": 0,
-	"rsp": 1,
-	"rax": 2,
-	"rbx": 3,
-	"rcx": 4,
-	"rdx": 5,
+// ScopeRegisters returns registers for the specified scope.
+func (d *Debugger) ScopeRegisters(goid, frame, deferredCall int, floatingPoint bool) (*op.DwarfRegisters, error) {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
 
-	// arm64
-	"pc": 0,
-	"sp": 1,
+	s, err := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
+	if err != nil {
+		return nil, err
+	}
+	return &s.Regs, nil
 }
 
-func convertVars(pv []*proc.Variable) []api.Variable {
-	if pv == nil {
-		return nil
-	}
-	vars := make([]api.Variable, 0, len(pv))
-	for _, v := range pv {
-		vars = append(vars, *api.ConvertVar(v))
-	}
-	return vars
+// DwarfRegisterToString returns the name and value representation of the given register.
+func (d *Debugger) DwarfRegisterToString(i int, reg *op.DwarfRegister) (string, bool, string) {
+	return d.target.BinInfo().Arch.DwarfRegisterToString(i, reg)
 }
 
 // LocalVariables returns a list of the local variables.
-func (d *Debugger) LocalVariables(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) {
+func (d *Debugger) LocalVariables(goid, frame, deferredCall int, cfg proc.LoadConfig) ([]*proc.Variable, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
-	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
+	s, err := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
 	if err != nil {
 		return nil, err
 	}
-	pv, err := s.LocalVariables(cfg)
-	if err != nil {
-		return nil, err
-	}
-	return convertVars(pv), err
+	return s.LocalVariables(cfg)
 }
 
 // FunctionArguments returns the arguments to the current function.
-func (d *Debugger) FunctionArguments(scope api.EvalScope, cfg proc.LoadConfig) ([]api.Variable, error) {
+func (d *Debugger) FunctionArguments(goid, frame, deferredCall int, cfg proc.LoadConfig) ([]*proc.Variable, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
-	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
-	if err != nil {
-		return nil, err
-	}
-	pv, err := s.FunctionArguments(cfg)
+	s, err := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
 	if err != nil {
 		return nil, err
 	}
-	return convertVars(pv), nil
+	return s.FunctionArguments(cfg)
 }
 
 // EvalVariableInScope will attempt to evaluate the variable represented by 'symbol'
 // in the scope provided.
-func (d *Debugger) EvalVariableInScope(scope api.EvalScope, symbol string, cfg proc.LoadConfig) (*api.Variable, error) {
+func (d *Debugger) EvalVariableInScope(goid, frame, deferredCall int, symbol string, cfg proc.LoadConfig) (*proc.Variable, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
-	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
+	s, err := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
 	if err != nil {
 		return nil, err
 	}
-	v, err := s.EvalVariable(symbol, cfg)
-	if err != nil {
-		return nil, err
-	}
-	return api.ConvertVar(v), err
+	return s.EvalVariable(symbol, cfg)
 }
 
 // SetVariableInScope will set the value of the variable represented by
 // 'symbol' to the value given, in the given scope.
-func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string) error {
+func (d *Debugger) SetVariableInScope(goid, frame, deferredCall int, symbol, value string) error {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
-	s, err := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
+	s, err := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
 	if err != nil {
 		return err
 	}
@@ -1326,25 +1268,16 @@ func (d *Debugger) SetVariableInScope(scope api.EvalScope, symbol, value string)
 }
 
 // Goroutines will return a list of goroutines in the target process.
-func (d *Debugger) Goroutines(start, count int) ([]*api.Goroutine, int, error) {
+func (d *Debugger) Goroutines(start, count int) ([]*proc.G, int, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
-
-	goroutines := []*api.Goroutine{}
-	gs, nextg, err := proc.GoroutinesInfo(d.target, start, count)
-	if err != nil {
-		return nil, 0, err
-	}
-	for _, g := range gs {
-		goroutines = append(goroutines, api.ConvertGoroutine(g))
-	}
-	return goroutines, nextg, err
+	return proc.GoroutinesInfo(d.target, start, count)
 }
 
 // Stacktrace returns a list of Stackframes for the given goroutine. The
 // length of the returned list will be min(stack_len, depth).
 // If 'full' is true, then local vars, function args, etc will be returned as well.
-func (d *Debugger) Stacktrace(goroutineID, depth int, opts api.StacktraceOptions, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
+func (d *Debugger) Stacktrace(goroutineID, depth int, opts api.StacktraceOptions) ([]proc.Stackframe, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -1352,23 +1285,16 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, opts api.StacktraceOptions
 		return nil, err
 	}
 
-	var rawlocs []proc.Stackframe
-
 	g, err := proc.FindGoroutine(d.target, goroutineID)
 	if err != nil {
 		return nil, err
 	}
 
 	if g == nil {
-		rawlocs, err = proc.ThreadStacktrace(d.target.CurrentThread(), depth)
+		return proc.ThreadStacktrace(d.target.CurrentThread(), depth)
 	} else {
-		rawlocs, err = g.Stacktrace(depth, proc.StacktraceOptions(opts))
-	}
-	if err != nil {
-		return nil, err
+		return g.Stacktrace(depth, proc.StacktraceOptions(opts))
 	}
-
-	return d.convertStacktrace(rawlocs, cfg)
 }
 
 // Ancestors returns the stacktraces for the ancestors of a goroutine.
@@ -1413,6 +1339,15 @@ func (d *Debugger) Ancestors(goroutineID, numAncestors, depth int) ([]api.Ancest
 	return r, nil
 }
 
+// ConvertStacktrace converts a slice of proc.Stackframe into a slice of
+// api.Stackframe, loading local variables and arguments of each frame if
+// cfg is not nil.
+func (d *Debugger) ConvertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
+	return d.convertStacktrace(rawlocs, cfg)
+}
+
 func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadConfig) ([]api.Stackframe, error) {
 	locations := make([]api.Stackframe, 0, len(rawlocs))
 	for i := range rawlocs {
@@ -1441,8 +1376,8 @@ func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadCo
 				return nil, err
 			}
 
-			frame.Locals = convertVars(locals)
-			frame.Arguments = convertVars(arguments)
+			frame.Locals = api.ConvertVars(locals)
+			frame.Arguments = api.ConvertVars(arguments)
 		}
 		locations = append(locations, frame)
 	}
@@ -1480,8 +1415,28 @@ func (d *Debugger) convertDefers(defers []*proc.Defer) []api.Defer {
 	return r
 }
 
+// CurrentPackage returns the fully qualified name of the
+// package corresponding to the function location of the
+// current thread.
+func (d *Debugger) CurrentPackage() (string, error) {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
+
+	if _, err := d.target.Valid(); err != nil {
+		return "", err
+	}
+	loc, err := d.target.CurrentThread().Location()
+	if err != nil {
+		return "", err
+	}
+	if loc.Fn == nil {
+		return "", fmt.Errorf("unable to determine current package due to unspecified function location")
+	}
+	return loc.Fn.PackageName(), nil
+}
+
 // FindLocation will find the location specified by 'locStr'.
-func (d *Debugger) FindLocation(scope api.EvalScope, locStr string, includeNonExecutableLines bool) ([]api.Location, error) {
+func (d *Debugger) FindLocation(goid, frame, deferredCall int, locStr string, includeNonExecutableLines bool) ([]api.Location, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -1494,7 +1449,7 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string, includeNonEx
 		return nil, err
 	}
 
-	s, _ := proc.ConvertEvalScope(d.target, scope.GoroutineID, scope.Frame, scope.DeferredCall)
+	s, _ := proc.ConvertEvalScope(d.target, goid, frame, deferredCall)
 
 	locs, err := loc.Find(d.target, d.processArgs, s, locStr, includeNonExecutableLines)
 	for i := range locs {
@@ -1511,7 +1466,7 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string, includeNonEx
 
 // Disassemble code between startPC and endPC.
 // if endPC == 0 it will find the function containing startPC and disassemble the whole function.
-func (d *Debugger) Disassemble(goroutineID int, addr1, addr2 uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
+func (d *Debugger) Disassemble(goroutineID int, addr1, addr2 uint64) ([]proc.AsmInstruction, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
 
@@ -1539,17 +1494,13 @@ func (d *Debugger) Disassemble(goroutineID int, addr1, addr2 uint64, flavour api
 	}
 	regs, _ := curthread.Registers()
 
-	insts, err := proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
-	if err != nil {
-		return nil, err
-	}
-	disass := make(api.AsmInstructions, len(insts))
-
-	for i := range insts {
-		disass[i] = api.ConvertAsmInstruction(insts[i], insts[i].Text(proc.AssemblyFlavour(flavour), d.target.BinInfo()))
-	}
+	return proc.Disassemble(curthread, regs, d.target.Breakpoints(), d.target.BinInfo(), addr1, addr2)
+}
 
-	return disass, nil
+func (d *Debugger) AsmInstructionText(inst *proc.AsmInstruction, flavour proc.AssemblyFlavour) string {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
+	return inst.Text(flavour, d.target.BinInfo())
 }
 
 // Recorded returns true if the target is a recording.
@@ -1559,6 +1510,13 @@ func (d *Debugger) Recorded() (recorded bool, tracedir string) {
 	return d.target.Recorded()
 }
 
+// CurrentThread returns the current thread.
+func (d *Debugger) CurrentThread() proc.Thread {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
+	return d.target.CurrentThread()
+}
+
 // Checkpoint will set a checkpoint specified by the locspec.
 func (d *Debugger) Checkpoint(where string) (int, error) {
 	d.targetMutex.Lock()
@@ -1567,18 +1525,10 @@ func (d *Debugger) Checkpoint(where string) (int, error) {
 }
 
 // Checkpoints will return a list of checkpoints.
-func (d *Debugger) Checkpoints() ([]api.Checkpoint, error) {
+func (d *Debugger) Checkpoints() ([]proc.Checkpoint, error) {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
-	cps, err := d.target.Checkpoints()
-	if err != nil {
-		return nil, err
-	}
-	r := make([]api.Checkpoint, len(cps))
-	for i := range cps {
-		r[i] = api.ConvertCheckpoint(cps[i])
-	}
-	return r, nil
+	return d.target.Checkpoints()
 }
 
 // ClearCheckpoint will clear the checkpoint of the given ID.
@@ -1589,22 +1539,17 @@ func (d *Debugger) ClearCheckpoint(id int) error {
 }
 
 // ListDynamicLibraries returns a list of loaded dynamic libraries.
-func (d *Debugger) ListDynamicLibraries() []api.Image {
+func (d *Debugger) ListDynamicLibraries() []*proc.Image {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
-	bi := d.target.BinInfo()
-	r := make([]api.Image, 0, len(bi.Images)-1)
-	// skips the first image because it's the executable file
-	for i := range bi.Images[1:] {
-		r = append(r, api.ConvertImage(bi.Images[i+1]))
-	}
-	return r
+	return d.target.BinInfo().Images[1:] // skips the first image because it's the executable file
+
 }
 
 // ExamineMemory returns the raw memory stored at the given address.
 // The amount of data to be read is specified by length.
 // 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()
 	defer d.targetMutex.Unlock()
 
@@ -1652,30 +1597,10 @@ func (d *Debugger) GetVersion(out *api.GetVersionOut) error {
 // ListPackagesBuildInfo returns the list of packages used by the program along with
 // the directory where each package was compiled and optionally the list of
 // files constituting the package.
-func (d *Debugger) ListPackagesBuildInfo(includeFiles bool) []api.PackageBuildInfo {
+func (d *Debugger) ListPackagesBuildInfo(includeFiles bool) []*proc.PackageBuildInfo {
 	d.targetMutex.Lock()
 	defer d.targetMutex.Unlock()
-	pkgs := d.target.BinInfo().ListPackagesBuildInfo(includeFiles)
-	r := make([]api.PackageBuildInfo, 0, len(pkgs))
-	for _, pkg := range pkgs {
-		var files []string
-
-		if len(pkg.Files) > 0 {
-			files = make([]string, 0, len(pkg.Files))
-			for file := range pkg.Files {
-				files = append(files, file)
-			}
-		}
-
-		sort.Strings(files)
-
-		r = append(r, api.PackageBuildInfo{
-			ImportPath:    pkg.ImportPath,
-			DirectoryPath: pkg.DirectoryPath,
-			Files:         files,
-		})
-	}
-	return r
+	return d.target.BinInfo().ListPackagesBuildInfo(includeFiles)
 }
 
 // StopRecording stops a recording (if one is in progress)
@@ -1688,6 +1613,16 @@ func (d *Debugger) StopRecording() error {
 	return d.stopRecording()
 }
 
+// LockTarget acquires the target mutex.
+func (d *Debugger) LockTarget() {
+	d.targetMutex.Lock()
+}
+
+// UnlockTarget releases the target mutex.
+func (d *Debugger) UnlockTarget() {
+	d.targetMutex.Unlock()
+}
+
 func go11DecodeErrorCheck(err error) error {
 	if _, isdecodeerr := err.(dwarf.DecodeError); !isdecodeerr {
 		return err
diff --git a/service/rpc1/server.go b/service/rpc1/server.go
index 128e7903..6f082c22 100644
--- a/service/rpc1/server.go
+++ b/service/rpc1/server.go
@@ -93,12 +93,12 @@ func (s *RPCServer) StacktraceGoroutine(args *StacktraceGoroutineArgs, locations
 	if args.Full {
 		loadcfg = &defaultLoadConfig
 	}
-	locs, err := s.debugger.Stacktrace(args.Id, args.Depth, 0, loadcfg)
+	locs, err := s.debugger.Stacktrace(args.Id, args.Depth, 0)
 	if err != nil {
 		return err
 	}
-	*locations = locs
-	return nil
+	*locations, err = s.debugger.ConvertStacktrace(locs, loadcfg)
+	return err
 }
 
 func (s *RPCServer) ListBreakpoints(arg interface{}, breakpoints *[]*api.Breakpoint) error {
@@ -147,8 +147,14 @@ func (s *RPCServer) AmendBreakpoint(amend *api.Breakpoint, unused *int) error {
 }
 
 func (s *RPCServer) ListThreads(arg interface{}, threads *[]*api.Thread) (err error) {
-	*threads, err = s.debugger.Threads()
-	return err
+	pthreads, err := s.debugger.Threads()
+	if err != nil {
+		return err
+	}
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+	*threads = api.ConvertThreads(pthreads)
+	return nil
 }
 
 func (s *RPCServer) GetThread(id int, thread *api.Thread) error {
@@ -159,7 +165,9 @@ func (s *RPCServer) GetThread(id int, thread *api.Thread) error {
 	if t == nil {
 		return fmt.Errorf("no thread with id %d", id)
 	}
-	*thread = *t
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+	*thread = *api.ConvertThread(t)
 	return nil
 }
 
@@ -178,7 +186,7 @@ func (s *RPCServer) ListPackageVars(filter string, variables *[]api.Variable) er
 	if err != nil {
 		return err
 	}
-	*variables = vars
+	*variables = api.ConvertVars(vars)
 	return nil
 }
 
@@ -200,7 +208,7 @@ func (s *RPCServer) ListThreadPackageVars(args *ThreadListArgs, variables *[]api
 	if err != nil {
 		return err
 	}
-	*variables = vars
+	*variables = api.ConvertVars(vars)
 	return nil
 }
 
@@ -210,29 +218,30 @@ func (s *RPCServer) ListRegisters(arg interface{}, registers *string) error {
 		return err
 	}
 
-	regs, err := s.debugger.Registers(state.CurrentThread.ID, nil, false)
+	dregs, err := s.debugger.ThreadRegisters(state.CurrentThread.ID, false)
 	if err != nil {
 		return err
 	}
+	regs := api.Registers(api.ConvertRegisters(dregs, s.debugger.DwarfRegisterToString, false))
 	*registers = regs.String()
 	return nil
 }
 
 func (s *RPCServer) ListLocalVars(scope api.EvalScope, variables *[]api.Variable) error {
-	vars, err := s.debugger.LocalVariables(scope, defaultLoadConfig)
+	vars, err := s.debugger.LocalVariables(scope.GoroutineID, scope.Frame, scope.DeferredCall, defaultLoadConfig)
 	if err != nil {
 		return err
 	}
-	*variables = vars
+	*variables = api.ConvertVars(vars)
 	return nil
 }
 
 func (s *RPCServer) ListFunctionArgs(scope api.EvalScope, variables *[]api.Variable) error {
-	vars, err := s.debugger.FunctionArguments(scope, defaultLoadConfig)
+	vars, err := s.debugger.FunctionArguments(scope.GoroutineID, scope.Frame, scope.DeferredCall, defaultLoadConfig)
 	if err != nil {
 		return err
 	}
-	*variables = vars
+	*variables = api.ConvertVars(vars)
 	return nil
 }
 
@@ -242,11 +251,11 @@ type EvalSymbolArgs struct {
 }
 
 func (s *RPCServer) EvalSymbol(args EvalSymbolArgs, variable *api.Variable) error {
-	v, err := s.debugger.EvalVariableInScope(args.Scope, args.Symbol, defaultLoadConfig)
+	v, err := s.debugger.EvalVariableInScope(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Symbol, defaultLoadConfig)
 	if err != nil {
 		return err
 	}
-	*variable = *v
+	*variable = *api.ConvertVar(v)
 	return nil
 }
 
@@ -258,7 +267,7 @@ type SetSymbolArgs struct {
 
 func (s *RPCServer) SetSymbol(args SetSymbolArgs, unused *int) error {
 	*unused = 0
-	return s.debugger.SetVariableInScope(args.Scope, args.Symbol, args.Value)
+	return s.debugger.SetVariableInScope(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Symbol, args.Value)
 }
 
 func (s *RPCServer) ListSources(filter string, sources *[]string) error {
@@ -293,7 +302,9 @@ func (s *RPCServer) ListGoroutines(arg interface{}, goroutines *[]*api.Goroutine
 	if err != nil {
 		return err
 	}
-	*goroutines = gs
+	s.debugger.LockTarget()
+	s.debugger.UnlockTarget()
+	*goroutines = api.ConvertGoroutines(gs)
 	return nil
 }
 
@@ -311,7 +322,7 @@ type FindLocationArgs struct {
 
 func (c *RPCServer) FindLocation(args FindLocationArgs, answer *[]api.Location) error {
 	var err error
-	*answer, err = c.debugger.FindLocation(args.Scope, args.Loc, false)
+	*answer, err = c.debugger.FindLocation(args.Scope.GoroutineID, args.Scope.Frame, args.Scope.DeferredCall, args.Loc, false)
 	return err
 }
 
@@ -323,6 +334,13 @@ type DisassembleRequest struct {
 
 func (c *RPCServer) Disassemble(args DisassembleRequest, answer *api.AsmInstructions) error {
 	var err error
-	*answer, err = c.debugger.Disassemble(args.Scope.GoroutineID, args.StartPC, args.EndPC, args.Flavour)
-	return err
+	insts, err := c.debugger.Disassemble(args.Scope.GoroutineID, args.StartPC, args.EndPC)
+	if err != nil {
+		return err
+	}
+	*answer = make(api.AsmInstructions, len(insts))
+	for i := range insts {
+		(*answer)[i] = api.ConvertAsmInstruction(insts[i], c.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(args.Flavour)))
+	}
+	return nil
 }
diff --git a/service/rpc2/client.go b/service/rpc2/client.go
index 7c6924f0..7de4dcb9 100644
--- a/service/rpc2/client.go
+++ b/service/rpc2/client.go
@@ -441,15 +441,14 @@ func (c *RPCClient) ListDynamicLibraries() ([]api.Image, error) {
 	return out.List, nil
 }
 
-func (c *RPCClient) ExamineMemory(address uintptr, count int) ([]byte, error) {
+func (c *RPCClient) ExamineMemory(address uint64, count int) ([]byte, bool, error) {
 	out := &ExaminedMemoryOut{}
 
 	err := c.call("ExamineMemory", ExamineMemoryIn{Length: count, Address: address}, out)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
-
-	return out.Mem, nil
+	return out.Mem, out.IsLittleEndian, nil
 }
 
 func (c *RPCClient) StopRecording() error {
diff --git a/service/rpc2/server.go b/service/rpc2/server.go
index 024bd29d..5d8c51c4 100644
--- a/service/rpc2/server.go
+++ b/service/rpc2/server.go
@@ -3,8 +3,11 @@ package rpc2
 import (
 	"errors"
 	"fmt"
+	"sort"
 	"time"
 
+	"github.com/go-delve/delve/pkg/dwarf/op"
+	"github.com/go-delve/delve/pkg/proc"
 	"github.com/go-delve/delve/service"
 	"github.com/go-delve/delve/service/api"
 	"github.com/go-delve/delve/service/debugger"
@@ -189,7 +192,11 @@ func (s *RPCServer) Stacktrace(arg StacktraceIn, out *StacktraceOut) error {
 		arg.Opts |= api.StacktraceReadDefers
 	}
 	var err error
-	out.Locations, err = s.debugger.Stacktrace(arg.Id, arg.Depth, arg.Opts, api.LoadConfigToProc(cfg))
+	rawlocs, err := s.debugger.Stacktrace(arg.Id, arg.Depth, arg.Opts)
+	if err != nil {
+		return err
+	}
+	out.Locations, err = s.debugger.ConvertStacktrace(rawlocs, api.LoadConfigToProc(cfg))
 	return err
 }
 
@@ -320,8 +327,14 @@ type ListThreadsOut struct {
 
 // ListThreads lists all threads.
 func (s *RPCServer) ListThreads(arg ListThreadsIn, out *ListThreadsOut) (err error) {
-	out.Threads, err = s.debugger.Threads()
-	return err
+	threads, err := s.debugger.Threads()
+	if err != nil {
+		return err
+	}
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+	out.Threads = api.ConvertThreads(threads)
+	return nil
 }
 
 type GetThreadIn struct {
@@ -341,7 +354,9 @@ func (s *RPCServer) GetThread(arg GetThreadIn, out *GetThreadOut) error {
 	if t == nil {
 		return fmt.Errorf("no thread with id %d", arg.Id)
 	}
-	out.Thread = t
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+	out.Thread = api.ConvertThread(t)
 	return nil
 }
 
@@ -370,7 +385,7 @@ func (s *RPCServer) ListPackageVars(arg ListPackageVarsIn, out *ListPackageVarsO
 	if err != nil {
 		return err
 	}
-	out.Variables = vars
+	out.Variables = api.ConvertVars(vars)
 	return nil
 }
 
@@ -397,11 +412,18 @@ func (s *RPCServer) ListRegisters(arg ListRegistersIn, out *ListRegistersOut) er
 		arg.ThreadID = state.CurrentThread.ID
 	}
 
-	regs, err := s.debugger.Registers(arg.ThreadID, arg.Scope, arg.IncludeFp)
+	var regs *op.DwarfRegisters
+	var err error
+
+	if arg.Scope != nil {
+		regs, err = s.debugger.ScopeRegisters(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.IncludeFp)
+	} else {
+		regs, err = s.debugger.ThreadRegisters(arg.ThreadID, arg.IncludeFp)
+	}
 	if err != nil {
 		return err
 	}
-	out.Regs = regs
+	out.Regs = api.ConvertRegisters(regs, s.debugger.DwarfRegisterToString, arg.IncludeFp)
 	out.Registers = out.Regs.String()
 
 	return nil
@@ -418,11 +440,11 @@ type ListLocalVarsOut struct {
 
 // ListLocalVars lists all local variables in scope.
 func (s *RPCServer) ListLocalVars(arg ListLocalVarsIn, out *ListLocalVarsOut) error {
-	vars, err := s.debugger.LocalVariables(arg.Scope, *api.LoadConfigToProc(&arg.Cfg))
+	vars, err := s.debugger.LocalVariables(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
 	if err != nil {
 		return err
 	}
-	out.Variables = vars
+	out.Variables = api.ConvertVars(vars)
 	return nil
 }
 
@@ -437,11 +459,11 @@ type ListFunctionArgsOut struct {
 
 // ListFunctionArgs lists all arguments to the current function
 func (s *RPCServer) ListFunctionArgs(arg ListFunctionArgsIn, out *ListFunctionArgsOut) error {
-	vars, err := s.debugger.FunctionArguments(arg.Scope, *api.LoadConfigToProc(&arg.Cfg))
+	vars, err := s.debugger.FunctionArguments(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, *api.LoadConfigToProc(&arg.Cfg))
 	if err != nil {
 		return err
 	}
-	out.Args = vars
+	out.Args = api.ConvertVars(vars)
 	return nil
 }
 
@@ -464,11 +486,11 @@ func (s *RPCServer) Eval(arg EvalIn, out *EvalOut) error {
 	if cfg == nil {
 		cfg = &api.LoadConfig{FollowPointers: true, MaxVariableRecurse: 1, MaxStringLen: 64, MaxArrayValues: 64, MaxStructFields: -1}
 	}
-	v, err := s.debugger.EvalVariableInScope(arg.Scope, arg.Expr, *api.LoadConfigToProc(cfg))
+	v, err := s.debugger.EvalVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Expr, *api.LoadConfigToProc(cfg))
 	if err != nil {
 		return err
 	}
-	out.Variable = v
+	out.Variable = api.ConvertVar(v)
 	return nil
 }
 
@@ -484,7 +506,7 @@ type SetOut struct {
 // Set sets the value of a variable. Only numerical types and
 // pointers are currently supported.
 func (s *RPCServer) Set(arg SetIn, out *SetOut) error {
-	return s.debugger.SetVariableInScope(arg.Scope, arg.Symbol, arg.Value)
+	return s.debugger.SetVariableInScope(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Symbol, arg.Value)
 }
 
 type ListSourcesIn struct {
@@ -562,7 +584,9 @@ func (s *RPCServer) ListGoroutines(arg ListGoroutinesIn, out *ListGoroutinesOut)
 	if err != nil {
 		return err
 	}
-	out.Goroutines = gs
+	s.debugger.LockTarget()
+	defer s.debugger.UnlockTarget()
+	out.Goroutines = api.ConvertGoroutines(gs)
 	out.Nextg = nextg
 	return nil
 }
@@ -607,7 +631,7 @@ type FindLocationOut struct {
 // NOTE: this function does not actually set breakpoints.
 func (c *RPCServer) FindLocation(arg FindLocationIn, out *FindLocationOut) error {
 	var err error
-	out.Locations, err = c.debugger.FindLocation(arg.Scope, arg.Loc, arg.IncludeNonExecutableLines)
+	out.Locations, err = c.debugger.FindLocation(arg.Scope.GoroutineID, arg.Scope.Frame, arg.Scope.DeferredCall, arg.Loc, arg.IncludeNonExecutableLines)
 	return err
 }
 
@@ -630,8 +654,15 @@ type DisassembleOut struct {
 // Disassemble will also try to calculate the destination address of an absolute indirect CALL if it happens to be the instruction the selected goroutine is stopped at.
 func (c *RPCServer) Disassemble(arg DisassembleIn, out *DisassembleOut) error {
 	var err error
-	out.Disassemble, err = c.debugger.Disassemble(arg.Scope.GoroutineID, arg.StartPC, arg.EndPC, arg.Flavour)
-	return err
+	insts, err := c.debugger.Disassemble(arg.Scope.GoroutineID, arg.StartPC, arg.EndPC)
+	if err != nil {
+		return err
+	}
+	out.Disassemble = make(api.AsmInstructions, len(insts))
+	for i := range insts {
+		out.Disassemble[i] = api.ConvertAsmInstruction(insts[i], c.debugger.AsmInstructionText(&insts[i], proc.AssemblyFlavour(arg.Flavour)))
+	}
+	return nil
 }
 
 type RecordedIn struct {
@@ -670,8 +701,15 @@ type ListCheckpointsOut struct {
 
 func (s *RPCServer) ListCheckpoints(arg ListCheckpointsIn, out *ListCheckpointsOut) error {
 	var err error
-	out.Checkpoints, err = s.debugger.Checkpoints()
-	return err
+	cps, err := s.debugger.Checkpoints()
+	if err != nil {
+		return err
+	}
+	out.Checkpoints = make([]api.Checkpoint, len(cps))
+	for i := range cps {
+		out.Checkpoints[i] = api.Checkpoint(cps[i])
+	}
+	return nil
 }
 
 type ClearCheckpointIn struct {
@@ -740,7 +778,11 @@ type ListDynamicLibrariesOut struct {
 }
 
 func (s *RPCServer) ListDynamicLibraries(in ListDynamicLibrariesIn, out *ListDynamicLibrariesOut) error {
-	out.List = s.debugger.ListDynamicLibraries()
+	imgs := s.debugger.ListDynamicLibraries()
+	out.List = make([]api.Image, 0, len(imgs))
+	for i := range imgs {
+		out.List[i] = api.ConvertImage(imgs[i])
+	}
 	return nil
 }
 
@@ -760,19 +802,39 @@ type ListPackagesBuildInfoOut struct {
 // Note that the directory path is a best guess and may be wrong is a tool
 // other than cmd/go is used to perform the build.
 func (s *RPCServer) ListPackagesBuildInfo(in ListPackagesBuildInfoIn, out *ListPackagesBuildInfoOut) error {
-	out.List = s.debugger.ListPackagesBuildInfo(in.IncludeFiles)
+	pkgs := s.debugger.ListPackagesBuildInfo(in.IncludeFiles)
+	out.List = make([]api.PackageBuildInfo, 0, len(pkgs))
+	for _, pkg := range pkgs {
+		var files []string
+
+		if len(pkg.Files) > 0 {
+			files = make([]string, 0, len(pkg.Files))
+			for file := range pkg.Files {
+				files = append(files, file)
+			}
+		}
+
+		sort.Strings(files)
+
+		out.List = append(out.List, api.PackageBuildInfo{
+			ImportPath:    pkg.ImportPath,
+			DirectoryPath: pkg.DirectoryPath,
+			Files:         files,
+		})
+	}
 	return nil
 }
 
 // ExamineMemoryIn holds the arguments of ExamineMemory
 type ExamineMemoryIn struct {
-	Address uintptr
+	Address uint64
 	Length  int
 }
 
 // ExaminedMemoryOut holds the return values of ExamineMemory
 type ExaminedMemoryOut struct {
-	Mem []byte
+	Mem            []byte
+	IsLittleEndian bool
 }
 
 func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) error {
@@ -785,6 +847,8 @@ func (s *RPCServer) ExamineMemory(arg ExamineMemoryIn, out *ExaminedMemoryOut) e
 	}
 
 	out.Mem = Mem
+	out.IsLittleEndian = true //TODO: get byte order from debugger.target.BinInfo().Arch
+
 	return nil
 }
 
diff --git a/vendor/github.com/google/go-dap/.travis.yml b/vendor/github.com/google/go-dap/.travis.yml
index 54bc099d..f976928d 100644
--- a/vendor/github.com/google/go-dap/.travis.yml
+++ b/vendor/github.com/google/go-dap/.travis.yml
@@ -1,7 +1,11 @@
+# For Travis to run this for pending PRs and pushes to the master branch, make
+# sure to add a Webhook in the Github repository Settings to send all events to
+# https://notify.travis-ci.org
 language: go
 
 go:
-- 1.13.x
+  - 1.13.x
+  - 1.14.x
 
 env:
   global:
diff --git a/vendor/github.com/google/go-dap/schematypes.go b/vendor/github.com/google/go-dap/schematypes.go
index 597903af..369d7a2d 100644
--- a/vendor/github.com/google/go-dap/schematypes.go
+++ b/vendor/github.com/google/go-dap/schematypes.go
@@ -28,12 +28,35 @@ type Message interface {
 	GetSeq() int
 }
 
+// RequestMessage is an interface implemented by all Request-types.
+type RequestMessage interface {
+	Message
+	// GetRequest provides access to the embedded Request.
+	GetRequest() *Request
+}
+
+// ResponseMessage is an interface implemented by all Response-types.
+type ResponseMessage interface {
+	Message
+	// GetResponse provides access to the embedded Response.
+	GetResponse() *Response
+}
+
+// EventMessage is an interface implemented by all Event-types.
+type EventMessage interface {
+	Message
+	// GetEvent provides access to the embedded Event.
+	GetEvent() *Event
+}
+
 // ProtocolMessage: Base class of requests, responses, and events.
 type ProtocolMessage struct {
 	Seq  int    `json:"seq"`
 	Type string `json:"type"`
 }
 
+func (m *ProtocolMessage) GetSeq() int { return m.Seq }
+
 // Request: A client or debug adapter initiated request.
 type Request struct {
 	ProtocolMessage
@@ -69,22 +92,31 @@ type ErrorResponseBody struct {
 	Error ErrorMessage `json:"error,omitempty"`
 }
 
-// CancelRequest: The 'cancel' request is used by the frontend to indicate that it is no longer interested in the result produced by a specific request issued earlier.
+func (r *ErrorResponse) GetResponse() *Response { return &r.Response }
+
+// CancelRequest: The 'cancel' request is used by the frontend in two situations:
+// - to indicate that it is no longer interested in the result produced by a specific request issued earlier
+// - to cancel a progress sequence. Clients should only call this request if the capability 'supportsCancelRequest' is true.
 // This request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' in honouring this request but there are no guarantees.
 // The 'cancel' request may return an error if it could not cancel an operation but a frontend should refrain from presenting this error to end users.
 // A frontend client should only call this request if the capability 'supportsCancelRequest' is true.
-// The request that got canceled still needs to send a response back.
-// This can either be a normal result ('success' attribute true) or an error response ('success' attribute false and the 'message' set to 'cancelled').
+// The request that got canceled still needs to send a response back. This can either be a normal result ('success' attribute true)
+// or an error response ('success' attribute false and the 'message' set to 'cancelled').
 // Returning partial results from a cancelled request is possible but please note that a frontend client has no generic way for detecting that a response is partial or not.
+//  The progress that got cancelled still needs to send a 'progressEnd' event back.
+//  A client should not assume that progress just got cancelled after sending the 'cancel' request.
 type CancelRequest struct {
 	Request
 
 	Arguments CancelArguments `json:"arguments,omitempty"`
 }
 
+func (r *CancelRequest) GetRequest() *Request { return &r.Request }
+
 // CancelArguments: Arguments for 'cancel' request.
 type CancelArguments struct {
-	RequestId int `json:"requestId,omitempty"`
+	RequestId  int    `json:"requestId,omitempty"`
+	ProgressId string `json:"progressId,omitempty"`
 }
 
 // CancelResponse: Response to 'cancel' request. This is just an acknowledgement, so no body field is required.
@@ -92,12 +124,14 @@ type CancelResponse struct {
 	Response
 }
 
+func (r *CancelResponse) GetResponse() *Response { return &r.Response }
+
 // InitializedEvent: This event indicates that the debug adapter is ready to accept configuration requests (e.g. SetBreakpointsRequest, SetExceptionBreakpointsRequest).
 // A debug adapter is expected to send this event when it is ready to accept configuration requests (but not before the 'initialize' request has finished).
 // The sequence of events/requests is as follows:
 // - adapters sends 'initialized' event (after the 'initialize' request has returned)
 // - frontend sends zero or more 'setBreakpoints' requests
-// - frontend sends one 'setFunctionBreakpoints' request
+// - frontend sends one 'setFunctionBreakpoints' request (if capability 'supportsFunctionBreakpoints' is true)
 // - frontend sends a 'setExceptionBreakpoints' request if one or more 'exceptionBreakpointFilters' have been defined (or if 'supportsConfigurationDoneRequest' is not defined or false)
 // - frontend sends other future configuration requests
 // - frontend sends one 'configurationDone' request to indicate the end of the configuration.
@@ -105,8 +139,10 @@ type InitializedEvent struct {
 	Event
 }
 
+func (e *InitializedEvent) GetEvent() *Event { return &e.Event }
+
 // StoppedEvent: The event indicates that the execution of the debuggee has stopped due to some condition.
-// This can be caused by a break point previously set, a stepping action has completed, by executing a debugger statement etc.
+// This can be caused by a break point previously set, a stepping request has completed, by executing a debugger statement etc.
 type StoppedEvent struct {
 	Event
 
@@ -122,6 +158,8 @@ type StoppedEventBody struct {
 	AllThreadsStopped bool   `json:"allThreadsStopped,omitempty"`
 }
 
+func (e *StoppedEvent) GetEvent() *Event { return &e.Event }
+
 // ContinuedEvent: The event indicates that the execution of the debuggee has continued.
 // Please note: a debug adapter is not expected to send this event in response to a request that implies that execution continues, e.g. 'launch' or 'continue'.
 // It is only necessary to send a 'continued' event if there was no previous request that implied this.
@@ -136,6 +174,8 @@ type ContinuedEventBody struct {
 	AllThreadsContinued bool `json:"allThreadsContinued,omitempty"`
 }
 
+func (e *ContinuedEvent) GetEvent() *Event { return &e.Event }
+
 // ExitedEvent: The event indicates that the debuggee has exited and returns its exit code.
 type ExitedEvent struct {
 	Event
@@ -147,6 +187,8 @@ type ExitedEventBody struct {
 	ExitCode int `json:"exitCode"`
 }
 
+func (e *ExitedEvent) GetEvent() *Event { return &e.Event }
+
 // TerminatedEvent: The event indicates that debugging of the debuggee has terminated. This does **not** mean that the debuggee itself has exited.
 type TerminatedEvent struct {
 	Event
@@ -158,6 +200,8 @@ type TerminatedEventBody struct {
 	Restart interface{} `json:"restart,omitempty"`
 }
 
+func (e *TerminatedEvent) GetEvent() *Event { return &e.Event }
+
 // ThreadEvent: The event indicates that a thread has started or exited.
 type ThreadEvent struct {
 	Event
@@ -170,6 +214,8 @@ type ThreadEventBody struct {
 	ThreadId int    `json:"threadId"`
 }
 
+func (e *ThreadEvent) GetEvent() *Event { return &e.Event }
+
 // OutputEvent: The event indicates that the target has produced some output.
 type OutputEvent struct {
 	Event
@@ -180,6 +226,7 @@ type OutputEvent struct {
 type OutputEventBody struct {
 	Category           string      `json:"category,omitempty"`
 	Output             string      `json:"output"`
+	Group              string      `json:"group,omitempty"`
 	VariablesReference int         `json:"variablesReference,omitempty"`
 	Source             Source      `json:"source,omitempty"`
 	Line               int         `json:"line,omitempty"`
@@ -187,6 +234,8 @@ type OutputEventBody struct {
 	Data               interface{} `json:"data,omitempty"`
 }
 
+func (e *OutputEvent) GetEvent() *Event { return &e.Event }
+
 // BreakpointEvent: The event indicates that some information about a breakpoint has changed.
 type BreakpointEvent struct {
 	Event
@@ -199,6 +248,8 @@ type BreakpointEventBody struct {
 	Breakpoint Breakpoint `json:"breakpoint"`
 }
 
+func (e *BreakpointEvent) GetEvent() *Event { return &e.Event }
+
 // ModuleEvent: The event indicates that some information about a module has changed.
 type ModuleEvent struct {
 	Event
@@ -211,6 +262,8 @@ type ModuleEventBody struct {
 	Module Module `json:"module"`
 }
 
+func (e *ModuleEvent) GetEvent() *Event { return &e.Event }
+
 // LoadedSourceEvent: The event indicates that some source has been added, changed, or removed from the set of all loaded sources.
 type LoadedSourceEvent struct {
 	Event
@@ -223,6 +276,8 @@ type LoadedSourceEventBody struct {
 	Source Source `json:"source"`
 }
 
+func (e *LoadedSourceEvent) GetEvent() *Event { return &e.Event }
+
 // ProcessEvent: The event indicates that the debugger has begun debugging a new process. Either one that it has launched, or one that it has attached to.
 type ProcessEvent struct {
 	Event
@@ -238,6 +293,8 @@ type ProcessEventBody struct {
 	PointerSize     int    `json:"pointerSize,omitempty"`
 }
 
+func (e *ProcessEvent) GetEvent() *Event { return &e.Event }
+
 // CapabilitiesEvent: The event indicates that one or more capabilities have changed.
 // Since the capabilities are dependent on the frontend and its UI, it might not be possible to change that at random times (or too late).
 // Consequently this event has a hint characteristic: a frontend can only be expected to make a 'best effort' in honouring individual capabilities but there are no guarantees.
@@ -252,13 +309,72 @@ type CapabilitiesEventBody struct {
 	Capabilities Capabilities `json:"capabilities"`
 }
 
-// RunInTerminalRequest: This request is sent from the debug adapter to the client to run a command in a terminal. This is typically used to launch the debuggee in a terminal provided by the client.
+func (e *CapabilitiesEvent) GetEvent() *Event { return &e.Event }
+
+// ProgressStartEvent: The event signals that a long running operation is about to start and
+// provides additional information for the client to set up a corresponding progress and cancellation UI.
+// The client is free to delay the showing of the UI in order to reduce flicker.
+// This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.
+type ProgressStartEvent struct {
+	Event
+
+	Body ProgressStartEventBody `json:"body"`
+}
+
+type ProgressStartEventBody struct {
+	ProgressId  string `json:"progressId"`
+	Title       string `json:"title"`
+	RequestId   int    `json:"requestId,omitempty"`
+	Cancellable bool   `json:"cancellable,omitempty"`
+	Message     string `json:"message,omitempty"`
+	Percentage  int    `json:"percentage,omitempty"`
+}
+
+func (e *ProgressStartEvent) GetEvent() *Event { return &e.Event }
+
+// ProgressUpdateEvent: The event signals that the progress reporting needs to updated with a new message and/or percentage.
+// The client does not have to update the UI immediately, but the clients needs to keep track of the message and/or percentage values.
+// This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.
+type ProgressUpdateEvent struct {
+	Event
+
+	Body ProgressUpdateEventBody `json:"body"`
+}
+
+type ProgressUpdateEventBody struct {
+	ProgressId string `json:"progressId"`
+	Message    string `json:"message,omitempty"`
+	Percentage int    `json:"percentage,omitempty"`
+}
+
+func (e *ProgressUpdateEvent) GetEvent() *Event { return &e.Event }
+
+// ProgressEndEvent: The event signals the end of the progress reporting with an optional final message.
+// This event should only be sent if the client has passed the value true for the 'supportsProgressReporting' capability of the 'initialize' request.
+type ProgressEndEvent struct {
+	Event
+
+	Body ProgressEndEventBody `json:"body"`
+}
+
+type ProgressEndEventBody struct {
+	ProgressId string `json:"progressId"`
+	Message    string `json:"message,omitempty"`
+}
+
+func (e *ProgressEndEvent) GetEvent() *Event { return &e.Event }
+
+// RunInTerminalRequest: This optional request is sent from the debug adapter to the client to run a command in a terminal.
+// This is typically used to launch the debuggee in a terminal provided by the client.
+// This request should only be called if the client has passed the value true for the 'supportsRunInTerminalRequest' capability of the 'initialize' request.
 type RunInTerminalRequest struct {
 	Request
 
 	Arguments RunInTerminalRequestArguments `json:"arguments"`
 }
 
+func (r *RunInTerminalRequest) GetRequest() *Request { return &r.Request }
+
 // RunInTerminalRequestArguments: Arguments for 'runInTerminal' request.
 type RunInTerminalRequestArguments struct {
 	Kind  string                 `json:"kind,omitempty"`
@@ -280,8 +396,12 @@ type RunInTerminalResponseBody struct {
 	ShellProcessId int `json:"shellProcessId,omitempty"`
 }
 
-// InitializeRequest: The 'initialize' request is sent as the first request from the client to the debug adapter in order to configure it with client capabilities and to retrieve capabilities from the debug adapter.
-// Until the debug adapter has responded to with an 'initialize' response, the client must not send any additional requests or events to the debug adapter. In addition the debug adapter is not allowed to send any requests or events to the client until it has responded with an 'initialize' response.
+func (r *RunInTerminalResponse) GetResponse() *Response { return &r.Response }
+
+// InitializeRequest: The 'initialize' request is sent as the first request from the client to the debug adapter
+// in order to configure it with client capabilities and to retrieve capabilities from the debug adapter.
+// Until the debug adapter has responded to with an 'initialize' response, the client must not send any additional requests or events to the debug adapter.
+// In addition the debug adapter is not allowed to send any requests or events to the client until it has responded with an 'initialize' response.
 // The 'initialize' request may only be sent once.
 type InitializeRequest struct {
 	Request
@@ -289,6 +409,8 @@ type InitializeRequest struct {
 	Arguments InitializeRequestArguments `json:"arguments"`
 }
 
+func (r *InitializeRequest) GetRequest() *Request { return &r.Request }
+
 // InitializeRequestArguments: Arguments for 'initialize' request.
 type InitializeRequestArguments struct {
 	ClientID                     string `json:"clientID,omitempty"`
@@ -302,6 +424,7 @@ type InitializeRequestArguments struct {
 	SupportsVariablePaging       bool   `json:"supportsVariablePaging,omitempty"`
 	SupportsRunInTerminalRequest bool   `json:"supportsRunInTerminalRequest,omitempty"`
 	SupportsMemoryReferences     bool   `json:"supportsMemoryReferences,omitempty"`
+	SupportsProgressReporting    bool   `json:"supportsProgressReporting,omitempty"`
 }
 
 // InitializeResponse: Response to 'initialize' request.
@@ -311,13 +434,19 @@ type InitializeResponse struct {
 	Body Capabilities `json:"body,omitempty"`
 }
 
-// ConfigurationDoneRequest: The client of the debug protocol must send this request at the end of the sequence of configuration requests (which was started by the 'initialized' event).
+func (r *InitializeResponse) GetResponse() *Response { return &r.Response }
+
+// ConfigurationDoneRequest: This optional request indicates that the client has finished initialization of the debug adapter.
+// So it is the last request in the sequence of configuration requests (which was started by the 'initialized' event).
+// Clients should only call this request if the capability 'supportsConfigurationDoneRequest' is true.
 type ConfigurationDoneRequest struct {
 	Request
 
 	Arguments ConfigurationDoneArguments `json:"arguments,omitempty"`
 }
 
+func (r *ConfigurationDoneRequest) GetRequest() *Request { return &r.Request }
+
 // ConfigurationDoneArguments: Arguments for 'configurationDone' request.
 type ConfigurationDoneArguments struct {
 }
@@ -327,25 +456,35 @@ type ConfigurationDoneResponse struct {
 	Response
 }
 
-// LaunchRequest: The launch request is sent from the client to the debug adapter to start the debuggee with or without debugging (if 'noDebug' is true). Since launching is debugger/runtime specific, the arguments for this request are not part of this specification.
+func (r *ConfigurationDoneResponse) GetResponse() *Response { return &r.Response }
+
+// LaunchRequest: This launch request is sent from the client to the debug adapter to start the debuggee with or without debugging (if 'noDebug' is true).
+// Since launching is debugger/runtime specific, the arguments for this request are not part of this specification.
 type LaunchRequest struct {
 	Request
 
 	Arguments map[string]interface{} `json:"arguments"`
 }
 
+func (r *LaunchRequest) GetRequest() *Request { return &r.Request }
+
 // LaunchResponse: Response to 'launch' request. This is just an acknowledgement, so no body field is required.
 type LaunchResponse struct {
 	Response
 }
 
-// AttachRequest: The attach request is sent from the client to the debug adapter to attach to a debuggee that is already running. Since attaching is debugger/runtime specific, the arguments for this request are not part of this specification.
+func (r *LaunchResponse) GetResponse() *Response { return &r.Response }
+
+// AttachRequest: The attach request is sent from the client to the debug adapter to attach to a debuggee that is already running.
+// Since attaching is debugger/runtime specific, the arguments for this request are not part of this specification.
 type AttachRequest struct {
 	Request
 
 	Arguments AttachRequestArguments `json:"arguments"`
 }
 
+func (r *AttachRequest) GetRequest() *Request { return &r.Request }
+
 // AttachRequestArguments: Arguments for 'attach' request. Additional attributes are implementation specific.
 type AttachRequestArguments struct {
 	Restart interface{} `json:"__restart,omitempty"`
@@ -356,16 +495,18 @@ type AttachResponse struct {
 	Response
 }
 
-// RestartRequest: Restarts a debug session. If the capability 'supportsRestartRequest' is missing or has the value false,
-// the client will implement 'restart' by terminating the debug adapter first and then launching it anew.
-// A debug adapter can override this default behaviour by implementing a restart request
-// and setting the capability 'supportsRestartRequest' to true.
+func (r *AttachResponse) GetResponse() *Response { return &r.Response }
+
+// RestartRequest: Restarts a debug session. Clients should only call this request if the capability 'supportsRestartRequest' is true.
+// If the capability is missing or has the value false, a typical client will emulate 'restart' by terminating the debug adapter first and then launching it anew.
 type RestartRequest struct {
 	Request
 
 	Arguments RestartArguments `json:"arguments,omitempty"`
 }
 
+func (r *RestartRequest) GetRequest() *Request { return &r.Request }
+
 // RestartArguments: Arguments for 'restart' request.
 type RestartArguments struct {
 }
@@ -375,13 +516,21 @@ type RestartResponse struct {
 	Response
 }
 
-// DisconnectRequest: The 'disconnect' request is sent from the client to the debug adapter in order to stop debugging. It asks the debug adapter to disconnect from the debuggee and to terminate the debug adapter. If the debuggee has been started with the 'launch' request, the 'disconnect' request terminates the debuggee. If the 'attach' request was used to connect to the debuggee, 'disconnect' does not terminate the debuggee. This behavior can be controlled with the 'terminateDebuggee' argument (if supported by the debug adapter).
+func (r *RestartResponse) GetResponse() *Response { return &r.Response }
+
+// DisconnectRequest: The 'disconnect' request is sent from the client to the debug adapter in order to stop debugging.
+// It asks the debug adapter to disconnect from the debuggee and to terminate the debug adapter.
+// If the debuggee has been started with the 'launch' request, the 'disconnect' request terminates the debuggee.
+// If the 'attach' request was used to connect to the debuggee, 'disconnect' does not terminate the debuggee.
+// This behavior can be controlled with the 'terminateDebuggee' argument (if supported by the debug adapter).
 type DisconnectRequest struct {
 	Request
 
 	Arguments DisconnectArguments `json:"arguments,omitempty"`
 }
 
+func (r *DisconnectRequest) GetRequest() *Request { return &r.Request }
+
 // DisconnectArguments: Arguments for 'disconnect' request.
 type DisconnectArguments struct {
 	Restart           bool `json:"restart,omitempty"`
@@ -393,13 +542,18 @@ type DisconnectResponse struct {
 	Response
 }
 
+func (r *DisconnectResponse) GetResponse() *Response { return &r.Response }
+
 // TerminateRequest: The 'terminate' request is sent from the client to the debug adapter in order to give the debuggee a chance for terminating itself.
+// Clients should only call this request if the capability 'supportsTerminateRequest' is true.
 type TerminateRequest struct {
 	Request
 
 	Arguments TerminateArguments `json:"arguments,omitempty"`
 }
 
+func (r *TerminateRequest) GetRequest() *Request { return &r.Request }
+
 // TerminateArguments: Arguments for 'terminate' request.
 type TerminateArguments struct {
 	Restart bool `json:"restart,omitempty"`
@@ -410,13 +564,18 @@ type TerminateResponse struct {
 	Response
 }
 
+func (r *TerminateResponse) GetResponse() *Response { return &r.Response }
+
 // BreakpointLocationsRequest: The 'breakpointLocations' request returns all possible locations for source breakpoints in a given range.
+// Clients should only call this request if the capability 'supportsBreakpointLocationsRequest' is true.
 type BreakpointLocationsRequest struct {
 	Request
 
 	Arguments BreakpointLocationsArguments `json:"arguments,omitempty"`
 }
 
+func (r *BreakpointLocationsRequest) GetRequest() *Request { return &r.Request }
+
 // BreakpointLocationsArguments: Arguments for 'breakpointLocations' request.
 type BreakpointLocationsArguments struct {
 	Source    Source `json:"source"`
@@ -438,6 +597,8 @@ type BreakpointLocationsResponseBody struct {
 	Breakpoints []BreakpointLocation `json:"breakpoints"`
 }
 
+func (r *BreakpointLocationsResponse) GetResponse() *Response { return &r.Response }
+
 // SetBreakpointsRequest: Sets multiple breakpoints for a single source and clears all previous breakpoints in that source.
 // To clear all breakpoint for a source, specify an empty array.
 // When a breakpoint is hit, a 'stopped' event (with reason 'breakpoint') is generated.
@@ -447,6 +608,8 @@ type SetBreakpointsRequest struct {
 	Arguments SetBreakpointsArguments `json:"arguments"`
 }
 
+func (r *SetBreakpointsRequest) GetRequest() *Request { return &r.Request }
+
 // SetBreakpointsArguments: Arguments for 'setBreakpoints' request.
 type SetBreakpointsArguments struct {
 	Source         Source             `json:"source"`
@@ -470,15 +633,20 @@ type SetBreakpointsResponseBody struct {
 	Breakpoints []Breakpoint `json:"breakpoints"`
 }
 
+func (r *SetBreakpointsResponse) GetResponse() *Response { return &r.Response }
+
 // SetFunctionBreakpointsRequest: Replaces all existing function breakpoints with new function breakpoints.
 // To clear all function breakpoints, specify an empty array.
 // When a function breakpoint is hit, a 'stopped' event (with reason 'function breakpoint') is generated.
+// Clients should only call this request if the capability 'supportsFunctionBreakpoints' is true.
 type SetFunctionBreakpointsRequest struct {
 	Request
 
 	Arguments SetFunctionBreakpointsArguments `json:"arguments"`
 }
 
+func (r *SetFunctionBreakpointsRequest) GetRequest() *Request { return &r.Request }
+
 // SetFunctionBreakpointsArguments: Arguments for 'setFunctionBreakpoints' request.
 type SetFunctionBreakpointsArguments struct {
 	Breakpoints []FunctionBreakpoint `json:"breakpoints"`
@@ -496,13 +664,19 @@ type SetFunctionBreakpointsResponseBody struct {
 	Breakpoints []Breakpoint `json:"breakpoints"`
 }
 
-// SetExceptionBreakpointsRequest: The request configures the debuggers response to thrown exceptions. If an exception is configured to break, a 'stopped' event is fired (with reason 'exception').
+func (r *SetFunctionBreakpointsResponse) GetResponse() *Response { return &r.Response }
+
+// SetExceptionBreakpointsRequest: The request configures the debuggers response to thrown exceptions.
+// If an exception is configured to break, a 'stopped' event is fired (with reason 'exception').
+// Clients should only call this request if the capability 'exceptionBreakpointFilters' returns one or more filters.
 type SetExceptionBreakpointsRequest struct {
 	Request
 
 	Arguments SetExceptionBreakpointsArguments `json:"arguments"`
 }
 
+func (r *SetExceptionBreakpointsRequest) GetRequest() *Request { return &r.Request }
+
 // SetExceptionBreakpointsArguments: Arguments for 'setExceptionBreakpoints' request.
 type SetExceptionBreakpointsArguments struct {
 	Filters          []string           `json:"filters"`
@@ -514,13 +688,18 @@ type SetExceptionBreakpointsResponse struct {
 	Response
 }
 
+func (r *SetExceptionBreakpointsResponse) GetResponse() *Response { return &r.Response }
+
 // DataBreakpointInfoRequest: Obtains information on a possible data breakpoint that could be set on an expression or variable.
+// Clients should only call this request if the capability 'supportsDataBreakpoints' is true.
 type DataBreakpointInfoRequest struct {
 	Request
 
 	Arguments DataBreakpointInfoArguments `json:"arguments"`
 }
 
+func (r *DataBreakpointInfoRequest) GetRequest() *Request { return &r.Request }
+
 // DataBreakpointInfoArguments: Arguments for 'dataBreakpointInfo' request.
 type DataBreakpointInfoArguments struct {
 	VariablesReference int    `json:"variablesReference,omitempty"`
@@ -541,15 +720,20 @@ type DataBreakpointInfoResponseBody struct {
 	CanPersist  bool                       `json:"canPersist,omitempty"`
 }
 
+func (r *DataBreakpointInfoResponse) GetResponse() *Response { return &r.Response }
+
 // SetDataBreakpointsRequest: Replaces all existing data breakpoints with new data breakpoints.
 // To clear all data breakpoints, specify an empty array.
 // When a data breakpoint is hit, a 'stopped' event (with reason 'data breakpoint') is generated.
+// Clients should only call this request if the capability 'supportsDataBreakpoints' is true.
 type SetDataBreakpointsRequest struct {
 	Request
 
 	Arguments SetDataBreakpointsArguments `json:"arguments"`
 }
 
+func (r *SetDataBreakpointsRequest) GetRequest() *Request { return &r.Request }
+
 // SetDataBreakpointsArguments: Arguments for 'setDataBreakpoints' request.
 type SetDataBreakpointsArguments struct {
 	Breakpoints []DataBreakpoint `json:"breakpoints"`
@@ -567,6 +751,38 @@ type SetDataBreakpointsResponseBody struct {
 	Breakpoints []Breakpoint `json:"breakpoints"`
 }
 
+func (r *SetDataBreakpointsResponse) GetResponse() *Response { return &r.Response }
+
+// SetInstructionBreakpointsRequest: Replaces all existing instruction breakpoints. Typically, instruction breakpoints would be set from a diassembly window.
+// To clear all instruction breakpoints, specify an empty array.
+// When an instruction breakpoint is hit, a 'stopped' event (with reason 'instruction breakpoint') is generated.
+// Clients should only call this request if the capability 'supportsInstructionBreakpoints' is true.
+type SetInstructionBreakpointsRequest struct {
+	Request
+
+	Arguments SetInstructionBreakpointsArguments `json:"arguments"`
+}
+
+func (r *SetInstructionBreakpointsRequest) GetRequest() *Request { return &r.Request }
+
+// SetInstructionBreakpointsArguments: Arguments for 'setInstructionBreakpoints' request
+type SetInstructionBreakpointsArguments struct {
+	Breakpoints []InstructionBreakpoint `json:"breakpoints"`
+}
+
+// SetInstructionBreakpointsResponse: Response to 'setInstructionBreakpoints' request
+type SetInstructionBreakpointsResponse struct {
+	Response
+
+	Body SetInstructionBreakpointsResponseBody `json:"body"`
+}
+
+type SetInstructionBreakpointsResponseBody struct {
+	Breakpoints []Breakpoint `json:"breakpoints"`
+}
+
+func (r *SetInstructionBreakpointsResponse) GetResponse() *Response { return &r.Response }
+
 // ContinueRequest: The request starts the debuggee to run again.
 type ContinueRequest struct {
 	Request
@@ -574,6 +790,8 @@ type ContinueRequest struct {
 	Arguments ContinueArguments `json:"arguments"`
 }
 
+func (r *ContinueRequest) GetRequest() *Request { return &r.Request }
+
 // ContinueArguments: Arguments for 'continue' request.
 type ContinueArguments struct {
 	ThreadId int `json:"threadId"`
@@ -587,9 +805,11 @@ type ContinueResponse struct {
 }
 
 type ContinueResponseBody struct {
-	AllThreadsContinued bool `json:"allThreadsContinued,omitempty"`
+	AllThreadsContinued bool `json:"allThreadsContinued"`
 }
 
+func (r *ContinueResponse) GetResponse() *Response { return &r.Response }
+
 // NextRequest: The request starts the debuggee to run again for one step.
 // The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.
 type NextRequest struct {
@@ -598,9 +818,12 @@ type NextRequest struct {
 	Arguments NextArguments `json:"arguments"`
 }
 
+func (r *NextRequest) GetRequest() *Request { return &r.Request }
+
 // NextArguments: Arguments for 'next' request.
 type NextArguments struct {
-	ThreadId int `json:"threadId"`
+	ThreadId    int                 `json:"threadId"`
+	Granularity SteppingGranularity `json:"granularity,omitempty"`
 }
 
 // NextResponse: Response to 'next' request. This is just an acknowledgement, so no body field is required.
@@ -608,6 +831,8 @@ type NextResponse struct {
 	Response
 }
 
+func (r *NextResponse) GetResponse() *Response { return &r.Response }
+
 // StepInRequest: The request starts the debuggee to step into a function/method if possible.
 // If it cannot step into a target, 'stepIn' behaves like 'next'.
 // The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.
@@ -620,10 +845,13 @@ type StepInRequest struct {
 	Arguments StepInArguments `json:"arguments"`
 }
 
+func (r *StepInRequest) GetRequest() *Request { return &r.Request }
+
 // StepInArguments: Arguments for 'stepIn' request.
 type StepInArguments struct {
-	ThreadId int `json:"threadId"`
-	TargetId int `json:"targetId,omitempty"`
+	ThreadId    int                 `json:"threadId"`
+	TargetId    int                 `json:"targetId,omitempty"`
+	Granularity SteppingGranularity `json:"granularity,omitempty"`
 }
 
 // StepInResponse: Response to 'stepIn' request. This is just an acknowledgement, so no body field is required.
@@ -631,6 +859,8 @@ type StepInResponse struct {
 	Response
 }
 
+func (r *StepInResponse) GetResponse() *Response { return &r.Response }
+
 // StepOutRequest: The request starts the debuggee to run again for one step.
 // The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.
 type StepOutRequest struct {
@@ -639,9 +869,12 @@ type StepOutRequest struct {
 	Arguments StepOutArguments `json:"arguments"`
 }
 
+func (r *StepOutRequest) GetRequest() *Request { return &r.Request }
+
 // StepOutArguments: Arguments for 'stepOut' request.
 type StepOutArguments struct {
-	ThreadId int `json:"threadId"`
+	ThreadId    int                 `json:"threadId"`
+	Granularity SteppingGranularity `json:"granularity,omitempty"`
 }
 
 // StepOutResponse: Response to 'stepOut' request. This is just an acknowledgement, so no body field is required.
@@ -649,17 +882,23 @@ type StepOutResponse struct {
 	Response
 }
 
+func (r *StepOutResponse) GetResponse() *Response { return &r.Response }
+
 // StepBackRequest: The request starts the debuggee to run one step backwards.
-// The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed. Clients should only call this request if the capability 'supportsStepBack' is true.
+// The debug adapter first sends the response and then a 'stopped' event (with reason 'step') after the step has completed.
+// Clients should only call this request if the capability 'supportsStepBack' is true.
 type StepBackRequest struct {
 	Request
 
 	Arguments StepBackArguments `json:"arguments"`
 }
 
+func (r *StepBackRequest) GetRequest() *Request { return &r.Request }
+
 // StepBackArguments: Arguments for 'stepBack' request.
 type StepBackArguments struct {
-	ThreadId int `json:"threadId"`
+	ThreadId    int                 `json:"threadId"`
+	Granularity SteppingGranularity `json:"granularity,omitempty"`
 }
 
 // StepBackResponse: Response to 'stepBack' request. This is just an acknowledgement, so no body field is required.
@@ -667,13 +906,18 @@ type StepBackResponse struct {
 	Response
 }
 
-// ReverseContinueRequest: The request starts the debuggee to run backward. Clients should only call this request if the capability 'supportsStepBack' is true.
+func (r *StepBackResponse) GetResponse() *Response { return &r.Response }
+
+// ReverseContinueRequest: The request starts the debuggee to run backward.
+// Clients should only call this request if the capability 'supportsStepBack' is true.
 type ReverseContinueRequest struct {
 	Request
 
 	Arguments ReverseContinueArguments `json:"arguments"`
 }
 
+func (r *ReverseContinueRequest) GetRequest() *Request { return &r.Request }
+
 // ReverseContinueArguments: Arguments for 'reverseContinue' request.
 type ReverseContinueArguments struct {
 	ThreadId int `json:"threadId"`
@@ -684,14 +928,19 @@ type ReverseContinueResponse struct {
 	Response
 }
 
+func (r *ReverseContinueResponse) GetResponse() *Response { return &r.Response }
+
 // RestartFrameRequest: The request restarts execution of the specified stackframe.
 // The debug adapter first sends the response and then a 'stopped' event (with reason 'restart') after the restart has completed.
+// Clients should only call this request if the capability 'supportsRestartFrame' is true.
 type RestartFrameRequest struct {
 	Request
 
 	Arguments RestartFrameArguments `json:"arguments"`
 }
 
+func (r *RestartFrameRequest) GetRequest() *Request { return &r.Request }
+
 // RestartFrameArguments: Arguments for 'restartFrame' request.
 type RestartFrameArguments struct {
 	FrameId int `json:"frameId"`
@@ -702,16 +951,21 @@ type RestartFrameResponse struct {
 	Response
 }
 
+func (r *RestartFrameResponse) GetResponse() *Response { return &r.Response }
+
 // GotoRequest: The request sets the location where the debuggee will continue to run.
 // This makes it possible to skip the execution of code or to executed code again.
 // The code between the current location and the goto target is not executed but skipped.
 // The debug adapter first sends the response and then a 'stopped' event with reason 'goto'.
+// Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true (because only then goto targets exist that can be passed as arguments).
 type GotoRequest struct {
 	Request
 
 	Arguments GotoArguments `json:"arguments"`
 }
 
+func (r *GotoRequest) GetRequest() *Request { return &r.Request }
+
 // GotoArguments: Arguments for 'goto' request.
 type GotoArguments struct {
 	ThreadId int `json:"threadId"`
@@ -723,6 +977,8 @@ type GotoResponse struct {
 	Response
 }
 
+func (r *GotoResponse) GetResponse() *Response { return &r.Response }
+
 // PauseRequest: The request suspends the debuggee.
 // The debug adapter first sends the response and then a 'stopped' event (with reason 'pause') after the thread has been paused successfully.
 type PauseRequest struct {
@@ -731,6 +987,8 @@ type PauseRequest struct {
 	Arguments PauseArguments `json:"arguments"`
 }
 
+func (r *PauseRequest) GetRequest() *Request { return &r.Request }
+
 // PauseArguments: Arguments for 'pause' request.
 type PauseArguments struct {
 	ThreadId int `json:"threadId"`
@@ -741,6 +999,8 @@ type PauseResponse struct {
 	Response
 }
 
+func (r *PauseResponse) GetResponse() *Response { return &r.Response }
+
 // StackTraceRequest: The request returns a stacktrace from the current execution state.
 type StackTraceRequest struct {
 	Request
@@ -748,6 +1008,8 @@ type StackTraceRequest struct {
 	Arguments StackTraceArguments `json:"arguments"`
 }
 
+func (r *StackTraceRequest) GetRequest() *Request { return &r.Request }
+
 // StackTraceArguments: Arguments for 'stackTrace' request.
 type StackTraceArguments struct {
 	ThreadId   int              `json:"threadId"`
@@ -768,6 +1030,8 @@ type StackTraceResponseBody struct {
 	TotalFrames int          `json:"totalFrames,omitempty"`
 }
 
+func (r *StackTraceResponse) GetResponse() *Response { return &r.Response }
+
 // ScopesRequest: The request returns the variable scopes for a given stackframe ID.
 type ScopesRequest struct {
 	Request
@@ -775,6 +1039,8 @@ type ScopesRequest struct {
 	Arguments ScopesArguments `json:"arguments"`
 }
 
+func (r *ScopesRequest) GetRequest() *Request { return &r.Request }
+
 // ScopesArguments: Arguments for 'scopes' request.
 type ScopesArguments struct {
 	FrameId int `json:"frameId"`
@@ -791,6 +1057,8 @@ type ScopesResponseBody struct {
 	Scopes []Scope `json:"scopes"`
 }
 
+func (r *ScopesResponse) GetResponse() *Response { return &r.Response }
+
 // VariablesRequest: Retrieves all child variables for the given variable reference.
 // An optional filter can be used to limit the fetched children to either named or indexed children.
 type VariablesRequest struct {
@@ -799,6 +1067,8 @@ type VariablesRequest struct {
 	Arguments VariablesArguments `json:"arguments"`
 }
 
+func (r *VariablesRequest) GetRequest() *Request { return &r.Request }
+
 // VariablesArguments: Arguments for 'variables' request.
 type VariablesArguments struct {
 	VariablesReference int         `json:"variablesReference"`
@@ -819,13 +1089,17 @@ type VariablesResponseBody struct {
 	Variables []Variable `json:"variables"`
 }
 
-// SetVariableRequest: Set the variable with the given name in the variable container to a new value.
+func (r *VariablesResponse) GetResponse() *Response { return &r.Response }
+
+// SetVariableRequest: Set the variable with the given name in the variable container to a new value. Clients should only call this request if the capability 'supportsSetVariable' is true.
 type SetVariableRequest struct {
 	Request
 
 	Arguments SetVariableArguments `json:"arguments"`
 }
 
+func (r *SetVariableRequest) GetRequest() *Request { return &r.Request }
+
 // SetVariableArguments: Arguments for 'setVariable' request.
 type SetVariableArguments struct {
 	VariablesReference int         `json:"variablesReference"`
@@ -849,6 +1123,8 @@ type SetVariableResponseBody struct {
 	IndexedVariables   int    `json:"indexedVariables,omitempty"`
 }
 
+func (r *SetVariableResponse) GetResponse() *Response { return &r.Response }
+
 // SourceRequest: The request retrieves the source code for a given source reference.
 type SourceRequest struct {
 	Request
@@ -856,6 +1132,8 @@ type SourceRequest struct {
 	Arguments SourceArguments `json:"arguments"`
 }
 
+func (r *SourceRequest) GetRequest() *Request { return &r.Request }
+
 // SourceArguments: Arguments for 'source' request.
 type SourceArguments struct {
 	Source          Source `json:"source,omitempty"`
@@ -874,11 +1152,15 @@ type SourceResponseBody struct {
 	MimeType string `json:"mimeType,omitempty"`
 }
 
+func (r *SourceResponse) GetResponse() *Response { return &r.Response }
+
 // ThreadsRequest: The request retrieves a list of all threads.
 type ThreadsRequest struct {
 	Request
 }
 
+func (r *ThreadsRequest) GetRequest() *Request { return &r.Request }
+
 // ThreadsResponse: Response to 'threads' request.
 type ThreadsResponse struct {
 	Response
@@ -890,13 +1172,18 @@ type ThreadsResponseBody struct {
 	Threads []Thread `json:"threads"`
 }
 
+func (r *ThreadsResponse) GetResponse() *Response { return &r.Response }
+
 // TerminateThreadsRequest: The request terminates the threads with the given ids.
+// Clients should only call this request if the capability 'supportsTerminateThreadsRequest' is true.
 type TerminateThreadsRequest struct {
 	Request
 
 	Arguments TerminateThreadsArguments `json:"arguments"`
 }
 
+func (r *TerminateThreadsRequest) GetRequest() *Request { return &r.Request }
+
 // TerminateThreadsArguments: Arguments for 'terminateThreads' request.
 type TerminateThreadsArguments struct {
 	ThreadIds []int `json:"threadIds,omitempty"`
@@ -907,13 +1194,18 @@ type TerminateThreadsResponse struct {
 	Response
 }
 
-// ModulesRequest: Modules can be retrieved from the debug adapter with the ModulesRequest which can either return all modules or a range of modules to support paging.
+func (r *TerminateThreadsResponse) GetResponse() *Response { return &r.Response }
+
+// ModulesRequest: Modules can be retrieved from the debug adapter with this request which can either return all modules or a range of modules to support paging.
+// Clients should only call this request if the capability 'supportsModulesRequest' is true.
 type ModulesRequest struct {
 	Request
 
 	Arguments ModulesArguments `json:"arguments"`
 }
 
+func (r *ModulesRequest) GetRequest() *Request { return &r.Request }
+
 // ModulesArguments: Arguments for 'modules' request.
 type ModulesArguments struct {
 	StartModule int `json:"startModule,omitempty"`
@@ -932,13 +1224,18 @@ type ModulesResponseBody struct {
 	TotalModules int      `json:"totalModules,omitempty"`
 }
 
+func (r *ModulesResponse) GetResponse() *Response { return &r.Response }
+
 // LoadedSourcesRequest: Retrieves the set of all sources currently loaded by the debugged process.
+// Clients should only call this request if the capability 'supportsLoadedSourcesRequest' is true.
 type LoadedSourcesRequest struct {
 	Request
 
 	Arguments LoadedSourcesArguments `json:"arguments,omitempty"`
 }
 
+func (r *LoadedSourcesRequest) GetRequest() *Request { return &r.Request }
+
 // LoadedSourcesArguments: Arguments for 'loadedSources' request.
 type LoadedSourcesArguments struct {
 }
@@ -954,6 +1251,8 @@ type LoadedSourcesResponseBody struct {
 	Sources []Source `json:"sources"`
 }
 
+func (r *LoadedSourcesResponse) GetResponse() *Response { return &r.Response }
+
 // EvaluateRequest: Evaluates the given expression in the context of the top most stack frame.
 // The expression has access to any variables and arguments that are in scope.
 type EvaluateRequest struct {
@@ -962,6 +1261,8 @@ type EvaluateRequest struct {
 	Arguments EvaluateArguments `json:"arguments"`
 }
 
+func (r *EvaluateRequest) GetRequest() *Request { return &r.Request }
+
 // EvaluateArguments: Arguments for 'evaluate' request.
 type EvaluateArguments struct {
 	Expression string      `json:"expression"`
@@ -987,14 +1288,19 @@ type EvaluateResponseBody struct {
 	MemoryReference    string                   `json:"memoryReference,omitempty"`
 }
 
+func (r *EvaluateResponse) GetResponse() *Response { return &r.Response }
+
 // SetExpressionRequest: Evaluates the given 'value' expression and assigns it to the 'expression' which must be a modifiable l-value.
 // The expressions have access to any variables and arguments that are in scope of the specified frame.
+// Clients should only call this request if the capability 'supportsSetExpression' is true.
 type SetExpressionRequest struct {
 	Request
 
 	Arguments SetExpressionArguments `json:"arguments"`
 }
 
+func (r *SetExpressionRequest) GetRequest() *Request { return &r.Request }
+
 // SetExpressionArguments: Arguments for 'setExpression' request.
 type SetExpressionArguments struct {
 	Expression string      `json:"expression"`
@@ -1019,15 +1325,20 @@ type SetExpressionResponseBody struct {
 	IndexedVariables   int                      `json:"indexedVariables,omitempty"`
 }
 
+func (r *SetExpressionResponse) GetResponse() *Response { return &r.Response }
+
 // StepInTargetsRequest: This request retrieves the possible stepIn targets for the specified stack frame.
 // These targets can be used in the 'stepIn' request.
 // The StepInTargets may only be called if the 'supportsStepInTargetsRequest' capability exists and is true.
+// Clients should only call this request if the capability 'supportsStepInTargetsRequest' is true.
 type StepInTargetsRequest struct {
 	Request
 
 	Arguments StepInTargetsArguments `json:"arguments"`
 }
 
+func (r *StepInTargetsRequest) GetRequest() *Request { return &r.Request }
+
 // StepInTargetsArguments: Arguments for 'stepInTargets' request.
 type StepInTargetsArguments struct {
 	FrameId int `json:"frameId"`
@@ -1044,15 +1355,19 @@ type StepInTargetsResponseBody struct {
 	Targets []StepInTarget `json:"targets"`
 }
 
+func (r *StepInTargetsResponse) GetResponse() *Response { return &r.Response }
+
 // GotoTargetsRequest: This request retrieves the possible goto targets for the specified source location.
 // These targets can be used in the 'goto' request.
-// The GotoTargets request may only be called if the 'supportsGotoTargetsRequest' capability exists and is true.
+// Clients should only call this request if the capability 'supportsGotoTargetsRequest' is true.
 type GotoTargetsRequest struct {
 	Request
 
 	Arguments GotoTargetsArguments `json:"arguments"`
 }
 
+func (r *GotoTargetsRequest) GetRequest() *Request { return &r.Request }
+
 // GotoTargetsArguments: Arguments for 'gotoTargets' request.
 type GotoTargetsArguments struct {
 	Source Source `json:"source"`
@@ -1071,14 +1386,18 @@ type GotoTargetsResponseBody struct {
 	Targets []GotoTarget `json:"targets"`
 }
 
+func (r *GotoTargetsResponse) GetResponse() *Response { return &r.Response }
+
 // CompletionsRequest: Returns a list of possible completions for a given caret position and text.
-// The CompletionsRequest may only be called if the 'supportsCompletionsRequest' capability exists and is true.
+// Clients should only call this request if the capability 'supportsCompletionsRequest' is true.
 type CompletionsRequest struct {
 	Request
 
 	Arguments CompletionsArguments `json:"arguments"`
 }
 
+func (r *CompletionsRequest) GetRequest() *Request { return &r.Request }
+
 // CompletionsArguments: Arguments for 'completions' request.
 type CompletionsArguments struct {
 	FrameId int    `json:"frameId,omitempty"`
@@ -1098,13 +1417,18 @@ type CompletionsResponseBody struct {
 	Targets []CompletionItem `json:"targets"`
 }
 
+func (r *CompletionsResponse) GetResponse() *Response { return &r.Response }
+
 // ExceptionInfoRequest: Retrieves the details of the exception that caused this event to be raised.
+// Clients should only call this request if the capability 'supportsExceptionInfoRequest' is true.
 type ExceptionInfoRequest struct {
 	Request
 
 	Arguments ExceptionInfoArguments `json:"arguments"`
 }
 
+func (r *ExceptionInfoRequest) GetRequest() *Request { return &r.Request }
+
 // ExceptionInfoArguments: Arguments for 'exceptionInfo' request.
 type ExceptionInfoArguments struct {
 	ThreadId int `json:"threadId"`
@@ -1124,13 +1448,18 @@ type ExceptionInfoResponseBody struct {
 	Details     ExceptionDetails   `json:"details,omitempty"`
 }
 
+func (r *ExceptionInfoResponse) GetResponse() *Response { return &r.Response }
+
 // ReadMemoryRequest: Reads bytes from memory at the provided location.
+// Clients should only call this request if the capability 'supportsReadMemoryRequest' is true.
 type ReadMemoryRequest struct {
 	Request
 
 	Arguments ReadMemoryArguments `json:"arguments"`
 }
 
+func (r *ReadMemoryRequest) GetRequest() *Request { return &r.Request }
+
 // ReadMemoryArguments: Arguments for 'readMemory' request.
 type ReadMemoryArguments struct {
 	MemoryReference string `json:"memoryReference"`
@@ -1151,13 +1480,18 @@ type ReadMemoryResponseBody struct {
 	Data            string `json:"data,omitempty"`
 }
 
+func (r *ReadMemoryResponse) GetResponse() *Response { return &r.Response }
+
 // DisassembleRequest: Disassembles code stored at the provided location.
+// Clients should only call this request if the capability 'supportsDisassembleRequest' is true.
 type DisassembleRequest struct {
 	Request
 
 	Arguments DisassembleArguments `json:"arguments"`
 }
 
+func (r *DisassembleRequest) GetRequest() *Request { return &r.Request }
+
 // DisassembleArguments: Arguments for 'disassemble' request.
 type DisassembleArguments struct {
 	MemoryReference   string `json:"memoryReference"`
@@ -1178,6 +1512,8 @@ type DisassembleResponseBody struct {
 	Instructions []DisassembledInstruction `json:"instructions"`
 }
 
+func (r *DisassembleResponse) GetResponse() *Response { return &r.Response }
+
 // Capabilities: Information about the capabilities of a debug adapter.
 type Capabilities struct {
 	SupportsConfigurationDoneRequest   bool                         `json:"supportsConfigurationDoneRequest,omitempty"`
@@ -1212,6 +1548,9 @@ type Capabilities struct {
 	SupportsDisassembleRequest         bool                         `json:"supportsDisassembleRequest,omitempty"`
 	SupportsCancelRequest              bool                         `json:"supportsCancelRequest,omitempty"`
 	SupportsBreakpointLocationsRequest bool                         `json:"supportsBreakpointLocationsRequest,omitempty"`
+	SupportsClipboardContext           bool                         `json:"supportsClipboardContext,omitempty"`
+	SupportsSteppingGranularity        bool                         `json:"supportsSteppingGranularity,omitempty"`
+	SupportsInstructionBreakpoints     bool                         `json:"supportsInstructionBreakpoints,omitempty"`
 }
 
 // ExceptionBreakpointsFilter: An ExceptionBreakpointsFilter is shown in the UI as an option for configuring how exceptions are dealt with.
@@ -1253,7 +1592,8 @@ type Module struct {
 	AddressRange   string      `json:"addressRange,omitempty"`
 }
 
-// ColumnDescriptor: A ColumnDescriptor specifies what module attribute to show in a column of the ModulesView, how to format it, and what the column's label should be.
+// ColumnDescriptor: A ColumnDescriptor specifies what module attribute to show in a column of the ModulesView, how to format it,
+// and what the column's label should be.
 // It is only used if the underlying UI actually supports this level of customization.
 type ColumnDescriptor struct {
 	AttributeName string `json:"attributeName"`
@@ -1275,7 +1615,8 @@ type Thread struct {
 	Name string `json:"name"`
 }
 
-// Source: A Source is a descriptor for source code. It is returned from the debug adapter as part of a StackFrame and it is used by clients when specifying breakpoints.
+// Source: A Source is a descriptor for source code.
+// It is returned from the debug adapter as part of a StackFrame and it is used by clients when specifying breakpoints.
 type Source struct {
 	Name             string      `json:"name,omitempty"`
 	Path             string      `json:"path,omitempty"`
@@ -1376,18 +1717,31 @@ type DataBreakpoint struct {
 	HitCondition string                   `json:"hitCondition,omitempty"`
 }
 
-// Breakpoint: Information about a Breakpoint created in setBreakpoints or setFunctionBreakpoints.
+// InstructionBreakpoint: Properties of a breakpoint passed to the setInstructionBreakpoints request
+type InstructionBreakpoint struct {
+	InstructionReference string `json:"instructionReference"`
+	Offset               int    `json:"offset,omitempty"`
+	Condition            string `json:"condition,omitempty"`
+	HitCondition         string `json:"hitCondition,omitempty"`
+}
+
+// Breakpoint: Information about a Breakpoint created in setBreakpoints, setFunctionBreakpoints, setInstructionBreakpoints, or setDataBreakpoints.
 type Breakpoint struct {
-	Id        int    `json:"id,omitempty"`
-	Verified  bool   `json:"verified"`
-	Message   string `json:"message,omitempty"`
-	Source    Source `json:"source,omitempty"`
-	Line      int    `json:"line,omitempty"`
-	Column    int    `json:"column,omitempty"`
-	EndLine   int    `json:"endLine,omitempty"`
-	EndColumn int    `json:"endColumn,omitempty"`
+	Id                   int    `json:"id,omitempty"`
+	Verified             bool   `json:"verified"`
+	Message              string `json:"message,omitempty"`
+	Source               Source `json:"source,omitempty"`
+	Line                 int    `json:"line,omitempty"`
+	Column               int    `json:"column,omitempty"`
+	EndLine              int    `json:"endLine,omitempty"`
+	EndColumn            int    `json:"endColumn,omitempty"`
+	InstructionReference string `json:"instructionReference,omitempty"`
+	Offset               int    `json:"offset,omitempty"`
 }
 
+// SteppingGranularity: The granularity of one 'step' in the stepping requests 'next', 'stepIn', 'stepOut', and 'stepBack'.
+type SteppingGranularity string
+
 // StepInTarget: A StepInTarget can be used in the 'stepIn' request and determines into which single target the stepIn request should step.
 type StepInTarget struct {
 	Id    int    `json:"id"`
@@ -1408,12 +1762,14 @@ type GotoTarget struct {
 
 // CompletionItem: CompletionItems are the suggestions returned from the CompletionsRequest.
 type CompletionItem struct {
-	Label    string             `json:"label"`
-	Text     string             `json:"text,omitempty"`
-	SortText string             `json:"sortText,omitempty"`
-	Type     CompletionItemType `json:"type,omitempty"`
-	Start    int                `json:"start,omitempty"`
-	Length   int                `json:"length,omitempty"`
+	Label           string             `json:"label"`
+	Text            string             `json:"text,omitempty"`
+	SortText        string             `json:"sortText,omitempty"`
+	Type            CompletionItemType `json:"type,omitempty"`
+	Start           int                `json:"start,omitempty"`
+	Length          int                `json:"length,omitempty"`
+	SelectionStart  int                `json:"selectionStart,omitempty"`
+	SelectionLength int                `json:"selectionLength,omitempty"`
 }
 
 // CompletionItemType: Some predefined types for the CompletionItem. Please note that not all clients have specific icons for all of them.
@@ -1459,7 +1815,9 @@ type ExceptionOptions struct {
 // userUnhandled: breaks if the exception is not handled by user code.
 type ExceptionBreakMode string
 
-// ExceptionPathSegment: An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions. If a segment consists of more than one name, it matches the names provided if 'negate' is false or missing or it matches anything except the names provided if 'negate' is true.
+// ExceptionPathSegment: An ExceptionPathSegment represents a segment in a path that is used to match leafs or nodes in a tree of exceptions.
+// If a segment consists of more than one name, it matches the names provided if 'negate' is false or missing or
+// it matches anything except the names provided if 'negate' is true.
 type ExceptionPathSegment struct {
 	Negate bool     `json:"negate,omitempty"`
 	Names  []string `json:"names"`
@@ -1487,102 +1845,3 @@ type DisassembledInstruction struct {
 	EndLine          int    `json:"endLine,omitempty"`
 	EndColumn        int    `json:"endColumn,omitempty"`
 }
-
-func (m *Request) GetSeq() int                         { return m.Seq }
-func (m *Event) GetSeq() int                           { return m.Seq }
-func (m *Response) GetSeq() int                        { return m.Seq }
-func (m *ErrorResponse) GetSeq() int                   { return m.Seq }
-func (m *CancelRequest) GetSeq() int                   { return m.Seq }
-func (m *CancelResponse) GetSeq() int                  { return m.Seq }
-func (m *InitializedEvent) GetSeq() int                { return m.Seq }
-func (m *StoppedEvent) GetSeq() int                    { return m.Seq }
-func (m *ContinuedEvent) GetSeq() int                  { return m.Seq }
-func (m *ExitedEvent) GetSeq() int                     { return m.Seq }
-func (m *TerminatedEvent) GetSeq() int                 { return m.Seq }
-func (m *ThreadEvent) GetSeq() int                     { return m.Seq }
-func (m *OutputEvent) GetSeq() int                     { return m.Seq }
-func (m *BreakpointEvent) GetSeq() int                 { return m.Seq }
-func (m *ModuleEvent) GetSeq() int                     { return m.Seq }
-func (m *LoadedSourceEvent) GetSeq() int               { return m.Seq }
-func (m *ProcessEvent) GetSeq() int                    { return m.Seq }
-func (m *CapabilitiesEvent) GetSeq() int               { return m.Seq }
-func (m *RunInTerminalRequest) GetSeq() int            { return m.Seq }
-func (m *RunInTerminalResponse) GetSeq() int           { return m.Seq }
-func (m *InitializeRequest) GetSeq() int               { return m.Seq }
-func (m *InitializeResponse) GetSeq() int              { return m.Seq }
-func (m *ConfigurationDoneRequest) GetSeq() int        { return m.Seq }
-func (m *ConfigurationDoneResponse) GetSeq() int       { return m.Seq }
-func (m *LaunchRequest) GetSeq() int                   { return m.Seq }
-func (m *LaunchResponse) GetSeq() int                  { return m.Seq }
-func (m *AttachRequest) GetSeq() int                   { return m.Seq }
-func (m *AttachResponse) GetSeq() int                  { return m.Seq }
-func (m *RestartRequest) GetSeq() int                  { return m.Seq }
-func (m *RestartResponse) GetSeq() int                 { return m.Seq }
-func (m *DisconnectRequest) GetSeq() int               { return m.Seq }
-func (m *DisconnectResponse) GetSeq() int              { return m.Seq }
-func (m *TerminateRequest) GetSeq() int                { return m.Seq }
-func (m *TerminateResponse) GetSeq() int               { return m.Seq }
-func (m *BreakpointLocationsRequest) GetSeq() int      { return m.Seq }
-func (m *BreakpointLocationsResponse) GetSeq() int     { return m.Seq }
-func (m *SetBreakpointsRequest) GetSeq() int           { return m.Seq }
-func (m *SetBreakpointsResponse) GetSeq() int          { return m.Seq }
-func (m *SetFunctionBreakpointsRequest) GetSeq() int   { return m.Seq }
-func (m *SetFunctionBreakpointsResponse) GetSeq() int  { return m.Seq }
-func (m *SetExceptionBreakpointsRequest) GetSeq() int  { return m.Seq }
-func (m *SetExceptionBreakpointsResponse) GetSeq() int { return m.Seq }
-func (m *DataBreakpointInfoRequest) GetSeq() int       { return m.Seq }
-func (m *DataBreakpointInfoResponse) GetSeq() int      { return m.Seq }
-func (m *SetDataBreakpointsRequest) GetSeq() int       { return m.Seq }
-func (m *SetDataBreakpointsResponse) GetSeq() int      { return m.Seq }
-func (m *ContinueRequest) GetSeq() int                 { return m.Seq }
-func (m *ContinueResponse) GetSeq() int                { return m.Seq }
-func (m *NextRequest) GetSeq() int                     { return m.Seq }
-func (m *NextResponse) GetSeq() int                    { return m.Seq }
-func (m *StepInRequest) GetSeq() int                   { return m.Seq }
-func (m *StepInResponse) GetSeq() int                  { return m.Seq }
-func (m *StepOutRequest) GetSeq() int                  { return m.Seq }
-func (m *StepOutResponse) GetSeq() int                 { return m.Seq }
-func (m *StepBackRequest) GetSeq() int                 { return m.Seq }
-func (m *StepBackResponse) GetSeq() int                { return m.Seq }
-func (m *ReverseContinueRequest) GetSeq() int          { return m.Seq }
-func (m *ReverseContinueResponse) GetSeq() int         { return m.Seq }
-func (m *RestartFrameRequest) GetSeq() int             { return m.Seq }
-func (m *RestartFrameResponse) GetSeq() int            { return m.Seq }
-func (m *GotoRequest) GetSeq() int                     { return m.Seq }
-func (m *GotoResponse) GetSeq() int                    { return m.Seq }
-func (m *PauseRequest) GetSeq() int                    { return m.Seq }
-func (m *PauseResponse) GetSeq() int                   { return m.Seq }
-func (m *StackTraceRequest) GetSeq() int               { return m.Seq }
-func (m *StackTraceResponse) GetSeq() int              { return m.Seq }
-func (m *ScopesRequest) GetSeq() int                   { return m.Seq }
-func (m *ScopesResponse) GetSeq() int                  { return m.Seq }
-func (m *VariablesRequest) GetSeq() int                { return m.Seq }
-func (m *VariablesResponse) GetSeq() int               { return m.Seq }
-func (m *SetVariableRequest) GetSeq() int              { return m.Seq }
-func (m *SetVariableResponse) GetSeq() int             { return m.Seq }
-func (m *SourceRequest) GetSeq() int                   { return m.Seq }
-func (m *SourceResponse) GetSeq() int                  { return m.Seq }
-func (m *ThreadsRequest) GetSeq() int                  { return m.Seq }
-func (m *ThreadsResponse) GetSeq() int                 { return m.Seq }
-func (m *TerminateThreadsRequest) GetSeq() int         { return m.Seq }
-func (m *TerminateThreadsResponse) GetSeq() int        { return m.Seq }
-func (m *ModulesRequest) GetSeq() int                  { return m.Seq }
-func (m *ModulesResponse) GetSeq() int                 { return m.Seq }
-func (m *LoadedSourcesRequest) GetSeq() int            { return m.Seq }
-func (m *LoadedSourcesResponse) GetSeq() int           { return m.Seq }
-func (m *EvaluateRequest) GetSeq() int                 { return m.Seq }
-func (m *EvaluateResponse) GetSeq() int                { return m.Seq }
-func (m *SetExpressionRequest) GetSeq() int            { return m.Seq }
-func (m *SetExpressionResponse) GetSeq() int           { return m.Seq }
-func (m *StepInTargetsRequest) GetSeq() int            { return m.Seq }
-func (m *StepInTargetsResponse) GetSeq() int           { return m.Seq }
-func (m *GotoTargetsRequest) GetSeq() int              { return m.Seq }
-func (m *GotoTargetsResponse) GetSeq() int             { return m.Seq }
-func (m *CompletionsRequest) GetSeq() int              { return m.Seq }
-func (m *CompletionsResponse) GetSeq() int             { return m.Seq }
-func (m *ExceptionInfoRequest) GetSeq() int            { return m.Seq }
-func (m *ExceptionInfoResponse) GetSeq() int           { return m.Seq }
-func (m *ReadMemoryRequest) GetSeq() int               { return m.Seq }
-func (m *ReadMemoryResponse) GetSeq() int              { return m.Seq }
-func (m *DisassembleRequest) GetSeq() int              { return m.Seq }
-func (m *DisassembleResponse) GetSeq() int             { return m.Seq }
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 79c866e9..c2c71726 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -4,7 +4,7 @@ github.com/cosiner/argv
 github.com/cpuguy83/go-md2man/md2man
 # github.com/creack/pty v1.1.9
 github.com/creack/pty
-# github.com/google/go-dap v0.2.0
+# github.com/google/go-dap v0.3.0
 github.com/google/go-dap
 # github.com/hashicorp/golang-lru v0.5.4
 github.com/hashicorp/golang-lru/simplelru


Test patch:
diff --git a/pkg/proc/core/core_test.go b/pkg/proc/core/core_test.go
index 297da186..43e1ebcd 100644
--- a/pkg/proc/core/core_test.go
+++ b/pkg/proc/core/core_test.go
@@ -50,13 +50,13 @@ func TestSplicedReader(t *testing.T) {
 
 	type region struct {
 		data   []byte
-		off    uintptr
-		length uintptr
+		off    uint64
+		length uint64
 	}
 	tests := []struct {
 		name     string
 		regions  []region
-		readAddr uintptr
+		readAddr uint64
 		readLen  int
 		want     []byte
 	}{
diff --git a/pkg/proc/dwarf_expr_test.go b/pkg/proc/dwarf_expr_test.go
index 2410ecc5..f5e34173 100644
--- a/pkg/proc/dwarf_expr_test.go
+++ b/pkg/proc/dwarf_expr_test.go
@@ -64,7 +64,7 @@ func newFakeMemory(base uint64, contents ...interface{}) *fakeMemory {
 	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 {
 		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
 }
 
-func (mem *fakeMemory) WriteMemory(uintptr, []byte) (int, error) {
+func (mem *fakeMemory) WriteMemory(uint64, []byte) (int, error) {
 	return 0, fmt.Errorf("not implemented")
 }
 
diff --git a/pkg/proc/proc_general_test.go b/pkg/proc/proc_general_test.go
index b23f8a80..25ce0aeb 100644
--- a/pkg/proc/proc_general_test.go
+++ b/pkg/proc/proc_general_test.go
@@ -24,7 +24,7 @@ func TestIssue554(t *testing.T) {
 	case 8:
 		addr = 0xffffffffffffffff
 	}
-	if mem.contains(uintptr(addr), 40) {
+	if mem.contains(addr, 40) {
 		t.Fatalf("should be false")
 	}
 }
@@ -41,7 +41,7 @@ type memRead struct {
 	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.reads = append(dm.reads, memRead{uint64(addr), len(buf)})
 	a := int64(addr) - int64(dm.base)
@@ -55,7 +55,7 @@ func (dm *dummyMem) ReadMemory(buf []byte, addr uintptr) (int, error) {
 	return len(buf), nil
 }
 
-func (dm *dummyMem) WriteMemory(uintptr, []byte) (int, error) {
+func (dm *dummyMem) WriteMemory(uint64, []byte) (int, error) {
 	panic("not supported")
 }
 
@@ -80,7 +80,7 @@ func TestReadCStringValue(t *testing.T) {
 		t.Logf("base is %#x\n", tc.base)
 		dm.base = tc.base
 		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 {
 			t.Errorf("base=%#x readCStringValue: %v", tc.base, err)
 		}
diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go
index fedc1fa1..9b609a3f 100644
--- a/pkg/proc/proc_test.go
+++ b/pkg/proc/proc_test.go
@@ -102,7 +102,7 @@ func getRegisters(p *proc.Target, t *testing.T) proc.Registers {
 
 func dataAtAddr(thread proc.MemoryReadWriter, addr uint64) ([]byte, error) {
 	data := make([]byte, 1)
-	_, err := thread.ReadMemory(data, uintptr(addr))
+	_, err := thread.ReadMemory(data, addr)
 	return data, err
 }
 
diff --git a/pkg/terminal/command_test.go b/pkg/terminal/command_test.go
index da9d553b..78ad1a61 100644
--- a/pkg/terminal/command_test.go
+++ b/pkg/terminal/command_test.go
@@ -1093,7 +1093,7 @@ func TestExamineMemoryCmd(t *testing.T) {
 			t.Fatalf("could convert %s into int64, err %s", addressStr, err)
 		}
 
-		res := term.MustExec("examinemem  -len 52 -fmt hex " + addressStr)
+		res := term.MustExec("examinemem  -count 52 -fmt hex " + addressStr)
 		t.Logf("the result of examining memory \n%s", res)
 		// check first line
 		firstLine := fmt.Sprintf("%#x:   0x0a   0x0b   0x0c   0x0d   0x0e   0x0f   0x10   0x11", address)
@@ -1109,7 +1109,7 @@ func TestExamineMemoryCmd(t *testing.T) {
 
 		// second examining memory
 		term.MustExec("continue")
-		res = term.MustExec("x -len 52 -fmt bin " + addressStr)
+		res = term.MustExec("x -count 52 -fmt bin " + addressStr)
 		t.Logf("the second result of examining memory result \n%s", res)
 
 		// check first line
diff --git a/service/api/prettyprint_test.go b/service/api/prettyprint_test.go
index 9ec90686..c4070ed1 100644
--- a/service/api/prettyprint_test.go
+++ b/service/api/prettyprint_test.go
@@ -2,6 +2,7 @@ package api
 
 import (
 	"fmt"
+	"math"
 	"strings"
 	"testing"
 )
@@ -17,7 +18,7 @@ func TestPrettyExamineMemory(t *testing.T) {
 		"0x10007:   0151   0152   0153   0154   0155   0156   0157   0160   ",
 		"0x1000f:   0161   0162   0163   0164   0165   0166   0167   0170   ",
 		"0x10017:   0171   0172"}
-	res := strings.Split(strings.TrimSpace(PrettyExamineMemory(addr, memArea, format)), "\n")
+	res := strings.Split(strings.TrimSpace(PrettyExamineMemory(addr, memArea, true, format, 1)), "\n")
 
 	if len(display) != len(res) {
 		t.Fatalf("wrong lines return, expected %d but got %d", len(display), len(res))
@@ -32,3 +33,27 @@ func TestPrettyExamineMemory(t *testing.T) {
 		}
 	}
 }
+
+func Test_byteArrayToUInt64(t *testing.T) {
+	tests := []struct {
+		name string
+		args []byte
+		want uint64
+	}{
+		{"case-nil", nil, 0},
+		{"case-empty", []byte{}, 0},
+		{"case-1", []byte{0x1}, 1},
+		{"case-2", []byte{0x12}, 18},
+		{"case-3", []byte{0x1, 0x2}, 513},
+		{"case-4", []byte{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x2}, 144397766876004609},
+		{"case-5", []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, math.MaxUint64},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := byteArrayToUInt64(tt.args, true)
+			if got != tt.want {
+				t.Errorf("byteArrayToUInt64() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/service/dap/server_test.go b/service/dap/server_test.go
index 55ad100f..fb870627 100644
--- a/service/dap/server_test.go
+++ b/service/dap/server_test.go
@@ -341,6 +341,9 @@ func TestSetBreakpoint(t *testing.T) {
 
 		client.ScopesRequest(1000)
 		scopes := client.ExpectScopesResponse(t)
+		if len(scopes.Body.Scopes) > 2 {
+			t.Errorf("\ngot  %#v\nwant len(Scopes)=2 (Arguments & Locals)", scopes)
+		}
 		expectScope(t, scopes, 0, "Arguments", 1000)
 		expectScope(t, scopes, 1, "Locals", 1001)
 
@@ -413,12 +416,12 @@ func expectScope(t *testing.T, got *dap.ScopesResponse, i int, name string, varR
 }
 
 // expectChildren is a helper for verifying the number of variables within a VariablesResponse.
-//      parentName - name of the enclosing variable or scope
+//      parentName - pseudoname of the enclosing variable or scope (used for error message only)
 //      numChildren - number of variables/fields/elements of this variable
 func expectChildren(t *testing.T, got *dap.VariablesResponse, parentName string, numChildren int) {
 	t.Helper()
 	if len(got.Body.Variables) != numChildren {
-		t.Errorf("\ngot  len(%s)=%d\nwant %d", parentName, len(got.Body.Variables), numChildren)
+		t.Errorf("\ngot  len(%s)=%d (children=%#v)\nwant len=%d", parentName, len(got.Body.Variables), got.Body.Variables, numChildren)
 	}
 }
 
@@ -432,7 +435,7 @@ func expectChildren(t *testing.T, got *dap.VariablesResponse, parentName string,
 func expectVar(t *testing.T, got *dap.VariablesResponse, i int, name, value string, useExactMatch, hasRef bool) (ref int) {
 	t.Helper()
 	if len(got.Body.Variables) <= i {
-		t.Errorf("\ngot  len=%d\nwant len>%d", len(got.Body.Variables), i)
+		t.Errorf("\ngot  len=%d (children=%#v)\nwant len>%d", len(got.Body.Variables), got.Body.Variables, i)
 		return
 	}
 	if i < 0 {
@@ -556,7 +559,9 @@ func TestScopesAndVariablesRequests(t *testing.T) {
 		runDebugSessionWithBPs(t, client,
 			// Launch
 			func() {
-				client.LaunchRequest("exec", fixture.Path, !stopOnEntry)
+				client.LaunchRequestWithArgs(map[string]interface{}{
+					"mode": "exec", "program": fixture.Path, "showGlobalVariables": true,
+				})
 			},
 			// Breakpoints are set within the program
 			fixture.Source, []int{},
@@ -580,6 +585,7 @@ func TestScopesAndVariablesRequests(t *testing.T) {
 					scopes := client.ExpectScopesResponse(t)
 					expectScope(t, scopes, 0, "Arguments", 1000)
 					expectScope(t, scopes, 1, "Locals", 1001)
+					expectScope(t, scopes, 2, "Globals (package main)", 1002)
 
 					// Arguments
 
@@ -596,6 +602,12 @@ func TestScopesAndVariablesRequests(t *testing.T) {
 						expectVarExact(t, bar, 1, "Bur", `"lorem"`, noChildren)
 					}
 
+					// Globals
+
+					client.VariablesRequest(1002)
+					globals := client.ExpectVariablesResponse(t)
+					expectVarExact(t, globals, 0, "p1", "10", noChildren)
+
 					// Locals
 
 					client.VariablesRequest(1001)
@@ -775,6 +787,7 @@ func TestScopesAndVariablesRequests(t *testing.T) {
 					scopes := client.ExpectScopesResponse(t)
 					expectScope(t, scopes, 0, "Arguments", 1000)
 					expectScope(t, scopes, 1, "Locals", 1001)
+					expectScope(t, scopes, 2, "Globals (package main)", 1002)
 
 					client.ScopesRequest(1111)
 					erres := client.ExpectErrorResponse(t)
@@ -791,6 +804,10 @@ func TestScopesAndVariablesRequests(t *testing.T) {
 					expectChildren(t, locals, "Locals", 1)
 					expectVarExact(t, locals, -1, "a1", `"bur"`, noChildren)
 
+					client.VariablesRequest(1002) // Globals
+					globals := client.ExpectVariablesResponse(t)
+					expectVarExact(t, globals, 0, "p1", "10", noChildren)
+
 					client.VariablesRequest(7777)
 					erres = client.ExpectErrorResponse(t)
 					if erres.Body.Error.Format != "Unable to lookup variable: unknown reference 7777" {
@@ -835,6 +852,9 @@ func TestScopesAndVariablesRequests2(t *testing.T) {
 
 					client.ScopesRequest(1000)
 					scopes := client.ExpectScopesResponse(t)
+					if len(scopes.Body.Scopes) > 2 {
+						t.Errorf("\ngot  %#v\nwant len(scopes)=2 (Argumes & Locals)", scopes)
+					}
 					expectScope(t, scopes, 0, "Arguments", 1000)
 					expectScope(t, scopes, 1, "Locals", 1001)
 
@@ -964,18 +984,18 @@ func TestScopesAndVariablesRequests2(t *testing.T) {
 						ref = expectVarExact(t, m4, 2, "[key 1]", "<main.astruct>", hasChildren)
 						if ref > 0 {
 							client.VariablesRequest(ref)
-							m4_key1 := client.ExpectVariablesResponse(t)
-							expectChildren(t, m4_key1, "m4_key1", 2)
-							expectVarExact(t, m4_key1, 0, "A", "2", noChildren)
-							expectVarExact(t, m4_key1, 1, "B", "2", noChildren)
+							m4Key1 := client.ExpectVariablesResponse(t)
+							expectChildren(t, m4Key1, "m4Key1", 2)
+							expectVarExact(t, m4Key1, 0, "A", "2", noChildren)
+							expectVarExact(t, m4Key1, 1, "B", "2", noChildren)
 						}
 						ref = expectVarExact(t, m4, 3, "[val 1]", "<main.astruct>", hasChildren)
 						if ref > 0 {
 							client.VariablesRequest(ref)
-							m4_val1 := client.ExpectVariablesResponse(t)
-							expectChildren(t, m4_val1, "m4_val1", 2)
-							expectVarExact(t, m4_val1, 0, "A", "22", noChildren)
-							expectVarExact(t, m4_val1, 1, "B", "22", noChildren)
+							m4Val1 := client.ExpectVariablesResponse(t)
+							expectChildren(t, m4Val1, "m4Val1", 2)
+							expectVarExact(t, m4Val1, 0, "A", "22", noChildren)
+							expectVarExact(t, m4Val1, 1, "B", "22", noChildren)
 						}
 					}
 					expectVarExact(t, locals, -1, "emptymap", "<map[string]string> (length: 0)", noChildren)
@@ -1020,6 +1040,73 @@ func TestScopesAndVariablesRequests2(t *testing.T) {
 	})
 }
 
+// TestGlobalScopeAndVariables launches the program with showGlobalVariables
+// arg set, executes to a breakpoint in the main package and tests that global
+// package main variables got loaded. It then steps into a function
+// in another package and tests that globals scope got updated to those vars.
+func TestGlobalScopeAndVariables(t *testing.T) {
+	runTest(t, "consts", func(client *daptest.Client, fixture protest.Fixture) {
+		runDebugSessionWithBPs(t, client,
+			// Launch
+			func() {
+				client.LaunchRequestWithArgs(map[string]interface{}{
+					"mode": "exec", "program": fixture.Path, "showGlobalVariables": true,
+				})
+			},
+			// Breakpoints are set within the program
+			fixture.Source, []int{},
+			[]onBreakpoint{{
+				// Stop at line 36
+				execute: func() {
+					client.StackTraceRequest(1, 0, 20)
+					stack := client.ExpectStackTraceResponse(t)
+					expectStackFrames(t, stack, 36, 1000, 3, 3)
+
+					client.ScopesRequest(1000)
+					scopes := client.ExpectScopesResponse(t)
+					expectScope(t, scopes, 0, "Arguments", 1000)
+					expectScope(t, scopes, 1, "Locals", 1001)
+					expectScope(t, scopes, 2, "Globals (package main)", 1002)
+
+					client.VariablesRequest(1002)
+					client.ExpectVariablesResponse(t)
+					// The program has no user-defined globals.
+					// Depending on the Go version, there might
+					// be some runtime globals (e.g. main..inittask)
+					// so testing for the total number is too fragile.
+
+					// Step into pkg.AnotherMethod()
+					client.StepInRequest(1)
+					client.ExpectStepInResponse(t)
+					client.ExpectStoppedEvent(t)
+
+					client.StackTraceRequest(1, 0, 20)
+					stack = client.ExpectStackTraceResponse(t)
+					expectStackFrames(t, stack, 14, 1000, 4, 4)
+
+					client.ScopesRequest(1000)
+					scopes = client.ExpectScopesResponse(t)
+					expectScope(t, scopes, 0, "Arguments", 1000)
+					expectScope(t, scopes, 1, "Locals", 1001)
+					expectScope(t, scopes, 2, "Globals (package github.com/go-delve/delve/_fixtures/internal/dir0/pkg)", 1002)
+
+					client.VariablesRequest(1002)
+					globals := client.ExpectVariablesResponse(t)
+					expectChildren(t, globals, "Globals", 1)
+					ref := expectVarExact(t, globals, 0, "SomeVar", "<github.com/go-delve/delve/_fixtures/internal/dir0/pkg.SomeType>", hasChildren)
+
+					if ref > 0 {
+						client.VariablesRequest(ref)
+						somevar := client.ExpectVariablesResponse(t)
+						expectChildren(t, somevar, "SomeVar", 1)
+						expectVarExact(t, somevar, 0, "X", "0", noChildren)
+					}
+				},
+				disconnect: false,
+			}})
+	})
+}
+
 // Tests that 'stackTraceDepth' from LaunchRequest is parsed and passed to
 // stacktrace requests handlers.
 func TestLaunchRequestWithStackTraceDepth(t *testing.T) {
diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go
index 3bacc717..858afcbc 100644
--- a/service/test/integration2_test.go
+++ b/service/test/integration2_test.go
@@ -2098,3 +2098,20 @@ func TestRedirects(t *testing.T) {
 		}
 	})
 }
+
+func TestIssue2162(t *testing.T) {
+	if buildMode == "pie" || runtime.GOOS == "windows" {
+		t.Skip("skip it for stepping into one place where no source for pc when on pie mode or windows")
+	}
+	withTestClient2("issue2162", t, func(c service.Client) {
+		_, err := c.CreateBreakpoint(&api.Breakpoint{FunctionName: "main.main"})
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+
+		_, err = c.Step()
+		if err != nil {
+			assertNoError(err, t, "Step()")
+		}
+	})
+}