3

I'm trying to create a plugin for gcc that allows you to instrument the prologue and the epilogue of a function.
The instrumentation code is inserted in two functions "instrument_entry" and "instrument_exit". These two functions are written in a file called instrumentation.h, which is included in the source code of the software I want to instrument. in a nutshell, it's very similar to the -finstrument-function of gcc

Unlike the option provided by gcc, through the plugin, I would like to take the code present in the function "instrument_entry" (I checked and this function contains only one basic block) and insert it in all other prologues of the functions present in the software.

I thought to take the sequence present in the basic block of the function "instrument_entry" and insert it in the first basic block of the function to be instrumented.

This is the code:

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 is the basic block of the "instrument_entry" function

The pass I created for gcc is called after the "cfg" pass:

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);

When I try to compile a test program with the plugin, I get this error:

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

Can somebody help me?

Mark
  • 51
  • 6
  • Good and hard question!. I'm trying to do the same thing, however, as an rtl pass. In my work, I tried to insert a call rtx_insn to the functions defined in shard files (that will be linked dynamically). If you try to copy the instructions to all the other functions, a huge overhead will you get! ... why you just try to insert a call function instruction instead of copying all instruction to each basic block?! – husin alhaj ahmade Dec 23 '20 at 16:35

0 Answers0