| // 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) |
| } |