mirror of
https://github.com/go-delve/delve.git
synced 2025-11-01 12:01:35 +08:00
proc/dwarf: Move util functions to dwarf package (#3252)
This commit is contained in:
150
pkg/dwarf/parseutil.go
Normal file
150
pkg/dwarf/parseutil.go
Normal file
@ -0,0 +1,150 @@
|
||||
package dwarf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/dwarf"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ReadString reads a null-terminated string from data.
|
||||
func ReadString(data *bytes.Buffer) (string, error) {
|
||||
str, err := data.ReadString(0x0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return str[:len(str)-1], nil
|
||||
}
|
||||
|
||||
// ReadUintRaw reads an integer of ptrSize bytes, with the specified byte order, from reader.
|
||||
func ReadUintRaw(reader io.Reader, order binary.ByteOrder, ptrSize int) (uint64, error) {
|
||||
switch ptrSize {
|
||||
case 2:
|
||||
var n uint16
|
||||
if err := binary.Read(reader, order, &n); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(n), nil
|
||||
case 4:
|
||||
var n uint32
|
||||
if err := binary.Read(reader, order, &n); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(n), nil
|
||||
case 8:
|
||||
var n uint64
|
||||
if err := binary.Read(reader, order, &n); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
return 0, fmt.Errorf("pointer size %d not supported", ptrSize)
|
||||
}
|
||||
|
||||
// WriteUint writes an integer of ptrSize bytes to writer, in the specified byte order.
|
||||
func WriteUint(writer io.Writer, order binary.ByteOrder, ptrSize int, data uint64) error {
|
||||
switch ptrSize {
|
||||
case 4:
|
||||
return binary.Write(writer, order, uint32(data))
|
||||
case 8:
|
||||
return binary.Write(writer, order, data)
|
||||
}
|
||||
return fmt.Errorf("pointer size %d not supported", ptrSize)
|
||||
}
|
||||
|
||||
// ReadDwarfLengthVersion reads a DWARF length field followed by a version field
|
||||
func ReadDwarfLengthVersion(data []byte) (length uint64, dwarf64 bool, version uint8, byteOrder binary.ByteOrder) {
|
||||
if len(data) < 4 {
|
||||
return 0, false, 0, binary.LittleEndian
|
||||
}
|
||||
|
||||
lengthfield := binary.LittleEndian.Uint32(data)
|
||||
voff := 4
|
||||
if lengthfield == ^uint32(0) {
|
||||
dwarf64 = true
|
||||
voff = 12
|
||||
}
|
||||
|
||||
if voff+1 >= len(data) {
|
||||
return 0, false, 0, binary.LittleEndian
|
||||
}
|
||||
|
||||
byteOrder = binary.LittleEndian
|
||||
x, y := data[voff], data[voff+1]
|
||||
switch {
|
||||
default:
|
||||
fallthrough
|
||||
case x == 0 && y == 0:
|
||||
version = 0
|
||||
byteOrder = binary.LittleEndian
|
||||
case x == 0:
|
||||
version = y
|
||||
byteOrder = binary.BigEndian
|
||||
case y == 0:
|
||||
version = x
|
||||
byteOrder = binary.LittleEndian
|
||||
}
|
||||
|
||||
if dwarf64 {
|
||||
length = byteOrder.Uint64(data[4:])
|
||||
} else {
|
||||
length = uint64(byteOrder.Uint32(data))
|
||||
}
|
||||
|
||||
return length, dwarf64, version, byteOrder
|
||||
}
|
||||
|
||||
const (
|
||||
_DW_UT_compile = 0x1 + iota
|
||||
_DW_UT_type
|
||||
_DW_UT_partial
|
||||
_DW_UT_skeleton
|
||||
_DW_UT_split_compile
|
||||
_DW_UT_split_type
|
||||
)
|
||||
|
||||
// ReadUnitVersions reads the DWARF version of each unit in a debug_info section and returns them as a map.
|
||||
func ReadUnitVersions(data []byte) map[dwarf.Offset]uint8 {
|
||||
r := make(map[dwarf.Offset]uint8)
|
||||
off := dwarf.Offset(0)
|
||||
for len(data) > 0 {
|
||||
length, dwarf64, version, _ := ReadDwarfLengthVersion(data)
|
||||
|
||||
data = data[4:]
|
||||
off += 4
|
||||
secoffsz := 4
|
||||
if dwarf64 {
|
||||
off += 8
|
||||
secoffsz = 8
|
||||
data = data[8:]
|
||||
}
|
||||
|
||||
var headerSize int
|
||||
|
||||
switch version {
|
||||
case 2, 3, 4:
|
||||
headerSize = 3 + secoffsz
|
||||
default: // 5 and later?
|
||||
unitType := data[2]
|
||||
|
||||
switch unitType {
|
||||
case _DW_UT_compile, _DW_UT_partial:
|
||||
headerSize = 5 + secoffsz
|
||||
|
||||
case _DW_UT_skeleton, _DW_UT_split_compile:
|
||||
headerSize = 4 + secoffsz + 8
|
||||
|
||||
case _DW_UT_type, _DW_UT_split_type:
|
||||
headerSize = 4 + secoffsz + 8 + secoffsz
|
||||
}
|
||||
}
|
||||
|
||||
r[off+dwarf.Offset(headerSize)] = version
|
||||
|
||||
data = data[length:] // skip contents
|
||||
off += dwarf.Offset(length)
|
||||
}
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user