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.
 
 
 

169 lines
3.8 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. package dwarf_test
  15. // Stripped-down, simplified version of ../../gosym/pclntab_test.go
  16. import (
  17. "fmt"
  18. "io/ioutil"
  19. "os"
  20. "os/exec"
  21. "path/filepath"
  22. "runtime"
  23. "strings"
  24. "testing"
  25. . "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
  26. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/elf"
  27. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/macho"
  28. )
  29. var (
  30. pclineTempDir string
  31. pclinetestBinary string
  32. )
  33. func dotest(self bool) bool {
  34. // For now, only works on amd64 platforms.
  35. if runtime.GOARCH != "amd64" {
  36. return false
  37. }
  38. // Self test reads test binary; only works on Linux or Mac.
  39. if self {
  40. if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
  41. return false
  42. }
  43. }
  44. // Command below expects "sh", so Unix.
  45. if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  46. return false
  47. }
  48. if pclinetestBinary != "" {
  49. return true
  50. }
  51. var err error
  52. pclineTempDir, err = ioutil.TempDir("", "pclinetest")
  53. if err != nil {
  54. panic(err)
  55. }
  56. if strings.Contains(pclineTempDir, " ") {
  57. panic("unexpected space in tempdir")
  58. }
  59. // This command builds pclinetest from ../../gosym/pclinetest.asm;
  60. // the resulting binary looks like it was built from pclinetest.s,
  61. // but we have renamed it to keep it away from the go tool.
  62. pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
  63. command := fmt.Sprintf("go tool asm -o %s.6 ../gosym/pclinetest.asm && go tool link -H %s -E main -o %s %s.6",
  64. pclinetestBinary, runtime.GOOS, pclinetestBinary, pclinetestBinary)
  65. cmd := exec.Command("sh", "-c", command)
  66. cmd.Stdout = os.Stdout
  67. cmd.Stderr = os.Stderr
  68. if err := cmd.Run(); err != nil {
  69. panic(err)
  70. }
  71. return true
  72. }
  73. func endtest() {
  74. if pclineTempDir != "" {
  75. os.RemoveAll(pclineTempDir)
  76. pclineTempDir = ""
  77. pclinetestBinary = ""
  78. }
  79. }
  80. func getData(file string) (*Data, error) {
  81. switch runtime.GOOS {
  82. case "linux":
  83. f, err := elf.Open(file)
  84. if err != nil {
  85. return nil, err
  86. }
  87. dwarf, err := f.DWARF()
  88. if err != nil {
  89. return nil, err
  90. }
  91. f.Close()
  92. return dwarf, nil
  93. case "darwin":
  94. f, err := macho.Open(file)
  95. if err != nil {
  96. return nil, err
  97. }
  98. dwarf, err := f.DWARF()
  99. if err != nil {
  100. return nil, err
  101. }
  102. f.Close()
  103. return dwarf, nil
  104. }
  105. panic("unimplemented DWARF for GOOS=" + runtime.GOOS)
  106. }
  107. func TestPCToLine(t *testing.T) {
  108. t.Skip("linker complains while building test binary")
  109. if !dotest(false) {
  110. return
  111. }
  112. defer endtest()
  113. data, err := getData(pclinetestBinary)
  114. if err != nil {
  115. t.Fatal(err)
  116. }
  117. // Test PCToLine.
  118. entry, err := data.LookupFunction("linefrompc")
  119. if err != nil {
  120. t.Fatal(err)
  121. }
  122. pc, ok := entry.Val(AttrLowpc).(uint64)
  123. if !ok {
  124. t.Fatal(`DWARF data for function "linefrompc" has no PC`)
  125. }
  126. for _, tt := range []struct {
  127. offset, want uint64
  128. }{
  129. {0, 2},
  130. {1, 3},
  131. {2, 4},
  132. {3, 4},
  133. {4, 5},
  134. {6, 5},
  135. {7, 6},
  136. {11, 6},
  137. {12, 7},
  138. {19, 7},
  139. {20, 8},
  140. {32, 8},
  141. {33, 9},
  142. {53, 9},
  143. {54, 10},
  144. } {
  145. file, line, err := data.PCToLine(pc + tt.offset)
  146. if err != nil {
  147. t.Fatal(err)
  148. }
  149. if !strings.HasSuffix(file, "/pclinetest.asm") {
  150. t.Errorf("got %s; want %s", file, ".../pclinetest.asm")
  151. }
  152. if line != tt.want {
  153. t.Errorf("line for offset %d: got %d; want %d", tt.offset, line, tt.want)
  154. }
  155. }
  156. }