劉彥宇,唐運(yùn)樂(lè)
(北海藝術(shù)設(shè)計(jì)職業(yè)學(xué)院 現(xiàn)代教育技術(shù)中心,廣西 北海 536000)
現(xiàn)有的軟件逆向工程分析方法主要有4種:詞法分析和語(yǔ)法分析;程序切片;動(dòng)態(tài)分析;圖形化方法[1]。在對(duì)現(xiàn)有源代碼進(jìn)行分析的過(guò)程中,首先想到的便是圖形化建模方法,使用Rational Rose、Visio、Rigio、StarUML等,進(jìn)行逆向建模,即通過(guò)對(duì)源代碼的自動(dòng)分析,提取出代碼各個(gè)層次上各類元素的相關(guān)信息,分析它們間的相互關(guān)系并生成多種類型的模型描述文檔[1-4]。但由于程序開(kāi)發(fā)本身的復(fù)雜性,以及這些分析工具關(guān)注重點(diǎn)所限,分析結(jié)果往往和預(yù)期相差很遠(yuǎn),像Visio逆向生成的類模型文檔,只包含了類的描述信息,缺少更多的類結(jié)構(gòu)信息。這就需要開(kāi)發(fā)人員在使用輔助工具的基礎(chǔ)上,更多的人為參與代碼分析。
為了幫助開(kāi)發(fā)者快速地閱讀理解程序源代碼,本文針對(duì)Java語(yǔ)言,以基于實(shí)體關(guān)系的C++元模型[5]為基礎(chǔ),擴(kuò)展了一種支持Java源代碼逆向建模的關(guān)系模型,按照關(guān)系模型設(shè)計(jì)代碼數(shù)據(jù)庫(kù)。
目前,現(xiàn)有逆向建模方法大致為,通過(guò)抽取源代碼信息,存入設(shè)計(jì)的表或數(shù)據(jù)庫(kù)中,再通過(guò)一些輔助工具或數(shù)據(jù)庫(kù)應(yīng)用程序?qū)Τ槿〉男畔⑦M(jìn)行模型描述[2-3,6-7]。這種方法在將抽取信息存入數(shù)據(jù)庫(kù)時(shí)所要設(shè)計(jì)的接口程序相對(duì)復(fù)雜。而基于實(shí)體關(guān)系的C++元模型可以很好的完成結(jié)構(gòu)化分析及細(xì)粒度搜索,同時(shí)它還可以平衡粒度尺寸及分析局限。本文在原有模型的基礎(chǔ)上進(jìn)行關(guān)系模型設(shè)計(jì),擴(kuò)展了兩方面內(nèi)容。第一,針對(duì)業(yè)界大量使用的Java語(yǔ)言,擴(kuò)展了特定語(yǔ)言的元模型。采用Java1.5的特性,通過(guò)這些特性可以有效控制元模型的復(fù)雜度,同時(shí)與Java語(yǔ)言中的文法概念相匹配后,便可以很容易的對(duì)抽取信息進(jìn)行分類處理,簡(jiǎn)化接口程序。第二,擴(kuò)展實(shí)體類型和關(guān)系類型,支持細(xì)粒度分析。
整個(gè)逆向建模過(guò)程如圖1所示,分三個(gè)步驟:第一,抽取源代碼信息,采用Eclipse AST對(duì)源代碼進(jìn)行解析;第二,存儲(chǔ)到代碼數(shù)據(jù)庫(kù);第三,生成模型描述文檔、進(jìn)行代碼信息檢索。
將代碼中的信息抽象為實(shí)體、關(guān)系,并且將它們與源程序使用的程序設(shè)計(jì)語(yǔ)言的文法概念相匹配,之后,便很容易對(duì)各種信息進(jìn)行分類處理。
實(shí)體可以與源代碼中的顯式聲明一致,例如Class、Interface、Method等,也可以與Array、Primitive這類Java類型一致。解析過(guò)程中如果實(shí)體類型無(wú)法描述,可以使用UNKNOWN代替。表1列出了全部實(shí)體類型,這些類型遵循Java語(yǔ)言規(guī)范(JLS)中定義的標(biāo)準(zhǔn)含義。
圖1 Java源代碼逆向建模過(guò)程
表1 實(shí)體類型
關(guān)系代表兩實(shí)體之間的依賴特性,因此所有關(guān)系都是從源實(shí)體到目標(biāo)實(shí)體的二元關(guān)系。程序在檢查過(guò)程中發(fā)現(xiàn)源實(shí)體,源實(shí)體相對(duì)較小并且包含有關(guān)系的觸發(fā)代碼。目標(biāo)實(shí)體則不同,它可以是關(guān)系涉及的本地實(shí)體,也可以是涉及到的Java標(biāo)準(zhǔn)庫(kù)或者其他外部的JAR。表2列出了完整的關(guān)系類型。
表2 關(guān)系類型
擴(kuò)展后的關(guān)系模型如圖2所示,由工程(Project)、文件(File)、實(shí)體(Entity)、關(guān)系(Relation)、注釋(Comment)五個(gè)部分組成。
圖2 擴(kuò)展后的關(guān)系模型
首先,為每個(gè)逆向建模的工程,建立一個(gè)Project模型元素。由于每個(gè)工程中含有Java源文件、JAR文件、類文件,因此建立File模型元素來(lái)代表三種類型文件。源文件及類文件通過(guò)它們內(nèi)部的多個(gè)Entity模型元素聯(lián)系起來(lái),而且在這些源實(shí)體及目標(biāo)實(shí)體之間形成Relation模型元素。另一方面,將Java工程打包生成的JAR文件,則包含全部Entity模型元素和Relation模型元素。對(duì)擴(kuò)展后的關(guān)系模型元素的詳細(xì)描述如下。
將抽取的源代碼信息存儲(chǔ)到代碼數(shù)據(jù)庫(kù)后,就可以通過(guò)數(shù)據(jù)庫(kù)查詢語(yǔ)句得到程序相關(guān)信息。同時(shí),通過(guò)開(kāi)發(fā)相應(yīng)的數(shù)據(jù)庫(kù)應(yīng)用程序,將源代碼信息轉(zhuǎn)換為更高層次的抽象視圖,以適當(dāng)?shù)男问缴赡P兔枋鑫臋n。
另一方面,由于關(guān)系數(shù)據(jù)庫(kù)無(wú)法對(duì)存儲(chǔ)在庫(kù)中字段內(nèi)容進(jìn)行檢索和分析,因此并未在數(shù)據(jù)庫(kù)中存儲(chǔ)詳細(xì)代碼數(shù)據(jù),而是采用代碼數(shù)據(jù)庫(kù)+Lucene[7-8]的模式,設(shè)計(jì)信息檢索部分。從代碼數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)來(lái)建立Lucene索引,將Lucene定義的索引文檔(document)與數(shù)據(jù)庫(kù)中的一個(gè)實(shí)體記錄匹配。Lucene中,文檔又是一些域(field)的序列,而域又是一些項(xiàng)(term)的序列,這里項(xiàng)就是最基本的檢索單元,是從一個(gè)實(shí)體的各部分中提取出來(lái)的字串。將代碼數(shù)據(jù)庫(kù)與Lucene結(jié)合既實(shí)現(xiàn)了全文檢索,又可以利用數(shù)據(jù)庫(kù)做復(fù)雜分析,實(shí)現(xiàn)模型描述文檔的建立。
擴(kuò)展后的關(guān)系模型支持源代碼的細(xì)粒度分析,生成的各層次元素復(fù)雜,適合局部源代碼建模,基于此開(kāi)發(fā)的逆向建模工具與同類工具相比,具有一定特色。
實(shí)驗(yàn)過(guò)程中,采用這種方法對(duì)開(kāi)源項(xiàng)目面向?qū)ο髷?shù)據(jù)庫(kù)db4o(for Java,version 8.0)的源代碼進(jìn)行了局部的模型描述,分別對(duì)db4o內(nèi)核的File Header(數(shù)據(jù)字典加載)、FreeSpace(空閑空間分配)、Internal Ids(分配對(duì)象OID)、Get(根據(jù) OID 獲取對(duì)象數(shù)據(jù))、Set(對(duì)象存儲(chǔ))[9]等5個(gè)方面進(jìn)行類模型描述。由于缺乏對(duì)比逆向建模細(xì)粒度分析優(yōu)劣的基準(zhǔn)測(cè)試及數(shù)據(jù)集,這里使用模型描述中獲得的實(shí)體數(shù)量作為評(píng)測(cè)參數(shù)。圖3顯示了基于擴(kuò)展關(guān)系模型開(kāi)發(fā)的逆向建模工具與Rational Rose、StarUML兩款工具在模型描述中獲得實(shí)體數(shù)量的對(duì)比。
結(jié)果顯示,由于分析粒度的不同,加之本文擴(kuò)展了實(shí)體及關(guān)系類型(不再只是類、字段、方法等顯式實(shí)體),在對(duì)db4o五個(gè)類模型描述中,基于文中方法的工具在細(xì)粒度分析上要明顯優(yōu)于其他兩款工具。
另一方面,通過(guò)代碼數(shù)據(jù)庫(kù)+Lucene的模式,可以提高源代碼分析的速度,同時(shí)為簡(jiǎn)單時(shí)序分析提供可能性。圖4,5是代碼數(shù)據(jù)庫(kù)+Lucene,結(jié)合人為分析得到的db4o對(duì)象存儲(chǔ)的序列圖。
圖3 模型中獲得的實(shí)體數(shù)量對(duì)比
在對(duì)實(shí)際項(xiàng)目進(jìn)行源代碼分析的過(guò)程中,可以采用粗粒度與細(xì)粒度分析相結(jié)合的方式,利用粗粒度分析項(xiàng)目整體概況,利用細(xì)粒度分析局部信息。但由于程序開(kāi)發(fā)本身的復(fù)雜性及眾多的設(shè)計(jì)模式,要更有效的表現(xiàn)設(shè)計(jì)思想及設(shè)計(jì)邏輯,減少人為參與代碼分析,還需要更具體的分析與匹配。
[1]Francoise Balmas,Kostas Kontogiannis.Introduction to the special issue on software analysis,evolution and reengineering[J].Science of Computer Programming,2006,60(2):117 -120.
[2]彭四偉,朱群雄.基于源代碼分析的逆向建模[J].計(jì)算機(jī)應(yīng)用研究,2006,23(7):52-54.
[3]Alexandru Telea,Heorhiy Byelas,Lucian Voinea.A Framework for Reverse Engineering Large C++Code Bases[J].Electronic Notes in Theoretical Computer Science,2009,233(3):143 -159.
[4]H Byelas,A Telea.Visualization of areas of interest in software architecture diagrams[A].SoftVis’06 Proceedings of the 2006 ACM symposium on Software visualization[C].New York:ACM Press,2006:20 -28.
[5]Yih - Farn Chen,Emden R Gansner,Eleftherios Koutsofios.A C++Data Model Supporting Reachability Analysis and Dead Code Detection[J].IEEE Transactions on Software Engineering,1998,24(9):682 -694.
[6]馬戀.基于關(guān)系數(shù)據(jù)庫(kù)的程序逆向分析架構(gòu)研究[D].長(zhǎng)沙:長(zhǎng)沙理工大學(xué),2007.
[7]Erik Linstead,Sushil Bajracharya,Trung Ngo.Sourcerer:mining and searching internet- scale software repositories[J].Data Mining and Knowledge Discovery,2009,18(2):300 -336.
[8]佚名.Lucene web site[CP/DK].http://lucene.apache.org,2012.
[9]佚名.Db4o web site[CP/DK].http://www.db 4o.com,2012.