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