capstone

Форк
0
/
MCInstPrinter.c 
257 строк · 7.7 Кб
1
/* Capstone Disassembly Engine */
2
/* By Rot127 <unisono@quyllur.org>, 2023 */
3

4
#include "MCInstPrinter.h"
5
#include "cs_priv.h"
6
#include <capstone/platform.h>
7

8
extern bool ARM_getFeatureBits(unsigned int mode, unsigned int feature);
9
extern bool PPC_getFeatureBits(unsigned int mode, unsigned int feature);
10
extern bool AArch64_getFeatureBits(unsigned int mode, unsigned int feature);
11
extern bool TriCore_getFeatureBits(unsigned int mode, unsigned int feature);
12

13
static bool testFeatureBits(const MCInst *MI, uint32_t Value)
14
{
15
	assert(MI && MI->csh);
16
	switch (MI->csh->arch) {
17
	default:
18
		assert(0 && "Not implemented for current arch.");
19
		return false;
20
#ifdef CAPSTONE_HAS_ARM
21
	case CS_ARCH_ARM:
22
		return ARM_getFeatureBits(MI->csh->mode, Value);
23
#endif
24
#ifdef CAPSTONE_HAS_POWERPC
25
	case CS_ARCH_PPC:
26
		return PPC_getFeatureBits(MI->csh->mode, Value);
27
#endif
28
#ifdef CAPSTONE_HAS_AARCH64
29
	case CS_ARCH_AARCH64:
30
		return AArch64_getFeatureBits(MI->csh->mode, Value);
31
#endif
32
#ifdef CAPSTONE_HAS_TRICORE
33
	case CS_ARCH_TRICORE:
34
		return TriCore_getFeatureBits(MI->csh->mode, Value);
35
#endif
36
	}
37
}
38

39
static bool matchAliasCondition(MCInst *MI, const MCRegisterInfo *MRI,
40
								unsigned *OpIdx, const AliasMatchingData *M,
41
								const AliasPatternCond *C,
42
								bool *OrPredicateResult)
43
{
44
	// Feature tests are special, they don't consume operands.
45
	if (C->Kind == AliasPatternCond_K_Feature)
46
		return testFeatureBits(MI, C->Value);
47
	if (C->Kind == AliasPatternCond_K_NegFeature)
48
		return !testFeatureBits(MI, C->Value);
49
	// For feature tests where just one feature is required in a list, set the
50
	// predicate result bit to whether the expression will return true, and only
51
	// return the real result at the end of list marker.
52
	if (C->Kind == AliasPatternCond_K_OrFeature) {
53
		*OrPredicateResult |= testFeatureBits(MI, C->Value);
54
		return true;
55
	}
56
	if (C->Kind == AliasPatternCond_K_OrNegFeature) {
57
		*OrPredicateResult |= !(testFeatureBits(MI, C->Value));
58
		return true;
59
	}
60
	if (C->Kind == AliasPatternCond_K_EndOrFeatures) {
61
		bool Res = *OrPredicateResult;
62
		*OrPredicateResult = false;
63
		return Res;
64
	}
65

66
	// Get and consume an operand.
67
	MCOperand *Opnd = MCInst_getOperand(MI, *OpIdx);
68
	++(*OpIdx);
69

70
	// Check the specific condition for the operand.
71
	switch (C->Kind) {
72
	default:
73
		assert(0 && "invalid kind");
74
	case AliasPatternCond_K_Imm:
75
		// Operand must be a specific immediate.
76
		return MCOperand_isImm(Opnd) &&
77
			   MCOperand_getImm(Opnd) == (int32_t)C->Value;
78
	case AliasPatternCond_K_Reg:
79
		// Operand must be a specific register.
80
		return MCOperand_isReg(Opnd) && MCOperand_getReg(Opnd) == C->Value;
81
	case AliasPatternCond_K_TiedReg:
82
		// Operand must match the register of another operand.
83
		return MCOperand_isReg(Opnd) &&
84
			   MCOperand_getReg(Opnd) ==
85
				   MCOperand_getReg(MCInst_getOperand(MI, C->Value));
86
	case AliasPatternCond_K_RegClass:
87
		// Operand must be a register in this class. Value is a register class
88
		// id.
89
		return MCOperand_isReg(Opnd) &&
90
			   MCRegisterClass_contains(
91
				   MCRegisterInfo_getRegClass(MRI, C->Value),
92
				   MCOperand_getReg(Opnd));
93
	case AliasPatternCond_K_Custom:
94
		// Operand must match some custom criteria.
95
		assert(M->ValidateMCOperand && "A custom validator should be set but isn't.");
96
		return M->ValidateMCOperand(Opnd, C->Value);
97
	case AliasPatternCond_K_Ignore:
98
		// Operand can be anything.
99
		return true;
100
	case AliasPatternCond_K_Feature:
101
	case AliasPatternCond_K_NegFeature:
102
	case AliasPatternCond_K_OrFeature:
103
	case AliasPatternCond_K_OrNegFeature:
104
	case AliasPatternCond_K_EndOrFeatures:
105
		assert(0 && "handled earlier");
106
	}
107
	return false;
108
}
109

110
/// Check if PatternsForOpcode is all zero.
111
static inline bool validOpToPatter(const PatternsForOpcode *P)
112
{
113
	return !(P->Opcode == 0 && P->PatternStart == 0 && P->NumPatterns == 0);
114
}
115

116
const char *matchAliasPatterns(MCInst *MI, const AliasMatchingData *M)
117
{
118
	// TODO Rewrite to C
119

120
	// auto It = lower_bound(M.OpToPatterns, MI->getOpcode(),
121
	//                       [](const PatternsForOpcode &L, unsigned Opcode) {
122
	//                         return L.Opcode < Opcode;
123
	//                       });
124
	// if (It == M.OpToPatterns.end() || It->Opcode != MI->getOpcode())
125
	//   return nullptr;
126

127
	// Binary search by opcode. Return false if there are no aliases for this
128
	// opcode.
129
	unsigned MIOpcode = MI->Opcode;
130
	size_t i = 0;
131
	uint32_t PatternOpcode = M->OpToPatterns[i].Opcode;
132
	while (PatternOpcode < MIOpcode && validOpToPatter(&M->OpToPatterns[i]))
133
		PatternOpcode = M->OpToPatterns[++i].Opcode;
134
	if (PatternOpcode != MI->Opcode || !validOpToPatter(&M->OpToPatterns[i]))
135
		return NULL;
136

137
	// // Try all patterns for this opcode.
138
	uint32_t AsmStrOffset = ~0U;
139
	const AliasPattern *Patterns = M->Patterns + M->OpToPatterns[i].PatternStart;
140
	for (const AliasPattern *P = Patterns;
141
		P != Patterns + M->OpToPatterns[i].NumPatterns; ++P) {
142
		// Check operand count first.
143
		if (MCInst_getNumOperands(MI) != P->NumOperands)
144
			return NULL;
145

146
		// Test all conditions for this pattern.
147
		const AliasPatternCond *Conds = M->PatternConds + P->AliasCondStart;
148
		unsigned OpIdx = 0;
149
		bool OrPredicateResult = false;
150
		bool allMatch = true;
151
		for (const AliasPatternCond *C = Conds; C != Conds + P->NumConds; ++C) {
152
			if (!matchAliasCondition(MI, MI->MRI, &OpIdx, M, C, &OrPredicateResult)) {
153
				allMatch = false;
154
				break;
155
			}
156
		}
157
		if (allMatch) {
158
			AsmStrOffset = P->AsmStrOffset;
159
			break;
160
		}
161
	}
162
	// If no alias matched, don't print an alias.
163
	if (AsmStrOffset == ~0U)
164
		return NULL;
165

166
	// Go to offset AsmStrOffset and use the null terminated string there. The
167
	// offset should point to the beginning of an alias string, so it should
168
	// either be zero or be preceded by a null byte.
169
	return M->AsmStrings + AsmStrOffset;
170
}
171

172
// TODO Add functionality to toggle the flag.
173
bool getUseMarkup(void) { return false; }
174

175
/// Utility functions to make adding mark ups simpler.
176
const char *markup(const char *s)
177
{
178
	static const char *no_markup = "";
179
	if (getUseMarkup())
180
		return s;
181
	else
182
		return no_markup;
183
}
184

185
// binary search for encoding in IndexType array
186
// return -1 if not found, or index if found
187
unsigned int binsearch_IndexTypeEncoding(const struct IndexType *index, size_t size, uint16_t encoding)
188
{
189
	// binary searching since the index is sorted in encoding order
190
	size_t left, right, m;
191

192
	right = size - 1;
193

194
	if (encoding < index[0].encoding || encoding > index[right].encoding)
195
		// not found
196
		return -1;
197

198
	left = 0;
199

200
	while(left <= right) {
201
		m = (left + right) / 2;
202
		if (encoding == index[m].encoding) {
203
			// LLVM actually uses lower_bound for the index table search
204
			// Here we need to check if a previous entry is of the same encoding
205
			// and return the first one.
206
			while (m > 0 && encoding == index[m - 1].encoding)
207
				--m;
208
			return m;
209
		}
210

211
		if (encoding < index[m].encoding)
212
			right = m - 1;
213
		else
214
			left = m + 1;
215
	}
216

217
	// not found
218
	return -1;
219
}
220

221
// binary search for encoding in IndexTypeStr array
222
// return -1 if not found, or index if found
223
unsigned int binsearch_IndexTypeStrEncoding(const struct IndexTypeStr *index, size_t size, const char *name)
224
{
225
	// binary searching since the index is sorted in encoding order
226
	size_t left, right, m;
227

228
	right = size - 1;
229

230
	size_t str_left_cmp = strcmp(name, index[0].name);
231
	size_t str_right_cmp = strcmp(name, index[right].name);
232
	if (str_left_cmp < 0 || str_right_cmp > 0)
233
		// not found
234
		return -1;
235

236
	left = 0;
237

238
	while(left <= right) {
239
		m = (left + right) / 2;
240
		if (strcmp(name, index[m].name) == 0) {
241
			// LLVM actually uses lower_bound for the index table search
242
			// Here we need to check if a previous entry is of the same encoding
243
			// and return the first one.
244
			while (m > 0 && (strcmp(name, index[m - 1].name) == 0))
245
				--m;
246
			return m;
247
		}
248

249
		if (strcmp(name, index[m].name) < 0)
250
			right = m - 1;
251
		else
252
			left = m + 1;
253
	}
254

255
	// not found
256
	return -1;
257
}
258

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.