Skip to content

Commit c78dd4e

Browse files
committed
wstring and textdefs optimizations.
1 parent 0bafbbb commit c78dd4e

5 files changed

Lines changed: 138 additions & 164 deletions

File tree

src/distorm.c

Lines changed: 86 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ This library is licensed under the BSD license. See the file COPYING.
4646
#ifndef DISTORM_LIGHT
4747

4848
/* Helper function to concatenate an explicit size when it's unknown from the operands. */
49-
static void distorm_format_size(_WString* str, const _DInst* di, int opNum)
49+
static void distorm_format_size(unsigned char** str, const _DInst* di, int opNum)
5050
{
5151
int isSizingRequired = 0;
5252
/*
@@ -93,22 +93,22 @@ static void distorm_format_size(_WString* str, const _DInst* di, int opNum)
9393

9494
if (isSizingRequired)
9595
{
96-
switch (di->ops[opNum].size)
96+
switch (di->ops[opNum].size / 8)
9797
{
98-
case 0: break; /* OT_MEM's unknown size. */
99-
case 8: strcat_WSN(str, "BYTE "); break;
100-
case 16: strcat_WSN(str, "WORD "); break;
101-
case 32: strcat_WSN(str, "DWORD "); break;
102-
case 64: strcat_WSN(str, "QWORD "); break;
103-
case 80: strcat_WSN(str, "TBYTE "); break;
104-
case 128: strcat_WSN(str, "DQWORD "); break;
105-
case 256: strcat_WSN(str, "YWORD "); break;
106-
default: /* Big oh uh if it gets here. */ break;
98+
/*case 0: break; /* OT_MEM's unknown size. */
99+
case 1: strcat_WSN(str, "BYTE "); break;
100+
case 2: strcat_WSN(str, "WORD "); break;
101+
case 4: strcat_WSN(str, "DWORD "); break;
102+
case 8: strcat_WSN(str, "QWORD "); break;
103+
case 10: strcat_WSN(str, "TBYTE "); break;
104+
case 16: strcat_WSN(str, "DQWORD "); break;
105+
case 32: strcat_WSN(str, "YWORD "); break;
106+
/*default: /* Big oh uh if it gets here. */ break;
107107
}
108108
}
109109
}
110110

111-
static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t addrMask)
111+
static void distorm_format_signed_disp(unsigned char** str, const _DInst* di, uint64_t addrMask)
112112
{
113113
int64_t tmpDisp64;
114114

@@ -128,11 +128,10 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
128128
_DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result)
129129
#endif
130130
{
131-
_WString* str;
132-
unsigned int i, isDefault;
131+
unsigned char* str;
132+
unsigned int i;
133133
int64_t tmpDisp64;
134134
uint64_t addrMask = (uint64_t)-1;
135-
uint8_t segment;
136135
const _WMnemonic* mnemonic;
137136
unsigned int suffixSize = 0;
138137

@@ -143,6 +142,8 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
143142
/* Gotta have full address for (di->addr - ci->codeOffset) to work in all modes. */
144143
str_hex(&result->instructionHex, (const char*)&ci->code[(unsigned int)(di->addr - ci->codeOffset)], di->size);
145144

145+
strfinalize_WS(&result->operands, (unsigned char*)&result->operands.p);
146+
146147
if (di->flags == FLAG_NOT_DECODABLE) {
147148
/* In-place considerations: DI is RESULT. Deref fields first. */
148149
unsigned int size = di->size;
@@ -151,16 +152,13 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
151152

152153
result->offset = offset;
153154
result->size = size;
154-
strclear_WS(&result->operands);
155-
strcpy_WSN(&result->mnemonic, "DB ");
156-
str_int(&result->mnemonic, byte);
155+
str = (unsigned char*)&result->mnemonic.p;
156+
strcat_WSN(&str, "DB ");
157+
str_int(&str, byte);
158+
strfinalize_WS(&result->mnemonic, str);
157159
return; /* Skip to next instruction. */
158160
}
159161

160-
/* Format operands: */
161-
str = &result->operands;
162-
strclear_WS(str);
163-
164162
/* Special treatment for String (movs, cmps, stos, lods, scas) instructions. */
165163
if ((di->opcode >= I_MOVS) && (di->opcode <= I_SCAS)) {
166164
/*
@@ -174,46 +172,51 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
174172
}
175173
}
176174

175+
str = (unsigned char*)&result->operands.p;
176+
177177
for (i = 0; ((i < OPERANDS_NO) && (di->ops[i].type != O_NONE)); i++) {
178-
if (i > 0) strcat_WSN(str, ", ");
178+
if (i > 0) strcat_WSN(&str, ", ");
179179
switch (di->ops[i].type)
180180
{
181181
case O_REG:
182-
strcat_WSR(str, &_REGISTERS[di->ops[i].index]);
182+
strcat_WSR(&str, &_REGISTERS[di->ops[i].index]);
183183
break;
184184
case O_IMM:
185185
/* If the instruction is 'push', show explicit size (except byte imm). */
186-
if ((di->opcode == I_PUSH) && (di->ops[i].size != 8)) distorm_format_size(str, di, i);
186+
if ((di->opcode == I_PUSH) && (di->ops[i].size != 8)) distorm_format_size(&str, di, i);
187187
/* Special fix for negative sign extended immediates. */
188188
if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8)) {
189189
if (di->imm.sbyte < 0) {
190-
chrcat_WS(str, MINUS_DISP_CHR);
191-
str_int(str, -di->imm.sbyte);
190+
chrcat_WS(&str, MINUS_DISP_CHR);
191+
tmpDisp64 = -di->imm.sbyte;
192+
str_int(&str, tmpDisp64);
192193
break;
193194
}
194195
}
195-
str_int(str, di->imm.qword);
196+
str_int(&str, di->imm.qword);
196197
break;
197198
case O_IMM1:
198-
str_int(str, di->imm.ex.i1);
199+
str_int(&str, di->imm.ex.i1);
199200
break;
200201
case O_IMM2:
201-
str_int(str, di->imm.ex.i2);
202+
str_int(&str, di->imm.ex.i2);
202203
break;
203204
case O_DISP:
204-
distorm_format_size(str, di, i);
205-
chrcat_WS(str, OPEN_CHR);
205+
distorm_format_size(&str, di, i);
206+
chrcat_WS(&str, OPEN_CHR);
206207
if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) {
207-
strcat_WSR(str, &_REGISTERS[SEGMENT_GET(di->segment)]);
208-
chrcat_WS(str, SEG_OFF_CHR);
208+
strcat_WSR(&str, &_REGISTERS[SEGMENT_GET(di->segment)]);
209+
chrcat_WS(&str, SEG_OFF_CHR);
209210
}
210211
tmpDisp64 = di->disp & addrMask;
211-
str_int(str, tmpDisp64);
212-
chrcat_WS(str, CLOSE_CHR);
212+
str_int(&str, tmpDisp64);
213+
chrcat_WS(&str, CLOSE_CHR);
213214
break;
214-
case O_SMEM:
215-
distorm_format_size(str, di, i);
216-
chrcat_WS(str, OPEN_CHR);
215+
case O_SMEM: {
216+
int isDefault;
217+
int segment;
218+
distorm_format_size(&str, di, i);
219+
chrcat_WS(&str, OPEN_CHR);
217220

218221
/*
219222
* This is where we need to take special care for String instructions.
@@ -240,55 +243,60 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
240243
case I_SCAS: isDefault = FALSE; break;
241244
}
242245
if (!isDefault && (segment != R_NONE)) {
243-
strcat_WSR(str, &_REGISTERS[segment]);
244-
chrcat_WS(str, SEG_OFF_CHR);
246+
strcat_WSR(&str, &_REGISTERS[segment]);
247+
chrcat_WS(&str, SEG_OFF_CHR);
245248
}
246249

247-
strcat_WSR(str, &_REGISTERS[di->ops[i].index]);
250+
strcat_WSR(&str, &_REGISTERS[di->ops[i].index]);
248251

249-
distorm_format_signed_disp(str, di, addrMask);
250-
chrcat_WS(str, CLOSE_CHR);
251-
break;
252+
distorm_format_signed_disp(&str, di, addrMask);
253+
chrcat_WS(&str, CLOSE_CHR);
254+
} break;
252255
case O_MEM:
253-
distorm_format_size(str, di, i);
254-
chrcat_WS(str, OPEN_CHR);
256+
distorm_format_size(&str, di, i);
257+
chrcat_WS(&str, OPEN_CHR);
255258
if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) {
256-
strcat_WSR(str, &_REGISTERS[SEGMENT_GET(di->segment)]);
257-
chrcat_WS(str, SEG_OFF_CHR);
259+
strcat_WSR(&str, &_REGISTERS[SEGMENT_GET(di->segment)]);
260+
chrcat_WS(&str, SEG_OFF_CHR);
258261
}
259262
if (di->base != R_NONE) {
260-
strcat_WSR(str, &_REGISTERS[di->base]);
261-
chrcat_WS(str, PLUS_DISP_CHR);
263+
strcat_WSR(&str, &_REGISTERS[di->base]);
264+
chrcat_WS(&str, PLUS_DISP_CHR);
262265
}
263-
strcat_WSR(str, &_REGISTERS[di->ops[i].index]);
266+
strcat_WSR(&str, &_REGISTERS[di->ops[i].index]);
264267
if (di->scale != 0) {
265-
chrcat_WS(str, '*');
266-
if (di->scale == 2) chrcat_WS(str, '2');
267-
else if (di->scale == 4) chrcat_WS(str, '4');
268-
else /* if (di->scale == 8) */ chrcat_WS(str, '8');
268+
if (di->scale == 2) strcat_WSN(&str, "*2");
269+
else if (di->scale == 4) strcat_WSN(&str, "*4");
270+
else /* if (di->scale == 8) */ strcat_WSN(&str, "*8");
269271
}
270272

271-
distorm_format_signed_disp(str, di, addrMask);
272-
chrcat_WS(str, CLOSE_CHR);
273+
distorm_format_signed_disp(&str, di, addrMask);
274+
chrcat_WS(&str, CLOSE_CHR);
273275
break;
274276
case O_PC:
275277
#ifdef SUPPORT_64BIT_OFFSET
276-
str_int(str, (di->imm.sqword + di->addr + di->size) & addrMask);
278+
str_int(&str, (di->imm.sqword + di->addr + di->size) & addrMask);
277279
#else
278280
tmpDisp64 = ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask;
279-
str_int(str, tmpDisp64);
281+
str_int(&str, tmpDisp64);
280282
#endif
281283
break;
282284
case O_PTR:
283-
str_int(str, di->imm.ptr.seg);
284-
chrcat_WS(str, SEG_OFF_CHR);
285-
str_int(str, di->imm.ptr.off);
285+
str_int(&str, di->imm.ptr.seg);
286+
chrcat_WS(&str, SEG_OFF_CHR);
287+
str_int(&str, di->imm.ptr.off);
286288
break;
287289
}
288290
}
289291

292+
/* Finalize the operands string. */
293+
strfinalize_WS(&result->operands, str);
294+
295+
296+
/* Not used anymore.
290297
if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN");
291298
else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN");
299+
*/
292300

293301
skipOperands:
294302
{
@@ -299,47 +307,43 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
299307

300308
mnemonic = (const _WMnemonic*)&_MNEMONICS[di->opcode];
301309

302-
str = &result->mnemonic;
310+
str = (unsigned char*)&result->mnemonic.p;
303311
if (prefix) {
304312
switch (prefix)
305313
{
306314
case FLAG_LOCK:
307-
strcpy_WSN(str, "LOCK ");
315+
strcat_WSN(&str, "LOCK ");
308316
break;
309317
case FLAG_REP:
310318
/* REP prefix for CMPS and SCAS is really a REPZ. */
311-
if ((di->opcode == I_CMPS) || (di->opcode == I_SCAS)) strcpy_WSN(str, "REPZ ");
312-
else strcpy_WSN(str, "REP ");
319+
if ((di->opcode == I_CMPS) || (di->opcode == I_SCAS)) strcat_WSN(&str, "REPZ ");
320+
else strcat_WSN(&str, "REP ");
313321
break;
314322
case FLAG_REPNZ:
315-
strcpy_WSN(str, "REPNZ ");
323+
strcat_WSN(&str, "REPNZ ");
316324
break;
317325
}
318-
}
319-
else {
320-
/* Init mnemonic string. */
321-
str->length = 0;
322-
}
326+
} else result->mnemonic.length = 0;
323327

324328
/*
325329
* Always copy 16 bytes from the mnemonic, we have a sentinel padding so we can read past.
326330
* This helps the compiler to remove the call to memcpy and therefore makes this copying much faster.
327331
* The longest instruction is exactly 16 chars long, but we null terminate the string below.
328332
*/
329-
memcpy((int8_t*)&str->p[str->length], mnemonic->p, 16);
330-
str->length += mnemonic->length;
333+
memcpy((int8_t*)str, mnemonic->p, 16);
334+
str += mnemonic->length;
331335

332336
if (suffixSize) {
333337
switch (suffixSize)
334338
{
335-
case 1: chrcat_WS(str, 'B'); break;
336-
case 2: chrcat_WS(str, 'W'); break;
337-
case 4: chrcat_WS(str, 'D'); break;
338-
case 8: chrcat_WS(str, 'Q'); break;
339+
case 1: chrcat_WS(&str, 'B'); break;
340+
case 2: chrcat_WS(&str, 'W'); break;
341+
case 4: chrcat_WS(&str, 'D'); break;
342+
case 8: chrcat_WS(&str, 'Q'); break;
339343
}
340344
}
341345

342-
str->p[str->length] = 0;
346+
strfinalize_WS(&result->mnemonic, str);
343347

344348
result->offset = offset;
345349
result->size = size;
@@ -354,7 +358,6 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
354358
{
355359
_DecodeResult res;
356360
_CodeInfo ci;
357-
unsigned int instsCount = 0, i;
358361

359362
*usedInstructionsCount = 0;
360363

@@ -389,8 +392,8 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
389392
if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16;
390393
else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32;
391394

392-
res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount);
393-
for (i = 0; i < instsCount; i++) {
395+
res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, usedInstructionsCount);
396+
for (unsigned int i = 0, instsCount = *usedInstructionsCount; i < instsCount; i++) {
394397
/* distorm_format is optimized and can work with same input/output buffer in-place. */
395398
#ifdef SUPPORT_64BIT_OFFSET
396399
distorm_format64(&ci, (_DInst*)&result[i], &result[i]);
@@ -399,7 +402,6 @@ static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t
399402
#endif
400403
}
401404

402-
*usedInstructionsCount = instsCount;
403405
return res;
404406
}
405407

0 commit comments

Comments
 (0)