簡體   English   中英

GCC預處理程序PLUS靜態分析?

[英]GCC preprocessor PLUS static analysis?

我知道如何運行gcc預處理程序 Gcc顯然會執行代碼的靜態分析/優化,因為如果您添加兩個常量或移位常量,則無論您保持“ a = constant << 3”還是手動執行該操作,生成的匯編代碼都是相同的並在代碼中包含“ a = shifted_constant”。

給定SHA256代碼中的切片,

  A=0x6a09e667;
  B=0xbb67ae85;
  C=0x3c6ef372;
  D=0xa54ff53a;
  E=0x510e527f;
  F=0x9b05688c;
  G=0x1f83d9ab;
  H=0x5be0cd19;

  P(A, B, C, D, E, F, G, H, W[ 0], 0x428a2f98);

運行gcc -EI后

 { tmp = ((((E) >> (6)) | ((E) << (32-(6)))) ^ (((E) >> (11))
       | ((E) << (32-(11)))) ^ (((E) >> (25)) | ((E) << (32-(25)))))
       + (G ^ (E & (F ^ G))) + 0x428a2f98 + W[ 0]; D += (tmp + H);
   H  += tmp + ((((A) >> (2)) | ((A) << (32-(2)))) ^ (((A) >> (13))
       | ((A) << (32-(13)))) ^ (((A) >> (22)) | ((A) << (32-(22)))))
       + ((A & B) | (C & (A | B))); };

對於P線,它是宏的嵌套宏。

很好,但是我想得到一個更摘要的結果,其中替換了常量,執行了常量算術等。因此,如果我得到的不是上述內容,則為:

{ tmp = hex_constant1 + W[0]; D += (tmp + 0x5be0cd19); H += tmp + hex_constant2; };

我更喜歡。 我沒有耐心手動計算表達式,但是基本上它們應該折疊為兩個十六進制常量。

是否有任何工具/命令行選項可以執行此操作?

GCC不會優化預處理的C代碼。 經過預處理后,此代碼會轉換為高級IR(GIMPLE),在大多數情況下都會應用該優化,然后再降低為像RTL這樣的低級IR。

您想要的是經過優化的GIMPLE轉儲以將其查找為常數。 您應該像這樣使用優化的樹轉儲:

gcc -O2 -fdump-tree-optimized test.c -S

然后查找類似test.c.211t.optimized的文件(數字211可能有所不同,具體取決於gcc版本)。 Gimple代碼與原始C非常相似,因此您可以從中讀取常量沒有問題。

大多數編譯器運行預處理器以獲取程序源的文本字符串,然后將其解析為編譯器內部數據結構。 解析完程序后,您將看不到編譯器對代碼的處理方式(嗯,也許編譯器具有某種調試轉儲,但您不能指望它)。

若要執行所需的操作,您需要在擴展的宏位置對代碼進行部分評估 沒有標准的編譯器可以幫助您做到這一點。

您需要一個程序轉換系統(PTS) ,該程序可以解析源代碼,應用代碼轉換,然后重新生成修改后的源文本。 一個好的PTS將使您編寫要應用的源到源轉換規則集,每個規則的形式為:

 when you see *this*, then replace it by *that* if *condition* is true

要進行簡單的常量折疊,您需要以下規則:

  rule  simplify_times_zero(e: power): product -> product
       " \e * 0 " ->  " \e ";

處理特殊乘數乘以零的特殊(代數)情況。 您顯然需要一堆這些規則,更多內容請參見下文。

您的PTS還必須能夠讀取您正在使用的C或C ++的特定方言,並且能夠將任何標識符解析為其定義(否則,您將無法知道E在使用時是常數)。

據我所知,唯一可以解析許多C或C ++方言並進行宏擴展的PTS是我們的DMS軟件再造工具包 它使用上面示例的語法接受規則。

您需要的其他規則是實際進行算術運算的規則:

rule fold_addition(c1: INT32CONSTANT, c2: INT32CONSTANT): product -> product =
     " \c1 + \c2 " ->  int32_multiply(c1,c2);

其中int32_multiply是執行數學運算的函數。 對於每個運算符和操作數類型,您都需要使用其中之一,以遵守C和C ++語言的規則。

您還需要執行替換已知值的規則:

rule substitute_defined_constant(i: IDENTIFIER): primitive -> primitive
  " \i " ->  macro_definition_value(i) if  is_defined_constant(i);

is_defined_constant在DMS前端為宏定義而建立的符號表中查找和標識符,並在引用i的地方檢查i是否為“ define i”形式的宏。 通過將其寫為條件,除非宏定義值實際存在,否則不會調用macro_definition_value函數。 DMS的C和C ++前端提供了原始符號表支持。

有了這套規則,以及將這些規則應用於感興趣的宏擴展點的規則策略,DMS應該能夠將方程式“折疊”為您表示的形式。 現在,所有轉換都在DMS的程序內部表示上完成,但是DMS可以漂亮地打印結果,以便您可以實際看到它。

作為開發UI中的常規功能,這可能非常有用。 實際設置所有這些並使其付諸實踐可能需要幾天的時間。 DMS是一個復雜的系統,而C和C ++則無濟於事。

如果您只打算執行一次或兩次,那么最好只是咬一下子彈,然后手工完成(或者如其他答案所示,如果可以,請使用調試檢查編譯器的輸出)。 如果這是日常任務,則PTS解決方案可能會節省大量時間(和准確性)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM