2013-06-06 33 views
1

我正在嘗試構建簡單的gcc插件。我是一個新手,但我想在未來實現更復雜的插件。 我閱讀了很多手冊,看起來我做的都對,但有些不對。 我無法構建它。每當我嘗試構建我的插件時,出現錯誤:構建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的插件,這個插件是我自己仔細下載和構建的。但結果是一樣的。

我的Makefile:

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 [email protected] $^ 

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插件寫作的好的,詳細的,不過時的手冊也是非常有用的。 任何幫助將不勝感激。

+1

您是否考慮使用[MELT](http://gcc-melt.org/)高級域特定語言來擴展GCC?它可能會更簡單... –

+1

我認爲這種可能性。但它不符合我的要求。據瞭解,MELT有一種特殊的語言來與GCC內部進行交互。我更喜歡使用衆所周知的語言C/C++,因爲我對MELT語言的成熟度和穩定性有所瞭解。另外,添加一些庫來擴展插件功能可能會有困難。 –

+0

至少在最後一點(添加一些庫),您的MELT擴展可以很容易地使用任何'pkg-config'urable庫。有關詳細信息,請諮詢[email protected]。 –

回答

2

試着改變Makefile到的最後第二條:

%.o :   %.c 
    gcc $(DEFINES) $(INCLUDES) -fPIC -o [email protected] -c $^ 

注意「-c」我已經添加它告訴它來編譯,但在此階段不鏈接。

+0

非常感謝!有用! :) –

0

這正是在網上找到的例子,如果沒有錯誤的話。編譯插件時,如果gcc提示找不到某些庫,而不是在編譯插件時使用-I來逐一指定每個庫,那麼我們可以使用Makefile來指定所有這些目錄嗎?謝謝