您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

310 行
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. // Mapping from PC to SP offset (called CFA - Canonical Frame Address - in DWARF).
  15. // This value is the offset from the stack pointer to the virtual frame pointer
  16. // (address of zeroth argument) at each PC value in the program.
  17. package dwarf
  18. import "fmt"
  19. // http://www.dwarfstd.org/doc/DWARF4.pdf Section 6.4 page 126
  20. // We implement only the CFA column of the table, not the location
  21. // information about other registers. In other words, we implement
  22. // only what we need to understand Go programs compiled by gc.
  23. // PCToSPOffset returns the offset, at the specified PC, to add to the
  24. // SP to reach the virtual frame pointer, which corresponds to the
  25. // address of the zeroth argument of the function, the word on the
  26. // stack immediately above the return PC.
  27. func (d *Data) PCToSPOffset(pc uint64) (offset int64, err error) {
  28. if len(d.frame) == 0 {
  29. return 0, fmt.Errorf("PCToSPOffset: no frame table")
  30. }
  31. var m frameMachine
  32. // Assume the first info unit is the same as us. Extremely likely. TODO?
  33. if len(d.unit) == 0 {
  34. return 0, fmt.Errorf("PCToSPOffset: no info section")
  35. }
  36. buf := makeBuf(d, &d.unit[0], "frame", 0, d.frame)
  37. for len(buf.data) > 0 {
  38. offset, err := m.evalCompilationUnit(&buf, pc)
  39. if err != nil {
  40. return 0, err
  41. }
  42. return offset, nil
  43. }
  44. return 0, fmt.Errorf("PCToSPOffset: no frame defined for PC %#x", pc)
  45. }
  46. // Call Frame instructions. Figure 40, page 181.
  47. // Structure is high two bits plus low 6 bits specified by + in comment.
  48. // Some take one or two operands.
  49. const (
  50. frameNop = 0<<6 + 0x00
  51. frameAdvanceLoc = 1<<6 + 0x00 // + delta
  52. frameOffset = 2<<6 + 0x00 // + register op: ULEB128 offset
  53. frameRestore = 3<<6 + 0x00 // + register
  54. frameSetLoc = 0<<6 + 0x01 // op: address
  55. frameAdvanceLoc1 = 0<<6 + 0x02 // op: 1-byte delta
  56. frameAdvanceLoc2 = 0<<6 + 0x03 // op: 2-byte delta
  57. frameAdvanceLoc4 = 0<<6 + 0x04 // op: 4-byte delta
  58. frameOffsetExtended = 0<<6 + 0x05 // ops: ULEB128 register ULEB128 offset
  59. frameRestoreExtended = 0<<6 + 0x06 // op: ULEB128 register
  60. frameUndefined = 0<<6 + 0x07 // op: ULEB128 register
  61. frameSameValue = 0<<6 + 0x08 // op: ULEB128 register
  62. frameRegister = 0<<6 + 0x09 // op: ULEB128 register ULEB128 register
  63. frameRememberState = 0<<6 + 0x0a
  64. frameRestoreState = 0<<6 + 0x0b
  65. frameDefCFA = 0<<6 + 0x0c // op: ULEB128 register ULEB128 offset
  66. frameDefCFARegister = 0<<6 + 0x0d // op: ULEB128 register
  67. frameDefCFAOffset = 0<<6 + 0x0e // op: ULEB128 offset
  68. frameDefCFAExpression = 0<<6 + 0x0f // op: BLOCK
  69. frameExpression = 0<<6 + 0x10 // op: ULEB128 register BLOCK
  70. frameOffsetExtendedSf = 0<<6 + 0x11 // op: ULEB128 register SLEB128 offset
  71. frameDefCFASf = 0<<6 + 0x12 // op: ULEB128 register SLEB128 offset
  72. frameDefCFAOffsetSf = 0<<6 + 0x13 // op: SLEB128 offset
  73. frameValOffset = 0<<6 + 0x14 // op: ULEB128 ULEB128
  74. frameValOffsetSf = 0<<6 + 0x15 // op: ULEB128 SLEB128
  75. frameValExpression = 0<<6 + 0x16 // op: ULEB128 BLOCK
  76. frameLoUser = 0<<6 + 0x1c
  77. frameHiUser = 0<<6 + 0x3f
  78. )
  79. // frameMachine represents the PC/SP engine.
  80. // Section 6.4, page 129.
  81. type frameMachine struct {
  82. // Initial values from CIE.
  83. version uint8 // Version number, "independent of DWARF version"
  84. augmentation string // Augmentation; treated as unexpected for now. TODO.
  85. addressSize uint8 // In DWARF v4 and above. Size of a target address.
  86. segmentSize uint8 // In DWARF v4 and above. Size of a segment selector.
  87. codeAlignmentFactor uint64 // Unit of code size in advance instructions.
  88. dataAlignmentFactor int64 // Unit of data size in certain offset instructions.
  89. returnAddressRegister int // Pseudo-register (actually data column) representing return address.
  90. returnRegisterOffset int64 // Offset to saved PC from CFA in bytes.
  91. // CFA definition.
  92. cfaRegister int // Which register represents the SP.
  93. cfaOffset int64 // CFA offset value.
  94. // Running machine.
  95. location uint64
  96. }
  97. // evalCompilationUnit scans the frame data for one compilation unit to retrieve
  98. // the offset information for the specified pc.
  99. func (m *frameMachine) evalCompilationUnit(b *buf, pc uint64) (int64, error) {
  100. err := m.parseCIE(b)
  101. if err != nil {
  102. return 0, err
  103. }
  104. for {
  105. offset, found, err := m.scanFDE(b, pc)
  106. if err != nil {
  107. return 0, err
  108. }
  109. if found {
  110. return offset, nil
  111. }
  112. }
  113. }
  114. // parseCIE assumes the incoming buffer starts with a CIE block and parses it
  115. // to initialize a frameMachine.
  116. func (m *frameMachine) parseCIE(allBuf *buf) error {
  117. length := int(allBuf.uint32())
  118. if len(allBuf.data) < length {
  119. return fmt.Errorf("CIE parse error: too short")
  120. }
  121. // Create buffer for just this section.
  122. b := allBuf.slice(length)
  123. cie := b.uint32()
  124. if cie != 0xFFFFFFFF {
  125. return fmt.Errorf("CIE parse error: not CIE: %x", cie)
  126. }
  127. m.version = b.uint8()
  128. if m.version != 3 && m.version != 4 {
  129. return fmt.Errorf("CIE parse error: unsupported version %d", m.version)
  130. }
  131. m.augmentation = b.string()
  132. if len(m.augmentation) > 0 {
  133. return fmt.Errorf("CIE: can't handled augmentation string %q", m.augmentation)
  134. }
  135. if m.version >= 4 {
  136. m.addressSize = b.uint8()
  137. m.segmentSize = b.uint8()
  138. } else {
  139. // Unused. Gc generates version 3, so these values will not be
  140. // set, but they are also not used so it's OK.
  141. }
  142. m.codeAlignmentFactor = b.uint()
  143. m.dataAlignmentFactor = b.int()
  144. m.returnAddressRegister = int(b.uint())
  145. // Initial instructions. At least for Go, establishes SP register number
  146. // and initial value of CFA offset at start of function.
  147. _, err := m.run(&b, ^uint64(0))
  148. if err != nil {
  149. return err
  150. }
  151. // There's padding, but we can ignore it.
  152. return nil
  153. }
  154. // scanFDE assumes the incoming buffer starts with a FDE block and parses it
  155. // to run a frameMachine and, if the PC is represented in its range, return
  156. // the CFA offset for that PC. The boolean returned reports whether the
  157. // PC is in range for this FDE.
  158. func (m *frameMachine) scanFDE(allBuf *buf, pc uint64) (int64, bool, error) {
  159. length := int(allBuf.uint32())
  160. if len(allBuf.data) < length {
  161. return 0, false, fmt.Errorf("FDE parse error: too short")
  162. }
  163. if length <= 0 {
  164. if length == 0 {
  165. // EOF.
  166. return 0, false, fmt.Errorf("PC %#x not found in PC/SP table", pc)
  167. }
  168. return 0, false, fmt.Errorf("bad FDE length %d", length)
  169. }
  170. // Create buffer for just this section.
  171. b := allBuf.slice(length)
  172. cieOffset := b.uint32() // TODO assumes 32 bits.
  173. // Expect 0: first CIE in this segment. TODO.
  174. if cieOffset != 0 {
  175. return 0, false, fmt.Errorf("FDE parse error: bad CIE offset: %.2x", cieOffset)
  176. }
  177. // Initial location.
  178. m.location = b.addr()
  179. addressRange := b.addr()
  180. // If the PC is not in this function, there's no point in executing the instructions.
  181. if pc < m.location || m.location+addressRange <= pc {
  182. return 0, false, nil
  183. }
  184. // The PC appears in this FDE. Scan to find the location.
  185. offset, err := m.run(&b, pc)
  186. if err != nil {
  187. return 0, false, err
  188. }
  189. // There's padding, but we can ignore it.
  190. return offset, true, nil
  191. }
  192. // run executes the instructions in the buffer, which has been sliced to contain
  193. // only the data for this block. When we run out of data, we return.
  194. // Since we are only called when we know the PC is in this block, reaching
  195. // EOF is not an error, it just means the final CFA definition matches the
  196. // tail of the block that holds the PC.
  197. // The return value is the CFA at the end of the block or the PC, whichever
  198. // comes first.
  199. func (m *frameMachine) run(b *buf, pc uint64) (int64, error) {
  200. // We run the machine at location == PC because if the PC is at the first
  201. // instruction of a block, the definition of its offset arrives as an
  202. // offset-defining operand after the PC is set to that location.
  203. for m.location <= pc && len(b.data) > 0 {
  204. op := b.uint8()
  205. // Ops with embedded operands
  206. switch op & 0xC0 {
  207. case frameAdvanceLoc: // (6.4.2.1)
  208. // delta in low bits
  209. m.location += uint64(op & 0x3F)
  210. continue
  211. case frameOffset: // (6.4.2.3)
  212. // Register in low bits; ULEB128 offset.
  213. // For Go binaries we only see this in the CIE for the return address register.
  214. if int(op&0x3F) != m.returnAddressRegister {
  215. return 0, fmt.Errorf("invalid frameOffset register R%d should be R%d", op&0x3f, m.returnAddressRegister)
  216. }
  217. m.returnRegisterOffset = int64(b.uint()) * m.dataAlignmentFactor
  218. continue
  219. case frameRestore: // (6.4.2.3)
  220. // register in low bits
  221. return 0, fmt.Errorf("unimplemented frameRestore(R%d)\n", op&0x3F)
  222. }
  223. // The remaining ops do not have embedded operands.
  224. switch op {
  225. // Row creation instructions (6.4.2.1)
  226. case frameNop:
  227. case frameSetLoc: // op: address
  228. return 0, fmt.Errorf("unimplemented setloc") // what size is operand?
  229. case frameAdvanceLoc1: // op: 1-byte delta
  230. m.location += uint64(b.uint8())
  231. case frameAdvanceLoc2: // op: 2-byte delta
  232. m.location += uint64(b.uint16())
  233. case frameAdvanceLoc4: // op: 4-byte delta
  234. m.location += uint64(b.uint32())
  235. // CFA definition instructions (6.4.2.2)
  236. case frameDefCFA: // op: ULEB128 register ULEB128 offset
  237. m.cfaRegister = int(b.int())
  238. m.cfaOffset = int64(b.uint())
  239. case frameDefCFASf: // op: ULEB128 register SLEB128 offset
  240. return 0, fmt.Errorf("unimplemented frameDefCFASf")
  241. case frameDefCFARegister: // op: ULEB128 register
  242. return 0, fmt.Errorf("unimplemented frameDefCFARegister")
  243. case frameDefCFAOffset: // op: ULEB128 offset
  244. return 0, fmt.Errorf("unimplemented frameDefCFAOffset")
  245. case frameDefCFAOffsetSf: // op: SLEB128 offset
  246. offset := b.int()
  247. m.cfaOffset = offset * m.dataAlignmentFactor
  248. // TODO: Verify we are using a factored offset.
  249. case frameDefCFAExpression: // op: BLOCK
  250. return 0, fmt.Errorf("unimplemented frameDefCFAExpression")
  251. // Register Rule instructions (6.4.2.3)
  252. case frameOffsetExtended: // ops: ULEB128 register ULEB128 offset
  253. // The same as frameOffset, but with the register specified in an operand.
  254. reg := b.uint()
  255. // For Go binaries we only see this in the CIE for the return address register.
  256. if reg != uint64(m.returnAddressRegister) {
  257. return 0, fmt.Errorf("invalid frameOffsetExtended: register R%d should be R%d", reg, m.returnAddressRegister)
  258. }
  259. m.returnRegisterOffset = int64(b.uint()) * m.dataAlignmentFactor
  260. case frameRestoreExtended: // op: ULEB128 register
  261. return 0, fmt.Errorf("unimplemented frameRestoreExtended")
  262. case frameUndefined: // op: ULEB128 register; unimplemented
  263. return 0, fmt.Errorf("unimplemented frameUndefined")
  264. case frameSameValue: // op: ULEB128 register
  265. return 0, fmt.Errorf("unimplemented frameSameValue")
  266. case frameRegister: // op: ULEB128 register ULEB128 register
  267. return 0, fmt.Errorf("unimplemented frameRegister")
  268. case frameRememberState:
  269. return 0, fmt.Errorf("unimplemented frameRememberState")
  270. case frameRestoreState:
  271. return 0, fmt.Errorf("unimplemented frameRestoreState")
  272. case frameExpression: // op: ULEB128 register BLOCK
  273. return 0, fmt.Errorf("unimplemented frameExpression")
  274. case frameOffsetExtendedSf: // op: ULEB128 register SLEB128 offset
  275. return 0, fmt.Errorf("unimplemented frameOffsetExtended_sf")
  276. case frameValOffset: // op: ULEB128 ULEB128
  277. return 0, fmt.Errorf("unimplemented frameValOffset")
  278. case frameValOffsetSf: // op: ULEB128 SLEB128
  279. return 0, fmt.Errorf("unimplemented frameValOffsetSf")
  280. case frameValExpression: // op: ULEB128 BLOCK
  281. return 0, fmt.Errorf("unimplemented frameValExpression")
  282. default:
  283. if frameLoUser <= op && op <= frameHiUser {
  284. return 0, fmt.Errorf("unknown user-defined frame op %#x", op)
  285. }
  286. return 0, fmt.Errorf("unknown frame op %#x", op)
  287. }
  288. }
  289. return m.cfaOffset, nil
  290. }