-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathrprec.cpp
334 lines (287 loc) · 9.08 KB
/
rprec.cpp
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/*
* Pin version of CRAFT rprec mode.
*
* Mike Lam, LLNL, Summer 2016
*/
#include <iostream>
#include <fstream>
#include <sstream>
#include <string.h>
#include <unistd.h>
#include "pin.H"
#include "pin_isa.H"
extern "C" {
#include "xed-interface.h"
}
#define MAX_STR_LEN 64
using namespace std;
/*
* command-line options
*/
KNOB<UINT32> KnobPrecLevel(KNOB_MODE_WRITEONCE, "pintool",
"r", "52", "# of bits of precision to be preserved");
/*
* application info (used to build output file name)
*/
static string appName = "default";
static INT appPid = 0;
/*
* total number of instructions instrumented (excluding duplicates)
*/
static unsigned long totalInstructions = 0;
/*
* truncation constants
*/
static UINT64 DFLAG = 0xffffffffffffffff;
static UINT64 FFLAG = 0xffffffff;
/*
* utility method: strip the path out of a filename
*/
const char* stripPath(const char *fn)
{
const char *name = strrchr(fn, '/');
if (name) {
return name+1;
} else {
return fn;
}
}
/*
* criteria that make an instruction relevant to floating-point analysis
*/
bool shouldInstrument(INS ins)
{
// extract instruction info
INT32 icategory = INS_Category(ins);
INT32 iextension = INS_Extension(ins);
// check for floating-point instructions
return (
icategory == XED_CATEGORY_SSE ||
icategory == XED_CATEGORY_AVX ||
icategory == XED_CATEGORY_AVX2 ||
iextension == XED_EXTENSION_SSE ||
iextension == XED_EXTENSION_SSE2 ||
iextension == XED_EXTENSION_SSE3 ||
iextension == XED_EXTENSION_SSE4 ||
iextension == XED_EXTENSION_SSE4A
);
}
/*
* criteria to check single-precision operands in an instruction
*/
bool isFP32(INS ins)
{
LEVEL_BASE::OPCODE iclass = INS_Opcode(ins);
switch (iclass) {
case XED_ICLASS_ADDSS: case XED_ICLASS_ADDPS:
case XED_ICLASS_SUBSS: case XED_ICLASS_SUBPS:
case XED_ICLASS_MULSS: case XED_ICLASS_MULPS:
case XED_ICLASS_DIVSS: case XED_ICLASS_DIVPS:
case XED_ICLASS_MINSS: case XED_ICLASS_MINPS:
case XED_ICLASS_MAXSS: case XED_ICLASS_MAXPS:
case XED_ICLASS_SQRTSS: case XED_ICLASS_SQRTPS:
case XED_ICLASS_CMPSS: case XED_ICLASS_CMPPS:
case XED_ICLASS_COMISS: case XED_ICLASS_UCOMISS:
return true;
}
return false;
}
/*
* criteria to check double-precision operands in an instruction
*/
bool isFP64(INS ins)
{
LEVEL_BASE::OPCODE iclass = INS_Opcode(ins);
switch (iclass) {
case XED_ICLASS_ADDSD: case XED_ICLASS_ADDPD:
case XED_ICLASS_SUBSD: case XED_ICLASS_SUBPD:
case XED_ICLASS_MULSD: case XED_ICLASS_MULPD:
case XED_ICLASS_DIVSD: case XED_ICLASS_DIVPD:
case XED_ICLASS_MINSD: case XED_ICLASS_MINPD:
case XED_ICLASS_MAXSD: case XED_ICLASS_MAXPD:
case XED_ICLASS_SQRTSD: case XED_ICLASS_SQRTPD:
case XED_ICLASS_CMPSD: case XED_ICLASS_CMPPD:
case XED_ICLASS_COMISD: case XED_ICLASS_UCOMISD:
return true;
}
return false;
}
/*
* criteria to check packed floating-point operands in an instruction
*/
bool isPackedSSE(INS ins)
{
LEVEL_BASE::OPCODE iclass = INS_Opcode(ins);
switch (iclass) {
case XED_ICLASS_ADDPS: case XED_ICLASS_ADDPD:
case XED_ICLASS_SUBPS: case XED_ICLASS_SUBPD:
case XED_ICLASS_MULPS: case XED_ICLASS_MULPD:
case XED_ICLASS_DIVPS: case XED_ICLASS_DIVPD:
case XED_ICLASS_MINPS: case XED_ICLASS_MINPD:
case XED_ICLASS_MAXPS: case XED_ICLASS_MAXPD:
case XED_ICLASS_SQRTPS: case XED_ICLASS_SQRTPD:
case XED_ICLASS_CMPPS: case XED_ICLASS_CMPPD:
return true;
}
return false;
}
/*
* run time: update min/max trackers for various kinds of operands
*/
VOID truncateMem32(UINT32 *loc)
{
//cout << "truncating " << *(float*)loc;
*loc = *loc & FFLAG;
//cout << " to " << *(float*)loc << endl;
}
VOID truncateReg32(PIN_REGISTER *reg)
{
truncateMem32((UINT32*)&(reg->flt[0]));
}
VOID truncateReg32Packed(PIN_REGISTER *reg)
{
truncateMem32((UINT32*)&(reg->flt[0]));
truncateMem32((UINT32*)&(reg->flt[1]));
truncateMem32((UINT32*)&(reg->flt[2]));
truncateMem32((UINT32*)&(reg->flt[3]));
}
VOID truncateMem64(UINT64 *loc)
{
//cout << "truncating " << *(double*)loc;
*loc = *loc & DFLAG;
//cout << " to " << *(double*)loc << endl;
}
VOID truncateReg64(PIN_REGISTER *reg)
{
truncateMem64((UINT64*)&(reg->dbl[0]));
}
VOID truncateReg64Packed(PIN_REGISTER *reg)
{
truncateMem64((UINT64*)&(reg->dbl[0]));
truncateMem64((UINT64*)&(reg->dbl[1]));
}
/*
* instrumentation time: save main executable image name for output file name
*/
VOID handleImage(IMG img, VOID *)
{
if (IMG_IsMainExecutable(img)) {
appName = stripPath(IMG_Name(img).c_str());
appPid = PIN_GetPid();
}
}
/*
* instrumentation time: insert calls to "truncate" functions
*/
VOID handleInstruction(INS ins, VOID *)
{
if (shouldInstrument(ins)) {
if (INS_IsMemoryWrite(ins)) {
if (INS_MemoryWriteSize(ins) == 8) {
// double-precision memory operand
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)truncateMem64,
IARG_MEMORYWRITE_EA,
IARG_END);
} else if (INS_MemoryWriteSize(ins) == 4) {
// single-precision memory operand
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)truncateMem32,
IARG_MEMORYWRITE_EA,
IARG_END);
}
}
for (UINT32 r = 0; r < INS_MaxNumWRegs(ins); r++) {
REG reg = INS_RegW(ins, r);
if (REG_is_xmm(reg) && isFP64(ins)) {
if (isPackedSSE(ins)) {
// double-precision packed register operand
INS_InsertCall(ins, IPOINT_BEFORE,
(AFUNPTR)truncateReg64Packed,
IARG_REG_REFERENCE, reg,
IARG_END);
} else {
// double-precision scalar register operand
INS_InsertCall(ins, IPOINT_BEFORE,
(AFUNPTR)truncateReg64,
IARG_REG_REFERENCE, reg,
IARG_END);
}
} else if (REG_is_xmm(reg) && isFP32(ins)) {
if (isPackedSSE(ins)) {
// single-precision packed register operand
INS_InsertCall(ins, IPOINT_BEFORE,
(AFUNPTR)truncateReg32Packed,
IARG_REG_REFERENCE, reg,
IARG_END);
} else {
// single-precision scalar register operand
INS_InsertCall(ins, IPOINT_BEFORE,
(AFUNPTR)truncateReg32,
IARG_REG_REFERENCE, reg,
IARG_END);
}
}
}
}
}
/*
* termination: log info
*/
VOID handleCleanup(INT32 code, VOID *v)
{
// extract current host name
char hostname[MAX_STR_LEN];
if (!gethostname(hostname, MAX_STR_LEN)) {
strncpy(hostname, "localhost", MAX_STR_LEN);
}
// add metadata to main log file
LOG("CRAFT: Analyzed " + appName + " [pid=" + decstr(appPid) +
"] running on " + hostname + "\n");
LOG("CRAFT: Handled " + decstr(totalInstructions) +
" unique instruction(s)\n");
LOG("CRAFT: Performed reduced-precision analysis with " +
decstr(KnobPrecLevel.Value()) + " bits preserved\n");
}
int main(int argc, char* argv[])
{
// initialize Pin
PIN_InitSymbols(); // we want symbol info if present
if (PIN_Init(argc, argv)) {
PIN_ERROR("This Pintool simulates reduced precision via truncation"
" of floating-point output operands\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
// uncomment to use AT&T syntax (to match the GNU debugger)
//PIN_SetSyntaxATT();
UINT32 keep = KnobPrecLevel.Value();
if (keep > 52) {
PIN_ERROR("Invalid precision level (must be >= 0 and <= 52)\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
UINT32 trunc64 = 52 - keep;
UINT32 trunc32 = (keep < 23 ? 23 - keep : 0);
for (UINT64 bit64 = 0x1, i = 0; i < trunc64; bit64 <<= 1, i++) {
DFLAG -= bit64;
}
for (UINT32 bit32 = 0x1, j = 0; j < trunc32; bit32 <<= 1, j++) {
FFLAG -= bit32;
}
/*
*cout << "keep: " << std::dec << KnobPrecLevel.Value()
* << " trunc64: " << std::dec << trunc64
* << " flag: " << std::hex << DFLAG
* << " trunc32: " << std::dec << trunc32
* << " flag: " << std::hex << FFLAG
* << endl;
*/
// register image callback
IMG_AddInstrumentFunction(handleImage, 0);
// register instruction callback
INS_AddInstrumentFunction(handleInstruction, 0);
// register cleanup callback
PIN_AddFiniFunction(handleCleanup, 0);
// begin execution
PIN_StartProgram();
return 0;
}