You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

379 lines
12 KiB

  1. // Copyright 2018 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Functions for reading values of various types from a program's memory.
  15. // +build linux
  16. package server
  17. import (
  18. "errors"
  19. "fmt"
  20. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug"
  21. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
  22. )
  23. // peekBytes reads len(buf) bytes at addr.
  24. func (s *Server) peekBytes(addr uint64, buf []byte) error {
  25. return s.ptracePeek(s.stoppedPid, uintptr(addr), buf)
  26. }
  27. // peekPtr reads a pointer at addr.
  28. func (s *Server) peekPtr(addr uint64) (uint64, error) {
  29. buf := make([]byte, s.arch.PointerSize)
  30. if err := s.peekBytes(addr, buf); err != nil {
  31. return 0, err
  32. }
  33. return s.arch.Uintptr(buf), nil
  34. }
  35. // peekUint8 reads a single byte at addr.
  36. func (s *Server) peekUint8(addr uint64) (byte, error) {
  37. buf := make([]byte, 1)
  38. if err := s.peekBytes(addr, buf); err != nil {
  39. return 0, err
  40. }
  41. return uint8(s.arch.UintN(buf)), nil
  42. }
  43. // peekInt reads an int of size n bytes at addr.
  44. func (s *Server) peekInt(addr uint64, n int64) (int64, error) {
  45. buf := make([]byte, n)
  46. if err := s.peekBytes(addr, buf); err != nil {
  47. return 0, err
  48. }
  49. return s.arch.IntN(buf), nil
  50. }
  51. // peekUint reads a uint of size n bytes at addr.
  52. func (s *Server) peekUint(addr uint64, n int64) (uint64, error) {
  53. buf := make([]byte, n)
  54. if err := s.peekBytes(addr, buf); err != nil {
  55. return 0, err
  56. }
  57. return s.arch.UintN(buf), nil
  58. }
  59. // peekSlice reads the header of a slice with the given type and address.
  60. func (s *Server) peekSlice(t *dwarf.SliceType, addr uint64) (debug.Slice, error) {
  61. ptr, err := s.peekPtrStructField(&t.StructType, addr, "array")
  62. if err != nil {
  63. return debug.Slice{}, fmt.Errorf("reading slice location: %s", err)
  64. }
  65. length, err := s.peekUintOrIntStructField(&t.StructType, addr, "len")
  66. if err != nil {
  67. return debug.Slice{}, fmt.Errorf("reading slice length: %s", err)
  68. }
  69. capacity, err := s.peekUintOrIntStructField(&t.StructType, addr, "cap")
  70. if err != nil {
  71. return debug.Slice{}, fmt.Errorf("reading slice capacity: %s", err)
  72. }
  73. if capacity < length {
  74. return debug.Slice{}, fmt.Errorf("slice's capacity %d is less than its length %d", capacity, length)
  75. }
  76. return debug.Slice{
  77. debug.Array{
  78. ElementTypeID: uint64(t.ElemType.Common().Offset),
  79. Address: uint64(ptr),
  80. Length: length,
  81. StrideBits: uint64(t.ElemType.Common().ByteSize) * 8,
  82. },
  83. capacity,
  84. }, nil
  85. }
  86. // peekString reads a string of the given type at the given address.
  87. // At most byteLimit bytes will be read. If the string is longer, "..." is appended.
  88. func (s *Server) peekString(typ *dwarf.StringType, a uint64, byteLimit uint64) (string, error) {
  89. ptr, err := s.peekPtrStructField(&typ.StructType, a, "str")
  90. if err != nil {
  91. return "", err
  92. }
  93. length, err := s.peekUintOrIntStructField(&typ.StructType, a, "len")
  94. if err != nil {
  95. return "", err
  96. }
  97. if length > byteLimit {
  98. buf := make([]byte, byteLimit, byteLimit+3)
  99. if err := s.peekBytes(ptr, buf); err != nil {
  100. return "", err
  101. } else {
  102. buf = append(buf, '.', '.', '.')
  103. return string(buf), nil
  104. }
  105. } else {
  106. buf := make([]byte, length)
  107. if err := s.peekBytes(ptr, buf); err != nil {
  108. return "", err
  109. } else {
  110. return string(buf), nil
  111. }
  112. }
  113. }
  114. // peekCString reads a NUL-terminated string at the given address.
  115. // At most byteLimit bytes will be read. If the string is longer, "..." is appended.
  116. // peekCString never returns errors; if an error occurs, the string will be truncated in some way.
  117. func (s *Server) peekCString(a uint64, byteLimit uint64) string {
  118. buf := make([]byte, byteLimit, byteLimit+3)
  119. s.peekBytes(a, buf)
  120. for i, c := range buf {
  121. if c == 0 {
  122. return string(buf[0:i])
  123. }
  124. }
  125. buf = append(buf, '.', '.', '.')
  126. return string(buf)
  127. }
  128. // peekPtrStructField reads a pointer in the field fieldName of the struct
  129. // of type t at addr.
  130. func (s *Server) peekPtrStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
  131. f, err := getField(t, fieldName)
  132. if err != nil {
  133. return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
  134. }
  135. if _, ok := f.Type.(*dwarf.PtrType); !ok {
  136. return 0, fmt.Errorf("field %s is not a pointer", fieldName)
  137. }
  138. return s.peekPtr(addr + uint64(f.ByteOffset))
  139. }
  140. // peekUintOrIntStructField reads a signed or unsigned integer in the field fieldName
  141. // of the struct of type t at addr. If the value is negative, it returns an error.
  142. // This function is used when the value should be non-negative, but the DWARF
  143. // type of the field may be signed or unsigned.
  144. func (s *Server) peekUintOrIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
  145. f, err := getField(t, fieldName)
  146. if err != nil {
  147. return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
  148. }
  149. ut, ok := f.Type.(*dwarf.UintType)
  150. if ok {
  151. return s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
  152. }
  153. it, ok := f.Type.(*dwarf.IntType)
  154. if !ok {
  155. return 0, fmt.Errorf("field %s is not an integer", fieldName)
  156. }
  157. i, err := s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
  158. if err != nil {
  159. return 0, err
  160. }
  161. if i < 0 {
  162. return 0, fmt.Errorf("field %s is negative", fieldName)
  163. }
  164. return uint64(i), nil
  165. }
  166. // peekUintStructField reads a uint in the field fieldName of the struct
  167. // of type t at addr. The size of the uint is determined by the field.
  168. func (s *Server) peekUintStructField(t *dwarf.StructType, addr uint64, fieldName string) (uint64, error) {
  169. f, err := getField(t, fieldName)
  170. if err != nil {
  171. return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
  172. }
  173. ut, ok := f.Type.(*dwarf.UintType)
  174. if !ok {
  175. return 0, fmt.Errorf("field %s is not an unsigned integer", fieldName)
  176. }
  177. return s.peekUint(addr+uint64(f.ByteOffset), ut.ByteSize)
  178. }
  179. // peekIntStructField reads an int in the field fieldName of the struct
  180. // of type t at addr. The size of the int is determined by the field.
  181. func (s *Server) peekIntStructField(t *dwarf.StructType, addr uint64, fieldName string) (int64, error) {
  182. f, err := getField(t, fieldName)
  183. if err != nil {
  184. return 0, fmt.Errorf("reading field %s: %s", fieldName, err)
  185. }
  186. it, ok := f.Type.(*dwarf.IntType)
  187. if !ok {
  188. return 0, fmt.Errorf("field %s is not a signed integer", fieldName)
  189. }
  190. return s.peekInt(addr+uint64(f.ByteOffset), it.ByteSize)
  191. }
  192. // peekStringStructField reads a string field from the struct of the given type
  193. // at the given address.
  194. // At most byteLimit bytes will be read. If the string is longer, "..." is appended.
  195. func (s *Server) peekStringStructField(t *dwarf.StructType, addr uint64, fieldName string, byteLimit uint64) (string, error) {
  196. f, err := getField(t, fieldName)
  197. if err != nil {
  198. return "", fmt.Errorf("reading field %s: %s", fieldName, err)
  199. }
  200. st, ok := followTypedefs(f.Type).(*dwarf.StringType)
  201. if !ok {
  202. return "", fmt.Errorf("field %s is not a string", fieldName)
  203. }
  204. return s.peekString(st, addr+uint64(f.ByteOffset), byteLimit)
  205. }
  206. // peekMapLocationAndType returns the address and DWARF type of the underlying
  207. // struct of a map variable.
  208. func (s *Server) peekMapLocationAndType(t *dwarf.MapType, a uint64) (uint64, *dwarf.StructType, error) {
  209. // Maps are pointers to structs.
  210. pt, ok := t.Type.(*dwarf.PtrType)
  211. if !ok {
  212. return 0, nil, errors.New("bad map type: not a pointer")
  213. }
  214. st, ok := pt.Type.(*dwarf.StructType)
  215. if !ok {
  216. return 0, nil, errors.New("bad map type: not a pointer to a struct")
  217. }
  218. // a is the address of a pointer to a struct. Get the pointer's value.
  219. a, err := s.peekPtr(a)
  220. if err != nil {
  221. return 0, nil, fmt.Errorf("reading map pointer: %s", err)
  222. }
  223. return a, st, nil
  224. }
  225. // peekMapValues reads a map at the given address and calls fn with the addresses for each (key, value) pair.
  226. // If fn returns false, peekMapValues stops.
  227. func (s *Server) peekMapValues(t *dwarf.MapType, a uint64, fn func(keyAddr, valAddr uint64, keyType, valType dwarf.Type) bool) error {
  228. a, st, err := s.peekMapLocationAndType(t, a)
  229. if err != nil {
  230. return err
  231. }
  232. if a == 0 {
  233. // The pointer was nil, so the map is empty.
  234. return nil
  235. }
  236. // Gather information about the struct type and the map bucket type.
  237. b, err := s.peekUintStructField(st, a, "B")
  238. if err != nil {
  239. return fmt.Errorf("reading map: %s", err)
  240. }
  241. buckets, err := s.peekPtrStructField(st, a, "buckets")
  242. if err != nil {
  243. return fmt.Errorf("reading map: %s", err)
  244. }
  245. oldbuckets, err := s.peekPtrStructField(st, a, "oldbuckets")
  246. if err != nil {
  247. return fmt.Errorf("reading map: %s", err)
  248. }
  249. bf, err := getField(st, "buckets")
  250. if err != nil {
  251. return fmt.Errorf("reading map: %s", err)
  252. }
  253. bucketPtrType, ok := bf.Type.(*dwarf.PtrType)
  254. if !ok {
  255. return errors.New("bad map bucket type: not a pointer")
  256. }
  257. bt, ok := bucketPtrType.Type.(*dwarf.StructType)
  258. if !ok {
  259. return errors.New("bad map bucket type: not a pointer to a struct")
  260. }
  261. bucketSize := uint64(bucketPtrType.Type.Size())
  262. tophashField, err := getField(bt, "tophash")
  263. if err != nil {
  264. return fmt.Errorf("reading map: %s", err)
  265. }
  266. bucketCnt := uint64(tophashField.Type.Size())
  267. tophashFieldOffset := uint64(tophashField.ByteOffset)
  268. keysField, err := getField(bt, "keys")
  269. if err != nil {
  270. return fmt.Errorf("reading map: %s", err)
  271. }
  272. keysType, ok := keysField.Type.(*dwarf.ArrayType)
  273. if !ok {
  274. return errors.New(`bad map bucket type: "keys" is not an array`)
  275. }
  276. keyType := keysType.Type
  277. keysStride := uint64(keysType.StrideBitSize / 8)
  278. keysFieldOffset := uint64(keysField.ByteOffset)
  279. valuesField, err := getField(bt, "values")
  280. if err != nil {
  281. return fmt.Errorf("reading map: %s", err)
  282. }
  283. valuesType, ok := valuesField.Type.(*dwarf.ArrayType)
  284. if !ok {
  285. return errors.New(`bad map bucket type: "values" is not an array`)
  286. }
  287. valueType := valuesType.Type
  288. valuesStride := uint64(valuesType.StrideBitSize / 8)
  289. valuesFieldOffset := uint64(valuesField.ByteOffset)
  290. overflowField, err := getField(bt, "overflow")
  291. if err != nil {
  292. return fmt.Errorf("reading map: %s", err)
  293. }
  294. overflowFieldOffset := uint64(overflowField.ByteOffset)
  295. // Iterate through the two arrays of buckets.
  296. bucketArrays := [2]struct {
  297. addr uint64
  298. size uint64
  299. }{
  300. {buckets, 1 << b},
  301. {oldbuckets, 1 << (b - 1)},
  302. }
  303. for _, bucketArray := range bucketArrays {
  304. if bucketArray.addr == 0 {
  305. continue
  306. }
  307. for i := uint64(0); i < bucketArray.size; i++ {
  308. bucketAddr := bucketArray.addr + i*bucketSize
  309. // Iterate through the linked list of buckets.
  310. // TODO: check for repeated bucket pointers.
  311. for bucketAddr != 0 {
  312. // Iterate through each entry in the bucket.
  313. for j := uint64(0); j < bucketCnt; j++ {
  314. tophash, err := s.peekUint8(bucketAddr + tophashFieldOffset + j)
  315. if err != nil {
  316. return errors.New("reading map: " + err.Error())
  317. }
  318. // From runtime/hashmap.go
  319. const minTopHash = 4
  320. if tophash < minTopHash {
  321. continue
  322. }
  323. keyAddr := bucketAddr + keysFieldOffset + j*keysStride
  324. valAddr := bucketAddr + valuesFieldOffset + j*valuesStride
  325. if !fn(keyAddr, valAddr, keyType, valueType) {
  326. return nil
  327. }
  328. }
  329. var err error
  330. bucketAddr, err = s.peekPtr(bucketAddr + overflowFieldOffset)
  331. if err != nil {
  332. return errors.New("reading map: " + err.Error())
  333. }
  334. }
  335. }
  336. }
  337. return nil
  338. }
  339. // peekMapLength returns the number of elements in a map at the given address.
  340. func (s *Server) peekMapLength(t *dwarf.MapType, a uint64) (uint64, error) {
  341. a, st, err := s.peekMapLocationAndType(t, a)
  342. if err != nil {
  343. return 0, err
  344. }
  345. if a == 0 {
  346. // The pointer was nil, so the map is empty.
  347. return 0, nil
  348. }
  349. length, err := s.peekUintOrIntStructField(st, a, "count")
  350. if err != nil {
  351. return 0, fmt.Errorf("reading map: %s", err)
  352. }
  353. return uint64(length), nil
  354. }