Skip to content

Commit baea8ee

Browse files
committed
Fix the plugin interface for composable patches.
The plugin no longer emits a "patch" message, but is called to emit the necessary components of a "patch" message, including code, data, and metadata.
1 parent 7c93b1c commit baea8ee

5 files changed

Lines changed: 143 additions & 99 deletions

File tree

examples/plugins/example.cpp

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020 National University of Singapore
2+
* Copyright (C) 2021 National University of Singapore
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a copy
55
* of this software and associated documentation files (the "Software"), to
@@ -147,10 +147,9 @@ extern void *e9_plugin_init_v1(FILE *out, const ELF *elf)
147147
/*
148148
* We match all control-flow transfer instructions.
149149
*/
150-
extern intptr_t e9_plugin_match_v1(FILE *out, const ELF *elf, const Instr *Is,
151-
size_t size, size_t idx, const InstrInfo *info, void *context)
150+
extern intptr_t e9_plugin_match_v1(FILE *out, const Context *cxt, void *arg)
152151
{
153-
switch (info->mnemonic)
152+
switch (cxt->I->mnemonic)
154153
{
155154
case MNEMONIC_RET:
156155
return 1;
@@ -173,29 +172,25 @@ extern intptr_t e9_plugin_match_v1(FILE *out, const ELF *elf, const Instr *Is,
173172
/*
174173
* Patch the selected instructions.
175174
*/
176-
extern void e9_plugin_patch_v1(FILE *out, const ELF *elf, const Instr *Is,
177-
size_t size, size_t idx, const InstrInfo *info, void *context)
175+
extern void e9_plugin_patch_v1(FILE *out, Phase phase, const Context *cxt,
176+
void *arg)
178177
{
179-
intptr_t counter = e9_plugin_match_v1(out, elf, Is, size, idx, info,
180-
context);
181-
if (counter == 0)
182-
return;
183-
counter = COUNTERS + (counter - 1) * sizeof(size_t);
184-
185-
// We instantiate the trampoline template with $counter pointing to
186-
// the counter corresponding to the instruction type:
187-
Metadata metadata[2];
188-
metadata[0].name = "counter";
189-
std::string buf;
190-
buf += "{\"rel32\":";
191-
buf += std::to_string(counter);
192-
buf += '}';
193-
metadata[0].data = buf.c_str();
194-
195-
metadata[1].name = nullptr;
196-
metadata[1].data = nullptr;
197-
198-
// Send a "patch" E9Patch API message.
199-
sendPatchMessage(out, "$cflimit", Is[idx].offset, metadata);
178+
switch (phase)
179+
{
180+
case PHASE_CODE:
181+
fputs("\"$cflimit\",", out);
182+
return;
183+
case PHASE_DATA:
184+
return;
185+
case PHASE_METADATA:
186+
{
187+
intptr_t counter = e9_plugin_match_v1(nullptr, cxt, arg);
188+
counter = COUNTERS + (counter - 1) * sizeof(size_t);
189+
fprintf(out, "\"$counter\":{\"rel32\":\"0x%lx\"},", counter);
190+
return;
191+
}
192+
default:
193+
return;
194+
}
200195
}
201196

src/e9tool/e9metadata.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,19 +1491,25 @@ static void sendArgumentDataMetadata(FILE *out, const char *name,
14911491
/*
14921492
* Build metadata.
14931493
*/
1494-
static bool sendMetadata(FILE *out, const ELF *elf, const Action *action,
1495-
size_t idx, const InstrInfo *I, intptr_t id)
1494+
static void sendMetadata(FILE *out, const ELF *elf, const Action *action,
1495+
size_t idx, const InstrInfo *I, intptr_t id, const Context *cxt)
14961496
{
14971497
if (action == nullptr)
1498-
return false;
1498+
return;
14991499
const Patch *patch = action->patch[idx];
15001500
const char *name = patch->name+1;
15011501

15021502
switch (patch->kind)
15031503
{
1504-
case PATCH_EXIT: case PATCH_EMPTY: case PATCH_PLUGIN: case PATCH_TRAP:
1505-
case PATCH_BREAK:
1506-
return false;
1504+
case PATCH_PLUGIN:
1505+
{
1506+
const Plugin *plugin = patch->plugin;
1507+
plugin->patchFunc(out, PHASE_METADATA, cxt, plugin->context);
1508+
return;
1509+
}
1510+
1511+
case PATCH_EXIT: case PATCH_EMPTY: case PATCH_TRAP: case PATCH_BREAK:
1512+
return;
15071513
case PATCH_PRINT:
15081514
{
15091515
sendDefinitionHeader(out, name, "DATA");
@@ -1514,9 +1520,8 @@ static bool sendMetadata(FILE *out, const ELF *elf, const Action *action,
15141520
sendDefinitionHeader(out, name, "ASM_LEN");
15151521
intptr_t len = strlen(I->string.instr) + 1;
15161522
sendIntegerData(out, 32, len);
1517-
sendDefinitionFooter(out, /*last=*/true);
1518-
1519-
return true;
1523+
sendDefinitionFooter(out);
1524+
return;
15201525
}
15211526
case PATCH_CALL:
15221527
{
@@ -1650,13 +1655,11 @@ static bool sendMetadata(FILE *out, const ELF *elf, const Action *action,
16501655
sendArgumentDataMetadata(out, name, arg, I, regno);
16511656
argno++;
16521657
}
1653-
sendDefinitionFooter(out, /*last=*/true);
1654-
1655-
return true;
1658+
sendDefinitionFooter(out);
1659+
return;
16561660
}
1657-
16581661
default:
1659-
return false;
1662+
return;
16601663
}
16611664
}
16621665

src/e9tool/e9plugin.h

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,58 @@
2929

3030
extern "C"
3131
{
32+
/*
33+
* Events.
34+
*/
3235
enum Event
3336
{
3437
EVENT_DISASSEMBLY_COMPLETE,
3538
EVENT_MATCHING_COMPLETE,
3639
EVENT_PATCHING_COMPLETE,
3740
};
3841

42+
/*
43+
* Patching phases.
44+
*/
45+
enum Phase
46+
{
47+
PHASE_CODE,
48+
PHASE_DATA,
49+
PHASE_METADATA
50+
};
51+
52+
/*
53+
* Context
54+
*/
55+
struct Context
56+
{
57+
const e9frontend::ELF * const elf; // Input ELF file
58+
const e9frontend::Instr * const Is; // All disasm instructions
59+
size_t size; // Size of Is
60+
ssize_t idx; // Current instruction idx
61+
const e9frontend::InstrInfo * const I; // Current instruction info
62+
intptr_t id; // Current patch ID
63+
};
64+
3965
typedef void *(*PluginInit)(FILE *out, const e9frontend::ELF *elf);
40-
typedef void (*PluginEvent)(FILE *out, const e9frontend::ELF *elf,
41-
const e9frontend::Instr *Is, size_t size, Event event, void *context);
42-
typedef intptr_t (*PluginMatch)(FILE *out, const e9frontend::ELF *elf,
43-
const e9frontend::Instr *Is, size_t size, size_t idx,
44-
const e9frontend::InstrInfo *info, void *context);
45-
typedef void (*PluginPatch)(FILE *out, const e9frontend::ELF *elf,
46-
const e9frontend::Instr *Is, size_t size, size_t idx,
47-
const e9frontend::InstrInfo *info, void *context);
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);
4872
typedef void (*PluginFini)(FILE *out, const e9frontend::ELF *elf,
49-
void *context);
73+
void *arg);
5074

5175
extern void *e9_plugin_init_v1(FILE *out, const e9frontend::ELF *elf);
52-
extern void e9_plugin_event_v1(FILE *out, const e9frontend::ELF *elf,
53-
const e9frontend::Instr *Is, size_t size, Event event, void *context);
54-
extern intptr_t e9_plugin_match_v1(FILE *out, const e9frontend::ELF *elf,
55-
const e9frontend::Instr *Is, size_t size, size_t idx,
56-
const e9frontend::InstrInfo *info, void *context);
57-
extern void e9_plugin_patch_v1(FILE *out, const e9frontend::ELF *elf,
58-
const e9frontend::Instr *Is, size_t size, size_t idx,
59-
const e9frontend::InstrInfo *info, void *context);
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);
6082
extern void e9_plugin_fini_v1(FILE *out, const e9frontend::ELF *elf,
61-
void *context);
83+
void *arg);
6284
}
6385

6486
#endif

src/e9tool/e9tool.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,13 @@ static Plugin *openPlugin(const char *basename)
448448
static void notifyPlugins(FILE *out, const ELF *elf, const Instr *Is,
449449
size_t size, Event event)
450450
{
451+
Context cxt = {elf, Is, size, -1, nullptr, -1};
451452
for (auto i: plugins)
452453
{
453454
Plugin *plugin = i.second;
454455
if (plugin->eventFunc == nullptr)
455456
continue;
456-
plugin->eventFunc(out, elf, Is, size, event, plugin->context);
457+
plugin->eventFunc(out, event, &cxt, plugin->context);
457458
}
458459
}
459460

@@ -463,13 +464,13 @@ static void notifyPlugins(FILE *out, const ELF *elf, const Instr *Is,
463464
static void matchPlugins(FILE *out, const ELF *elf, const Instr *Is,
464465
size_t size, size_t idx, const InstrInfo *I)
465466
{
467+
Context cxt = {elf, Is, size, (ssize_t)idx, I, -1};
466468
for (auto i: plugins)
467469
{
468470
Plugin *plugin = i.second;
469471
if (plugin->matchFunc == nullptr)
470472
continue;
471-
plugin->result = plugin->matchFunc(out, elf, Is, size, idx,
472-
I, plugin->context);
473+
plugin->result = plugin->matchFunc(out, &cxt, plugin->context);
473474
}
474475
}
475476

@@ -2151,18 +2152,33 @@ struct Metadata
21512152
* Send a trampoline.
21522153
*/
21532154
static bool sendTrampoline(FILE *out, const Action *action, size_t idx,
2154-
std::vector<Metadata> &metadata)
2155+
const Context *cxt, std::vector<Metadata> &metadata)
21552156
{
21562157
const Patch *patch = action->patch[idx];
2157-
sendString(out, patch->name);
2158-
sendSeparator(out);
21592158

2160-
if (patch->kind == PATCH_BREAK)
2161-
return true;
2159+
const Plugin *plugin = nullptr;
2160+
if (patch->kind == PATCH_PLUGIN)
2161+
{
2162+
plugin = patch->plugin;
2163+
if (plugin->patchFunc != nullptr)
2164+
plugin->patchFunc(out, PHASE_CODE, cxt, plugin->context);
2165+
}
2166+
else
2167+
{
2168+
sendString(out, patch->name);
2169+
sendSeparator(out);
2170+
if (patch->kind == PATCH_BREAK)
2171+
return true;
2172+
}
21622173

21632174
bool found = false;
21642175
switch (patch->kind)
21652176
{
2177+
case PATCH_PLUGIN:
2178+
plugin = patch->plugin;
2179+
if (plugin->patchFunc == nullptr)
2180+
break;
2181+
// Fallthrough
21662182
case PATCH_PRINT: case PATCH_CALL:
21672183
for (const auto &entry: metadata)
21682184
{
@@ -3074,11 +3090,12 @@ int main(int argc, char **argv)
30743090
done = !sendInstructionMessage(out, Is[j], Is[i].address);
30753091

30763092
// Send the "patch" message.
3093+
id++;
3094+
Context cxt = {&elf, Is.data(), count, i, &I, id};
30773095
sendMessageHeader(out, "patch");
30783096
sendParamHeader(out, "trampoline");
30793097
fputs("[\".Ltrampoline\",", out);
30803098
const Matching *M = Ms.matchings[Is[i].matching];
3081-
id++;
30823099

30833100
// BEFORE trampolines:
30843101
metadata.clear();
@@ -3089,7 +3106,7 @@ int main(int argc, char **argv)
30893106
{
30903107
if (action->patch[j]->pos != POS_BEFORE || seen_break)
30913108
continue;
3092-
seen_break = sendTrampoline(out, action, j, metadata);
3109+
seen_break = sendTrampoline(out, action, j, &cxt, metadata);
30933110
}
30943111
}
30953112

@@ -3106,7 +3123,7 @@ int main(int argc, char **argv)
31063123
"instruction \"%s\" at address 0x%lx", I.string.instr,
31073124
I.address);
31083125
seen_replace = true;
3109-
seen_break = sendTrampoline(out, action, j, metadata);
3126+
seen_break = sendTrampoline(out, action, j, &cxt, metadata);
31103127
}
31113128
}
31123129
if (!seen_replace && !seen_break)
@@ -3119,7 +3136,7 @@ int main(int argc, char **argv)
31193136
{
31203137
if (action->patch[j]->pos != POS_AFTER || seen_break)
31213138
continue;
3122-
seen_break = sendTrampoline(out, action, j, metadata);
3139+
seen_break = sendTrampoline(out, action, j, &cxt, metadata);
31233140
}
31243141
}
31253142
if (!seen_break)
@@ -3129,7 +3146,13 @@ int main(int argc, char **argv)
31293146
for (const auto &entry: metadata)
31303147
{
31313148
const Patch *patch = entry.action->patch[entry.idx];
3132-
fprintf(out, "\"$DATA@%s\",", patch->name+1);
3149+
if (patch->kind == PATCH_PLUGIN)
3150+
{
3151+
const Plugin *plugin = patch->plugin;
3152+
plugin->patchFunc(out, PHASE_DATA, &cxt, plugin->context);
3153+
}
3154+
else
3155+
fprintf(out, "\"$DATA@%s\",", patch->name+1);
31333156
}
31343157
fputc(']', out);
31353158
sendSeparator(out);
@@ -3139,10 +3162,7 @@ int main(int argc, char **argv)
31393162
sendParamHeader(out, "metadata");
31403163
sendMetadataHeader(out);
31413164
for (const auto &entry: metadata)
3142-
{
3143-
if (sendMetadata(out, &elf, entry.action, entry.idx, &I, id))
3144-
sendSeparator(out);
3145-
}
3165+
sendMetadata(out, &elf, entry.action, entry.idx, &I, id, &cxt);
31463166
sendMetadataFooter(out);
31473167
sendSeparator(out);
31483168
}

0 commit comments

Comments
 (0)