blob: a2f03ceee6943dacadc51308bcf4a30dd136211a [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Functions for reading values of various types from a program's memory.
package server
import (
"fmt"
"golang.org/x/debug/dwarf"
)
// peekBytes reads len(buf) bytes at addr.
func (s *Server) peekBytes(addr uint64, buf []byte) error {
return s.ptracePeek(s.stoppedPid, uintptr(addr), buf)
}
// peekPtr reads a pointer at addr.
func (s *Server) peekPtr(addr uint64) (uint64, error) {
buf := make([]byte, s.arch.PointerSize)
if err := s.peekBytes(addr, buf); err != nil {
return 0, err
}
return s.arch.Uintptr(buf), nil
}
// peekUint8 reads a single byte at addr.
func (s *Server) peekUint8(addr uint64) (byte, error) {
buf := make([]byte, 1)
if err := s.peekBytes(addr, buf); err != nil {
return 0, err
}
return uint8(s.arch.UintN(buf)), nil
}
// peekInt reads an int of size n bytes at addr.
func (s *Server) peekInt(addr uint64, n int64) (int64, error) {
buf := make([]byte, n)
if err := s.peekBytes(addr, buf); err != nil {
return 0, err
}
return s.arch.IntN(buf), nil
}
// peekUint reads a uint of size n bytes at addr.
func (s *Server) peekUint(addr uint64, n int64) (uint64, error) {
buf := make([]byte, n)
if err := s.peekBytes(addr, buf); err != nil {
return 0, err
}
return s.arch.UintN(buf), nil
}
// peekPtrStructField reads a pointer in the field fieldName of the struct
// of type t at addr.
func (s *Server) peekPtrStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
f, err := getField(t, fieldName)
if err != nil {
return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
}
if _, ok := f.Type.(*dwarf.PtrType); !ok {
return 0, fmt.Errorf("field %s is not a pointer", fieldName)
}
return s.peekPtr(addr + uint64(f.ByteOffset))
}
// peekUintOrIntStructField reads a signed or unsigned integer in the field fieldName
// of the struct of type t at addr. If the value is negative, it returns an error.
// This function is used when the value should be non-negative, but the DWARF
// type of the field may be signed or unsigned.
func (s *Server) peekUintOrIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
f, err := getField(t, fieldName)
if err != nil {
return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
}
ut, ok := f.Type.(*dwarf.UintType)
if ok {
return s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
}
it, ok := f.Type.(*dwarf.IntType)
if !ok {
return 0, fmt.Errorf("field %s is not an integer", fieldName)
}
i, err := s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
if err != nil {
return 0, err
}
if i < 0 {
return 0, fmt.Errorf("field %s is negative", fieldName)
}
return uint64(i), nil
}
// peekUintStructField reads a uint in the field fieldName of the struct
// of type t at addr. The size of the uint is determined by the field.
func (s *Server) peekUintStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
f, err := getField(t, fieldName)
if err != nil {
return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
}
ut, ok := f.Type.(*dwarf.UintType)
if !ok {
return 0, fmt.Errorf("field %s is not an unsigned integer", fieldName)
}
return s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
}
// peekIntStructField reads an int in the field fieldName of the struct
// of type t at addr. The size of the int is determined by the field.
func (s *Server) peekIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (int64, error) {
f, err := getField(t, fieldName)
if err != nil {
return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
}
it, ok := f.Type.(*dwarf.IntType)
if !ok {
return 0, fmt.Errorf("field %s is not a signed integer", fieldName)
}
return s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
}