构建gcc插件的问题

构建gcc插件的问题,gcc,build,gcc-plugins,Gcc,Build,Gcc Plugins,我正在尝试构建简单的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 fu

我正在尝试构建简单的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
我不知道怎么了。我执行了我找到的所有手册中描述的相同步骤

我有Ubuntu 12.04和gcc-4.6.3编译器

我安装了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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义为α(c)((c)>64&&(c)96&(c)0)
str=树操作数(str,0);
如果(树代码(str)!=字符串&&
树\操作数\长度(str)>0)
str=树操作数(str,0);
如果(树代码(str)!=字符串(CST)
返回空树;
其他的
返回str;
*/
}
静态AspellSpeller*初始拼写检查器(无效)
{
/*
AspellConfig*cfg;
AspellCanHaveError*err;
//配置并实例化拼写检查器
cfg=new_aspell_config();
aspell_配置_替换(cfg,“lang”,“en_US”);
err=新的拼写器(cfg);
如果(aspell\u错误\u编号(err)!=0)
{
puts(aspell_error_message(err));
返回NULL;
}
返回到拼写器(err);
*/
}
静态无效拼写检查(const\u gimple stmt、const\u tree str)
{
/*
char buf[32]={0};
常量字符*数据,*结束;
数据=树\字符串\指针(str);
printf(“拼写检查字符串:\'%s\'\n”,数据);
while(*数据)
{
//跳过非字母,包括空格
而(!是_α(数据[0]))
{
如果(数据[0]='\0')
返回;
++数据;
}
//找到单词的结尾
结束=数据;
while(是_α(end[0]))
++结束;
如果((结束-数据)>sizeof(buf))
返回;
memcpy(基本单位、数据、最终数据);
buf[结束数据]='\0';
如果(!(拼写器检查(拼写器、buf、结束-数据)))
警告位于(gimple_位置(stmt),0,“%s(拼写错误)”,buf;
数据=结束;
}
*/
}
静态无符号拼写器_exec(void)
{
/*
未签名的i;
const_tree街,op;
基本块bb;
gimple-stmt;
gimple_stmt_迭代器gsi;
对于每个__BB(BB)
对于(gsi=gsi_开始_bb(bb);!gsi_结束_p(gsi);gsi_下一个(&gsi))
{
stmt=gsi_stmt(gsi);
对于(i=0;ibasever、speller\u ver.basever、strlen(“4.6”))
返回-1;/*gcc的版本不正确*/
pass.pass=&speller\u pass.pass;
pass.reference_pass_name=“ssa”;
pass.ref\u pass\u instance\u number=1;
pass.pos\u op=pass\u pos\u INSERT\u AFTER;
/*告诉gcc我们希望在第一次SSA通过后被呼叫*/
注册回调(“拼写器”、“插件传递”、“管理器设置”、“NULL”和“传递”);
注册回调(“拼写器”、插件信息、空值和拼写器信息);
/*初始化我们的拼写检查器*/
如果(!(拼写器=init\u拼写检查器())
返回-1;
返回0;
}
注释的源代码也包含链接器未定义的函数调用。据我所知,问题与
register\u回调
函数相同

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

尝试将
生成文件的最后第二行更改为:

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

请注意“-c”这是一个在线示例,如果没有错误的话。在编译插件时,如果gcc提示某些库未找到,而不是在编译插件时使用
-I
逐个指定每个库,我们可以使用
生成文件吗<你可以考虑使用一个高级别的特定领域的语言来扩展GCC吗?这对你来说可能更简单……我考虑了这样的可能性。但是它不符合我的要求。据了解,熔体有一种特殊的语言与GCC内部交互。我更喜欢使用众所周知的语言C。/C++,因为我不知道MELT语言的成熟度和稳定性。另外,添加一些库来扩展插件功能时可能会有困难。至少在最后一点上(添加一些库)您的MELT扩展可以很容易地使用任何
pkg config
urable库-melt@googlegroups.com详细信息。出于好奇,您的GCC插件在做什么?这是我的第一个测试插件。:)在我修改并构建它之后,它搜索文件中的常量字符串。我想研究GCC插件的概念是如何工作的。可能是,它将在将来使用。