1

我正在尝试构建简单的 gcc 插件。我是新手,但我想在未来实现更复杂的插件。我阅读了很多手册,似乎我做的一切都是正确的,但有些地方是错误的。我无法建造它。每次我尝试构建我的插件时,我都会收到一个错误:

/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/ccjmG33v.o: In function `plugin_init':
plugin.c:(.text+0x9e): undefined reference to `register_callback'
plugin.c:(.text+0xc6): undefined reference to `register_callback'
collect2: ld returned 1 exit status
make: *** [plugin.o] Error 1

我不知道出了什么问题。我执行了与我找到的所有手册中描述的相同的步骤。

我有带有 gcc-4.6.3 编译器的 Ubuntu 12.04。

我安装了 gcc-4.6-plugin-dev。

我什至尝试构建基于 gcc_4.6.4 的插件,该插件是我自己仔细下载和构建的。但结果是一样的。

我的制作文件:

PLUGINS_DIR =    /usr/lib/gcc/i686-linux-gnu/4.6/plugin/include

INCLUDES = \
    -I$(PLUGINS_DIR)

DEFINES =        -Dbool=int -DTRUE=1 -DFALSE=0

plugin.so :      plugin.o
    gcc -shared -Wl,-export-dynamic -o plugin.so plugin.o

%.o :            %.c
    gcc $(DEFINES) $(INCLUDES) -fPIC -o $@ $^ 

clean :
    rm *.o *.so

插件源代码:

#include <aspell.h>
#include <gcc-plugin.h>
#include <coretypes.h>
#include <diagnostic.h>
#include <gimple.h>
#include <tree.h>
#include <tree-flow.h>
#include <tree-pass.h>




#define is_alpha(c) (((c)>64 && (c)<91) || ((c)>96 && (c)<123))


int plugin_is_GPL_compatible = 1;
static AspellSpeller *speller_g;


/* Help info about the plugin if one were to use gcc's --version --help */
static struct plugin_info speller_info =
{
    .version = "42",
    .help = "Hahahaha yeaaaaa....",
};


static struct plugin_gcc_version speller_ver =
{
    .basever = "4.6",
};


/* We don't need to run any tests before we execute our plugin pass */
static bool speller_gate(void)
{
    return true;
}


static const_tree is_str_cst(const_tree node)
{
/*
    const_tree str = node;

    // Filter out types we are ignoring 
    if (TREE_CODE(str) == VAR_DECL)
    {
        if (!(str = DECL_INITIAL(node)))
          return NULL_TREE;
        else if (TREE_OPERAND_LENGTH(str))
          str = TREE_OPERAND(str, 0);
    }
    else if (TREE_CODE(str) == ADDR_EXPR &&
             TREE_OPERAND_LENGTH(str) > 0)
      str = TREE_OPERAND(str, 0);

    if (TREE_CODE(str) != STRING_CST &&
        TREE_OPERAND_LENGTH(str) > 0)
      str = TREE_OPERAND(str, 0);

    if (TREE_CODE(str) != STRING_CST)
      return NULL_TREE;
    else
      return str;
*/
}


static AspellSpeller *init_spellchecker(void)
{
/*
    AspellConfig *cfg;
    AspellCanHaveError *err;

    // Configure and instantiate a spell checker 
    cfg = new_aspell_config();
    aspell_config_replace(cfg, "lang", "en_US");
    err = new_aspell_speller(cfg);
    if (aspell_error_number(err) != 0)
    {
        puts(aspell_error_message(err));
        return NULL;
    }

    return to_aspell_speller(err);
*/
}


static void spell_check(const_gimple stmt, const_tree str)
{
/*
    char buf[32] = {0};
    const char *data, *end;

    data = TREE_STRING_POINTER(str);
    printf("Spell checking string: \'%s\'\n", data);

    while (*data)
    {
        // Skip non alphas including whitespace 
        while (!is_alpha(data[0]))
        {
            if (data[0] == '\0')
              return;
            ++data;
        }

        // Find the end of the word 
        end = data;
        while (is_alpha(end[0]))
          ++end;

        if ((end - data) > sizeof(buf))
          return;

        memcpy(buf, data, end - data);
        buf[end-data] = '\0';
        if (!(aspell_speller_check(speller_g, buf, end - data)))
          warning_at(gimple_location(stmt), 0, "%s (bad spelling)", buf);
        data = end;
    }
*/
}


static unsigned speller_exec(void)
{
/*
    unsigned i;
    const_tree str, op;
    basic_block bb;
    gimple stmt;
    gimple_stmt_iterator gsi;

    FOR_EACH_BB(bb)
      for (gsi=gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
      {
          stmt = gsi_stmt(gsi);
          for (i=0; i<gimple_num_ops(stmt); ++i)
            if ((op = gimple_op(stmt, i)) && (str = is_str_cst(op)))
              spell_check(stmt, str);
      }

    return 0;
*/
}


/* See tree-pass.h for a list and desctiptions for the fields of this struct */
static struct gimple_opt_pass speller_pass = 
{
    .pass.type = GIMPLE_PASS,
    .pass.name = "speller",       /* For use in the dump file */
    .pass.gate = speller_gate,
    .pass.execute = speller_exec, /* Pass handler/callback */
};


/* Return 0 on success or error code on failure */
int plugin_init(struct plugin_name_args   *info,  /* Argument infor */
                struct plugin_gcc_version *ver)   /* Version of GCC */
{
    struct register_pass_info pass;

     if (strncmp(ver->basever, speller_ver.basever, strlen("4.6")))
       return -1; /* Incorrect version of gcc */

    pass.pass = &speller_pass.pass;
    pass.reference_pass_name = "ssa";
    pass.ref_pass_instance_number = 1;
    pass.pos_op = PASS_POS_INSERT_AFTER;

    /* Tell gcc we want to be called after the first SSA pass */
    register_callback("speller", PLUGIN_PASS_MANAGER_SETUP, NULL, &pass);
    register_callback("speller", PLUGIN_INFO, NULL, &speller_info);

    /* Initilize our spell checker */
    if (!(speller_g = init_spellchecker()))
      return -1;

    return 0;
}

注释的源代码也包含链接器未定义的函数调用。据我了解,问题与register_callback功能相同。

有人可以帮我解决这个问题吗?关于 gcc 插件编写的优秀、详细、不过时的手册也将非常有用。任何帮助将不胜感激。

4

2 回答 2

2

尝试将倒数第二行更改Makefile为:

%.o :            %.c
    gcc $(DEFINES) $(INCLUDES) -fPIC -o $@ -c $^

请注意我添加的“ -c ”告诉它编译,但在此阶段不链接。

于 2013-06-06T09:28:34.903 回答
0

如果没有记错的话,这正是在网上找到的一个例子。在编译插件的时候,如果gcc提示有些库没有找到,而不是-I在编译插件的时候用a来一一指定每个库,我们可以用aMakefile来指定所有这些目录吗?谢谢

于 2015-07-24T04:41:12.210 回答