Advertisement
goroh_kun

defineをIDAのenumにするスクリプトH2enum.idc

Jan 28th, 2012
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.74 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////////////
  2. //      This file create IDA Enums  by parsing C/C++ .H include file
  3. //
  4. // Version: 1.09
  5. //
  6. // History of changes:
  7. //
  8. // v1.00  28.09.1998  Started by Leonid Lisovsky  <lly@aha.ru>.
  9. // v1.01  02.12.1998  Bugfix & corrections to get more universality.
  10. // v1.02  04.12.1998  First step to resolve expressions.
  11. // v1.03  04.08.1999  More smart error messages,
  12. //                    second approach to resolve arithmetic expressions.
  13. // v1.04  08.08.1999  Arithmetic evaluator ready to use.
  14. // v1.05  05.10.1999  Corrections due to changes in IDA 3.85,
  15. //                    the right total counter was made. Constants
  16. //                    will not more be cuted off on the first blank.
  17. // v1.06  28.02.2000  Trailing spaces bugfix. C/C++ typecast workaround.
  18. // v1.07  24.03.2000  Correct 'Esc' handling. One wildcard for filtering
  19. //                    defines allowed now (Syntax: 'Prefix*Suffix').
  20. // v1.09  01.03.2002  Bugfix - FindDelim() wasn't returned FIRST delimiter.
  21. //
  22. // TODO: GetAtom() - Smart constant recognizing.
  23. //////////////////////////////////////////////////////////////////////////////
  24.  
  25. #include <idc.idc>
  26.  
  27. #define DEFINE_TOKEN    "#define"
  28. #define XREF_ARRAY  "h2enum_xrefs"
  29. #define EXPR_ARRAY      "h2enum_expr"
  30.  
  31. //////////////////////////////////////////////////////////////////////////////
  32.  
  33. // returns -1 if symbol is NOT 'space'
  34. static is_space(c)
  35. {
  36.     return strstr(" \t\r\n\b",c);
  37. }
  38.  
  39. // strip leading blank characters from string.
  40. static ltrim(str)
  41. {
  42.     auto pos,c,l;
  43.  
  44.     l = strlen(str);
  45.     pos = 0;
  46.     while (pos < l)
  47.     {
  48.         c = substr(str,pos,pos+1);
  49.         if (is_space(c) == -1) break;
  50.         pos++;
  51.     }
  52.     return substr(str,pos,-1);
  53. }
  54.  
  55. // strip trailing blank characters from string.
  56. static rtrim(str)
  57. {
  58.     auto pos,c;
  59.  
  60.     pos = strlen(str);
  61.     while (pos > 0)
  62.     {
  63.         c = substr(str,pos-1,pos);
  64.         if (is_space(c) == -1) break;
  65.         pos--;
  66.     }
  67.     return substr(str,0,pos);
  68. }
  69.  
  70. static __trim(str)
  71. {
  72.     return rtrim( ltrim(str) );
  73. }
  74.  
  75. // Find first delimiter position in string (SPACE or TAB).
  76. static FindDelim(str)
  77. {
  78.     auto pos1,pos2;
  79.  
  80.     pos1 = strstr(str," ");
  81.     pos2 = strstr(str,"\t");
  82.     if (pos1 == -1)  return pos2;
  83.     if (pos2 == -1)  return pos1;
  84.     if (pos1 < pos2) return pos1;
  85.     else         return pos2;
  86. }
  87.  
  88. // Find C/C++ comment start position in string ( // or /* ).
  89. static FindCcomment(str)
  90. {
  91.     auto pos;
  92.  
  93.     pos = strstr(str,"//");
  94.     if (pos == -1) return strstr(str,"/*");
  95.     else         return pos;
  96. }
  97.  
  98. // Test string for pattern (only ONE wildcard allowed)
  99. static pat1mat(str, pattern_R,pattern_L, wild_pos_R,wild_pos_L)
  100. {
  101.     // Starts with pattern
  102.     if ((wild_pos_L > 0) && (substr(str,0,wild_pos_L) != pattern_L))
  103.         return -1;
  104.     // Ends with pattern
  105.     if ((wild_pos_R > 0) && (substr(str,strlen(str)-wild_pos_R,-1) != pattern_R))
  106.         return -1;
  107.     return 0;
  108. }
  109.  
  110. // Add Constant with custom error messages
  111. static H_AddConst(enum_ID,enum_elem_name,enum_elem_val,str_no)
  112. {
  113.     auto v_idx, dupe_elem_name;
  114.  
  115.     v_idx = AddConst(enum_ID,enum_elem_name,enum_elem_val);
  116.     if (v_idx == CONST_ERROR_NAME)
  117.     {
  118.         Message("*DUPE* (line:%d) %s %0Xh\n",str_no,enum_elem_name,
  119.             enum_elem_val);
  120.     }
  121.     else if (v_idx == CONST_ERROR_VALUE)
  122.     {
  123.         dupe_elem_name=GetConstName(GetConst(enum_ID,enum_elem_val,-1));
  124.         Message("*DUPE VALUE* (line:%d) %s == %s  %0Xh\n",
  125.             str_no,enum_elem_name,dupe_elem_name,enum_elem_val);
  126.     }
  127. }
  128.  
  129. //----------------------------------------------------------------------------
  130. // Arithmetic evaluator functions
  131.  
  132. #define TOK_NONE    -1
  133. #define TOK_VAR     0
  134. #define TOK_PLUS    1
  135. #define TOK_MINUS   2
  136. #define TOK_OR      3
  137. #define TOK_AND     4
  138. #define TOK_XOR     5
  139. #define TOK_MULT    10
  140. #define TOK_DIV     11
  141. #define TOK_MOD     12
  142. #define TOK_NOT     20
  143. #define TOK_L_PAR   30
  144. #define TOK_R_PAR   31
  145.  
  146. // Parse and evaluate arithmetic expression
  147. static ParseExpr(str)
  148. {
  149.     auto expr_ID;
  150.     auto startpos,pos,v_idx;
  151.     auto c,is_token,token1,value;
  152.  
  153.     if ((expr_ID=GetArrayId(EXPR_ARRAY)) == -1)
  154.         if ((expr_ID=CreateArray(EXPR_ARRAY)) == -1)
  155.         {
  156.             Warning("Couldn't create array '%s' for evaluating expressions !",EXPR_ARRAY);
  157.             return;
  158.         }
  159.  
  160.     // Fill array with tokens
  161.     v_idx = 2;
  162.     startpos = 0;
  163.     is_token = 0;
  164.     for(pos=0; pos<strlen(str); pos++)
  165.     {
  166.         c = substr(str,pos,pos+1);
  167.         if ( (is_token==0) && (is_space(c)!=-1) )
  168.         {
  169.             startpos++;
  170.             continue;
  171.         }
  172.         if ((c==" ") || (c=="\t") || (c=="(") || (c==")") ||
  173.             (c=="+") || (c=="-") || (c=="*") || (c=="/") ||
  174.             (c=="|") || (c=="~") || (c=="&") || (c=="^") ||
  175.             (c=="%"))   // token delimiter checking
  176.         {
  177.             token1 = substr(str,startpos,pos);
  178.             if (token1 != "")
  179.             {   // Store variable or constant
  180.                 SetArrayString(expr_ID,v_idx++,token1);
  181.             }
  182.             startpos = pos+1;
  183.             if ((c!=" ") && (c!="\t")) // Store operator
  184.                 SetArrayString(expr_ID,v_idx++,c);
  185.             is_token = 0;
  186.         }
  187.         else is_token = 1;
  188.     }
  189.     if (is_token == 1)  // Store last token, if present
  190.     {
  191.         token1 = substr(str,startpos,-1);
  192.         if (token1 != "")
  193.         {
  194.             SetArrayString(expr_ID,v_idx++,token1);
  195.         }
  196.     }
  197.     SetArrayLong(expr_ID,0,2);  // Special elements: 0 - current token
  198.     SetArrayLong(expr_ID,1,v_idx);  //                   1 - array size
  199.  
  200.     // Evaluating value
  201.     if (v_idx > 2)
  202.         value = eval_1(expr_ID,0);
  203.     else
  204.         value = 0;
  205.     DeleteArray(expr_ID);
  206.     return value;
  207. }
  208.  
  209. // Add, Subtract, OR, AND , XOR
  210. static eval_1(expr_ID, prev_val)
  211. {
  212.     auto value,op;
  213.  
  214.     value = eval_2(expr_ID, prev_val);
  215.     while ( ((op=tok_type(expr_ID))==TOK_PLUS) || (op==TOK_MINUS) ||
  216.         (op==TOK_OR) || (op==TOK_AND) || (op==TOK_XOR) )
  217.     {
  218.         SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  219.  
  220.         if      (op == TOK_PLUS)  value = value + eval_2(expr_ID, value);
  221.         else if (op == TOK_MINUS) value = value - eval_2(expr_ID, value);
  222.         else if (op == TOK_OR)    value = value | eval_2(expr_ID, value);
  223.         else if (op == TOK_AND)   value = value & eval_2(expr_ID, value);
  224.         else if (op == TOK_XOR)   value = value ^ eval_2(expr_ID, value);
  225.     }
  226.     return value;
  227. }
  228.  
  229. // Multiply, Divide, Mod
  230. static eval_2(expr_ID, prev_val)
  231. {
  232.     auto value,op;
  233.  
  234.     value = eval_3(expr_ID, prev_val);
  235.     while ( ((op=tok_type(expr_ID))==TOK_MULT) || (op==TOK_DIV) ||
  236.         (op==TOK_MOD) )
  237.     {
  238.         SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  239.  
  240.         if      (op == TOK_MULT) value = value * eval_3(expr_ID, value);
  241.         else if (op == TOK_DIV)  value = value / eval_3(expr_ID, value);
  242.         else if (op == TOK_MOD)  value = value % eval_3(expr_ID, value);
  243.     }
  244.     return value;
  245. }
  246.  
  247. // Unary -, NOT
  248. static eval_3(expr_ID, prev_val)
  249. {
  250.     auto value,op;
  251.  
  252.     op = tok_type(expr_ID);
  253.     if ( (op==TOK_MINUS) || (op==TOK_NOT) )
  254.     {
  255.         SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  256.  
  257.         if      (op==TOK_MINUS) value = - eval_4(expr_ID, 0);
  258.         else if (op==TOK_NOT)   value = ~ eval_4(expr_ID, 0);
  259.     }
  260.     else    value = eval_4(expr_ID, prev_val);
  261.     return value;
  262. }
  263.  
  264. // Parentheses, constants
  265. static eval_4(expr_ID, prev_val)
  266. {
  267.     auto value,op;
  268.  
  269.     op = tok_type(expr_ID);
  270.     if (op==TOK_L_PAR)
  271.     {
  272.         SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  273.  
  274.         value = eval_1(expr_ID,prev_val);
  275.         if (tok_type(expr_ID) == TOK_R_PAR)
  276.             SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  277.         else
  278.             Message("*** Right parenthess missing!\n");
  279.         // Typecast workaround
  280.         op = tok_type(expr_ID);
  281.         if ( (op==TOK_VAR) || (op==TOK_L_PAR) )
  282.             value = eval_4(expr_ID,0);
  283.     }
  284.     else
  285.     {
  286.         if (op!=TOK_NONE)
  287.         {
  288.             value = GetAtom(GetArrayElement(AR_STR,expr_ID,GetArrayElement(AR_LONG,expr_ID,0)));
  289.  
  290.             SetArrayLong(expr_ID,0,GetArrayElement(AR_LONG,expr_ID,0)+1);
  291.         }
  292.         else value = 0;
  293.     }
  294.     return value;
  295. }
  296.  
  297. // return token type
  298. static tok_type(expr_ID)
  299. {
  300.     auto ind,tok;
  301.  
  302.     ind = GetArrayElement(AR_LONG,expr_ID,0);
  303.     if (ind >= GetArrayElement(AR_LONG,expr_ID,1)) return TOK_NONE; // Out of bounds
  304.     tok = GetArrayElement(AR_STR,expr_ID,ind);
  305.  
  306.     if ( tok == "+" ) return TOK_PLUS;
  307.     if ( tok == "-" ) return TOK_MINUS;
  308.     if ( tok == "|" ) return TOK_OR;
  309.     if ( tok == "&" ) return TOK_AND;
  310.     if ( tok == "^" ) return TOK_XOR;
  311.  
  312.     if ( tok == "*" ) return TOK_MULT;
  313.     if ( tok == "/" ) return TOK_DIV;
  314.     if ( tok == "%" ) return TOK_MOD;
  315.  
  316.     if ( tok == "~" ) return TOK_NOT;
  317.     if ( tok == "(" ) return TOK_L_PAR;
  318.     if ( tok == ")" ) return TOK_R_PAR;
  319.     return TOK_VAR;
  320. }
  321.  
  322. // return value of constant or variable
  323. static GetAtom(token)
  324. {
  325.     auto val;
  326.  
  327.     val = atol(token);      // try Decimal convert
  328.     if (val == 0)
  329.         val = xtol(token);  // try HEX convert
  330.     if (val == 0)
  331.         val = GetConstValue(GetConstByName(token));
  332.     return val;
  333. }
  334.  
  335. //////////////////////////////////////////////////////////////////////////////
  336.  
  337. // Main conversion routine
  338. static h2enum(H_File_Name,enum_name,enum_pattern)
  339. {
  340.         auto enum_ID,xref_ID,v_idx,total;
  341.         auto enum_elem_name,enum_elem_val;
  342.     auto enum_Tok_Pat_R,enum_Tok_Pat_L,enum_Tok_R,enum_Tok_L;
  343.     auto hh,in_str,pos,wrk_str,str_no,c;
  344.  
  345.         if ((hh=fopen(H_File_Name,"r")) == 0)
  346.     {
  347.         Warning("Couldn't open file '%s'!",H_File_Name);
  348.         return -1;
  349.     }
  350.     if (enum_name == "")
  351.             enum_name = AskIdent("WinMsg","Enter name for enumeration (alphas only):");
  352.     if (enum_name == "") return 1;
  353.         if ((enum_ID=GetEnum(enum_name)) == -1) // New enum
  354.                 if ((enum_ID=AddEnum(GetEnumQty() + 1, enum_name, FF_0NUMH)) == -1)
  355.         {
  356.             Warning("Couldn't create enumeration '%s'!",enum_name);
  357.             return -2;
  358.         }
  359.     if (enum_pattern == "")
  360.             enum_pattern = AskStr("WM_","Enter partial name for filtering defines:");
  361.     if (enum_pattern == "") return 1;
  362.         if ((pos=strstr(enum_pattern,'*')) != -1)
  363.     {   // Contain (or superseed) specified token
  364.         enum_Tok_R = strlen(enum_pattern) - pos - 1;
  365.         enum_Tok_L = pos;
  366.         enum_Tok_Pat_R = substr(enum_pattern,pos+1,-1);
  367.                 enum_Tok_Pat_L = substr(enum_pattern,0,pos);
  368.     }
  369.     else    // Starts with specified token by default
  370.     {
  371.         enum_Tok_R = 0;
  372.         enum_Tok_L = strlen(enum_pattern);
  373.         enum_Tok_Pat_R = "";
  374.         enum_Tok_Pat_L = enum_pattern;
  375.     }
  376.     if ((xref_ID=GetArrayId(XREF_ARRAY)) == -1)
  377.         if ((xref_ID=CreateArray(XREF_ARRAY)) == -1)
  378.         {
  379.             Warning("Couldn't create array '%s' for xrefs !",XREF_ARRAY);
  380.             return -3;
  381.         }
  382.     Message("Conversion started...\n");
  383.     total = GetEnumSize(enum_ID);
  384.  
  385. //Pass 1 - import definitions
  386.     str_no = 0;
  387.     while ((in_str=readstr(hh)) != -1)
  388.     {
  389.         str_no++;
  390.         if ((pos=strstr(in_str,DEFINE_TOKEN)) == -1 ) continue; // NO required token on line
  391.         in_str = ltrim(substr(in_str,pos+strlen(DEFINE_TOKEN),-1));
  392.         if ((pos=FindDelim(in_str))==-1) continue; // only 2 tokens i.e. "#define SOME"
  393.         enum_elem_name = rtrim(substr(in_str,0,pos));
  394.                 if (pat1mat(enum_elem_name,enum_Tok_Pat_R,enum_Tok_Pat_L,enum_Tok_R,enum_Tok_L) == 0)
  395.         {
  396.                 in_str = ltrim(substr(in_str,pos,-1));
  397.             pos = FindCcomment(in_str);
  398.             wrk_str = rtrim(substr(in_str,0,pos));
  399.             enum_elem_val = GetAtom(wrk_str);
  400.             if (enum_elem_val == 0)
  401.             { // Possible regular expression - resolving later
  402.                 if (SetHashString(xref_ID,enum_elem_name,wrk_str)==0)
  403.                     Message("*** Cannot Add xref %s = '%s'\n",enum_elem_name,wrk_str);
  404.                 continue;
  405.             }
  406.                 H_AddConst(enum_ID,enum_elem_name,enum_elem_val,str_no);
  407.         }
  408.     }
  409.     fclose(hh);
  410.  
  411. // Pass 2 - resolving regular expressions
  412. //
  413.     for (enum_elem_name=GetFirstHashKey(xref_ID);enum_elem_name!="";
  414.         enum_elem_name=GetNextHashKey(xref_ID,enum_elem_name))
  415.     {
  416.         wrk_str = GetHashString(xref_ID,enum_elem_name);
  417.         enum_elem_val = ParseExpr(wrk_str);
  418.             H_AddConst(enum_ID,enum_elem_name,enum_elem_val,-1);
  419.     }
  420.         DeleteArray(xref_ID);
  421.  
  422.     total = GetEnumSize(enum_ID) - total;
  423.     Message("Successful %d elements imported.\n",total);
  424.     return 0;
  425. }
  426.  
  427. static main()
  428. {
  429.     auto fil_nam;
  430.  
  431.     fil_nam = AskFile(0,"*.h","Choose a header(.H) file to parse:");
  432.     if (fil_nam == "") return;
  433.     h2enum(fil_nam,"","");
  434. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement