-
Notifications
You must be signed in to change notification settings - Fork 5
/
cbr.cpp
72 lines (61 loc) · 2.4 KB
/
cbr.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
#include "dr_api.h"
#include "cbr.h"
#include "cfg_impl.h"
#include "app.h"
#include <cstdint>
static void
taken_or_not(uintptr_t src, uintptr_t targ)
{
dr_mcontext_t mcontext = {sizeof(mcontext),DR_MC_ALL,};
void *drcontext = dr_get_current_drcontext();
safe_insert(src, targ);
/* Remove the bb from the cache so it will be re-built the next
* time it executes.
*/
/* Since the flush will remove the fragment we're already in,
* redirect execution to the fallthrough address.
*/
dr_flush_region((app_pc)src, 1);
dr_get_mcontext(drcontext, &mcontext);
mcontext.pc = (app_pc)targ;
dr_redirect_execution(&mcontext);
}
dr_emit_flags_t
cbr_event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr,
bool for_trace, bool translating, void *user_data)
{
if (!instr_is_cbr(instr))
return DR_EMIT_DEFAULT;
if (app_should_ignore_tag(tag))
return DR_EMIT_DEFAULT;
app_pc src = instr_get_app_pc(instr);
app_pc fall = (app_pc)decode_next_pc(drcontext, (byte *)src);
app_pc targ = instr_get_branch_target_pc(instr);
bool insert_targ = !branch_present((uintptr_t)src, (uintptr_t)targ);
bool insert_fall = !branch_present((uintptr_t)src, (uintptr_t)fall);
if (insert_targ || insert_fall) {
instr_t *label = INSTR_CREATE_label(drcontext);
instr_set_meta_no_translation(instr);
if (instr_is_cti_short(instr))
instr = instr_convert_short_meta_jmp_to_long(drcontext, bb, instr);
instr_set_target(instr, opnd_create_instr(label));
if (insert_fall) {
dr_insert_clean_call(drcontext, bb, NULL, (void *)taken_or_not, false, 2,
OPND_CREATE_INTPTR(src), OPND_CREATE_INTPTR(fall));
}
instrlist_preinsert(bb, NULL, INSTR_XL8
(XINST_CREATE_jump
(drcontext,
opnd_create_pc(fall)), fall));
instrlist_meta_preinsert(bb, NULL, label);
if (insert_targ) {
dr_insert_clean_call(drcontext, bb, NULL, (void *)taken_or_not, false, 2,
OPND_CREATE_INTPTR(src), OPND_CREATE_INTPTR(targ));
}
instrlist_preinsert(bb, NULL, INSTR_XL8
(XINST_CREATE_jump
(drcontext,
opnd_create_pc(targ)), targ));
}
return DR_EMIT_STORE_TRANSLATIONS;
}