Coverage Report

Created: 2023-12-08 06:05

/src/capstonenext/MCInst.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
4
#if defined(CAPSTONE_HAS_OSXKERNEL)
5
#include <Availability.h>
6
#include <libkern/libkern.h>
7
#else
8
#include <stdio.h>
9
#include <stdlib.h>
10
#endif
11
#include <string.h>
12
#include <assert.h>
13
14
#include "MCInst.h"
15
#include "utils.h"
16
17
2.04M
#define MCINST_CACHE (ARR_SIZE(mcInst->Operands) - 1)
18
19
void MCInst_Init(MCInst *inst)
20
3.32M
{
21
  // unnecessary to initialize in loop . its expensive and inst->size shuold be honored
22
3.32M
  inst->Operands[0].Kind = kInvalid;
23
3.32M
  inst->Operands[0].ImmVal = 0;
24
25
3.32M
  inst->Opcode = 0;
26
3.32M
  inst->OpcodePub = 0;
27
3.32M
  inst->size = 0;
28
3.32M
  inst->has_imm = false;
29
3.32M
  inst->op1_size = 0;
30
3.32M
  inst->ac_idx = 0;
31
3.32M
  inst->popcode_adjust = 0;
32
3.32M
  inst->assembly[0] = '\0';
33
3.32M
  inst->wasm_data.type = WASM_OP_INVALID;
34
3.32M
  inst->xAcquireRelease = 0;
35
162M
  for (int i = 0; i < MAX_MC_OPS; ++i)
36
159M
    inst->tied_op_idx[i] = -1;
37
3.32M
  inst->isAliasInstr = false;
38
3.32M
  inst->fillDetailOps = false;
39
3.32M
}
40
41
void MCInst_clear(MCInst *inst)
42
2.84M
{
43
2.84M
  inst->size = 0;
44
2.84M
}
45
46
// does not free @Op
47
void MCInst_insert0(MCInst *inst, int index, MCOperand *Op)
48
2.05M
{
49
2.05M
  assert(index < MAX_MC_OPS);
50
2.05M
  int i;
51
52
3.55M
  for(i = inst->size; i > index; i--)
53
    //memcpy(&(inst->Operands[i]), &(inst->Operands[i-1]), sizeof(MCOperand));
54
1.50M
    inst->Operands[i] = inst->Operands[i-1];
55
56
2.05M
  inst->Operands[index] = *Op;
57
2.05M
  inst->size++;
58
2.05M
}
59
60
void MCInst_setOpcode(MCInst *inst, unsigned Op)
61
3.32M
{
62
3.32M
  inst->Opcode = Op;
63
3.32M
}
64
65
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
66
45.8k
{
67
45.8k
  inst->OpcodePub = Op;
68
45.8k
}
69
70
unsigned MCInst_getOpcode(const MCInst *inst)
71
30.8M
{
72
30.8M
  return inst->Opcode;
73
30.8M
}
74
75
unsigned MCInst_getOpcodePub(const MCInst *inst)
76
3.39M
{
77
3.39M
  return inst->OpcodePub;
78
3.39M
}
79
80
MCOperand *MCInst_getOperand(MCInst *inst, unsigned i)
81
17.6M
{
82
17.6M
  assert(i < MAX_MC_OPS);
83
17.6M
  return &inst->Operands[i];
84
17.6M
}
85
86
unsigned MCInst_getNumOperands(const MCInst *inst)
87
9.20M
{
88
9.20M
  return inst->size;
89
9.20M
}
90
91
// This addOperand2 function doesnt free Op
92
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
93
465
{
94
465
  assert(inst->size < MAX_MC_OPS);
95
465
  inst->Operands[inst->size] = *Op;
96
97
465
  inst->size++;
98
465
}
99
100
bool MCOperand_isValid(const MCOperand *op)
101
0
{
102
0
  return op->Kind != kInvalid;
103
0
}
104
105
bool MCOperand_isReg(const MCOperand *op)
106
9.52M
{
107
9.52M
  return op->Kind == kRegister;
108
9.52M
}
109
110
bool MCOperand_isImm(const MCOperand *op)
111
2.95M
{
112
2.95M
  return op->Kind == kImmediate;
113
2.95M
}
114
115
bool MCOperand_isFPImm(const MCOperand *op)
116
0
{
117
0
  return op->Kind == kFPImmediate;
118
0
}
119
120
bool MCOperand_isDFPImm(const MCOperand *op)
121
2.76k
{
122
2.76k
  return op->Kind == kDFPImmediate;
123
2.76k
}
124
125
bool MCOperand_isExpr(const MCOperand *op)
126
99.7k
{
127
99.7k
  return op->Kind == kExpr;
128
99.7k
}
129
130
bool MCOperand_isInst(const MCOperand *op)
131
0
{
132
0
  return op->Kind == kInst;
133
0
}
134
135
/// getReg - Returns the register number.
136
unsigned MCOperand_getReg(const MCOperand *op)
137
12.0M
{
138
12.0M
  return op->RegVal;
139
12.0M
}
140
141
/// setReg - Set the register number.
142
void MCOperand_setReg(MCOperand *op, unsigned Reg)
143
12.4k
{
144
12.4k
  op->RegVal = Reg;
145
12.4k
}
146
147
int64_t MCOperand_getImm(const MCOperand *op)
148
6.54M
{
149
6.54M
  return op->ImmVal;
150
6.54M
}
151
152
void MCOperand_setImm(MCOperand *op, int64_t Val)
153
12.5k
{
154
12.5k
  op->ImmVal = Val;
155
12.5k
}
156
157
double MCOperand_getFPImm(const MCOperand *op)
158
0
{
159
0
  return op->FPImmVal;
160
0
}
161
162
void MCOperand_setFPImm(MCOperand *op, double Val)
163
0
{
164
0
  op->FPImmVal = Val;
165
0
}
166
167
MCOperand *MCOperand_CreateReg1(MCInst *mcInst, unsigned Reg)
168
1.17M
{
169
1.17M
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
170
171
1.17M
  op->MachineOperandType = kRegister;
172
1.17M
  op->Kind = kRegister;
173
1.17M
  op->RegVal = Reg;
174
175
1.17M
  return op;
176
1.17M
}
177
178
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
179
6.08M
{
180
6.08M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
181
6.08M
  mcInst->size++;
182
183
6.08M
  op->MachineOperandType = kRegister;
184
6.08M
  op->Kind = kRegister;
185
6.08M
  op->RegVal = Reg;
186
6.08M
}
187
188
MCOperand *MCOperand_CreateImm1(MCInst *mcInst, int64_t Val)
189
870k
{
190
870k
  MCOperand *op = &(mcInst->Operands[MCINST_CACHE]);
191
192
870k
  op->MachineOperandType = kImmediate;
193
870k
  op->Kind = kImmediate;
194
870k
  op->ImmVal = Val;
195
196
870k
  return op;
197
870k
}
198
199
void MCOperand_CreateImm0(MCInst *mcInst, int64_t Val)
200
2.88M
{
201
2.88M
  assert(mcInst->size < MAX_MC_OPS);
202
2.88M
  MCOperand *op = &(mcInst->Operands[mcInst->size]);
203
2.88M
  mcInst->size++;
204
205
2.88M
  op->MachineOperandType = kImmediate;
206
2.88M
  op->Kind = kImmediate;
207
2.88M
  op->ImmVal = Val;
208
2.88M
}
209
210
/// Check if any operand of the MCInstrDesc is predicable
211
bool MCInst_isPredicable(const MCInstrDesc *MIDesc)
212
1.02M
{
213
1.02M
  const MCOperandInfo *OpInfo = MIDesc->OpInfo;
214
1.02M
  unsigned NumOps = MIDesc->NumOperands;
215
4.47M
  for (unsigned i = 0; i < NumOps; ++i) {
216
4.41M
    if (MCOperandInfo_isPredicate(&OpInfo[i])) {
217
964k
      return true;
218
964k
    }
219
4.41M
  }
220
58.6k
  return false;
221
1.02M
}
222
223
/// Checks if tied operands exist in the instruction and sets
224
/// - The writeback flag in detail
225
/// - Saves the indices of the tied destination operands.
226
void MCInst_handleWriteback(MCInst *MI, const MCInstrDesc *InstDesc)
227
1.39M
{
228
1.39M
  const MCOperandInfo *OpInfo = InstDesc[MCInst_getOpcode(MI)].OpInfo;
229
1.39M
  unsigned short NumOps = InstDesc[MCInst_getOpcode(MI)].NumOperands;
230
231
1.39M
  unsigned i;
232
7.96M
  for (i = 0; i < NumOps; ++i) {
233
6.56M
    if (MCOperandInfo_isTiedToOp(&OpInfo[i])) {
234
292k
      int idx = MCOperandInfo_getOperandConstraint(
235
292k
        &InstDesc[MCInst_getOpcode(MI)], i,
236
292k
        MCOI_TIED_TO);
237
238
292k
      if (idx == -1)
239
0
        continue;
240
241
292k
      if (i >= MAX_MC_OPS) {
242
0
        assert(0 &&
243
0
               "Maximum number of MC operands reached.");
244
0
      }
245
292k
      MI->tied_op_idx[i] = idx;
246
247
292k
      if (MI->flat_insn->detail)
248
292k
        MI->flat_insn->detail->writeback = true;
249
292k
    }
250
6.56M
  }
251
1.39M
}
252
253
/// Check if operand with OpNum is tied by another operand
254
/// (operand is tying destination).
255
bool MCInst_opIsTied(const MCInst *MI, unsigned OpNum)
256
4.49M
{
257
4.49M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
258
211M
  for (int i = 0; i < MAX_MC_OPS; ++i) {
259
206M
    if (MI->tied_op_idx[i] == OpNum)
260
198k
      return true;
261
206M
  }
262
4.29M
  return false;
263
4.49M
}
264
265
/// Check if operand with OpNum is tying another operand
266
/// (operand is tying src).
267
bool MCInst_opIsTying(const MCInst *MI, unsigned OpNum)
268
4.44M
{
269
4.44M
  assert(OpNum < MAX_MC_OPS && "Maximum number of MC operands exceeded.");
270
4.44M
  return MI->tied_op_idx[OpNum] != -1;
271
4.44M
}
272
273
/// Returns the value of the @MCInst operand at index @OpNum.
274
uint64_t MCInst_getOpVal(MCInst *MI, unsigned OpNum)
275
4.33M
{
276
4.33M
  assert(OpNum < MAX_MC_OPS);
277
4.33M
  MCOperand *op = MCInst_getOperand(MI, OpNum);
278
4.33M
  if (MCOperand_isReg(op))
279
3.07M
    return MCOperand_getReg(op);
280
1.26M
  else if (MCOperand_isImm(op))
281
1.26M
    return MCOperand_getImm(op);
282
0
  else
283
0
    assert(0 && "Operand type not handled in this getter.");
284
0
  return MCOperand_getImm(op);
285
4.33M
}
286
287
1.43M
void MCInst_setIsAlias(MCInst *MI, bool Flag) {
288
1.43M
  assert(MI);
289
1.43M
  MI->isAliasInstr = Flag;
290
1.43M
  MI->flat_insn->is_alias = Flag;
291
1.43M
}
292
293
/// @brief Copies the relevant members of a temporary MCInst to
294
/// the main MCInst. This is used if TryDecode was run on a temporary MCInst.
295
/// @param MI The main MCInst
296
/// @param TmpMI The temporary MCInst.
297
344
void MCInst_updateWithTmpMI(MCInst *MI, MCInst *TmpMI) {
298
344
  MI->size = TmpMI->size;
299
344
  MI->Opcode = TmpMI->Opcode;
300
344
  assert(MI->size < MAX_MC_OPS);
301
344
  memcpy(MI->Operands, TmpMI->Operands, sizeof(MI->Operands[0]) * MI->size);
302
344
}