我正在尝试构建简单的 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 插件编写的优秀、详细、不过时的手册也将非常有用。任何帮助将不胜感激。