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.
 
 
 

157 line
3.5 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 go1.10
  15. package dwarf_test
  16. // Stripped-down, simplified version of ../../gosym/pclntab_test.go
  17. import (
  18. "fmt"
  19. "io/ioutil"
  20. "os"
  21. "os/exec"
  22. "path/filepath"
  23. "runtime"
  24. "strings"
  25. "testing"
  26. . "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
  27. )
  28. var (
  29. pclineTempDir string
  30. pclinetestBinary string
  31. )
  32. func dotest(self bool) bool {
  33. // For now, only works on amd64 platforms.
  34. if runtime.GOARCH != "amd64" {
  35. return false
  36. }
  37. // Self test reads test binary; only works on Linux or Mac.
  38. if self {
  39. if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
  40. return false
  41. }
  42. }
  43. // Command below expects "sh", so Unix.
  44. if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  45. return false
  46. }
  47. if pclinetestBinary != "" {
  48. return true
  49. }
  50. var err error
  51. pclineTempDir, err = ioutil.TempDir("", "pclinetest")
  52. if err != nil {
  53. panic(err)
  54. }
  55. if strings.Contains(pclineTempDir, " ") {
  56. panic("unexpected space in tempdir")
  57. }
  58. pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
  59. command := fmt.Sprintf("go tool compile -o %s.6 testdata/pclinetest.go && go tool link -H %s -E main -o %s %s.6",
  60. pclinetestBinary, runtime.GOOS, pclinetestBinary, pclinetestBinary)
  61. cmd := exec.Command("sh", "-c", command)
  62. cmd.Stdout = os.Stdout
  63. cmd.Stderr = os.Stderr
  64. if err := cmd.Run(); err != nil {
  65. panic(err)
  66. }
  67. return true
  68. }
  69. func endtest() {
  70. if pclineTempDir != "" {
  71. os.RemoveAll(pclineTempDir)
  72. pclineTempDir = ""
  73. pclinetestBinary = ""
  74. }
  75. }
  76. func TestPCAndLine(t *testing.T) {
  77. t.Skip("This stopped working in Go 1.12")
  78. // TODO(jba): go1.9: use subtests
  79. if !dotest(false) {
  80. return
  81. }
  82. defer endtest()
  83. data, err := getData(pclinetestBinary)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. testLineToBreakpointPCs(t, data)
  88. testPCToLine(t, data)
  89. }
  90. func testPCToLine(t *testing.T, data *Data) {
  91. entry, err := data.LookupFunction("main.main")
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. pc, ok := entry.Val(AttrLowpc).(uint64)
  96. if !ok {
  97. t.Fatal(`DWARF data for function "main" has no PC`)
  98. }
  99. for _, tt := range []struct {
  100. offset, want uint64
  101. }{
  102. {0, 19},
  103. {19, 19},
  104. {33, 20},
  105. {97, 22},
  106. {165, 23},
  107. } {
  108. file, line, err := data.PCToLine(pc + tt.offset)
  109. if err != nil {
  110. t.Fatal(err)
  111. }
  112. if !strings.HasSuffix(file, "/pclinetest.go") {
  113. t.Errorf("got %s; want %s", file, "/pclinetest.go")
  114. }
  115. if line != tt.want {
  116. t.Errorf("line for offset %d: got %d; want %d", tt.offset, line, tt.want)
  117. }
  118. }
  119. }
  120. func testLineToBreakpointPCs(t *testing.T, data *Data) {
  121. for _, tt := range []struct {
  122. line uint64
  123. want bool
  124. }{
  125. {18, false},
  126. {19, true},
  127. {20, true},
  128. {21, false},
  129. {22, true},
  130. {23, true},
  131. {24, false},
  132. } {
  133. pcs, err := data.LineToBreakpointPCs("pclinetest.go", uint64(tt.line))
  134. if err != nil {
  135. t.Fatal(err)
  136. }
  137. if got := len(pcs) > 0; got != tt.want {
  138. t.Errorf("line %d: got pcs=%t, want pcs=%t", tt.line, got, tt.want)
  139. }
  140. }
  141. }