BPFDisassembler.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //===- BPFDisassembler.cpp - Disassembler for BPF ---------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is part of the BPF Disassembler.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "MCTargetDesc/BPFMCTargetDesc.h"
  13. #include "TargetInfo/BPFTargetInfo.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. #include "llvm/MC/MCAsmInfo.h"
  16. #include "llvm/MC/MCContext.h"
  17. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  18. #include "llvm/MC/MCFixedLenDisassembler.h"
  19. #include "llvm/MC/MCInst.h"
  20. #include "llvm/MC/TargetRegistry.h"
  21. #include "llvm/Support/MathExtras.h"
  22. #include <cstdint>
  23. using namespace llvm;
  24. #define DEBUG_TYPE "bpf-disassembler"
  25. typedef MCDisassembler::DecodeStatus DecodeStatus;
  26. namespace {
  27. /// A disassembler class for BPF.
  28. class BPFDisassembler : public MCDisassembler {
  29. public:
  30. enum BPF_CLASS {
  31. BPF_LD = 0x0,
  32. BPF_LDX = 0x1,
  33. BPF_ST = 0x2,
  34. BPF_STX = 0x3,
  35. BPF_ALU = 0x4,
  36. BPF_JMP = 0x5,
  37. BPF_JMP32 = 0x6,
  38. BPF_ALU64 = 0x7
  39. };
  40. enum BPF_SIZE {
  41. BPF_W = 0x0,
  42. BPF_H = 0x1,
  43. BPF_B = 0x2,
  44. BPF_DW = 0x3
  45. };
  46. enum BPF_MODE {
  47. BPF_IMM = 0x0,
  48. BPF_ABS = 0x1,
  49. BPF_IND = 0x2,
  50. BPF_MEM = 0x3,
  51. BPF_LEN = 0x4,
  52. BPF_MSH = 0x5,
  53. BPF_ATOMIC = 0x6
  54. };
  55. BPFDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
  56. : MCDisassembler(STI, Ctx) {}
  57. ~BPFDisassembler() override = default;
  58. DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
  59. ArrayRef<uint8_t> Bytes, uint64_t Address,
  60. raw_ostream &CStream) const override;
  61. uint8_t getInstClass(uint64_t Inst) const { return (Inst >> 56) & 0x7; };
  62. uint8_t getInstSize(uint64_t Inst) const { return (Inst >> 59) & 0x3; };
  63. uint8_t getInstMode(uint64_t Inst) const { return (Inst >> 61) & 0x7; };
  64. };
  65. } // end anonymous namespace
  66. static MCDisassembler *createBPFDisassembler(const Target &T,
  67. const MCSubtargetInfo &STI,
  68. MCContext &Ctx) {
  69. return new BPFDisassembler(STI, Ctx);
  70. }
  71. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFDisassembler() {
  72. // Register the disassembler.
  73. TargetRegistry::RegisterMCDisassembler(getTheBPFTarget(),
  74. createBPFDisassembler);
  75. TargetRegistry::RegisterMCDisassembler(getTheBPFleTarget(),
  76. createBPFDisassembler);
  77. TargetRegistry::RegisterMCDisassembler(getTheBPFbeTarget(),
  78. createBPFDisassembler);
  79. }
  80. static const unsigned GPRDecoderTable[] = {
  81. BPF::R0, BPF::R1, BPF::R2, BPF::R3, BPF::R4, BPF::R5,
  82. BPF::R6, BPF::R7, BPF::R8, BPF::R9, BPF::R10, BPF::R11};
  83. static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
  84. uint64_t /*Address*/,
  85. const void * /*Decoder*/) {
  86. if (RegNo > 11)
  87. return MCDisassembler::Fail;
  88. unsigned Reg = GPRDecoderTable[RegNo];
  89. Inst.addOperand(MCOperand::createReg(Reg));
  90. return MCDisassembler::Success;
  91. }
  92. static const unsigned GPR32DecoderTable[] = {
  93. BPF::W0, BPF::W1, BPF::W2, BPF::W3, BPF::W4, BPF::W5,
  94. BPF::W6, BPF::W7, BPF::W8, BPF::W9, BPF::W10, BPF::W11};
  95. static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
  96. uint64_t /*Address*/,
  97. const void * /*Decoder*/) {
  98. if (RegNo > 11)
  99. return MCDisassembler::Fail;
  100. unsigned Reg = GPR32DecoderTable[RegNo];
  101. Inst.addOperand(MCOperand::createReg(Reg));
  102. return MCDisassembler::Success;
  103. }
  104. static DecodeStatus decodeMemoryOpValue(MCInst &Inst, unsigned Insn,
  105. uint64_t Address, const void *Decoder) {
  106. unsigned Register = (Insn >> 16) & 0xf;
  107. if (Register > 11)
  108. return MCDisassembler::Fail;
  109. Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
  110. unsigned Offset = (Insn & 0xffff);
  111. Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
  112. return MCDisassembler::Success;
  113. }
  114. #include "BPFGenDisassemblerTables.inc"
  115. static DecodeStatus readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
  116. uint64_t &Size, uint64_t &Insn,
  117. bool IsLittleEndian) {
  118. uint64_t Lo, Hi;
  119. if (Bytes.size() < 8) {
  120. Size = 0;
  121. return MCDisassembler::Fail;
  122. }
  123. Size = 8;
  124. if (IsLittleEndian) {
  125. Hi = (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 0) | (Bytes[3] << 8);
  126. Lo = (Bytes[4] << 0) | (Bytes[5] << 8) | (Bytes[6] << 16) | (Bytes[7] << 24);
  127. } else {
  128. Hi = (Bytes[0] << 24) | ((Bytes[1] & 0x0F) << 20) | ((Bytes[1] & 0xF0) << 12) |
  129. (Bytes[2] << 8) | (Bytes[3] << 0);
  130. Lo = (Bytes[4] << 24) | (Bytes[5] << 16) | (Bytes[6] << 8) | (Bytes[7] << 0);
  131. }
  132. Insn = Make_64(Hi, Lo);
  133. return MCDisassembler::Success;
  134. }
  135. DecodeStatus BPFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
  136. ArrayRef<uint8_t> Bytes,
  137. uint64_t Address,
  138. raw_ostream &CStream) const {
  139. bool IsLittleEndian = getContext().getAsmInfo()->isLittleEndian();
  140. uint64_t Insn, Hi;
  141. DecodeStatus Result;
  142. Result = readInstruction64(Bytes, Address, Size, Insn, IsLittleEndian);
  143. if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
  144. uint8_t InstClass = getInstClass(Insn);
  145. uint8_t InstMode = getInstMode(Insn);
  146. if ((InstClass == BPF_LDX || InstClass == BPF_STX) &&
  147. getInstSize(Insn) != BPF_DW &&
  148. (InstMode == BPF_MEM || InstMode == BPF_ATOMIC) &&
  149. STI.getFeatureBits()[BPF::ALU32])
  150. Result = decodeInstruction(DecoderTableBPFALU3264, Instr, Insn, Address,
  151. this, STI);
  152. else
  153. Result = decodeInstruction(DecoderTableBPF64, Instr, Insn, Address, this,
  154. STI);
  155. if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
  156. switch (Instr.getOpcode()) {
  157. case BPF::LD_imm64:
  158. case BPF::LD_pseudo: {
  159. if (Bytes.size() < 16) {
  160. Size = 0;
  161. return MCDisassembler::Fail;
  162. }
  163. Size = 16;
  164. if (IsLittleEndian)
  165. Hi = (Bytes[12] << 0) | (Bytes[13] << 8) | (Bytes[14] << 16) | (Bytes[15] << 24);
  166. else
  167. Hi = (Bytes[12] << 24) | (Bytes[13] << 16) | (Bytes[14] << 8) | (Bytes[15] << 0);
  168. auto& Op = Instr.getOperand(1);
  169. Op.setImm(Make_64(Hi, Op.getImm()));
  170. break;
  171. }
  172. case BPF::LD_ABS_B:
  173. case BPF::LD_ABS_H:
  174. case BPF::LD_ABS_W:
  175. case BPF::LD_IND_B:
  176. case BPF::LD_IND_H:
  177. case BPF::LD_IND_W: {
  178. auto Op = Instr.getOperand(0);
  179. Instr.clear();
  180. Instr.addOperand(MCOperand::createReg(BPF::R6));
  181. Instr.addOperand(Op);
  182. break;
  183. }
  184. }
  185. return Result;
  186. }
  187. typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
  188. const void *Decoder);