如何寫個程序找出現有C++工程里的所有函數?
最近試過寫點簡單語法分析,發現還是底子不夠,好多分析錯誤的。
我在想VS編譯時肯定有函數信息,這個能不能拿出來?或者說繼續鑽研語法分析,這裡有什麼技巧?
請用Clang:Introduction to the Clang AST
遍歷一下Clang所parse出來的AST里的所有FunctionDecl就好了。後面有答案提到了正好做這件事的教程,把鏈接借用過來:結構化編譯器前端 Clang 介紹
至於Visual C++,它的前端(c1xx.dll)雖然會生成AST給後端(c2.dll),但它是通過5個臨時文件傳遞的,而這些文件的格式沒任何對外公開的文檔,想自己解析它多麻煩吶。還是乖乖用Clang好了。
=========================================================
如果還是對Visual C++念念不舍,請去找找Phoenix Compiler的下載。Phoenix SDK June 2008 CTP可以(只能)插在Visual Studio 2008上用。
安裝Phoenix SDK之後,它帶的c2.dll可以替代原本Visual C++的編譯器後端,而且裡面的大量功能都有API暴露出來,要想獲取所有C++函數聲明的話寫個簡單的plugin就好了。在Phoenix SDK里,有個FuncNames sample plugin,可以把所有被編譯的C++函數的名字(mangled name)輸出出來;這些mangled name可以用Visual C++自帶的undname.exe(name undecorator)來轉換回到人可讀的形式。
這plugin可以用C#或C++來寫。C#版,最核心的部分其實就這樣:public class FuncNamePhase: Phx.Phases.Phase
{
// ...
protected override void Execute(Phx.Unit unit)
{
if (!unit.IsFunctionUnit) return;
var function = unit.AsFunctionUnit;
Phx.Output.WriteLine("Function {0}", function.NameString);
}
}
很方便對不對? &>_&<
=========================================================
要自己讀Visual C++在debug編譯模式生成的PDB文件的話也行。請參考:
PDB Files: What Every Developer Must Know
How to Inspect the Content of a Program Database (PDB) File可以藉助Debug Interface Access SDK來讀取PDB文件的內容。為啥強調debug模式生成的PDB文件呢?因為release模式生成的PDB文件損失的信息比較多,如果目的是獲取項目里的函數的列表的話,用release模式得不償失。CCI里也有一個PdbReader,不過我沒用它來讀過Visual C++生成的PDB文件,不知道能不能用。我記得ibm有篇教學文檔就是講用clang獲得所有函數的結構化編譯器前端 Clang 介紹我記得沒錯
想要從VS編譯的結果拿出來的話,也可以通過 DIA來查詢項目生成的符號文件(PDB)裡面的所有的函數和聲明(主要查詢SymTagFunction就行了)。這裡就個一個例子,從符號文件裡面還原了項目裡面所有的 class 定義。
如果是debug版生成了帶調試信息的pdb文件,可以從pdb文件中讀取信息.
Is there a way to read a C/C++ PDB file contents?
Linux里有個工具叫nm。編譯出.o文件之後,可以用
nm --defined-only *.o | c++filt
查看每個文件里的函數名。可以看看是不是你想要的。
Windows里對應的工具是dumpbin.exe,或者用cygwin裡面的nm。
參考連接:symbols - Microsoft equivalent of the nm commandDescription of the DUMPBIN utilityDUMPBIN Reference直接上代碼:
gcc中實現,在cfg圖構建好之後添加即可 ,以下使用gcc插件實現:int plugin_init (struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
{ int i; int argc = plugin_info-&>argc; struct plugin_argument *argv = plugin_info-&>argv;if (!plugin_default_version_check (version, gcc_version))
return 1; register_callback(plugin_info-&>base_name, PLUGIN_ALL_IPA_PASSES_END, (plugin_callback_func)GetFunction_Main, NULL);return 0;
}
void GetFunction_Main(){
printf(("
========Start analyzing file %s.========
", in_fnames[0]));
count_sum++;
printf("Current function name: %s.", current_function_name()); /*set the current function to NULL.*/ }}
找個開源的能顯示函數的IDE,或者代碼閱讀器,看看源碼。
推薦閱讀:
※為什麼int型的負數會比字元串函數length()返回的值大?
※C++ 用輸入的變數作為數組長度是壞習慣嗎?
※在oi/acm中,有什麼冷門但好用的stl函數?
※如何向完全不懂編程的小夥伴解釋「程序寫死」?
※為什麼 C++ 只比 VBA 快 4倍?