-
Notifications
You must be signed in to change notification settings - Fork 42
/
tnt_asm.c
228 lines (185 loc) · 5.58 KB
/
tnt_asm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*
*
* Not sure if it's possible to get the guest architecture at run time.
* The instrument() function in tnt_translate.c has a parameter
* VexArchInfo* archinfo_host, but this is the host, not the guest.
* This is called from VEX/priv/main_main.c
*
* So instead, I use a macro because that's the way valgrind seems to do
* it internally at compilation time, see coregrind/m_machine.c
*
* So I copy their macros here and set the correct architecture,
* then use capstone to disassemble [0]. An example can be found at [1].
*
* For installation, see [2]. It may vary depending on your platform.
* Headers should be installed under <YOUR_INCLUDE>/capstone/
*
* [0] http://www.capstone-engine.org
* [1] http://www.capstone-engine.org/lang_c.html
* [2] http://www.capstone-engine.org/documentation.html
*
* */
#include "pub_tool_tooliface.h"
#include "pub_tool_libcassert.h"
#include "pub_tool_libcprint.h" // VG_(*printf)
#include "pub_tool_hashtable.h" // For tnt_include.h, VgHashtable
#include "tnt_include.h"
#include "tnt_asm.h"
// capstone stuff
#include <inttypes.h>
#include <capstone.h>
/*
as defined in capstone.h
========================
cs_arch:
-------
CS_ARCH_ARM = 0, // ARM architecture (including Thumb, Thumb-2)
CS_ARCH_ARM64, // ARM-64, also called AArch64
CS_ARCH_MIPS, // Mips architecture
CS_ARCH_X86, // X86 architecture (including x86 & x86-64)
CS_ARCH_PPC, // PowerPC architecture
CS_ARCH_SPARC, // Sparc architecture
CS_ARCH_SYSZ, // SystemZ architecture
CS_ARCH_XCORE, // XCore architecture
CS_ARCH_MAX,
CS_ARCH_ALL = 0xFFFF, // All architectures - for cs_support()
cs_mode:
-------
CS_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode)
CS_MODE_ARM = 0, // 32-bit ARM
CS_MODE_16 = 1 << 1, // 16-bit mode (X86)
CS_MODE_32 = 1 << 2, // 32-bit mode (X86)
CS_MODE_64 = 1 << 3, // 64-bit mode (X86, PPC)
CS_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2
CS_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series
CS_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM
CS_MODE_MICRO = 1 << 4, // MicroMips mode (MIPS)
CS_MODE_MIPS3 = 1 << 5, // Mips III ISA
CS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA
CS_MODE_MIPSGP64 = 1 << 7, // General Purpose Registers are 64-bit wide (MIPS)
CS_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc)
CS_MODE_BIG_ENDIAN = 1 << 31, // big-endian mode
CS_MODE_MIPS32 = CS_MODE_32, // Mips32 ISA (Mips)
CS_MODE_MIPS64 = CS_MODE_64, //
*/
// global variables
#define INVALID (-1)
static csh handle = INVALID;
static cs_insn *insn = (void*)INVALID;
static cs_arch arch = INVALID;
static cs_mode mode = INVALID;
#if defined(VGA_arm)
static csh handle2 = INVALID;
static cs_mode mode2 = INVALID;
#endif
static Bool is_init(void) {
return (handle != INVALID && arch != INVALID && mode != INVALID);
}
static void reset(void) {
handle = INVALID;
insn = (void*)INVALID;
arch = INVALID;
mode = INVALID;
}
/*
*
* # CAPSTONE_VALGRIND
ifdef CAPSTONE_VALGRIND
LDFLAGS += -nodefaultlibs -nostartfiles
#hellow rold
endif
*
*
* */
Bool TNT_(asm_init)(void) {
// here we set the global var
/*
* My understanding from reading coregrind/m_machine.c is that:
* - x86 is only 32 bits
* - amd64 is amd and x86-64
* - the rest is self-explanatory
*
* see http://www.capstone-engine.org/lang_c.html for the mapping to capstone
*/
cs_err err = CS_ERR_OK;
tl_assert ( ! is_init() );
reset();
#if defined(VGA_x86)
arch = CS_ARCH_X86;
mode = CS_MODE_32;
#elif defined(VGA_amd64)
arch = CS_ARCH_X86;
mode = CS_MODE_64;
#elif defined(VGA_ppc32)
arch = CS_ARCH_PPC;
mode = CS_MODE_32;
#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
arch = CS_ARCH_PPC;
mode = CS_MODE_64;
#elif defined(VGA_arm)
arch = CS_ARCH_ARM;
mode = CS_MODE_ARM; // default
mode2 = CS_MODE_THUMB; // if ARM mode fails
#elif defined(VGA_arm64)
arch = CS_ARCH_ARM64;
mode = CS_MODE_ARM; // need to check these
#elif defined(VGA_s390x)
arch = CS_ARCH_SYSZ;
mode = CS_MODE_64; // check this
#elif defined(VGA_mips32)
arch = CS_ARCH_MIPS;
mode = CS_MODE_MIPS32;
#elif defined(VGA_mips64)
arch = CS_ARCH_MIPS;
mode = CS_MODE_MIPS64;
#else
Platform not supported!
#endif
if ( (err=cs_open(arch, mode, &handle)) != CS_ERR_OK) {
VG_(printf)("Failed cs_open");
goto end;
}
#if defined(VGA_arm)
if ( (err=cs_open(arch, mode2, &handle2)) != CS_ERR_OK) {
VG_(printf)("Failed cs_open");
goto end;
}
#endif
//// use AT&T syntax -- not sure this will fail on non-intel platforms...
//if ( (err=cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT)) != CS_ERR_OK) {
// VG_(printf)("Failed cs_option. Make your capstone was NOT compiled with CAPSTONE_X86_ATT_DISABLE");
// goto end;
//}
end:
return (err==CS_ERR_OK);
}
void TNT_(asm_release)(void) {
tl_assert ( is_init() );
cs_close(&handle);
reset();
}
Bool TNT_(asm_guest_pprint)(Addr a, SizeT len, char *out, SizeT olen) {
tl_assert ( is_init() );
size_t count;
Bool ret = False;
// see http://www.capstone-engine.org/lang_c.html
count = cs_disasm(handle, (uint8_t*)a, len, a, 0, &insn);
if (count > 0) {
// Only copy the first instruction
VG_(snprintf)(out, olen, "%s %s", insn[0].mnemonic, insn[0].op_str);
cs_free(insn, count);
ret = True;
}
#if defined(VGA_arm)
else { // if primary mode fails, try secondary mode
count = cs_disasm(handle2, (uint8_t*)a, len, a, 0, &insn);
if (count > 0) {
// Only copy the first instruction
VG_(snprintf)(out, olen, "%s %s", insn[0].mnemonic, insn[0].op_str);
cs_free(insn, count);
ret = True;
}
}
#endif
return ret;
}