BPFDisassembler.cpp 7.2 KB

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