Extended Berkeley Packet Filter (eBPF) assembler and virtual machine
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.

262 lines
5.4KB

  1. package ebpf
  2. import (
  3. "fmt"
  4. )
  5. type LoadConstant struct {
  6. Dst Register
  7. Value uint64
  8. Size uint8
  9. }
  10. func (a LoadConstant) Assemble() (RawInstruction, error) {
  11. return RawInstruction{
  12. Op: opClassLoad | sizeDoubleWord | modeImmediate,
  13. Dst: a.Dst,
  14. Immediate: a.Value,
  15. }, nil
  16. }
  17. func (a LoadConstant) String() string {
  18. return fmt.Sprintf("lddw %s, %#x", a.Dst, a.Value)
  19. }
  20. type LoadAbsolute struct {
  21. Dst, Src Register
  22. Value uint64
  23. Size uint8 // Size of the load value (in bytes).
  24. }
  25. func (a LoadAbsolute) Assemble() (RawInstruction, error) {
  26. var size Opcode
  27. switch a.Size {
  28. case 1:
  29. size = sizeByte
  30. case 2:
  31. size = sizeHalfWord
  32. case 4:
  33. size = sizeWord
  34. case 8:
  35. size = sizeDoubleWord
  36. default:
  37. return RawInstruction{}, fmt.Errorf("ebpf: invalid load absolute size %d", a.Size)
  38. }
  39. return RawInstruction{
  40. Op: opClassLoad | size | modeAbsolute,
  41. Dst: a.Dst,
  42. Src: a.Src,
  43. Immediate: a.Value,
  44. }, nil
  45. }
  46. func (a LoadAbsolute) String() string {
  47. var mnemonic string
  48. switch a.Size {
  49. case 1:
  50. mnemonic = "ldabsb"
  51. case 2:
  52. mnemonic = "ldabsh"
  53. case 4:
  54. mnemonic = "ldabsw"
  55. case 8:
  56. mnemonic = "ldabsdw"
  57. default:
  58. return fmt.Sprintf("# invalid LoadAbsolute dst=%s, src=%s, size=%d, value=%#x", a.Dst, a.Src, a.Size, a.Value)
  59. }
  60. return fmt.Sprintf("%s %s, %s, %#x", mnemonic, a.Src, a.Dst, a.Value)
  61. }
  62. type LoadIndirect struct {
  63. Dst, Src Register
  64. Value uint64
  65. Size uint8 // Size of the load value (in bytes).
  66. }
  67. func (a LoadIndirect) Assemble() (RawInstruction, error) {
  68. var size Opcode
  69. switch a.Size {
  70. case 1:
  71. size = sizeByte
  72. case 2:
  73. size = sizeHalfWord
  74. case 4:
  75. size = sizeWord
  76. case 8:
  77. size = sizeDoubleWord
  78. default:
  79. return RawInstruction{}, fmt.Errorf("ebpf: invalid load indirect size %d", a.Size)
  80. }
  81. return RawInstruction{
  82. Op: opClassLoad | size | modeIndirect,
  83. Dst: a.Dst,
  84. Src: a.Src,
  85. Immediate: a.Value,
  86. }, nil
  87. }
  88. func (a LoadIndirect) String() string {
  89. var mnemonic string
  90. switch a.Size {
  91. case 1:
  92. mnemonic = "ldindb"
  93. case 2:
  94. mnemonic = "ldindh"
  95. case 4:
  96. mnemonic = "ldindw"
  97. case 8:
  98. mnemonic = "ldinddw"
  99. default:
  100. return fmt.Sprintf("# invalid LoadIndirect dst=%s, src=%s, size=%d, value=%#x", a.Dst, a.Src, a.Size, a.Value)
  101. }
  102. return fmt.Sprintf("%s %s, %s, %#x", mnemonic, a.Src, a.Dst, a.Value)
  103. }
  104. type LoadRegister struct {
  105. Dst, Src Register
  106. Offset int16
  107. Size uint8 // Size of the load value (in bytes).
  108. }
  109. func (a LoadRegister) Assemble() (RawInstruction, error) {
  110. var size Opcode
  111. switch a.Size {
  112. case 1:
  113. size = sizeByte
  114. case 2:
  115. size = sizeHalfWord
  116. case 4:
  117. size = sizeWord
  118. case 8:
  119. size = sizeDoubleWord
  120. default:
  121. return RawInstruction{}, fmt.Errorf("ebpf: invalid load memory size %d", a.Size)
  122. }
  123. return RawInstruction{
  124. Op: opClassLoadX | size | modeMemory,
  125. Dst: a.Dst,
  126. Src: a.Src,
  127. Offset: a.Offset,
  128. }, nil
  129. }
  130. func (a LoadRegister) String() string {
  131. var mnemonic string
  132. switch a.Size {
  133. case 1:
  134. mnemonic = "ldxb"
  135. case 2:
  136. mnemonic = "ldxh"
  137. case 4:
  138. mnemonic = "ldxw"
  139. case 8:
  140. mnemonic = "ldxdw"
  141. default:
  142. return fmt.Sprintf("# invalid LoadRegister dst=%s, src=%s, size=%d, offset=%d", a.Dst, a.Src, a.Size, a.Offset)
  143. }
  144. return fmt.Sprintf("%s %s, [%s+%#x]", mnemonic, a.Dst, a.Src, a.Offset)
  145. }
  146. type StoreImmediate struct {
  147. Dst Register
  148. Offset int16
  149. Value uint32
  150. Size uint8
  151. }
  152. func (a StoreImmediate) Assemble() (RawInstruction, error) {
  153. var size Opcode
  154. switch a.Size {
  155. case 1:
  156. size = sizeByte
  157. case 2:
  158. size = sizeHalfWord
  159. case 4:
  160. size = sizeWord
  161. case 8:
  162. size = sizeDoubleWord
  163. default:
  164. return RawInstruction{}, fmt.Errorf("ebpf: invalid store immediate size %d", a.Size)
  165. }
  166. return RawInstruction{
  167. Op: opClassStore | size | modeMemory,
  168. Dst: a.Dst,
  169. Offset: a.Offset,
  170. Immediate: uint64(a.Value),
  171. }, nil
  172. }
  173. func (a StoreImmediate) String() string {
  174. var mnemonic, sign string
  175. switch a.Size {
  176. case 1:
  177. mnemonic = "stb"
  178. case 2:
  179. mnemonic = "sth"
  180. case 4:
  181. mnemonic = "stw"
  182. case 8:
  183. mnemonic = "stdw"
  184. default:
  185. return fmt.Sprintf("# invalid StoreImmediate dst=%s, size=%d, offset=%d, value=%#x", a.Dst, a.Size, a.Offset, a.Value)
  186. }
  187. if a.Offset >= 0 {
  188. sign = "+"
  189. }
  190. return fmt.Sprintf("%s [%s%s%#x], %#x", mnemonic, a.Dst, sign, a.Offset, a.Value)
  191. }
  192. type StoreRegister struct {
  193. Dst, Src Register
  194. Offset int16
  195. Size uint8
  196. }
  197. func (a StoreRegister) Assemble() (RawInstruction, error) {
  198. var size Opcode
  199. switch a.Size {
  200. case 1:
  201. size = sizeByte
  202. case 2:
  203. size = sizeHalfWord
  204. case 4:
  205. size = sizeWord
  206. case 8:
  207. size = sizeDoubleWord
  208. default:
  209. return RawInstruction{}, fmt.Errorf("ebpf: invalid store memory size %d", a.Size)
  210. }
  211. return RawInstruction{
  212. Op: opClassStoreX | size | modeMemory,
  213. Dst: a.Dst,
  214. Src: a.Src,
  215. Offset: a.Offset,
  216. }, nil
  217. }
  218. func (a StoreRegister) String() string {
  219. var mnemonic string
  220. switch a.Size {
  221. case 1:
  222. mnemonic = "stxb"
  223. case 2:
  224. mnemonic = "stxh"
  225. case 4:
  226. mnemonic = "stxw"
  227. case 8:
  228. mnemonic = "stxdw"
  229. default:
  230. return fmt.Sprintf("# invalid StoreRegister dst=%s, src=%s, size=%d, offset=%#x", a.Dst, a.Src, a.Size, a.Offset)
  231. }
  232. return fmt.Sprintf("%s [%s+%#x], %s", mnemonic, a.Dst, a.Offset, a.Src)
  233. }
  234. var (
  235. _ Instruction = (*LoadConstant)(nil)
  236. _ Instruction = (*LoadAbsolute)(nil)
  237. _ Instruction = (*LoadIndirect)(nil)
  238. _ Instruction = (*LoadRegister)(nil)
  239. _ Instruction = (*StoreImmediate)(nil)
  240. _ Instruction = (*StoreRegister)(nil)
  241. )