Плагин GCC: можно ли переместить последовательность базового блока одной функции в базовый блок другой функции?
Я пытаюсь создать плагин для gcc, который позволяет вам инструментировать пролог и эпилог функции.
Код инструментария вставлен в две функции "instrument_entry" и "instrument_exit". Эти две функции записаны в файле с именем Instrumentation.h, который включен в исходный код программного обеспечения, которое я хочу инструментировать. в двух словах, это очень похоже на
-finstrument-function
из gcc
В отличие от опции, предоставляемой gcc, через плагин я хотел бы взять код, присутствующий в функции "instrument_entry" (я проверил, и эта функция содержит только один базовый блок), и вставить его во все другие прологи функций, присутствующих в программного обеспечения.
Я подумал взять последовательность, присутствующую в базовом блоке функции "instrument_entry", и вставить ее в первый базовый блок функции, которую нужно инструментировать.
Это код:
static basic_block bb_entry_instr;
static unsigned int instrument_functions(function *fun){
std::string func_name = function_name(fun);
if(func_name == "instrument_entry"){
basic_block bb;
bb = ENTRY_BLOCK_PTR_FOR_FN(fun);
bb = bb->next_bb;
bb_entry_instr = bb;
std::cout << "Instrumentation code found! " << std::endl;
}
if(func_name != "instrument_entry" && func_name != "instrument_exit"){
basic_block bb;
bb = ENTRY_BLOCK_PTR_FOR_FN(fun);
bb = bb->next_bb;
gimple_stmt_iterator gsi = gsi_start_bb(bb);
gsi_insert_seq_before(&gsi, bb_seq(bb_entry_instr), GSI_NEW_STMT);
}
} // end of instrument_functions()
bb_entry_instr
- базовый блок функции "instrument_entry"
Передача, которую я создал для gcc, вызывается после передачи "cfg":
namespace {
const pass_data instrumentation_pass_data = {
GIMPLE_PASS,
"instr_pass2", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_gimple_any, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
0 /* todo_flags_finish */
};
struct instrumentation_pass : gimple_opt_pass {
instrumentation_pass(gcc::context *ctx) : gimple_opt_pass(instrumentation_pass_data, ctx){}
unsigned int execute(function *fun) {
return instrument_functions(fun);
}
};
}
int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version){
... // plugin_default_version_check
struct register_pass_info instr_pass_info;
instr_pass_info.pass = new instrumentation_pass(g);
instr_pass_info.reference_pass_name = "cfg";
instr_pass_info.ref_pass_instance_number = 1;
instr_pass_info.pos_op = PASS_POS_INSERT_AFTER;
}
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &instr_pass_info);
Когда я пытаюсь скомпилировать тестовую программу с плагином, я получаю такую ошибку:
during RTL pass: expand
test_01.c: In function ‘instrument_entry’:
test_01.c:13:9: internal compiler error: in get_rtx_for_ssa_name, at tree-outof-ssa.h:62
13 | fgets(name, 0xff, stdin);
| ^~~~~~~~~~~~~~~~~~~~~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-9/README.Bugs> for instructions.
make: *** [Makefile:14: test] Error 1
Кто-нибудь может мне помочь?