Skip to content

Commit b5cd50c

Browse files
committed
Update E9Patch documentation & simplify plugins
1 parent e5c7e31 commit b5cd50c

8 files changed

Lines changed: 213 additions & 170 deletions

File tree

doc/e9patch-programming-guide.md

Lines changed: 140 additions & 102 deletions
Large diffs are not rendered by default.

examples/plugins/example.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ using namespace e9frontend;
5353
/*
5454
* Initialize the counters and the trampoline.
5555
*/
56-
extern void *e9_plugin_init_v1(FILE *out, const ELF *elf)
56+
extern void *e9_plugin_init_v1(const Context *cxt)
5757
{
5858
// The e9_plugin_init_v1() is called once per plugin by E9Tool. This can
5959
// be used to emit additional E9Patch messages, such as address space
@@ -71,7 +71,7 @@ extern void *e9_plugin_init_v1(FILE *out, const ELF *elf)
7171
if (limit_str != nullptr)
7272
limit = (ssize_t)atoll(limit_str);
7373
const ssize_t counters[3] = {limit, limit, limit};
74-
sendReserveMessage(out,
74+
sendReserveMessage(cxt->out,
7575
(intptr_t)COUNTERS, // Memory virtual address
7676
(const uint8_t *)counters, // Memory contents
7777
sizeof(counters), // Memory size
@@ -133,15 +133,15 @@ extern void *e9_plugin_init_v1(FILE *out, const ELF *elf)
133133
code << 0x48 << ',' << 0x8d << ',' << 0xa4 << ',' << 0x24 << ','
134134
<< 0x00 << ',' << 0x40 << ',' << 0x00 << ',' << 0x00;
135135

136-
sendTrampolineMessage(out, "$limit", code.str().c_str());
136+
sendTrampolineMessage(cxt->out, "$limit", code.str().c_str());
137137

138138
return nullptr;
139139
}
140140

141141
/*
142142
* We match all control-flow transfer instructions.
143143
*/
144-
extern intptr_t e9_plugin_match_v1(FILE *out, const Context *cxt, void *arg)
144+
extern intptr_t e9_plugin_match_v1(const Context *cxt)
145145
{
146146
// The e9_plugin_match_v1() function is invoked once by E9Tool for each
147147
// disassembled instruction. The function should return a value that is
@@ -172,8 +172,7 @@ extern intptr_t e9_plugin_match_v1(FILE *out, const Context *cxt, void *arg)
172172
/*
173173
* Patch the selected instructions.
174174
*/
175-
extern void e9_plugin_patch_v1(FILE *out, Phase phase, const Context *cxt,
176-
void *arg)
175+
extern void e9_plugin_patch_v1(const Context *cxt, Phase phase)
177176
{
178177
// The e9_plugin_patch_v1() function is invoked by E9Tool in order to
179178
// build "patch" messages for E9Patch. This function is invoked in three
@@ -201,7 +200,7 @@ extern void e9_plugin_patch_v1(FILE *out, Phase phase, const Context *cxt,
201200
case PHASE_CODE:
202201
// The trampoline code simply invokes the $limit template
203202
// (defined above):
204-
fputs("\"$limit\",", out);
203+
fputs("\"$limit\",", cxt->out);
205204
return;
206205
case PHASE_DATA:
207206
// There is no trampoline data:
@@ -210,9 +209,9 @@ extern void e9_plugin_patch_v1(FILE *out, Phase phase, const Context *cxt,
210209
{
211210
// The trampoline metadata instantiates the $counter macro with
212211
// the counter address corresponding to the instruction type:
213-
intptr_t counter = e9_plugin_match_v1(nullptr, cxt, arg);
212+
intptr_t counter = e9_plugin_match_v1(cxt);
214213
counter = COUNTERS + (counter - 1) * sizeof(size_t);
215-
fprintf(out, "\"$counter\":{\"rel32\":\"0x%lx\"},", counter);
214+
fprintf(cxt->out, "\"$counter\":{\"rel32\":\"0x%lx\"},", counter);
216215
return;
217216
}
218217
default:

src/e9patch/e9json.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ static Entry makeMacroEntry(const char *macro)
601601
case 'b':
602602
if (strcmp(macro, "$bytes") == 0)
603603
{
604-
entry.kind = ENTRY_INSTRUCTION_BYTES;
604+
entry.kind = ENTRY_INSTR_BYTES;
605605
return entry;
606606
}
607607
else if (strcmp(macro, "$break") == 0)
@@ -611,16 +611,16 @@ static Entry makeMacroEntry(const char *macro)
611611
}
612612
break;
613613
case 'i':
614-
if (strcmp(macro, "$instruction") == 0)
614+
if (strcmp(macro, "$instr") == 0)
615615
{
616-
entry.kind = ENTRY_INSTRUCTION;
616+
entry.kind = ENTRY_INSTR;
617617
return entry;
618618
}
619619
break;
620620
case 't':
621-
if (strcmp(macro, "$taken") == 0)
621+
if (strcmp(macro, "$take") == 0)
622622
{
623-
entry.kind = ENTRY_TAKEN;
623+
entry.kind = ENTRY_TAKE;
624624
return entry;
625625
}
626626
break;

src/e9patch/e9patch.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ enum EntryKind
171171
ENTRY_INT16,
172172
ENTRY_INT32,
173173
ENTRY_INT64,
174-
ENTRY_INSTRUCTION,
175-
ENTRY_INSTRUCTION_BYTES,
174+
ENTRY_INSTR,
175+
ENTRY_INSTR_BYTES,
176176
ENTRY_BREAK,
177-
ENTRY_TAKEN,
177+
ENTRY_TAKE,
178178
};
179179

180180
/*

src/e9patch/e9trampoline.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void __attribute__((__constructor__(8000))) evicteeTrampolineInit(void)
7474
T->prot = PROT_READ | PROT_EXEC;
7575
T->num_entries = num_entries;
7676
T->preload = false;
77-
T->entries[0].kind = ENTRY_INSTRUCTION;
77+
T->entries[0].kind = ENTRY_INSTR;
7878
T->entries[0].length = 0;
7979
T->entries[0].bytes = nullptr;
8080
T->entries[1].kind = ENTRY_BREAK;
@@ -394,7 +394,7 @@ static int getTrampolineSize(const Binary *B, const Trampoline *T,
394394
case ENTRY_REL32:
395395
size += sizeof(int32_t);
396396
continue;
397-
case ENTRY_INSTRUCTION:
397+
case ENTRY_INSTR:
398398
{
399399
int r = relocateInstr(I->addr, /*offset=*/0, I->original.bytes,
400400
I->size, I->pic, nullptr);
@@ -403,14 +403,14 @@ static int getTrampolineSize(const Binary *B, const Trampoline *T,
403403
size += r;
404404
continue;
405405
}
406-
case ENTRY_INSTRUCTION_BYTES:
406+
case ENTRY_INSTR_BYTES:
407407
size += I->size;
408408
continue;
409409
case ENTRY_BREAK:
410410
size += buildBreak(B, I, /*offset=*/0, entry.optimize,
411411
BUILD_SIZE);
412412
continue;
413-
case ENTRY_TAKEN:
413+
case ENTRY_TAKE:
414414
size += /*sizeof(jmpq)=*/5;
415415
continue;
416416
}
@@ -462,14 +462,14 @@ static intptr_t getBuiltinLabelAddress(const Binary *B, const Instr *I,
462462
return (intptr_t)I->addr;
463463
break;
464464
case 't':
465-
if (strcmp(label, ".Ltaken") == 0)
465+
if (strcmp(label, ".Ltake") == 0)
466466
{
467467
intptr_t target = getCFTTarget(I->addr, I->original.bytes,
468468
I->size, CFT_JCC);
469469
if (target == INTPTR_MIN)
470470
error("failed to build trampoline; instruction at address "
471471
"0x%lx is not a conditional branch (as required by "
472-
"\".Ltaken\")", I->addr);
472+
"\".Ltake\")", I->addr);
473473
return target;
474474
}
475475
break;
@@ -542,21 +542,21 @@ static size_t getTrampolineBounds(const Binary *B, const Trampoline *T,
542542
}
543543
continue;
544544
}
545-
case ENTRY_INSTRUCTION:
545+
case ENTRY_INSTR:
546546
{
547547
int r = relocateInstr(I->addr, /*offset=*/0, I->original.bytes,
548548
I->size, I->pic, nullptr);
549549
size += (r < 0? 0: r);
550550
continue;
551551
}
552-
case ENTRY_INSTRUCTION_BYTES:
552+
case ENTRY_INSTR_BYTES:
553553
size += I->size;
554554
continue;
555555
case ENTRY_BREAK:
556556
size += buildBreak(B, I, /*offset=*/0, entry.optimize,
557557
BUILD_SIZE);
558558
continue;
559-
case ENTRY_TAKEN:
559+
case ENTRY_TAKE:
560560
size += /*sizeof(jmpq)=*/5;
561561
continue;
562562
}
@@ -631,18 +631,18 @@ static off_t buildLabelSet(const Binary *B, const Trampoline *T,
631631
case ENTRY_REL32:
632632
offset += sizeof(int32_t);
633633
continue;
634-
case ENTRY_INSTRUCTION:
634+
case ENTRY_INSTR:
635635
offset += relocateInstr(I->addr, /*offset=*/0,
636636
I->original.bytes, I->size, I->pic, nullptr);
637637
continue;
638-
case ENTRY_INSTRUCTION_BYTES:
638+
case ENTRY_INSTR_BYTES:
639639
offset += I->size;
640640
continue;
641641
case ENTRY_BREAK:
642642
offset += buildBreak(B, I, offset, entry.optimize,
643643
BUILD_SIZE, brk, nullptr);
644644
continue;
645-
case ENTRY_TAKEN:
645+
case ENTRY_TAKE:
646646
offset += /*sizeof(jmpq)=*/5;
647647
continue;
648648
}
@@ -781,14 +781,14 @@ static void buildBytes(const Binary *B, const Trampoline *T,
781781
continue;
782782
}
783783

784-
case ENTRY_INSTRUCTION:
784+
case ENTRY_INSTR:
785785
{
786786
relocateInstr(I->addr, entry32 + buf.size(),
787787
I->original.bytes, I->size, I->pic, &buf);
788788
continue;
789789
}
790790

791-
case ENTRY_INSTRUCTION_BYTES:
791+
case ENTRY_INSTR_BYTES:
792792
buf.push(I->original.bytes, I->size);
793793
break;
794794

@@ -797,7 +797,7 @@ static void buildBytes(const Binary *B, const Trampoline *T,
797797
BUILD_BYTES, &brk, &buf);
798798
break;
799799

800-
case ENTRY_TAKEN:
800+
case ENTRY_TAKE:
801801
{
802802
intptr_t target = getCFTTarget(I->addr, I->original.bytes,
803803
I->size, CFT_JCC);
@@ -940,9 +940,9 @@ bool TrampolineCmp::operator()(const Trampoline *a, const Trampoline *b) const
940940
return (entry_a->uint64 < entry_b->uint64);
941941
}
942942
break;
943-
case ENTRY_DEBUG: case ENTRY_INSTRUCTION:
944-
case ENTRY_INSTRUCTION_BYTES: case ENTRY_BREAK:
945-
case ENTRY_TAKEN:
943+
case ENTRY_DEBUG: case ENTRY_INSTR:
944+
case ENTRY_INSTR_BYTES: case ENTRY_BREAK:
945+
case ENTRY_TAKE:
946946
break;
947947
}
948948
}

src/e9tool/e9metadata.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,7 @@ static void sendArgumentDataMetadata(FILE *out, const char *name,
14921492
* Build metadata.
14931493
*/
14941494
static void sendMetadata(FILE *out, const ELF *elf, const Action *action,
1495-
size_t idx, const InstrInfo *I, intptr_t id, const Context *cxt)
1495+
size_t idx, const InstrInfo *I, intptr_t id, Context *cxt)
14961496
{
14971497
if (action == nullptr)
14981498
return;
@@ -1504,7 +1504,8 @@ static void sendMetadata(FILE *out, const ELF *elf, const Action *action,
15041504
case PATCH_PLUGIN:
15051505
{
15061506
const Plugin *plugin = patch->plugin;
1507-
plugin->patchFunc(out, PHASE_METADATA, cxt, plugin->context);
1507+
cxt->context = plugin->context;
1508+
plugin->patchFunc(cxt, PHASE_METADATA);
15081509
return;
15091510
}
15101511

src/e9tool/e9plugin.h

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,33 +54,27 @@ extern "C"
5454
*/
5555
struct Context
5656
{
57+
FILE *out; // The output stream
58+
void *context; // The user context
5759
const e9frontend::ELF * const elf; // Input ELF file
5860
const e9frontend::Instr * const Is; // All disasm instructions
59-
size_t size; // Size of Is
61+
ssize_t size; // Size of Is
6062
ssize_t idx; // Current instruction idx
6163
const e9frontend::InstrInfo * const I; // Current instruction info
6264
intptr_t id; // Current patch ID
6365
};
6466

65-
typedef void *(*PluginInit)(FILE *out, const e9frontend::ELF *elf);
66-
typedef void (*PluginEvent)(FILE *out, Event event, const Context *cxt,
67-
void *arg);
68-
typedef intptr_t (*PluginMatch)(FILE *out, const Context *cxt,
69-
void *arg);
70-
typedef void (*PluginPatch)(FILE *out, Phase phase, const Context *cxt,
71-
void *arg);
72-
typedef void (*PluginFini)(FILE *out, const e9frontend::ELF *elf,
73-
void *arg);
67+
typedef void *(*PluginInit)(const Context *cxt);
68+
typedef void (*PluginEvent)(const Context *cxt, Event event);
69+
typedef intptr_t (*PluginMatch)(const Context *cxt);
70+
typedef void (*PluginPatch)(const Context *cxt, Phase phase);
71+
typedef void (*PluginFini)(const Context *cxt);
7472

75-
extern void *e9_plugin_init_v1(FILE *out, const e9frontend::ELF *elf);
76-
extern void e9_plugin_event_v1(FILE *out, Event event, const Context *cxt,
77-
void *arg);
78-
extern intptr_t e9_plugin_match_v1(FILE *out, const Context *cxt,
79-
void *arg);
80-
extern void e9_plugin_patch_v1(FILE *out, Phase phase, const Context *cxt,
81-
void *arg);
82-
extern void e9_plugin_fini_v1(FILE *out, const e9frontend::ELF *elf,
83-
void *arg);
73+
extern void *e9_plugin_init_v1(const Context *cxt);
74+
extern void e9_plugin_event_v1(const Context *cxt, Event event);
75+
extern intptr_t e9_plugin_match_v1(const Context *cxt);
76+
extern void e9_plugin_patch_v1(const Context *cxt, Phase phase);
77+
extern void e9_plugin_fini_v1(const Context *cxt);
8478
}
8579

8680
#endif

0 commit comments

Comments
 (0)