third_party/delve/dwarf: refresh to add support for DWARF 5

This patch pulls in some additional pieces from Delve that add support
for DWARF 5. Prior to this point the code copied from delve here was
specific to DWARF 2; once the Go compiler starts generating DWARF
version 5 we need more machinery to handle that.

Updates golang/go#26379.

Change-Id: Ib7bee1101101459e8eb5f7c62c625f0b7b53411f
Reviewed-on: https://go-review.googlesource.com/c/debug/+/654255
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/third_party/delve/README.md b/third_party/delve/README.md
index 89ef824..67d3252 100644
--- a/third_party/delve/README.md
+++ b/third_party/delve/README.md
@@ -4,4 +4,6 @@
 primarily on DWARF utilities. The most important part copied over is
 the stack program interpreter, though the regnum package is useful too.
 
-Copied at commit 84c99e508c835a9b9d44bbde9558496d3583256c.
+Copied at commit e6e7aeb667057ad6a98120ebf3591fbafdedb19d, with additions to support DWARF5.
+
+
diff --git a/third_party/delve/dwarf/godwarf/addr.go b/third_party/delve/dwarf/godwarf/addr.go
new file mode 100644
index 0000000..6c5bf48
--- /dev/null
+++ b/third_party/delve/dwarf/godwarf/addr.go
@@ -0,0 +1,60 @@
+package godwarf
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+
+	"golang.org/x/debug/third_party/delve/dwarf"
+)
+
+// DebugAddrSection represents the debug_addr section of DWARFv5.
+// See DWARFv5 section 7.27 page 241 and following.
+type DebugAddrSection struct {
+	byteOrder binary.ByteOrder
+	ptrSz     int
+	data      []byte
+}
+
+// ParseAddr parses the header of a debug_addr section.
+func ParseAddr(data []byte) *DebugAddrSection {
+	if len(data) == 0 {
+		return nil
+	}
+	r := &DebugAddrSection{data: data}
+	_, dwarf64, _, byteOrder := dwarf.ReadDwarfLengthVersion(data)
+	r.byteOrder = byteOrder
+	data = data[6:]
+	if dwarf64 {
+		data = data[8:]
+	}
+
+	addrSz := data[0]
+	segSelSz := data[1]
+	r.ptrSz = int(addrSz + segSelSz)
+
+	return r
+}
+
+// GetSubsection returns the subsection of debug_addr starting at addrBase
+func (addr *DebugAddrSection) GetSubsection(addrBase uint64) *DebugAddr {
+	if addr == nil {
+		return nil
+	}
+	return &DebugAddr{DebugAddrSection: addr, addrBase: addrBase}
+}
+
+// DebugAddr represents a subsection of the debug_addr section with a specific base address
+type DebugAddr struct {
+	*DebugAddrSection
+	addrBase uint64
+}
+
+// Get returns the address at index idx starting from addrBase.
+func (addr *DebugAddr) Get(idx uint64) (uint64, error) {
+	if addr == nil || addr.DebugAddrSection == nil {
+		return 0, errors.New("debug_addr section not present")
+	}
+	off := idx*uint64(addr.ptrSz) + addr.addrBase
+	return dwarf.ReadUintRaw(bytes.NewReader(addr.data[off:]), addr.byteOrder, addr.ptrSz)
+}
diff --git a/third_party/delve/dwarf/loclist/dwarf5_loclist.go b/third_party/delve/dwarf/loclist/dwarf5_loclist.go
new file mode 100644
index 0000000..d5f98fd
--- /dev/null
+++ b/third_party/delve/dwarf/loclist/dwarf5_loclist.go
@@ -0,0 +1,163 @@
+package loclist
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+
+	"golang.org/x/debug/third_party/delve/dwarf"
+	"golang.org/x/debug/third_party/delve/dwarf/godwarf"
+	"golang.org/x/debug/third_party/delve/dwarf/leb128"
+)
+
+// Dwarf5Reader parses and presents DWARF loclist information for DWARF version 5 and later.
+// See DWARFv5 section 7.29 page 243 and following.
+type Dwarf5Reader struct {
+	byteOrder binary.ByteOrder
+	ptrSz     int
+	data      []byte
+}
+
+func NewDwarf5Reader(data []byte) *Dwarf5Reader {
+	if len(data) == 0 {
+		return nil
+	}
+	r := &Dwarf5Reader{data: data}
+
+	_, dwarf64, _, byteOrder := dwarf.ReadDwarfLengthVersion(data)
+	r.byteOrder = byteOrder
+
+	data = data[6:]
+	if dwarf64 {
+		data = data[8:]
+	}
+
+	addrSz := data[0]
+	segSelSz := data[1]
+	r.ptrSz = int(addrSz + segSelSz)
+
+	// Not read:
+	// - offset_entry_count (4 bytes)
+	// - offset table (offset_entry_count*4 or offset_entry_count*8 if dwarf64 is set)
+
+	return r
+}
+
+func (rdr *Dwarf5Reader) Empty() bool {
+	return rdr == nil
+}
+
+type loclistsIterator struct {
+	rdr        *Dwarf5Reader
+	debugAddr  *godwarf.DebugAddr
+	buf        *bytes.Buffer
+	staticBase uint64
+	base       uint64 // base for offsets in the list
+
+	onRange      bool
+	atEnd        bool
+	start, end   uint64
+	instr        []byte
+	defaultInstr []byte
+	err          error
+}
+
+const (
+	_DW_LLE_end_of_list      uint8 = 0x0
+	_DW_LLE_base_addressx    uint8 = 0x1
+	_DW_LLE_startx_endx      uint8 = 0x2
+	_DW_LLE_startx_length    uint8 = 0x3
+	_DW_LLE_offset_pair      uint8 = 0x4
+	_DW_LLE_default_location uint8 = 0x5
+	_DW_LLE_base_address     uint8 = 0x6
+	_DW_LLE_start_end        uint8 = 0x7
+	_DW_LLE_start_length     uint8 = 0x8
+)
+
+func (it *loclistsIterator) next() bool {
+	if it.err != nil || it.atEnd {
+		return false
+	}
+	opcode, err := it.buf.ReadByte()
+	if err != nil {
+		it.err = err
+		return false
+	}
+	switch opcode {
+	case _DW_LLE_end_of_list:
+		it.atEnd = true
+		it.onRange = false
+		return false
+
+	case _DW_LLE_base_addressx:
+		baseIdx, _ := leb128.DecodeUnsigned(it.buf)
+		it.base, it.err = it.debugAddr.Get(baseIdx)
+		it.base += it.staticBase
+		it.onRange = false
+
+	case _DW_LLE_startx_endx:
+		startIdx, _ := leb128.DecodeUnsigned(it.buf)
+		endIdx, _ := leb128.DecodeUnsigned(it.buf)
+		it.readInstr()
+
+		it.start, it.err = it.debugAddr.Get(startIdx)
+		if it.err == nil {
+			it.end, it.err = it.debugAddr.Get(endIdx)
+		}
+		it.onRange = true
+
+	case _DW_LLE_startx_length:
+		startIdx, _ := leb128.DecodeUnsigned(it.buf)
+		length, _ := leb128.DecodeUnsigned(it.buf)
+		it.readInstr()
+
+		it.start, it.err = it.debugAddr.Get(startIdx)
+		it.end = it.start + length
+		it.onRange = true
+
+	case _DW_LLE_offset_pair:
+		off1, _ := leb128.DecodeUnsigned(it.buf)
+		off2, _ := leb128.DecodeUnsigned(it.buf)
+		it.readInstr()
+
+		it.start = it.base + off1
+		it.end = it.base + off2
+		it.onRange = true
+
+	case _DW_LLE_default_location:
+		it.readInstr()
+		it.defaultInstr = it.instr
+		it.onRange = false
+
+	case _DW_LLE_base_address:
+		it.base, it.err = dwarf.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
+		it.base += it.staticBase
+		it.onRange = false
+
+	case _DW_LLE_start_end:
+		it.start, it.err = dwarf.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
+		it.end, it.err = dwarf.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
+		it.readInstr()
+		it.onRange = true
+
+	case _DW_LLE_start_length:
+		it.start, it.err = dwarf.ReadUintRaw(it.buf, it.rdr.byteOrder, it.rdr.ptrSz)
+		length, _ := leb128.DecodeUnsigned(it.buf)
+		it.readInstr()
+		it.end = it.start + length
+		it.onRange = true
+
+	default:
+		it.err = fmt.Errorf("unknown opcode %#x at %#x", opcode, len(it.rdr.data)-it.buf.Len())
+		it.onRange = false
+		it.atEnd = true
+		return false
+	}
+
+	return true
+}
+
+func (it *loclistsIterator) readInstr() {
+	length, _ := leb128.DecodeUnsigned(it.buf)
+	it.instr = it.buf.Next(int(length))
+}
diff --git a/third_party/delve/dwarf/loclist/dwarf5_loclist_additions.go b/third_party/delve/dwarf/loclist/dwarf5_loclist_additions.go
new file mode 100644
index 0000000..37f75b8
--- /dev/null
+++ b/third_party/delve/dwarf/loclist/dwarf5_loclist_additions.go
@@ -0,0 +1,34 @@
+package loclist
+
+import (
+	"bytes"
+
+	"golang.org/x/debug/third_party/delve/dwarf/godwarf"
+)
+
+// Enumerate walks through all of the location list entries for a
+// given variable in a given function and enumerates them, returning
+// to the client. Note that this function doesn't exist in the delve
+// source; it was written here so as to be able to do something
+// similar to what's done with DWARF 2 location lists. Here off is the
+// offset within the .debug_loclists section containing the start of
+// the entries for the function in question, staticBase is the
+// start-of-text address for the executable, and debugAddr
+// encapsulates the portion of the .debug_addr section containing
+// entries for the current compilation unit.
+func (rdr *Dwarf5Reader) Enumerate(off int64, staticBase uint64, debugAddr *godwarf.DebugAddr) ([]Entry, error) {
+	result := []Entry{}
+
+	it := &loclistsIterator{rdr: rdr, debugAddr: debugAddr, buf: bytes.NewBuffer(rdr.data), staticBase: staticBase}
+	it.buf.Next(int(off))
+
+	for it.next() {
+		if !it.onRange {
+			continue
+		}
+		e := Entry{it.start, it.end, it.instr}
+		result = append(result, e)
+	}
+
+	return result, it.err
+}
diff --git a/third_party/delve/dwarf/parseutil.go b/third_party/delve/dwarf/parseutil.go
index d8ed2b0..a25f47f 100644
--- a/third_party/delve/dwarf/parseutil.go
+++ b/third_party/delve/dwarf/parseutil.go
@@ -131,7 +131,7 @@
 
 			switch unitType {
 			case _DW_UT_compile, _DW_UT_partial:
-				headerSize = 5 + secoffsz
+				headerSize = 4 + secoffsz
 
 			case _DW_UT_skeleton, _DW_UT_split_compile:
 				headerSize = 4 + secoffsz + 8