diff -upr .pc/symdb_enhance_plugin/gcc/c-family/c-common.h gcc/c-family/c-common.h
--- .pc/symdb_enhance_plugin/gcc/c-family/c-common.h	2011-12-21 04:44:13.000000000 +0800
+++ gcc/c-family/c-common.h	2012-05-25 14:56:56.776263281 +0800
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  
 #include "splay-tree.h"
 #include "cpplib.h"
 #include "ggc.h"
+#include "c-pragma.h"
 
 /* In order for the format checking to accept the C frontend
    diagnostic framework extensions, you must include this file before
@@ -1116,4 +1117,43 @@ struct GTY(()) tree_userdef_literal {
 
 extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
 
+/* The following local token type is used.  */
+
+/* A keyword.  */
+#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
+
+/* More information about the type of a CPP_NAME token.  */
+typedef enum c_id_kind {
+  /* An ordinary identifier.  */
+  C_ID_ID,
+  /* An identifier declared as a typedef name.  */
+  C_ID_TYPENAME,
+  /* An identifier declared as an Objective-C class name.  */
+  C_ID_CLASSNAME,
+  /* An address space identifier.  */
+  C_ID_ADDRSPACE,
+  /* Not an identifier.  */
+  C_ID_NONE
+} c_id_kind;
+
+/* A single C token after string literal concatenation and conversion
+   of preprocessing tokens to tokens.  */
+typedef struct GTY (()) c_token {
+  /* The kind of token.  */
+  ENUM_BITFIELD (cpp_ttype) type : 8;
+  /* If this token is a CPP_NAME, this value indicates whether also
+     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
+  ENUM_BITFIELD (c_id_kind) id_kind : 8;
+  /* If this token is a keyword, this value indicates which keyword.
+     Otherwise, this value is RID_MAX.  */
+  ENUM_BITFIELD (rid) keyword : 8;
+  /* If this token is a CPP_PRAGMA, this indicates the pragma that
+     was seen.  Otherwise it is PRAGMA_NONE.  */
+  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
+  /* The value associated with this token, if any.  */
+  tree value;
+  /* The location at which this token was found.  */
+  location_t location;
+} c_token;
+
 #endif /* ! GCC_C_COMMON_H */
diff -upr .pc/symdb_enhance_plugin/gcc/c-family/c-lex.c gcc/c-family/c-lex.c
--- .pc/symdb_enhance_plugin/gcc/c-family/c-lex.c	2011-10-27 03:31:16.000000000 +0800
+++ gcc/c-family/c-lex.c	2012-05-25 14:56:56.767134882 +0800
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  
 #include "splay-tree.h"
 #include "debug.h"
 #include "target.h"
+#include "plugin.h"
 
 /* We may keep statistics about how long which files took to compile.  */
 static int header_time, body_time;
@@ -380,6 +381,7 @@ c_lex_with_flags (tree *value, location_
 	    case CPP_STRING32:
 	    case CPP_UTF8STRING:
 	      type = lex_string (tok, value, true, true);
+		  tok = NULL;
 	      break;
 
 	    case CPP_NAME:
@@ -481,6 +483,7 @@ c_lex_with_flags (tree *value, location_
 	{
 	  type = lex_string (tok, value, false,
 			     (lex_flags & C_LEX_STRING_NO_TRANSLATE) == 0);
+	  tok = NULL;
 	  break;
 	}
       *value = build_string (tok->val.str.len, (const char *) tok->val.str.text);
@@ -515,6 +518,7 @@ c_lex_with_flags (tree *value, location_
     }
 
   timevar_pop (TV_CPP);
+  invoke_plugin_callbacks (PLUGIN_CPP_TOKEN, (cpp_token*) tok);
 
   return type;
 }
diff -upr .pc/symdb_enhance_plugin/gcc/c-parser.c gcc/c-parser.c
--- .pc/symdb_enhance_plugin/gcc/c-parser.c	2011-12-21 04:44:13.000000000 +0800
+++ gcc/c-parser.c	2012-05-25 14:56:56.772261126 +0800
@@ -121,45 +121,6 @@ c_parse_init (void)
    C++).  It would then be possible to share more of the C and C++
    lexer code, if desired.  */
 
-/* The following local token type is used.  */
-
-/* A keyword.  */
-#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
-
-/* More information about the type of a CPP_NAME token.  */
-typedef enum c_id_kind {
-  /* An ordinary identifier.  */
-  C_ID_ID,
-  /* An identifier declared as a typedef name.  */
-  C_ID_TYPENAME,
-  /* An identifier declared as an Objective-C class name.  */
-  C_ID_CLASSNAME,
-  /* An address space identifier.  */
-  C_ID_ADDRSPACE,
-  /* Not an identifier.  */
-  C_ID_NONE
-} c_id_kind;
-
-/* A single C token after string literal concatenation and conversion
-   of preprocessing tokens to tokens.  */
-typedef struct GTY (()) c_token {
-  /* The kind of token.  */
-  ENUM_BITFIELD (cpp_ttype) type : 8;
-  /* If this token is a CPP_NAME, this value indicates whether also
-     declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
-  ENUM_BITFIELD (c_id_kind) id_kind : 8;
-  /* If this token is a keyword, this value indicates which keyword.
-     Otherwise, this value is RID_MAX.  */
-  ENUM_BITFIELD (rid) keyword : 8;
-  /* If this token is a CPP_PRAGMA, this indicates the pragma that
-     was seen.  Otherwise it is PRAGMA_NONE.  */
-  ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
-  /* The location at which this token was found.  */
-  location_t location;
-  /* The value associated with this token, if any.  */
-  tree value;
-} c_token;
-
 /* A parser structure recording information about the state and
    context of parsing.  Includes lexer information with up to two
    tokens of look-ahead; more are not needed for C.  */
@@ -388,6 +349,7 @@ c_lex_one_token (c_parser *parser, c_tok
       break;
     }
   timevar_pop (TV_LEX);
+  invoke_plugin_callbacks (PLUGIN_C_TOKEN, token);
 }
 
 /* Return a pointer to the next token from PARSER, reading it in if
@@ -1360,6 +1322,7 @@ c_parser_external_declaration (c_parser 
 	 an @interface or @protocol with prefix attributes).  We can
 	 only tell which after parsing the declaration specifiers, if
 	 any, and the first declarator.  */
+      invoke_plugin_callbacks (PLUGIN_EXTERN_DECL, NULL);
       c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL);
       break;
     }
@@ -1488,6 +1451,11 @@ c_parser_declaration_or_fndef (c_parser 
       return;
     }
   finish_declspecs (specs);
+  {
+    void* pair[2]; pair[0] = specs; pair[1] = (void*) parser->tokens_avail;
+    if (!nested)
+      invoke_plugin_callbacks (PLUGIN_EXTERN_DECLSPECS, pair);
+  }
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       if (empty_ok)
@@ -1622,6 +1590,11 @@ c_parser_declaration_or_fndef (c_parser 
 	{
 	  tree asm_name = NULL_TREE;
 	  tree postfix_attrs = NULL_TREE;
+	  {
+	    void* pair[2]; pair[0] = specs; pair[1] = declarator;
+        if (!nested)
+          invoke_plugin_callbacks (PLUGIN_EXTERN_VAR, pair);
+	  }
 	  if (!diagnosed_no_specs && !specs->declspecs_seen_p)
 	    {
 	      diagnosed_no_specs = true;
@@ -1748,11 +1721,15 @@ c_parser_declaration_or_fndef (c_parser 
 	 declarator with a nonempty identifier list in a definition;
 	 and postfix attributes have never been accepted here in
 	 function definitions either.  */
+      if (!nested)
+        invoke_plugin_callbacks (PLUGIN_EXTERN_FUNC_OLD_PARAM, NULL);
       while (c_parser_next_token_is_not (parser, CPP_EOF)
 	     && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
 	c_parser_declaration_or_fndef (parser, false, false, false,
 				       true, false, NULL);
       store_parm_decls ();
+      if (!nested)
+        invoke_plugin_callbacks (PLUGIN_EXTERN_FUNC, declarator);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
 	= c_parser_peek_token (parser)->location;
       fnbody = c_parser_compound_statement (parser);
@@ -2266,6 +2243,7 @@ c_parser_enum_specifier (c_parser *parse
 	    }
 	  token = c_parser_peek_token (parser);
 	  enum_id = token->value;
+      invoke_plugin_callbacks (PLUGIN_ENUM_SPECIFIER, enum_id);
 	  /* Set the location in case we create a decl now.  */
 	  c_parser_set_source_position_from_token (token);
 	  decl_loc = value_loc = token->location;
@@ -6865,6 +6843,7 @@ c_parser_postfix_expression_after_primar
 	  break;
 	case CPP_OPEN_PAREN:
 	  /* Function call.  */
+      invoke_plugin_callbacks (PLUGIN_CALL_FUNCTION, expr.value);
 	  c_parser_consume_token (parser);
 	  if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
 	    exprlist = NULL;
diff -upr .pc/symdb_enhance_plugin/gcc/doc/plugins.texi gcc/doc/plugins.texi
--- .pc/symdb_enhance_plugin/gcc/doc/plugins.texi	2011-08-11 23:57:38.000000000 +0800
+++ gcc/doc/plugins.texi	2012-05-25 14:56:56.775216761 +0800
@@ -184,6 +184,23 @@ enum plugin_event
   PLUGIN_EARLY_GIMPLE_PASSES_END,
   /* Called when a pass is first instantiated.  */
   PLUGIN_NEW_PASS,
+  PLUGIN_CPP_TOKEN,                /* Called when GCC gets a cpp token. */
+  PLUGIN_C_TOKEN,                  /* Called when GCC gets a c token. */
+  /* An extern declaration (file-scope) is encounted. */
+  PLUGIN_EXTERN_DECL,
+  /* Cooperate PLUGIN_EXTERN_FUNC to parse a function with old-style parameter
+   * declaration. */
+  PLUGIN_EXTERN_FUNC_OLD_PARAM,
+  /* An extern function definition is parsed. */
+  PLUGIN_EXTERN_FUNC,
+  /* An extern variable definition is parsed. */
+  PLUGIN_EXTERN_VAR,
+  /* An extern declaration specifier definition is parsed. */
+  PLUGIN_EXTERN_DECLSPECS,
+  /* A function is called. */
+  PLUGIN_CALL_FUNCTION,
+  /* An enum specifier is parsed. */
+  PLUGIN_ENUM_SPECIFIER,
 
   PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
diff -upr .pc/symdb_enhance_plugin/gcc/plugin.c gcc/plugin.c
--- .pc/symdb_enhance_plugin/gcc/plugin.c	2011-10-19 21:20:22.000000000 +0800
+++ gcc/plugin.c	2012-05-25 14:56:56.774266369 +0800
@@ -439,6 +439,15 @@ register_callback (const char *plugin_na
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_CPP_TOKEN:
+      case PLUGIN_C_TOKEN:
+      case PLUGIN_EXTERN_DECL:
+      case PLUGIN_EXTERN_FUNC_OLD_PARAM:
+      case PLUGIN_EXTERN_FUNC:
+      case PLUGIN_EXTERN_VAR:
+      case PLUGIN_EXTERN_DECLSPECS:
+      case PLUGIN_CALL_FUNCTION:
+      case PLUGIN_ENUM_SPECIFIER:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -516,6 +525,15 @@ invoke_plugin_callbacks_full (int event,
       case PLUGIN_EARLY_GIMPLE_PASSES_START:
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
+      case PLUGIN_CPP_TOKEN:
+      case PLUGIN_C_TOKEN:
+      case PLUGIN_EXTERN_DECL:
+      case PLUGIN_EXTERN_FUNC_OLD_PARAM:
+      case PLUGIN_EXTERN_FUNC:
+      case PLUGIN_EXTERN_VAR:
+      case PLUGIN_EXTERN_DECLSPECS:
+      case PLUGIN_CALL_FUNCTION:
+      case PLUGIN_ENUM_SPECIFIER:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
diff -upr .pc/symdb_enhance_plugin/gcc/plugin.def gcc/plugin.def
--- .pc/symdb_enhance_plugin/gcc/plugin.def	2011-08-11 23:57:38.000000000 +0800
+++ gcc/plugin.def	2012-05-25 14:56:56.766145511 +0800
@@ -92,6 +92,34 @@ DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END
 /* Called when a pass is first instantiated.  */
 DEFEVENT (PLUGIN_NEW_PASS)
 
+/* Called when a cpp token is extracted.  */
+DEFEVENT (PLUGIN_CPP_TOKEN)
+
+/* Called when a c token is extracted.  */
+DEFEVENT (PLUGIN_C_TOKEN)
+
+/* An extern declaration (file-scope) is encounted. */
+DEFEVENT (PLUGIN_EXTERN_DECL)
+
+/* Cooperate PLUGIN_EXTERN_FUNC to parse a function with old-style parameter
+ * declaration. */
+DEFEVENT (PLUGIN_EXTERN_FUNC_OLD_PARAM)
+
+/* Called when an extern function definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_FUNC)
+
+/* Called when an extern variable definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_VAR)
+
+/* An extern declaration specifier definition is parsed. */
+DEFEVENT (PLUGIN_EXTERN_DECLSPECS)
+
+/* A function is called. */
+DEFEVENT (PLUGIN_CALL_FUNCTION)
+
+/* Called when an enum specifier is parsed. */
+DEFEVENT (PLUGIN_ENUM_SPECIFIER)
+
 /* After the hard-coded events above, plugins can dynamically allocate events
    at run time.
    PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element.  */
