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.
 
 
 

1075 lines
39 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. // +build linux
  15. package peek_test
  16. import (
  17. "flag"
  18. "fmt"
  19. "log"
  20. "os"
  21. "os/exec"
  22. "reflect"
  23. "regexp"
  24. "sync"
  25. "testing"
  26. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug"
  27. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/local"
  28. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/remote"
  29. )
  30. var expectedVarValues = map[string]interface{}{
  31. `main.Z_bool_false`: false,
  32. `main.Z_bool_true`: true,
  33. `main.Z_complex128`: complex128(1.987654321 - 2.987654321i),
  34. `main.Z_complex64`: complex64(1.54321 + 2.54321i),
  35. `main.Z_float32`: float32(1.54321),
  36. `main.Z_float64`: float64(1.987654321),
  37. `main.Z_int16`: int16(-32321),
  38. `main.Z_int32`: int32(-1987654321),
  39. `main.Z_int64`: int64(-9012345678987654321),
  40. `main.Z_int8`: int8(-121),
  41. `main.Z_uint16`: uint16(54321),
  42. `main.Z_uint32`: uint32(3217654321),
  43. `main.Z_uint64`: uint64(12345678900987654321),
  44. `main.Z_uint8`: uint8(231),
  45. }
  46. // TODO: the string forms of some types we're testing aren't stable
  47. var expectedVars = map[string]string{
  48. `main.Z_array`: `[5]int8{-121, 121, 3, 2, 1}`,
  49. `main.Z_array_empty`: `[0]int8{}`,
  50. `main.Z_bool_false`: `false`,
  51. `main.Z_bool_true`: `true`,
  52. `main.Z_channel`: `(chan int16 0xX)`,
  53. `main.Z_channel_2`: `(chan int16 0xX)`,
  54. `main.Z_channel_buffered`: `(chan int16 0xX [6/10])`,
  55. `main.Z_channel_nil`: `(chan int16 <nil>)`,
  56. `main.Z_array_of_empties`: `[2]{}{{} {}, ({} 0xX)}`,
  57. `main.Z_complex128`: `(1.987654321-2.987654321i)`,
  58. `main.Z_complex64`: `(1.54321+2.54321i)`,
  59. `main.Z_float32`: `1.54321`,
  60. `main.Z_float64`: `1.987654321`,
  61. `main.Z_func_int8_r_int8`: `func(int8, *int8) void @0xX `,
  62. `main.Z_func_int8_r_pint8`: `func(int8, **int8) void @0xX `,
  63. `main.Z_func_bar`: `func(*main.FooStruct) void @0xX `,
  64. `main.Z_func_nil`: `func(int8, *int8) void @0xX `,
  65. `main.Z_int`: `-21`,
  66. `main.Z_int16`: `-32321`,
  67. `main.Z_int32`: `-1987654321`,
  68. `main.Z_int64`: `-9012345678987654321`,
  69. `main.Z_int8`: `-121`,
  70. `main.Z_int_typedef`: `88`,
  71. `main.Z_interface`: `("*main.FooStruct", 0xX)`,
  72. `main.Z_interface_nil`: `(<nil>, <nil>)`,
  73. `main.Z_interface_typed_nil`: `("*main.FooStruct", <nil>)`,
  74. `main.Z_map`: `map[-21:3.54321]`,
  75. `main.Z_map_2`: `map[1024:1]`,
  76. `main.Z_map_3`: `map[1024:1 512:-1]`,
  77. `main.Z_map_empty`: `map[]`,
  78. `main.Z_map_nil`: `map[]`,
  79. `main.Z_pointer`: `0xX`,
  80. `main.Z_pointer_nil`: `0x0`,
  81. `main.Z_slice`: `[]uint8{115, 108, 105, 99, 101}`,
  82. `main.Z_slice_2`: `[]int8{-121, 121}`,
  83. `main.Z_slice_nil`: `[]uint8{}`,
  84. `main.Z_string`: `"I'm a string"`,
  85. `main.Z_struct`: `main.FooStruct {21, "hi"}`,
  86. `main.Z_uint`: `21`,
  87. `main.Z_uint16`: `54321`,
  88. `main.Z_uint32`: `3217654321`,
  89. `main.Z_uint64`: `12345678900987654321`,
  90. `main.Z_uint8`: `231`,
  91. `main.Z_uintptr`: `21`,
  92. `main.Z_unsafe_pointer`: `0xX`,
  93. `main.Z_unsafe_pointer_nil`: `0x0`,
  94. }
  95. // expectedEvaluate contains expected results of the debug.Evaluate function.
  96. // A nil value indicates that an error is expected.
  97. var expectedEvaluate = map[string]debug.Value{
  98. `x`: int16(42),
  99. `local_array`: debug.Array{42, 42, 5, 8},
  100. `local_channel`: debug.Channel{42, 42, 42, 0, 0, 2, 0},
  101. `local_channel_buffered`: debug.Channel{42, 42, 42, 6, 10, 2, 8},
  102. `local_map`: debug.Map{42, 42, 1},
  103. `local_map_2`: debug.Map{42, 42, 1},
  104. `local_map_3`: debug.Map{42, 42, 2},
  105. `local_map_empty`: debug.Map{42, 42, 0},
  106. `x + 5`: int16(47),
  107. `x - 5`: int16(37),
  108. `x / 5`: int16(8),
  109. `x % 5`: int16(2),
  110. `x & 2`: int16(2),
  111. `x | 1`: int16(43),
  112. `x ^ 3`: int16(41),
  113. `5 + x`: int16(47),
  114. `5 - x`: int16(-37),
  115. `100 / x`: int16(2),
  116. `100 % x`: int16(16),
  117. `2 & x`: int16(2),
  118. `1 | x`: int16(43),
  119. `3 ^ x`: int16(41),
  120. `12`: 12,
  121. `+42`: 42,
  122. `23i`: 23i,
  123. `34.0`: 34.0,
  124. `34.5`: 34.5,
  125. `1e5`: 100000.0,
  126. `0x42`: 66,
  127. `'c'`: 'c',
  128. `"de"`: debug.String{2, `de`},
  129. "`ef`": debug.String{2, `ef`},
  130. `"de" + "fg"`: debug.String{4, `defg`},
  131. `/* comment */ -5`: -5,
  132. `false`: false,
  133. `true`: true,
  134. `!false`: true,
  135. `!true`: false,
  136. `5 + 5`: 10,
  137. `true || false`: true,
  138. `false || false`: false,
  139. `true && false`: false,
  140. `true && true`: true,
  141. `!(5 > 8)`: true,
  142. `10 + 'a'`: 'k',
  143. `10 + 10.5`: 20.5,
  144. `10 + 10.5i`: 10 + 10.5i,
  145. `'a' + 10.5`: 107.5,
  146. `'a' + 10.5i`: 97 + 10.5i,
  147. `10.5 + 20.5i`: 10.5 + 20.5i,
  148. `10 * 20`: 200,
  149. `10.0 - 20.5`: -10.5,
  150. `(6 + 8i) * 4`: 24 + 32i,
  151. `(6 + 8i) * (1 + 1i)`: -2 + 14i,
  152. `(6 + 8i) * (6 - 8i)`: complex128(100),
  153. `(6 + 8i) / (3 + 4i)`: complex128(2),
  154. `local_array[2]`: int8(3),
  155. `&local_array[1]`: debug.Pointer{42, 42},
  156. `local_map[-21]`: float32(3.54321),
  157. `local_map[+21]`: float32(0),
  158. `local_map_3[1024]`: int8(1),
  159. `local_map_3[512]`: int8(-1),
  160. `local_map_empty[21]`: float32(0),
  161. `"hello"[2]`: uint8('l'),
  162. `local_array[1:3][1]`: int8(3),
  163. `local_array[0:4][2:3][0]`: int8(3),
  164. `local_array[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
  165. `local_array[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
  166. `local_array[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3},
  167. `local_array[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4},
  168. `local_array[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4},
  169. `local_array[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
  170. `local_array[1:][1:][1:]`: debug.Slice{debug.Array{42, 42, 2, 8}, 2},
  171. `(&local_array)[:]`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
  172. `(&local_array)[:2]`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
  173. `(&local_array)[2:]`: debug.Slice{debug.Array{42, 42, 3, 8}, 3},
  174. `(&local_array)[1:3]`: debug.Slice{debug.Array{42, 42, 2, 8}, 4},
  175. `(&local_array)[:3:4]`: debug.Slice{debug.Array{42, 42, 3, 8}, 4},
  176. `(&local_array)[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
  177. `lookup("main.Z_array")`: debug.Array{42, 42, 5, 8},
  178. `lookup("main.Z_array_empty")`: debug.Array{42, 42, 0, 8},
  179. `lookup("main.Z_bool_false")`: false,
  180. `lookup("main.Z_bool_true")`: true,
  181. `lookup("main.Z_channel")`: debug.Channel{42, 42, 42, 0, 0, 2, 0},
  182. `lookup("main.Z_channel_buffered")`: debug.Channel{42, 42, 42, 6, 10, 2, 8},
  183. `lookup("main.Z_channel_nil")`: debug.Channel{42, 0, 0, 0, 0, 2, 0},
  184. `lookup("main.Z_array_of_empties")`: debug.Array{42, 42, 2, 0},
  185. `lookup("main.Z_complex128")`: complex128(1.987654321 - 2.987654321i),
  186. `lookup("main.Z_complex64")`: complex64(1.54321 + 2.54321i),
  187. `lookup("main.Z_float32")`: float32(1.54321),
  188. `lookup("main.Z_float64")`: float64(1.987654321),
  189. `lookup("main.Z_func_int8_r_int8")`: debug.Func{42},
  190. `lookup("main.Z_func_int8_r_pint8")`: debug.Func{42},
  191. `lookup("main.Z_func_bar")`: debug.Func{42},
  192. `lookup("main.Z_func_nil")`: debug.Func{0},
  193. `lookup("main.Z_int")`: -21,
  194. `lookup("main.Z_int16")`: int16(-32321),
  195. `lookup("main.Z_int32")`: int32(-1987654321),
  196. `lookup("main.Z_int64")`: int64(-9012345678987654321),
  197. `lookup("main.Z_int8")`: int8(-121),
  198. `lookup("main.Z_int_typedef")`: int16(88),
  199. `lookup("main.Z_interface")`: debug.Interface{},
  200. `lookup("main.Z_interface_nil")`: debug.Interface{},
  201. `lookup("main.Z_interface_typed_nil")`: debug.Interface{},
  202. `lookup("main.Z_map")`: debug.Map{42, 42, 1},
  203. `lookup("main.Z_map_2")`: debug.Map{42, 42, 1},
  204. `lookup("main.Z_map_3")`: debug.Map{42, 42, 2},
  205. `lookup("main.Z_map_empty")`: debug.Map{42, 42, 0},
  206. `lookup("main.Z_map_nil")`: debug.Map{42, 42, 0},
  207. `lookup("main.Z_pointer")`: debug.Pointer{42, 42},
  208. `lookup("main.Z_pointer_nil")`: debug.Pointer{42, 0},
  209. `lookup("main.Z_slice")`: debug.Slice{debug.Array{42, 42, 5, 8}, 5},
  210. `lookup("main.Z_slice_2")`: debug.Slice{debug.Array{42, 42, 2, 8}, 5},
  211. `lookup("main.Z_slice_nil")`: debug.Slice{debug.Array{42, 0, 0, 8}, 0},
  212. `lookup("main.Z_string")`: debug.String{12, `I'm a string`},
  213. `lookup("main.Z_struct")`: debug.Struct{[]debug.StructField{{"a", debug.Var{}}, {"b", debug.Var{}}}},
  214. `lookup("main.Z_uint")`: uint(21),
  215. `lookup("main.Z_uint16")`: uint16(54321),
  216. `lookup("main.Z_uint32")`: uint32(3217654321),
  217. `lookup("main.Z_uint64")`: uint64(12345678900987654321),
  218. `lookup("main.Z_uint8")`: uint8(231),
  219. `lookup("main.Z_uintptr")`: uint(21),
  220. `lookup("main.Z_unsafe_pointer")`: debug.Pointer{0, 42},
  221. `lookup("main.Z_unsafe_pointer_nil")`: debug.Pointer{0, 0},
  222. `lookup("main.Z_int") + lookup("main.Z_int")`: -42,
  223. `lookup("main.Z_int16") < 0`: true,
  224. `lookup("main.Z_uint32") + lookup("main.Z_uint32")`: uint32(2140341346),
  225. `lookup("main.Z_bool_true") || lookup("main.Z_bool_false")`: true,
  226. `lookup("main.Z_bool_true") && lookup("main.Z_bool_false")`: false,
  227. `lookup("main.Z_bool_false") || lookup("main.Z_bool_false")`: false,
  228. `!lookup("main.Z_bool_true")`: false,
  229. `!lookup("main.Z_bool_false")`: true,
  230. `lookup("main.Z_array")[2]`: int8(3),
  231. `lookup("main.Z_array")[1:3][1]`: int8(3),
  232. `lookup("main.Z_array")[0:4][2:3][0]`: int8(3),
  233. `lookup("main.Z_array_of_empties")[0]`: debug.Struct{},
  234. `lookup("main.Z_complex128") * 10.0`: complex128(19.87654321 - 29.87654321i),
  235. `lookup("main.Z_complex64") * 0.1`: complex64(0.154321 + 0.254321i),
  236. `lookup("main.Z_float32") * 10.0`: float32(15.4321),
  237. `lookup("main.Z_float64") * 0.1`: float64(0.1987654321),
  238. `lookup("main.Z_int") + 1`: int(-20),
  239. `lookup("main.Z_int16") - 10`: int16(-32331),
  240. `lookup("main.Z_int32") / 10`: int32(-198765432),
  241. `lookup("main.Z_int64") / 10`: int64(-901234567898765432),
  242. `lookup("main.Z_int8") + 10`: int8(-111),
  243. `lookup("main.Z_map")[-21]`: float32(3.54321),
  244. `lookup("main.Z_map")[+21]`: float32(0),
  245. `lookup("main.Z_map_empty")[21]`: float32(0),
  246. `lookup("main.Z_slice")[1]`: uint8(108),
  247. `lookup("main.Z_slice_2")[1]`: int8(121),
  248. `lookup("main.Z_slice")[1:5][0:3][1]`: uint8('i'),
  249. `lookup("main.Z_array")[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
  250. `(&lookup("main.Z_array"))[1:3:4]`: debug.Slice{debug.Array{42, 42, 2, 8}, 3},
  251. `lookup("main.Z_string") + "!"`: debug.String{13, `I'm a string!`},
  252. `lookup("main.Z_struct").a`: 21,
  253. `(&lookup("main.Z_struct")).a`: 21,
  254. `lookup("main.Z_uint")/10`: uint(2),
  255. `lookup("main.Z_uint16")/10`: uint16(5432),
  256. `lookup("main.Z_uint32")/10`: uint32(321765432),
  257. `lookup("main.Z_uint64")/10`: uint64(1234567890098765432),
  258. `lookup("main.Z_uint8")/10`: uint8(23),
  259. `lookup("main.Z_pointer").a`: 21,
  260. `(*lookup("main.Z_pointer")).a`: 21,
  261. `(&*lookup("main.Z_pointer")).a`: 21,
  262. `lookup("main.Z_pointer").b`: debug.String{2, `hi`},
  263. `(*lookup("main.Z_pointer")).b`: debug.String{2, `hi`},
  264. `(&*lookup("main.Z_pointer")).b`: debug.String{2, `hi`},
  265. `lookup("main.Z_map_nil")[32]`: float32(0),
  266. `&lookup("main.Z_int16")`: debug.Pointer{42, 42},
  267. `&lookup("main.Z_array")[1]`: debug.Pointer{42, 42},
  268. `&lookup("main.Z_slice")[1]`: debug.Pointer{42, 42},
  269. `*&lookup("main.Z_int16")`: int16(-32321),
  270. `*&*&*&*&lookup("main.Z_int16")`: int16(-32321),
  271. `lookup("time.Local")`: debug.Pointer{42, 42},
  272. `5 + false`: nil,
  273. ``: nil,
  274. `x + ""`: nil,
  275. `x / 0`: nil,
  276. `0 / 0`: nil,
  277. `'a' / ('a'-'a')`: nil,
  278. `0.0 / 0.0`: nil,
  279. `3i / 0.0`: nil,
  280. `x % 0`: nil,
  281. `0 % 0`: nil,
  282. `'a' % ('a'-'a')`: nil,
  283. `local_array[-2] + 1`: nil,
  284. `local_array[22] + 1`: nil,
  285. `local_slice[-2] + 1`: nil,
  286. `local_slice[22] + 1`: nil,
  287. `local_string[-2]`: nil,
  288. `local_string[22]`: nil,
  289. `"hello"[-2]`: nil,
  290. `"hello"[22]`: nil,
  291. `local_pointer_nil.a`: nil,
  292. `(local_struct).c`: nil,
  293. `(&local_struct).c`: nil,
  294. `(*local_pointer).c`: nil,
  295. `lookup("not a real symbol")`: nil,
  296. `lookup("x")`: nil,
  297. `lookup(x)`: nil,
  298. `lookup(42)`: nil,
  299. }
  300. func isHex(r uint8) bool {
  301. switch {
  302. case '0' <= r && r <= '9':
  303. return true
  304. case 'a' <= r && r <= 'f':
  305. return true
  306. case 'A' <= r && r <= 'F':
  307. return true
  308. default:
  309. return false
  310. }
  311. }
  312. // structRE is used by matches to remove 'struct ' from type names, which is not
  313. // output by every version of the compiler.
  314. var structRE = regexp.MustCompile("struct *")
  315. // Check s matches the pattern in p.
  316. // An 'X' in p greedily matches one or more hex characters in s.
  317. func matches(p, s string) bool {
  318. // Remove 'struct' and following spaces from s.
  319. s = structRE.ReplaceAllString(s, "")
  320. j := 0
  321. for i := 0; i < len(p); i++ {
  322. if j == len(s) {
  323. return false
  324. }
  325. c := p[i]
  326. if c == 'X' {
  327. if !isHex(s[j]) {
  328. return false
  329. }
  330. for j < len(s) && isHex(s[j]) {
  331. j++
  332. }
  333. continue
  334. }
  335. if c != s[j] {
  336. return false
  337. }
  338. j++
  339. }
  340. return j == len(s)
  341. }
  342. const (
  343. proxySrc = "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/cmd/debugproxy"
  344. traceeSrc = "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/tests/peek/testdata"
  345. )
  346. var (
  347. // Locations of the proxy and tracee executables.
  348. proxyBinary = "./debugproxy.out"
  349. traceeBinary = "./tracee.out"
  350. // Onces that ensure initProxy and initTracee are called at most once.
  351. proxyOnce sync.Once
  352. traceeOnce sync.Once
  353. // Flags for setting the location of the proxy and tracee, so they don't need to be built.
  354. proxyFlag = flag.String("proxy", "", "Location of debugproxy. If empty, proxy will be built.")
  355. traceeFlag = flag.String("target", "", "Location of target. If empty, target will be built.")
  356. // Executables this test has built, which will be removed on completion of the tests.
  357. filesToRemove []string
  358. )
  359. func TestMain(m *testing.M) {
  360. flag.Parse()
  361. x := m.Run()
  362. for _, f := range filesToRemove {
  363. os.Remove(f)
  364. }
  365. os.Exit(x)
  366. }
  367. func run(name string, args ...string) error {
  368. cmd := exec.Command(name, args...)
  369. cmd.Stdout = os.Stdout
  370. cmd.Stderr = os.Stderr
  371. return cmd.Run()
  372. }
  373. func initProxy() {
  374. if *proxyFlag != "" {
  375. proxyBinary = *proxyFlag
  376. remote.DebugproxyCmd = proxyBinary
  377. return
  378. }
  379. if err := run("go", "build", "-o", proxyBinary, proxySrc); err != nil {
  380. log.Fatalf("couldn't build proxy: %v", err)
  381. }
  382. filesToRemove = append(filesToRemove, proxyBinary)
  383. remote.DebugproxyCmd = proxyBinary
  384. }
  385. func initTracee() {
  386. if *traceeFlag != "" {
  387. traceeBinary = *traceeFlag
  388. return
  389. }
  390. if err := run("go", "build", "-o", traceeBinary, traceeSrc); err != nil {
  391. log.Fatalf("couldn't build target: %v", err)
  392. }
  393. filesToRemove = append(filesToRemove, traceeBinary)
  394. }
  395. func TestLocalProgram(t *testing.T) {
  396. t.Skip("Fails looking for runtime.lessstack for some reason")
  397. traceeOnce.Do(initTracee)
  398. prog, err := local.New(traceeBinary)
  399. if err != nil {
  400. t.Fatal("local.New:", err)
  401. }
  402. testProgram(t, prog)
  403. }
  404. func TestRemoteProgram(t *testing.T) {
  405. t.Skip("Fails looking for runtime.lessstack for some reason")
  406. traceeOnce.Do(initTracee)
  407. proxyOnce.Do(initProxy)
  408. prog, err := remote.New("localhost", traceeBinary)
  409. if err != nil {
  410. t.Fatal("remote.New:", err)
  411. }
  412. testProgram(t, prog)
  413. }
  414. func testProgram(t *testing.T, prog debug.Program) {
  415. _, err := prog.Run("some", "arguments")
  416. if err != nil {
  417. log.Fatalf("Run: %v", err)
  418. }
  419. pcs, err := prog.BreakpointAtFunction("main.foo")
  420. if err != nil {
  421. log.Fatalf("BreakpointAtFunction: %v", err)
  422. }
  423. fmt.Printf("breakpoints set at %x\n", pcs)
  424. _, err = prog.Resume()
  425. if err != nil {
  426. log.Fatalf("Resume: %v", err)
  427. }
  428. gs, err := prog.Goroutines()
  429. if err != nil {
  430. t.Fatalf("Goroutines(): got error %s", err)
  431. }
  432. for _, g := range gs {
  433. fmt.Println(g)
  434. for _, f := range g.StackFrames {
  435. fmt.Println(f)
  436. }
  437. }
  438. frames, err := prog.Frames(100)
  439. if err != nil {
  440. log.Fatalf("prog.Frames error: %v", err)
  441. }
  442. fmt.Printf("%#v\n", frames)
  443. if len(frames) == 0 {
  444. t.Fatalf("no stack frames returned")
  445. }
  446. if frames[0].Function != "main.foo" {
  447. t.Errorf("function name: got %s expected main.foo", frames[0].Function)
  448. }
  449. if len(frames[0].Params) != 2 {
  450. t.Errorf("got %d parameters, expected 2", len(frames[0].Params))
  451. } else {
  452. x := frames[0].Params[0]
  453. y := frames[0].Params[1]
  454. if x.Name != "x" {
  455. x, y = y, x
  456. }
  457. if x.Name != "x" {
  458. t.Errorf("parameter name: got %s expected x", x.Name)
  459. }
  460. if y.Name != "y" {
  461. t.Errorf("parameter name: got %s expected y", y.Name)
  462. }
  463. if val, err := prog.Value(x.Var); err != nil {
  464. t.Errorf("value of x: %s", err)
  465. } else if val != int16(42) {
  466. t.Errorf("value of x: got %T(%v) expected int16(42)", val, val)
  467. }
  468. if val, err := prog.Value(y.Var); err != nil {
  469. t.Errorf("value of y: %s", err)
  470. } else if val != float32(1.5) {
  471. t.Errorf("value of y: got %T(%v) expected float32(1.5)", val, val)
  472. }
  473. }
  474. varnames, err := prog.Eval(`re:main\.Z_.*`)
  475. if err != nil {
  476. log.Fatalf("prog.Eval error: %v", err)
  477. }
  478. // Evaluate each of the variables found above, and check they match
  479. // expectedVars.
  480. seen := make(map[string]bool)
  481. for _, v := range varnames {
  482. val, err := prog.Eval("val:" + v)
  483. if err != nil {
  484. log.Fatalf("prog.Eval error for %s: %v", v, err)
  485. } else {
  486. fmt.Printf("%s = %v\n", v, val)
  487. if seen[v] {
  488. log.Fatalf("repeated variable %s\n", v)
  489. }
  490. seen[v] = true
  491. if len(val) != 1 {
  492. log.Fatalf("should be one value for %s\n", v)
  493. }
  494. expected, ok := expectedVars[v]
  495. if !ok {
  496. log.Fatalf("unexpected variable %s\n", v)
  497. } else {
  498. if !matches(expected, val[0]) {
  499. log.Fatalf("expected %s = %s\n", v, expected)
  500. }
  501. }
  502. }
  503. }
  504. for v, e := range expectedVars {
  505. if !seen[v] {
  506. log.Fatalf("didn't get %s = %s\n", v, e)
  507. }
  508. }
  509. // Remove the breakpoint at main.foo.
  510. err = prog.DeleteBreakpoints(pcs)
  511. if err != nil {
  512. log.Fatalf("DeleteBreakpoints: %v", err)
  513. }
  514. // Set a breakpoint at line 125, resume, and check we stopped there.
  515. pcsLine125, err := prog.BreakpointAtLine("testdata/main.go", 125)
  516. if err != nil {
  517. t.Fatal("BreakpointAtLine:", err)
  518. }
  519. status, err := prog.Resume()
  520. if err != nil {
  521. log.Fatalf("Resume: %v", err)
  522. }
  523. stoppedAt := func(pcs []uint64) bool {
  524. for _, pc := range pcs {
  525. if status.PC == pc {
  526. return true
  527. }
  528. }
  529. return false
  530. }
  531. if !stoppedAt(pcsLine125) {
  532. t.Errorf("stopped at %X; expected one of %X.", status.PC, pcsLine125)
  533. }
  534. for k, v := range expectedEvaluate {
  535. val, err := prog.Evaluate(k)
  536. if v == nil {
  537. if err == nil {
  538. t.Errorf("got Evaluate(%s) = %v, expected error", k, val)
  539. }
  540. continue
  541. }
  542. if err != nil {
  543. t.Errorf("Evaluate(%s): got error %s, expected %v", k, err, v)
  544. continue
  545. }
  546. typ := reflect.TypeOf(v)
  547. if typ != reflect.TypeOf(val) && typ != reflect.TypeOf(int(0)) && typ != reflect.TypeOf(uint(0)) {
  548. t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
  549. continue
  550. }
  551. // For types with fields like Address, TypeID, etc., we can't know the exact
  552. // value, so we only test whether those fields are zero or not.
  553. switch v := v.(type) {
  554. default:
  555. if v != val {
  556. t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
  557. }
  558. case debug.Array:
  559. val := val.(debug.Array)
  560. if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
  561. t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
  562. }
  563. if v.ElementTypeID != 0 && val.ElementTypeID == 0 {
  564. t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val)
  565. }
  566. if v.Address == 0 && val.Address != 0 {
  567. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  568. }
  569. if v.Address != 0 && val.Address == 0 {
  570. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  571. }
  572. case debug.Slice:
  573. val := val.(debug.Slice)
  574. if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
  575. t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
  576. }
  577. if v.ElementTypeID != 0 && val.ElementTypeID == 0 {
  578. t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val)
  579. }
  580. if v.Address == 0 && val.Address != 0 {
  581. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  582. }
  583. if v.Address != 0 && val.Address == 0 {
  584. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  585. }
  586. case debug.Map:
  587. val := val.(debug.Map)
  588. if v.TypeID == 0 && val.TypeID != 0 {
  589. t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val)
  590. }
  591. if v.TypeID != 0 && val.TypeID == 0 {
  592. t.Errorf("got Evaluate(%s) = %+v, expected non-zero TypeID", k, val)
  593. }
  594. if v.Address == 0 && val.Address != 0 {
  595. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  596. }
  597. if v.Address != 0 && val.Address == 0 {
  598. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  599. }
  600. case debug.Pointer:
  601. val := val.(debug.Pointer)
  602. if v.TypeID == 0 && val.TypeID != 0 {
  603. t.Errorf("got Evaluate(%s) = %+v, expected zero TypeID", k, val)
  604. }
  605. if v.TypeID != 0 && val.TypeID == 0 {
  606. t.Errorf("got Evaluate(%s) = %+v, expected non-zero TypeID", k, val)
  607. }
  608. if v.Address == 0 && val.Address != 0 {
  609. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  610. }
  611. if v.Address != 0 && val.Address == 0 {
  612. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  613. }
  614. case debug.Channel:
  615. val := val.(debug.Channel)
  616. if v.ElementTypeID == 0 && val.ElementTypeID != 0 {
  617. t.Errorf("got Evaluate(%s) = %+v, expected zero ElementTypeID", k, val)
  618. }
  619. if v.ElementTypeID != 0 && val.ElementTypeID == 0 {
  620. t.Errorf("got Evaluate(%s) = %+v, expected non-zero ElementTypeID", k, val)
  621. }
  622. if v.Address == 0 && val.Address != 0 {
  623. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  624. }
  625. if v.Address != 0 && val.Address == 0 {
  626. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  627. }
  628. if v.Buffer == 0 && val.Buffer != 0 {
  629. t.Errorf("got Evaluate(%s) = %+v, expected zero Buffer", k, val)
  630. }
  631. if v.Buffer != 0 && val.Buffer == 0 {
  632. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Buffer", k, val)
  633. }
  634. case debug.Struct:
  635. val := val.(debug.Struct)
  636. if len(v.Fields) != len(val.Fields) {
  637. t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
  638. break
  639. }
  640. for i := range v.Fields {
  641. a := v.Fields[i].Name
  642. b := val.Fields[i].Name
  643. if a != b {
  644. t.Errorf("Evaluate(%s): field name mismatch: %s vs %s", k, a, b)
  645. break
  646. }
  647. }
  648. case debug.Func:
  649. val := val.(debug.Func)
  650. if v.Address == 0 && val.Address != 0 {
  651. t.Errorf("got Evaluate(%s) = %+v, expected zero Address", k, val)
  652. }
  653. if v.Address != 0 && val.Address == 0 {
  654. t.Errorf("got Evaluate(%s) = %+v, expected non-zero Address", k, val)
  655. }
  656. case int:
  657. // ints in a remote program can be returned as int32 or int64
  658. switch val := val.(type) {
  659. case int32:
  660. if val != int32(v) {
  661. t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v)
  662. }
  663. case int64:
  664. if val != int64(v) {
  665. t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v)
  666. }
  667. default:
  668. t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
  669. }
  670. case uint:
  671. // uints in a remote program can be returned as uint32 or uint64
  672. switch val := val.(type) {
  673. case uint32:
  674. if val != uint32(v) {
  675. t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v)
  676. }
  677. case uint64:
  678. if val != uint64(v) {
  679. t.Errorf("got Evaluate(%s) = %T(%v), expected %v", k, val, val, v)
  680. }
  681. default:
  682. t.Errorf("got Evaluate(%s) = %T(%v), expected %T(%v)", k, val, val, v, v)
  683. }
  684. }
  685. }
  686. // Evaluate a struct.
  687. v := `lookup("main.Z_struct")`
  688. val, err := prog.Evaluate(v)
  689. if err != nil {
  690. t.Fatalf("Evaluate: %s", err)
  691. }
  692. s, ok := val.(debug.Struct)
  693. if !ok {
  694. t.Fatalf("got Evaluate(%q) = %T(%v), expected debug.Struct", v, val, val)
  695. }
  696. // Check the values of its fields.
  697. if len(s.Fields) != 2 {
  698. t.Fatalf("got Evaluate(%q) = %+v, expected 2 fields", v, s)
  699. }
  700. if v0, err := prog.Value(s.Fields[0].Var); err != nil {
  701. t.Errorf("Value: %s", err)
  702. } else if v0 != int32(21) && v0 != int64(21) {
  703. t.Errorf("Value: got %T(%v), expected 21", v0, v0)
  704. }
  705. if v1, err := prog.Value(s.Fields[1].Var); err != nil {
  706. t.Errorf("Value: %s", err)
  707. } else if v1 != (debug.String{2, "hi"}) {
  708. t.Errorf("Value: got %T(%v), expected `hi`", v1, v1)
  709. }
  710. // Remove the breakpoint at line 125, set a breakpoint at main.f1 and main.f2,
  711. // then delete the breakpoint at main.f1. Resume, then check we stopped at
  712. // main.f2.
  713. err = prog.DeleteBreakpoints(pcsLine125)
  714. if err != nil {
  715. log.Fatalf("DeleteBreakpoints: %v", err)
  716. }
  717. pcs1, err := prog.BreakpointAtFunction("main.f1")
  718. if err != nil {
  719. log.Fatalf("BreakpointAtFunction: %v", err)
  720. }
  721. pcs2, err := prog.BreakpointAtFunction("main.f2")
  722. if err != nil {
  723. log.Fatalf("BreakpointAtFunction: %v", err)
  724. }
  725. err = prog.DeleteBreakpoints(pcs1)
  726. if err != nil {
  727. log.Fatalf("DeleteBreakpoints: %v", err)
  728. }
  729. status, err = prog.Resume()
  730. if err != nil {
  731. log.Fatalf("Resume: %v", err)
  732. }
  733. if !stoppedAt(pcs2) {
  734. t.Errorf("stopped at %X; expected one of %X.", status.PC, pcs2)
  735. }
  736. // Check we get the expected results calling VarByName then Value
  737. // for the variables in expectedVarValues.
  738. for name, exp := range expectedVarValues {
  739. if v, err := prog.VarByName(name); err != nil {
  740. t.Errorf("VarByName(%s): %s", name, err)
  741. } else if val, err := prog.Value(v); err != nil {
  742. t.Errorf("value of %s: %s", name, err)
  743. } else if val != exp {
  744. t.Errorf("value of %s: got %T(%v) want %T(%v)", name, val, val, exp, exp)
  745. }
  746. }
  747. // Check some error cases for VarByName and Value.
  748. if _, err = prog.VarByName("not a real name"); err == nil {
  749. t.Error("VarByName for invalid name: expected error")
  750. }
  751. if _, err = prog.Value(debug.Var{}); err == nil {
  752. t.Error("value of invalid var: expected error")
  753. }
  754. if v, err := prog.VarByName("main.Z_int16"); err != nil {
  755. t.Error("VarByName(main.Z_int16) error:", err)
  756. } else {
  757. v.Address = 0
  758. // v now has a valid type but a bad address.
  759. _, err = prog.Value(v)
  760. if err == nil {
  761. t.Error("value of invalid location: expected error")
  762. }
  763. }
  764. // checkValue tests that we can get a Var for a variable with the given name,
  765. // that we can then get the value of that Var, and that calling fn for that
  766. // value succeeds.
  767. checkValue := func(name string, fn func(val debug.Value) error) {
  768. if v, err := prog.VarByName(name); err != nil {
  769. t.Errorf("VarByName(%s): %s", name, err)
  770. } else if val, err := prog.Value(v); err != nil {
  771. t.Errorf("value of %s: %s", name, err)
  772. } else if err := fn(val); err != nil {
  773. t.Errorf("value of %s: %s", name, err)
  774. }
  775. }
  776. checkValue("main.Z_uintptr", func(val debug.Value) error {
  777. if val != uint32(21) && val != uint64(21) {
  778. // Z_uintptr should be an unsigned integer with size equal to the debugged
  779. // program's address size.
  780. return fmt.Errorf("got %T(%v) want 21", val, val)
  781. }
  782. return nil
  783. })
  784. checkValue("main.Z_int", func(val debug.Value) error {
  785. if val != int32(-21) && val != int64(-21) {
  786. return fmt.Errorf("got %T(%v) want -21", val, val)
  787. }
  788. return nil
  789. })
  790. checkValue("main.Z_uint", func(val debug.Value) error {
  791. if val != uint32(21) && val != uint64(21) {
  792. return fmt.Errorf("got %T(%v) want 21", val, val)
  793. }
  794. return nil
  795. })
  796. checkValue("main.Z_pointer", func(val debug.Value) error {
  797. if _, ok := val.(debug.Pointer); !ok {
  798. return fmt.Errorf("got %T(%v) expected Pointer", val, val)
  799. }
  800. return nil
  801. })
  802. checkValue("main.Z_pointer_nil", func(val debug.Value) error {
  803. if p, ok := val.(debug.Pointer); !ok {
  804. return fmt.Errorf("got %T(%v) expected Pointer", val, val)
  805. } else if p.Address != 0 {
  806. return fmt.Errorf("got %T(%v) expected nil pointer", val, val)
  807. }
  808. return nil
  809. })
  810. checkValue("main.Z_array", func(val debug.Value) error {
  811. a, ok := val.(debug.Array)
  812. if !ok {
  813. return fmt.Errorf("got %T(%v) expected Array", val, val)
  814. }
  815. if a.Len() != 5 {
  816. return fmt.Errorf("got array length %d expected 5", a.Len())
  817. }
  818. expected := [5]int8{-121, 121, 3, 2, 1}
  819. for i := uint64(0); i < 5; i++ {
  820. if v, err := prog.Value(a.Element(i)); err != nil {
  821. return fmt.Errorf("reading element %d: %s", i, err)
  822. } else if v != expected[i] {
  823. return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i])
  824. }
  825. }
  826. return nil
  827. })
  828. checkValue("main.Z_slice", func(val debug.Value) error {
  829. s, ok := val.(debug.Slice)
  830. if !ok {
  831. return fmt.Errorf("got %T(%v) expected Slice", val, val)
  832. }
  833. if s.Len() != 5 {
  834. return fmt.Errorf("got slice length %d expected 5", s.Len())
  835. }
  836. expected := []uint8{115, 108, 105, 99, 101}
  837. for i := uint64(0); i < 5; i++ {
  838. if v, err := prog.Value(s.Element(i)); err != nil {
  839. return fmt.Errorf("reading element %d: %s", i, err)
  840. } else if v != expected[i] {
  841. return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i])
  842. }
  843. }
  844. return nil
  845. })
  846. checkValue("main.Z_map_empty", func(val debug.Value) error {
  847. m, ok := val.(debug.Map)
  848. if !ok {
  849. return fmt.Errorf("got %T(%v) expected Map", val, val)
  850. }
  851. if m.Length != 0 {
  852. return fmt.Errorf("got map length %d expected 0", m.Length)
  853. }
  854. return nil
  855. })
  856. checkValue("main.Z_map_nil", func(val debug.Value) error {
  857. m, ok := val.(debug.Map)
  858. if !ok {
  859. return fmt.Errorf("got %T(%v) expected Map", val, val)
  860. }
  861. if m.Length != 0 {
  862. return fmt.Errorf("got map length %d expected 0", m.Length)
  863. }
  864. return nil
  865. })
  866. checkValue("main.Z_map_3", func(val debug.Value) error {
  867. m, ok := val.(debug.Map)
  868. if !ok {
  869. return fmt.Errorf("got %T(%v) expected Map", val, val)
  870. }
  871. if m.Length != 2 {
  872. return fmt.Errorf("got map length %d expected 2", m.Length)
  873. }
  874. keyVar0, valVar0, err := prog.MapElement(m, 0)
  875. if err != nil {
  876. return err
  877. }
  878. keyVar1, valVar1, err := prog.MapElement(m, 1)
  879. if err != nil {
  880. return err
  881. }
  882. key0, err := prog.Value(keyVar0)
  883. if err != nil {
  884. return err
  885. }
  886. key1, err := prog.Value(keyVar1)
  887. if err != nil {
  888. return err
  889. }
  890. val0, err := prog.Value(valVar0)
  891. if err != nil {
  892. return err
  893. }
  894. val1, err := prog.Value(valVar1)
  895. if err != nil {
  896. return err
  897. }
  898. // The map should contain 1024,1 and 512,-1 in some order.
  899. ok1 := key0 == int16(1024) && val0 == int8(1) && key1 == int16(512) && val1 == int8(-1)
  900. ok2 := key1 == int16(1024) && val1 == int8(1) && key0 == int16(512) && val0 == int8(-1)
  901. if !ok1 && !ok2 {
  902. return fmt.Errorf("got values (%d,%d) and (%d,%d), expected (1024,1) and (512,-1) in some order", key0, val0, key1, val1)
  903. }
  904. _, _, err = prog.MapElement(m, 2)
  905. if err == nil {
  906. return fmt.Errorf("MapElement: reading at a bad index succeeded, expected error")
  907. }
  908. return nil
  909. })
  910. checkValue("main.Z_string", func(val debug.Value) error {
  911. s, ok := val.(debug.String)
  912. if !ok {
  913. return fmt.Errorf("got %T(%v) expected String", val, val)
  914. }
  915. if s.Length != 12 {
  916. return fmt.Errorf("got string length %d expected 12", s.Length)
  917. }
  918. expected := "I'm a string"
  919. if s.String != expected {
  920. return fmt.Errorf("got %s expected %s", s.String, expected)
  921. }
  922. return nil
  923. })
  924. checkValue("main.Z_channel", func(val debug.Value) error {
  925. c, ok := val.(debug.Channel)
  926. if !ok {
  927. return fmt.Errorf("got %T(%v) expected Channel", val, val)
  928. }
  929. if c.Buffer == 0 {
  930. return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer)
  931. }
  932. if c.Length != 0 {
  933. return fmt.Errorf("got length %d expected 0", c.Length)
  934. }
  935. if c.Capacity != 0 {
  936. return fmt.Errorf("got capacity %d expected 0", c.Capacity)
  937. }
  938. return nil
  939. })
  940. checkValue("main.Z_channel_2", func(val debug.Value) error {
  941. c, ok := val.(debug.Channel)
  942. if !ok {
  943. return fmt.Errorf("got %T(%v) expected Channel", val, val)
  944. }
  945. if c.Buffer == 0 {
  946. return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer)
  947. }
  948. if c.Length != 0 {
  949. return fmt.Errorf("got length %d expected 0", c.Length)
  950. }
  951. if c.Capacity != 0 {
  952. return fmt.Errorf("got capacity %d expected 0", c.Capacity)
  953. }
  954. return nil
  955. })
  956. checkValue("main.Z_channel_nil", func(val debug.Value) error {
  957. c, ok := val.(debug.Channel)
  958. if !ok {
  959. return fmt.Errorf("got %T(%v) expected Channel", val, val)
  960. }
  961. if c.Buffer != 0 {
  962. return fmt.Errorf("got buffer address %d expected 0", c.Buffer)
  963. }
  964. if c.Length != 0 {
  965. return fmt.Errorf("got length %d expected 0", c.Length)
  966. }
  967. if c.Capacity != 0 {
  968. return fmt.Errorf("got capacity %d expected 0", c.Capacity)
  969. }
  970. return nil
  971. })
  972. checkValue("main.Z_channel_buffered", func(val debug.Value) error {
  973. c, ok := val.(debug.Channel)
  974. if !ok {
  975. return fmt.Errorf("got %T(%v) expected Channel", val, val)
  976. }
  977. if c.Buffer == 0 {
  978. return fmt.Errorf("got buffer address %d expected nonzero", c.Buffer)
  979. }
  980. if c.Length != 6 {
  981. return fmt.Errorf("got length %d expected 6", c.Length)
  982. }
  983. if c.Capacity != 10 {
  984. return fmt.Errorf("got capacity %d expected 10", c.Capacity)
  985. }
  986. if c.Stride != 2 {
  987. return fmt.Errorf("got stride %d expected 2", c.Stride)
  988. }
  989. expected := []int16{8, 9, 10, 11, 12, 13}
  990. for i := uint64(0); i < 6; i++ {
  991. if v, err := prog.Value(c.Element(i)); err != nil {
  992. return fmt.Errorf("reading element %d: %s", i, err)
  993. } else if v != expected[i] {
  994. return fmt.Errorf("element %d: got %T(%v) want %T(%d)", i, v, v, expected[i], expected[i])
  995. }
  996. }
  997. v := c.Element(6)
  998. if v.Address != 0 {
  999. return fmt.Errorf("invalid element returned Var with address %d, expected 0", v.Address)
  1000. }
  1001. return nil
  1002. })
  1003. checkValue("main.Z_func_bar", func(val debug.Value) error {
  1004. f, ok := val.(debug.Func)
  1005. if !ok {
  1006. return fmt.Errorf("got %T(%v) expected Func", val, val)
  1007. }
  1008. if f.Address == 0 {
  1009. return fmt.Errorf("got func address %d expected nonzero", f.Address)
  1010. }
  1011. return nil
  1012. })
  1013. checkValue("main.Z_func_nil", func(val debug.Value) error {
  1014. f, ok := val.(debug.Func)
  1015. if !ok {
  1016. return fmt.Errorf("got %T(%v) expected Func", val, val)
  1017. }
  1018. if f.Address != 0 {
  1019. return fmt.Errorf("got func address %d expected zero", f.Address)
  1020. }
  1021. return nil
  1022. })
  1023. }