一種基于cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法【專利摘要】本發(fā)明公開(kāi)了一種基于cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法,其特征是:首先建立多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表,其次虛函數(shù)調(diào)用時(shí),根據(jù)類類型指針的動(dòng)態(tài)類型和靜態(tài)類型信息,通過(guò)新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表返回被調(diào)用的虛函數(shù)名稱,結(jié)合虛函數(shù)調(diào)用時(shí)參數(shù),唯一確定被調(diào)用的虛函數(shù)。通過(guò)使用編譯器中間文件class文件,建立與編譯器建表規(guī)則一致的新虛函數(shù)鏈表等,通過(guò)記錄類類型指針的靜態(tài)類型和動(dòng)態(tài)類型,結(jié)合建立的新虛函數(shù)鏈表等,實(shí)現(xiàn)靜態(tài)分析時(shí)準(zhǔn)確獲取動(dòng)態(tài)運(yùn)行時(shí)信息,準(zhǔn)確確定被調(diào)用的虛函數(shù),從而提高了靜態(tài)分析精確性,更加符合程序邏輯?!緦@f(shuō)明】—種基于Cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法【
技術(shù)領(lǐng)域:
】[0001]本發(fā)明涉及軟件分析領(lǐng)域,具體地說(shuō)是一種基于Cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法?!?br>背景技術(shù):
】[0002]隨著時(shí)代的進(jìn)步,軟件的功能越來(lái)越復(fù)雜,用戶對(duì)軟件的要求也越來(lái)越高。同時(shí)伴隨著計(jì)算機(jī)相關(guān)技術(shù)的發(fā)展,軟件規(guī)模越來(lái)越龐大,開(kāi)發(fā)的復(fù)雜性急劇增加。[0003]隨著軟件規(guī)模的增大,為了保證軟件質(zhì)量,對(duì)測(cè)試提出了更大的挑戰(zhàn)。尤其對(duì)于應(yīng)用于實(shí)時(shí)性控制等特殊應(yīng)用場(chǎng)景時(shí),軟件發(fā)生故障時(shí)將會(huì)導(dǎo)致不可估量的后果,對(duì)軟件可靠性要求更高。為了最大程度保證軟件可靠性,需要大量測(cè)試軟件。[0004]在軟件測(cè)試中,可以分動(dòng)態(tài)測(cè)試為和靜態(tài)測(cè)試,前者通過(guò)實(shí)際運(yùn)行被測(cè)試程序,觀察運(yùn)行結(jié)果與預(yù)期差異,后者無(wú)需程序運(yùn)行,通過(guò)代碼分析確定程序缺陷。隨著軟件代碼規(guī)模的增大,運(yùn)行空間急劇擴(kuò)大,動(dòng)態(tài)測(cè)試很難達(dá)到100%覆蓋率,為軟件健壯性和安全性留下隱患,同時(shí)隨著測(cè)試覆蓋程度的增加,測(cè)試成本也在急劇增加。通過(guò)靜態(tài)分析程序,例如分析程序結(jié)構(gòu),分析程序函數(shù)調(diào)用關(guān)系,分析程序邏輯,可以更有效發(fā)現(xiàn)程序問(wèn)題,效率通常高于動(dòng)態(tài)測(cè)試。[0005]在軟件編碼中,大量代碼使用C++語(yǔ)言開(kāi)發(fā)。在靜態(tài)分析C++源程序時(shí),通常需要獲取函數(shù)調(diào)用路徑,基于函數(shù)調(diào)用路徑分析程序。源程序中存在多個(gè)函數(shù)調(diào)用路徑,通過(guò)分析每個(gè)函數(shù)調(diào)用路徑,進(jìn)而發(fā)現(xiàn)程序中的問(wèn)題?!?br/>發(fā)明內(nèi)容】[0006]本發(fā)明提出一種具有可操作性的基于cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法,以期在靜態(tài)分析中準(zhǔn)確獲取動(dòng)態(tài)運(yùn)行時(shí)信息,提高靜態(tài)分析準(zhǔn)確性,實(shí)現(xiàn)靜態(tài)分析更加符合程序語(yǔ)義。[0007]本發(fā)明為解決技術(shù)問(wèn)題采用如下技術(shù)方案:[0008]本發(fā)明一種基于cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法,基于Linux平臺(tái)G++編譯器實(shí)現(xiàn),其特點(diǎn)是按如下步驟進(jìn)行:[0009]步驟1、建立多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表:[0010]步驟1.1、利用所述G++編譯器對(duì)C++源程序進(jìn)行編譯時(shí),添加編譯參數(shù)fdump-tree-cfg和編譯參數(shù)fdump-class-hierarchy后進(jìn)行編譯,由所述編譯參數(shù)fdump-tree-cfg生成cfg文件,由所述編譯參數(shù)fdump-class-hierarchy獲得編譯器生成的多個(gè)類的虛函數(shù)表,并保存在class文件中;所述class文件中包括被G++編譯器改編的虛函數(shù)名稱;[0011]步驟1.2、提取所述class文件中的多個(gè)類的虛函數(shù)表,并把被G++編譯器改編的虛函數(shù)名稱恢復(fù)為C++源程序中的虛函數(shù)名稱,按虛函數(shù)在class文件中出現(xiàn)的順序使用鏈表按序進(jìn)行存儲(chǔ),鏈表中每個(gè)節(jié)點(diǎn)對(duì)應(yīng)編譯器生成的虛函數(shù)表中一行,從而建立多個(gè)類的新虛函數(shù)鏈表,所述新虛函數(shù)鏈表中存儲(chǔ)的函數(shù)名稱與源程序中虛函數(shù)名稱一致;當(dāng)一個(gè)類含有基類時(shí),所述編譯器生成的虛函數(shù)表和新虛函數(shù)鏈表中包括被直接繼承和重寫的基類虛函數(shù)以及派生類自有虛函數(shù);將所述被直接繼承或重寫的基類虛函數(shù)定義為基類對(duì)應(yīng)的虛函數(shù);[0012]步驟1.3、在所述class文件中編譯器生成的虛函數(shù)表中,編譯器選擇一行開(kāi)始存放所述基類對(duì)應(yīng)虛函數(shù);提取并使用鏈表記錄所述基類對(duì)應(yīng)虛函數(shù)在新虛函數(shù)鏈表的中起始存放位置,從而建立類的虛函數(shù)起始位置偏移鏈表;所述虛函數(shù)起始位置偏移鏈表中每個(gè)節(jié)點(diǎn)存儲(chǔ)基類對(duì)應(yīng)虛函數(shù)和派生類的首個(gè)虛函數(shù)在派生類的虛函數(shù)表中起始偏移位置;所述起始偏移位置使用指向類的新虛函數(shù)鏈表節(jié)點(diǎn)的指針表示;[0013]步驟2、虛函數(shù)調(diào)用:[0014]步驟2.1、在cfg文件中,以“0BJ_TYPE_REF(other;pointer_>num)(pointer,parameter)”格式表示虛函數(shù)調(diào)用,other為無(wú)需處理的字符,pointer為類類型的指針變量名稱,num為一整數(shù),parameter為虛函數(shù)參數(shù)列表,當(dāng)虛函數(shù)無(wú)參數(shù)時(shí),以“OBJ_TYPE_REF(other;pointer->num)(pointer)”標(biāo)識(shí)虛函數(shù)調(diào)用,通過(guò)pointer指針調(diào)用虛函數(shù)時(shí),根據(jù)所述pointer指針的動(dòng)態(tài)類型,從所述建立的多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表中,選擇pointer指針動(dòng)態(tài)類型對(duì)應(yīng)的新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表;[0015]步驟2.2、對(duì)虛函數(shù)起始位置偏移鏈表進(jìn)行遍歷并找到一節(jié)點(diǎn),所述節(jié)點(diǎn)中存放了對(duì)應(yīng)pointer指針靜態(tài)類型的起始位置偏移信息,所述起始偏移位置使用指向新虛函數(shù)鏈表節(jié)點(diǎn)的指針進(jìn)行表示,通過(guò)所述指針找到新虛函數(shù)鏈表中的相應(yīng)節(jié)點(diǎn)作為查找起始節(jié)占.[0016]步驟2.3、根據(jù)所述cfg文件中pointer指針調(diào)用虛函數(shù)格式中的num整數(shù),從所述查找起始節(jié)點(diǎn)開(kāi)始查找第num個(gè)鏈表節(jié)點(diǎn),且查找起始節(jié)點(diǎn)為第O個(gè)鏈表節(jié)點(diǎn),并返回第num個(gè)節(jié)點(diǎn)中存儲(chǔ)的虛函數(shù)名稱;[0017]步驟2.4、通過(guò)cfg文件中虛函數(shù)調(diào)用中的parameter虛函數(shù)參數(shù)列表,使用C++中重載規(guī)則,唯一確定被調(diào)用的虛函數(shù),從而完成虛函數(shù)調(diào)用解析。[0018]與現(xiàn)有技術(shù)相比,本發(fā)明的有益效果在于:[0019]1、本發(fā)明通過(guò)使用編譯器中間文件cfg文件,cfg文件與源程序語(yǔ)義一致且格式更加規(guī)則,避免了直接處理源程序復(fù)雜靈活的書寫方式,降低了分析難度,提高了分析準(zhǔn)確性。[0020]2、本發(fā)明通過(guò)使用編譯器中間文件class文件,可以建立和編譯器建立虛函數(shù)表規(guī)則完全一致的新虛函數(shù)鏈表等,避免了通過(guò)分析C++源程序,并根據(jù)復(fù)雜的編譯器建表規(guī)則建立虛函數(shù)表,保證了使用與cfg完全對(duì)應(yīng)一致的虛函數(shù)表。提高了建表效率和準(zhǔn)確性。[0021]3、本發(fā)明通過(guò)在分析cfg文件的一條函數(shù)調(diào)用路徑時(shí),記錄對(duì)類類型指針的操作,例如賦值操作,進(jìn)而記錄類類型指針的靜態(tài)類型和動(dòng)態(tài)類型,結(jié)合建立的虛函數(shù)鏈表等,實(shí)現(xiàn)靜態(tài)分析時(shí)準(zhǔn)確獲取動(dòng)態(tài)運(yùn)行時(shí)信息,準(zhǔn)確確定這條函數(shù)調(diào)用路徑中被調(diào)用的虛函數(shù),提高了靜態(tài)分析精確性,更加符合程序邏輯。【具體實(shí)施方式】[0022]本實(shí)施例中,一種基于cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法是基于Linux平臺(tái)G++編譯器實(shí)現(xiàn)的,并以64位Linux系統(tǒng)GCC4.7.1為例,是先建立多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表,其次虛函數(shù)調(diào)用時(shí),根據(jù)類類型指針的動(dòng)態(tài)類型和靜態(tài)類型,使用新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表返回被調(diào)用的虛函數(shù)名稱,結(jié)合虛函數(shù)參數(shù),唯一確定被調(diào)用的虛函數(shù)。通過(guò)使用編譯器中間文件class文件,建立和編譯器建立虛函數(shù)表規(guī)則完全一致的新虛函數(shù)鏈表等,通過(guò)記錄類類型指針的靜態(tài)類型和動(dòng)態(tài)類型,結(jié)合建立的新虛函數(shù)鏈表等,實(shí)現(xiàn)靜態(tài)分析時(shí)準(zhǔn)確獲取動(dòng)態(tài)運(yùn)行時(shí)信息;具體地說(shuō),是按如下步驟進(jìn)行:[0023]步驟1、建立多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表:[0024]步驟1.1、利用G++編譯器對(duì)C++源程序進(jìn)行編譯時(shí),添加編譯參數(shù)fdump-tree-cfg和編譯參數(shù)fdump-class-hierarchy后進(jìn)行編譯,由編譯參數(shù)fdump-tree-cfg生成cfg文件,cfg文件為編譯器生成的以cfg為文件名稱后綴的文件,同時(shí)cfg文件與源程序語(yǔ)義一致且格式規(guī)則,降低了靜態(tài)分析難度;由編譯參數(shù)fdump-class-hierarchy獲得編譯器生成的多個(gè)類的虛函數(shù)表,并保存在class文件中;class文件為編譯器生成的以class為后綴的文件;class文件中包括被G++編譯器改編的虛函數(shù)名稱;[0025]虛函數(shù)表中每個(gè)虛函數(shù)在內(nèi)存中占用sizeof(char*)個(gè)字節(jié),其中sizeof(char*)標(biāo)識(shí)一個(gè)指針類型占用空間大小,在32位系統(tǒng)中為4字節(jié),64位系統(tǒng)中為8字節(jié)。[0026]步驟1.2、提取所述class文件中的多個(gè)類的虛函數(shù)表,并把被G++編譯器改編的虛函數(shù)名稱恢復(fù)為C++源程序中的虛函數(shù)名稱,按虛函數(shù)在class文件中出現(xiàn)的順序使用鏈表按序進(jìn)行存儲(chǔ),鏈表中每個(gè)節(jié)點(diǎn)對(duì)應(yīng)編譯器生成的虛函數(shù)表中一行,從而建立多個(gè)類的新虛函數(shù)鏈表,所述新虛函數(shù)鏈表中存儲(chǔ)的函數(shù)名稱與源程序中虛函數(shù)名稱一致;當(dāng)一個(gè)類含有基類時(shí),所述編譯器生成的虛函數(shù)表和新虛函數(shù)鏈表中包括被直接繼承和重寫的基類虛函數(shù)以及派生類自有虛函數(shù);將所述被直接繼承或重寫的基類虛函數(shù)定義為基類對(duì)應(yīng)的虛函數(shù);[0027]在class文件中,編譯器生成的類虛函數(shù)表以一定字符標(biāo)識(shí)開(kāi)始。標(biāo)識(shí)類的虛函數(shù)表開(kāi)始的字符格式為:“VtableforclaSS_name”(以下簡(jiǎn)稱為字符格式I)。緊鄰特定字符標(biāo)識(shí)I的下一行采用“class_name::other:numuentries”格式(以下簡(jiǎn)稱字符格式2),其中claSS_name標(biāo)識(shí)類的完整名稱,若類被聲明定義在命名空間中,則類的完整名稱包含命名空間,例如,類cat被聲明定義在命名空間animal中,則類cat的完整名稱為animal::cat,other標(biāo)志一連續(xù)存儲(chǔ)的無(wú)關(guān)字符,無(wú)需處理,numu標(biāo)識(shí)符中的‘u’是一整數(shù)num末尾緊鄰的單個(gè)字符,例如“1u”,整數(shù)num標(biāo)識(shí)了類的虛函數(shù)表中含有的num個(gè)單元(編譯器生成的虛函數(shù)表一行簡(jiǎn)稱為單元,每個(gè)單元占用一行,有的單元不描述虛函數(shù))。字符格式I表示當(dāng)前的單元是class_name類的虛函數(shù)表,當(dāng)前建立的新虛函數(shù)鏈表屬于class_name類。[0028]緊鄰的字符格式2之后的行是編譯器生成的虛函數(shù)表的每個(gè)單元。采用鏈表存儲(chǔ)類的虛函數(shù)表的所有單元,每個(gè)虛函數(shù)表單元占用一個(gè)鏈表節(jié)點(diǎn),且鏈表中節(jié)點(diǎn)順序與虛函數(shù)表中個(gè)單元順序一致,鏈表第一個(gè)節(jié)點(diǎn)即為虛函數(shù)表第一個(gè)單元,同時(shí)每新建立一個(gè)鏈表節(jié)點(diǎn)均加入到鏈表尾部,以下均稱存儲(chǔ)虛函數(shù)表的鏈表為新虛函數(shù)鏈表。若新虛函數(shù)鏈表中節(jié)點(diǎn)對(duì)應(yīng)class文件中單元對(duì)應(yīng)一個(gè)虛函數(shù),則鏈表節(jié)點(diǎn)存儲(chǔ)虛函數(shù)與源程序一致的函數(shù)名稱。[0029]編譯器生成的虛函數(shù)表單元格式如下:[0030](I)、虛函數(shù)距整個(gè)虛函數(shù)表起始位置的字節(jié)(以下稱為在虛函數(shù)表中偏移),之后以空格填充分割;[0031](2)、緊鄰⑴的同一行,以(int(*)(...))字符串填充;[0032](3)、緊鄰⑵的同一行,可能出現(xiàn)多種情況;[0033]a)若以是負(fù)數(shù)或數(shù)字“O”或“(&”開(kāi)始,將其后字符串內(nèi)容存放在新建立的鏈表節(jié)點(diǎn),并將鏈表節(jié)點(diǎn)插入到虛函數(shù)鏈表尾部,此時(shí)當(dāng)前單元不是具體虛函數(shù),轉(zhuǎn)(4)處理;[0034]b)米用“class_name::funct1n_name”格式存儲(chǔ),class_name同上,funct1n_name分為發(fā)生函數(shù)名稱改編和未發(fā)生名稱改編兩種情況。發(fā)生名稱改編時(shí),funct1n_name的格式由編譯器的實(shí)現(xiàn)決定。未發(fā)生名稱改編的行,funCti0n_name字符串與源程序中虛函數(shù)名稱一致。發(fā)生名稱改編的單元,需從funct1n_name中提取與源程序一致的函數(shù)名稱??梢酝ㄟ^(guò)“c++filtfunct1n_name”獲取源程序中虛函數(shù)名稱,其中c++filt為L(zhǎng)inux系統(tǒng)中命令,funct1n_name同上。在編程實(shí)現(xiàn)通過(guò)funct1n_name獲取虛函數(shù)名稱時(shí),可以調(diào)用popen等函數(shù)獲取命令執(zhí)行結(jié)果,同時(shí)使用c++filt命令處理沒(méi)有發(fā)生名稱改編的funct1n_name時(shí),通過(guò)命令執(zhí)行也可以得到正確的結(jié)果。通過(guò)c++filt命令獲取源程序中的虛函數(shù)名稱后,新建立虛函數(shù)表節(jié)點(diǎn)并存儲(chǔ)源程序中的虛函數(shù)名稱,將新建立虛函數(shù)表節(jié)點(diǎn)插入虛函數(shù)鏈表尾部,轉(zhuǎn)(4)處理[0035](4)、若仍有單元未處理,轉(zhuǎn)(I)分析處理[0036]步驟1.3、在所述class文件中編譯器生成的虛函數(shù)表中,編譯器選擇一行開(kāi)始存放所述基類對(duì)應(yīng)虛函數(shù);提取并使用鏈表記錄所述基類對(duì)應(yīng)虛函數(shù)在新虛函數(shù)鏈表的中起始存放位置,從而建立類的虛函數(shù)起始位置偏移鏈表;所述虛函數(shù)起始位置偏移鏈表中每個(gè)節(jié)點(diǎn)存儲(chǔ)基類對(duì)應(yīng)虛函數(shù)和派生類的首個(gè)虛函數(shù)在派生類的虛函數(shù)表中起始偏移位置;派生類的首個(gè)虛函數(shù)指在class文件中,編譯器生成派生類的虛函數(shù)表中首個(gè)描述虛函數(shù)的單元,所述起始偏移位置使用指向類的新虛函數(shù)鏈表節(jié)點(diǎn)的指針表示;[0037]class文件中的格式“Classclass_name_derived”,標(biāo)識(shí)了class__name_derived類的虛函數(shù)起始位置偏移信息在class文件中的存放位置,從“Classclass_name_derived”所在的文件位置開(kāi)始,根據(jù)class文件內(nèi)容建立class_name_derived類的虛函數(shù)起始位置偏移鏈表。其中class_name_derived表示類全稱,以下所述中的class_name_base也表不類全稱,類全稱和numu含義如上。對(duì)于含有class_name_base類全稱的行,若下一行中出現(xiàn)“vptr=((other)+numu)”時(shí),通過(guò)計(jì)算num/sizeof(char*)表達(dá)式的值,可以確定class_name_base類對(duì)應(yīng)虛函數(shù)起始偏移位置對(duì)應(yīng)class_name_derived類的新虛函數(shù)鏈表的第(num/sizeof(char*))個(gè)節(jié)點(diǎn),其中sizeof(char*)表示一個(gè)指針占用的字節(jié)數(shù),class_name_derived類的新虛函數(shù)鏈表首個(gè)節(jié)點(diǎn)為第O個(gè)節(jié)點(diǎn),同時(shí)在class_name_derived類的虛函數(shù)起始位置偏移鏈表中添加新節(jié)點(diǎn),新節(jié)點(diǎn)中存儲(chǔ)了class_name_base類的名稱和一個(gè)指針,所述指針指向了class_name_derived類的新虛函數(shù)鏈表中第(num/sizeof(char*))個(gè)節(jié)點(diǎn)。[0038]步驟2、虛函數(shù)調(diào)用[0039]步驟2.1、在cfg文件中,以“0BJ_TYPE_REF(other;pointer_>num)(pointer,parameter)”格式表示虛函數(shù)調(diào)用,other為無(wú)需處理的字符,pointer為類類型的指針變量名稱,num為一整數(shù),parameter為虛函數(shù)參數(shù)列表,當(dāng)虛函數(shù)無(wú)參數(shù)時(shí),以“OBJ_TYPE_REF(other;pointer->num)(pointer)”標(biāo)識(shí)虛函數(shù)調(diào)用,通過(guò)pointer指針調(diào)用虛函數(shù)時(shí),根據(jù)所述pointer指針的動(dòng)態(tài)類型,從建立的多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表中,選擇pointer指針動(dòng)態(tài)類型對(duì)應(yīng)的新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表;以下步驟使用的新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表,均是本步驟中選擇的新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表;[0040]類類型指針pointer的靜態(tài)類型指在聲明pointer指針時(shí)的類型,pointer指針的動(dòng)態(tài)類型與pointer指針當(dāng)前指向的對(duì)象類型有關(guān),動(dòng)態(tài)類型和靜態(tài)類型可以不一致,例如pointer靜態(tài)類型是基類類型,動(dòng)態(tài)類型為pointer靜態(tài)類型對(duì)應(yīng)的類的派生類。在分析cfg文件時(shí),需要記錄類類型指針的動(dòng)態(tài)類型和靜態(tài)類型信息。[0041]步驟2.2、對(duì)虛函數(shù)起始位置偏移鏈表進(jìn)行遍歷并找到一節(jié)點(diǎn),所述節(jié)點(diǎn)中存放了對(duì)應(yīng)pointer指針靜態(tài)類型的起始位置偏移信息,所述起始偏移位置使用指向新虛函數(shù)鏈表節(jié)點(diǎn)的指針進(jìn)行表示,通過(guò)所述指針找到新虛函數(shù)鏈表中的一節(jié)點(diǎn)作為查找起始節(jié)點(diǎn);[0042]步驟2.3、根據(jù)所述cfg文件中pointer指針調(diào)用虛函數(shù)格式中的num整數(shù),從查找起始節(jié)點(diǎn)開(kāi)始查找第num個(gè)鏈表節(jié)點(diǎn),且查找起始節(jié)點(diǎn)是第O個(gè)鏈表節(jié)點(diǎn),并返回第num個(gè)節(jié)點(diǎn)中存儲(chǔ)的虛函數(shù)名稱;[0043]步驟2.4、通過(guò)cfg文件中虛函數(shù)調(diào)用中的parameter虛函數(shù)參數(shù)列表,使用C++中重載規(guī)則,唯一確定被調(diào)用的虛函數(shù),從而完成虛函數(shù)調(diào)用解析。[0044]C++支持函數(shù)重載。當(dāng)函數(shù)重載是,同一函數(shù)名稱需要不同的函數(shù)簽名區(qū)分不同函數(shù),即函數(shù)參數(shù)類型和參數(shù)個(gè)數(shù)的不同區(qū)分重載函數(shù)。類的新虛函數(shù)鏈表中節(jié)點(diǎn)只記錄了虛函數(shù)名稱,在通過(guò)新虛函數(shù)鏈表返回虛函數(shù)名稱之后根據(jù)cfg文件中調(diào)用虛函數(shù)時(shí)參數(shù)信息,唯一確定被調(diào)用的虛函數(shù)?!緳?quán)利要求】1.一種基于Cfg文件靜態(tài)分析C++虛函數(shù)調(diào)用的方法,基于Linux平臺(tái)G++編譯器實(shí)現(xiàn),其特征是按如下步驟進(jìn)行:步驟1、建立多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表:步驟1.1、利用所述G++編譯器對(duì)C++源程序進(jìn)行編譯時(shí),添加編譯參數(shù)fdump-tree-cfg和編譯參數(shù)fdump-class-hierarchy后進(jìn)行編譯,由所述編譯參數(shù)fdump-tree-cfg生成cfg文件,由所述編譯參數(shù)fdump-class-hierarchy獲得編譯器生成的多個(gè)類的虛函數(shù)表,并保存在class文件中;所述class文件中包括被G++編譯器改編的虛函數(shù)名稱;步驟1.2、提取所述class文件中的多個(gè)類的虛函數(shù)表,并把被G++編譯器改編的虛函數(shù)名稱恢復(fù)為C++源程序中的虛函數(shù)名稱,按虛函數(shù)在class文件中出現(xiàn)的順序使用鏈表按序進(jìn)行存儲(chǔ),鏈表中每個(gè)節(jié)點(diǎn)對(duì)應(yīng)編譯器生成的虛函數(shù)表中一行,從而建立多個(gè)類的新虛函數(shù)鏈表,所述新虛函數(shù)鏈表中存儲(chǔ)的函數(shù)名稱與源程序中虛函數(shù)名稱一致;當(dāng)一個(gè)類含有基類時(shí),所述編譯器生成的虛函數(shù)表和新虛函數(shù)鏈表中包括被直接繼承和重寫的基類虛函數(shù)以及派生類自有虛函數(shù);將所述被直接繼承或重寫的基類虛函數(shù)定義為基類對(duì)應(yīng)的虛函數(shù);步驟1.3、在所述class文件中編譯器生成的虛函數(shù)表中,編譯器選擇一行開(kāi)始存放所述基類對(duì)應(yīng)虛函數(shù);提取并使用鏈表記錄所述基類對(duì)應(yīng)虛函數(shù)在新虛函數(shù)鏈表的中起始存放位置,從而建立類的虛函數(shù)起始位置偏移鏈表;所述虛函數(shù)起始位置偏移鏈表中每個(gè)節(jié)點(diǎn)存儲(chǔ)基類對(duì)應(yīng)虛函數(shù)和派生類的首個(gè)虛函數(shù)在派生類的虛函數(shù)表中起始偏移位置;所述起始偏移位置使用指向類的新虛函數(shù)鏈表節(jié)點(diǎn)的指針表示;步驟2、虛函數(shù)調(diào)用:步驟2.1、在cfg文件中,以“OBJ_TYPE_REF(other;pointer_>num)(pointer,parameter)”格式表示虛函數(shù)調(diào)用,other為無(wú)需處理的字符,pointer為類類型的指針變量名稱,num為一整數(shù),parameter為虛函數(shù)參數(shù)列表,當(dāng)虛函數(shù)無(wú)參數(shù)時(shí),以“OBJ_TYPE_REF(other;pointer->num)(pointer)”標(biāo)識(shí)虛函數(shù)調(diào)用,通過(guò)pointer指針調(diào)用虛函數(shù)時(shí),根據(jù)所述pointer指針的動(dòng)態(tài)類型,從所述建立的多個(gè)類的新虛函數(shù)鏈表和多個(gè)類的虛函數(shù)起始位置偏移鏈表中,選擇pointer指針動(dòng)態(tài)類型對(duì)應(yīng)的新虛函數(shù)鏈表和虛函數(shù)起始位置偏移鏈表;步驟2.2、對(duì)虛函數(shù)起始位置偏移鏈表進(jìn)行遍歷并找到一節(jié)點(diǎn),所述節(jié)點(diǎn)中存放了對(duì)應(yīng)pointer指針靜態(tài)類型的起始位置偏移信息,所述起始偏移位置使用指向新虛函數(shù)鏈表節(jié)點(diǎn)的指針進(jìn)行表示,通過(guò)所述指針找到新虛函數(shù)鏈表中的相應(yīng)節(jié)點(diǎn)作為查找起始節(jié)點(diǎn);步驟2.3、根據(jù)所述cfg文件中pointer指針調(diào)用虛函數(shù)格式中的num整數(shù),從所述查找起始節(jié)點(diǎn)開(kāi)始查找第num個(gè)鏈表節(jié)點(diǎn),且查找起始節(jié)點(diǎn)為第O個(gè)鏈表節(jié)點(diǎn),并返回第num個(gè)節(jié)點(diǎn)中存儲(chǔ)的虛函數(shù)名稱;步驟2.4、通過(guò)cfg文件中虛函數(shù)調(diào)用中的parameter虛函數(shù)參數(shù)列表,使用C++中重載規(guī)則,唯一確定被調(diào)用的虛函數(shù),從而完成虛函數(shù)調(diào)用解析?!疚臋n編號(hào)】G06F9/45GK104331368SQ201410658925【公開(kāi)日】2015年2月4日申請(qǐng)日期:2014年11月18日優(yōu)先權(quán)日:2014年11月18日【發(fā)明者】顧乃杰,馮光輝,張明,曹華雄申請(qǐng)人:合肥康捷信息科技有限公司