1. 程式人生 > >手把手教你開發 clang 外掛

手把手教你開發 clang 外掛

Clang是llvm的編譯器前端,非常適合進行原始碼分析.目前開源的oclint就是基於clang進行的程式碼靜態檢查.工作中遇到了一些問題需要進行程式碼分析,所以學習了外掛的開發流程.既然開發外掛就要有合適的IDE,Mac上最合適的無疑是xcode了.本文將講述如何使用xcode開發clang外掛,在此之前請先了解clang的相關知識.

1、編譯外掛

1.1、程式碼下載

1.2、新增外掛程式碼

a.建立外掛所在資料夾(示例程式碼見 demo)
這裡寫圖片描述

b.編寫cmakelists檔案

這裡寫圖片描述
c.新增外掛程式碼
這裡寫圖片描述

1.3、編譯程式碼

有兩種編譯方式,一種使用cmake直接編譯,一種使用IDE。這裡介紹下使用xcode的編譯方式。

a. 生成 xcodeproj 檔案

cd /opt
sudo mkdir llvm
sudo chown `whoami` llvm
cd llvm
export LLVM_HOME=`pwd`

git clone -b release_39 [email protected].com:llvm-mirror/llvm.git llvm
git clone -b release_39 [email protected].com:llvm-mirror/clang.git llvm/tools/clang
git clone -b release_39 [email protected]
.com:llvm-mirror/clang-tools-extra.git llvm/tools/clang/tools/extra git clone -b release_39 [email protected].com:llvm-mirror/compiler-rt.git llvm/projects/compiler-rt mkdir llvm_build cd llvm_build cmake -G Xcode ../llvm -DCMAKE_BUILD_TYPE:STRING=MinSizeRel

這裡寫圖片描述

b. 選擇自動生成 schmema
這裡寫圖片描述
c. 編譯 clang,myplugin 和 libclang

這裡寫圖片描述

d. 最終效果

這裡寫圖片描述

2、使用外掛

2.1、hook xcode

a. 執行以下兩個命令

sudo mv HackedClang.xcplugin `xcode-select -print-path`/../PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins
sudo mv HackedBuildSystem.xcspec `xcode-select -print-path`/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications

如果自定義 clang 路徑和展示的名稱,則修改以下檔案

這裡寫圖片描述
b. Xcode 配置
這裡寫圖片描述
c. 新增 other_flags

這裡寫圖片描述

-Xclang -load -Xclang /opt/llvm/clangplugin/libONEExtractVCPlugin.dylib -Xclang -add-plugin -Xclang ONEExtractVCPlugin -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1

/opt/llvm/clangplugin/libMyPlugin.dylib:是動態庫地址
MyPlugin:外掛名稱
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1:使用的c++庫

2.2、命令列呼叫 clang 外掛

直接替換紅框的 clang 為自己編譯的 clang 即可
這裡寫圖片描述

2.2 常用 API 介紹

a. 註冊外掛

static clang::FrontendPluginRegistry::Add<my::MyASTAction>
X("MyPluginName", "MyPlugin description");

第一個引數是外掛名稱,第二個是外掛描述

b. 傳遞引數到外掛

bool MyASTAction::ParseArgs(const CompilerInstance &CI, const std::vector<std::string>& args) {
        size_t cnt = args.size();
        for(int i = 0;i < cnt;i++){
            cout<<"myparam:"<<args.at(i)<<endl;
        }
       return true;
}

編譯的時候新增plugin對應的param就可以通過該方法將param獲取到.例如在other_cflag除了上期配置外新增中新增-Xclang -plugin-arg-MyPlugin -Xclang $SRCROOT/..,就可以將srcroot的路徑打印出來

  • ast 解析完成呼叫
    void MyASTConsumer::HandleTranslationUnit(ASTContext &context){}
  • 獲取父類名稱:interfDecl->getSuperClass()->>getNameAsString()
  • 是否是實現類:if(isa<ObjCImplDecl>(decl)){}

  • 是否是category: if(isa<ObjCCategoryDecl>(decl)){}

  • 是否是協議: if(isa<ObjCProtocolDecl>(decl)){}
  • 是否是 property:if(isa<ObjCPropertyDecl>(decl)){}

是否是例項變數:objcIsInstanceMethod = propertyDecl->isInstanceProperty();
property型別(修飾符例如NSString):propertyDecl->getType().getAsString();
getter方法名稱:propertyDecl->getGetterName().getAsString()
setter方法名稱:propertyDecl->getSetterName().getAsString()
是否只讀:propertyDecl->isReadOnly()
是否是類property:propertyDecl->isClassProperty()
是否是原子性:propertyDecl->isAtomic()

b. 是否是成員變數 :if (isa<ObjCIvarDecl>(decl)) {}
成員變數名稱:ivarDecl->getNameAsString()

c. 是否是引數 : if (isa<ObjCTypeParamDecl>(decl)){}

@interface NSDictionary<Key : id<NSCopying>, Value>@end
key,value就是paramter
  • 是否是方法 : if(isa<ObjCMethodDecl>(decl)){}
是否是例項方法: methodDecl->isInstanceMethod()
selector名稱: methodDecl->getSelector().getAsString()
返回值型別:methodDecl->getReturnType().getAsString()
引數:
for(ArrayRef<ParmVarDecl *>::iterator it = methodDecl->param_begin();it!=methodDecl->param_end();it++){
    cout<<"引數:"<<((*it)->getNameAsString())<<"引數型別:"<<(*it)->getType().getAsString()<<endl;
}

d. 是否是變數方法列舉等 if(isa<DeclRefExpr>(s)){}

宣告的名稱:callExpr->getDecl()->->getNameAsString()
是否是變數:isa<VarDecl>(decl)
是否是函式:isa<FunctionDecl>(decl)
是否是列舉:isa<EnumConstantDecl>(decl)

e. 向object-c物件傳送訊息 isa<ObjCMessageExpr>(s)

呼叫者:objcExpr->getSelector().getAsString() 
函式本身名稱: objcExpr->getSelector().getAsString() 
接受訊息型別:objcExpr->getReceiverType().getAsString()

3、獲取編譯命令

3.1、獲取編譯命令

xcodebuild clean
xcodebuild -workspace OneTravel.xcworkspace -scheme OneTravel CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -dry-run -configuration Release| ruby onepretty

解釋:
CODE_SIGN_IDENTITY=”” CODE_SIGNING_REQUIRED=NO:表示不需要證書編譯
-dry-run:只獲取編譯命令,執行

onepretty: 從xcpretty中抽取的工具,移除了無用程式碼,添加了複製標頭檔案軟連線功能

3.2、修改編譯命令

針對 libtool 的命令適配,其他引數見連結

a.移除-gmodules: 這個命令會打包編譯資訊,自定義的libtool不支援,而且也沒有用。

b.移除 -c和-o及其引數: 僅解析ast,這是無用引數

c.新增引用c++庫(如果要解析一些.cpp和.mm檔案): -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1

d.替換工具: 將 clang 替換成自己的工具,如onec -- -x --後面對應對應,雙橫線參見

示例如下(精簡版):

/Users/xx/Documents/plugin/bin/bin/onec /Users/xx/Documents/conn_connection.cpp  -outdir=~/Desktop -- -x c++ -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1

4、libtool 工具開發

4.1 新增程式碼和 CMake檔案

這裡寫圖片描述

E88D7FA1-A055-4AE1-A218-14100B54ABD1

進入 llvm_build 資料夾清空原來的檔案,重新編譯程式碼 cmake -G Xcode ../llvm -DCMAKE_BUILD_TYPE:STRING=MinSizeRel

4.2 一些模組的簡介

一些clang元件的作用:
libclangLex:預處理、詞法分析、巨集處理、詞元(token)、語法構造;
libclangAST:該庫是用來建立、管理、遍歷AST
libclangParse:語法分析,用來解析詞法分析後的結果
libclangSema:語義分析
libclangCodeGen:目標相關的程式碼分析
libclangAnaylysis:用於進行靜態分析用的
libclangRewrite:程式碼重新寫入(不知道該怎麼解釋,稍後理解了再做解釋)
libclangBasic:clang的基礎雜項庫

5、 外掛和 libtool 工具簡單對比

外掛 libtool
解析速度 稍快
包大小
獲取編譯命令 直接使用 xcodebuild 生成的命令
與 xcode 整合 可以

由於 libtool 和clang 外掛的大部分api可以通用,因此實際工作用中選擇哪個都可以,如果出現問題,兩者的程式碼可以低成本的相互遷移。

相關推薦

手把手開發 clang 外掛

Clang是llvm的編譯器前端,非常適合進行原始碼分析.目前開源的oclint就是基於clang進行的程式碼靜態檢查.工作中遇到了一些問題需要進行程式碼分析,所以學習了外掛的開發流程.既然開發外掛就要有合適的IDE,Mac上最合適的無疑是xcode了.本文將講

手把手開發chrome擴展一:開發Chrome Extenstion其實很簡單

evernote 把手 擴展 data文件夾 現在 效果 界面 nag blog 手把手教你開發chrome擴展一:開發Chrome Extenstion其實很簡單 手把手教你開發Chrome擴展二:為html添加行為 手把手教你開發Chrome擴展三:關於本地存儲數據

手把手開發jquery插件(一)

PE ora ID outside sep write -c visio .sh Just as the auther of jQuery Tools said: 上海代孕 http://www.xyrjkf.cn/ jQuery UI has a so-called

手把手開發App(HelloWorld)

建立HelloWorld應用 啟動HBuilder(下載地址:http://www.dcloud.io/); 在選單欄中選擇“檔案”-> “新建”->“移動App”(快捷鍵Ctrl+N A),開啟“建立移動App”對話方塊,在應用名稱中輸入“HelloWorld”;

手把手開發一個babel-plugin

需求 在最近的開發過程中,不同的專案、不同的頁面都需要用到某種UI控制元件,於是很自然的將這些UI控制元件拆出來,單獨建立了一個程式碼庫進行維護。下面是我的元件庫大致的目錄結構如下: ... - lib - components - comp

手把手編寫Logstash外掛

使用過Logstash的朋友都知道,它強大的外掛生態幾乎覆蓋了所有的開源框架。從基本的http、tcp、udp、file,到強大的kafa、redis、ganglia,還有豐富的解析工具,比如date、json、grok、kv等等,有了它再也不用擔心資料不好蒐集了! 不過需求是無限的,如果這些框架都不滿足怎麼

手把手開發基於深度學習的人臉識別【考勤/簽到】系統

人臉識別介紹 人臉識別技術是一項非接觸式、使用者友好、非配合型的計算機視覺識別技術。隨著機器學習、深度學習等技術的發展,人臉識別的應用正日趨完善和成熟。本文將介紹人臉識別技術如何用於考勤/簽到系統。 本文將主要從以下幾個方面闡述: 平臺環境需求涉及的技術點人臉識

【備忘】2018年最新node.js+ES+Koa2手把手開發一個短視訊網站視訊教程

1) 2018年前端程式設計趨勢2) ES6與ES7 語法特性與編寫規範3) Koa 框架 API深入講解4) Koa1 、Koa2、 Express 三大框架特點5) 開始搭建一個短片網站6) 利用爬蟲爬取網站所需基礎資料7) 深度學習 Node.js 非同步 IO8)

開發jQuery外掛(轉)

要說jQuery 最成功的地方,我認為是它的可擴充套件性吸引了眾多開發者為其開發外掛,從而建立起了一個生態系統。這好比大公司們爭相做平臺一樣,得平臺者得天下。蘋果,微軟,谷歌等巨頭,都有各自的平臺及生態圈。 學會使用jQuery並不難,因為它簡單易學,並且相信你接觸jQuery後肯定也使用或熟悉了不少其

Android studio 2 手把手使用kotlin外掛

Kotlin for Android 最近谷歌IO大會, 把kotlin納入了Android開發首選語言, 估計這與谷歌和oracle一直在打官司的緣故分不開吧, 而且kotlin本身就很好用,不只是增加語法糖,而且kotlin-native是基於自己的run

手把手開發docker一樣的命令列

目錄前言一、安裝二、初始化應用初始化專案建立入口檔案cmd/root.go建立主程式main.go三、如何自定義命令建立hello子命令建立version子命令四、如何設定flag選項全域性選項本地選項設定必填繫結配置五、如何設定arguments使用示例六、如何使用引數獲取flag引數獲取args引數七、如

從0開始,手把手開發並部署上線一個知識測驗微信小程式

## 上線專案演示 微信搜尋[放馬來答]或掃以下二維碼體驗: ![](https://gitee.com/kamiba/images4mk2/raw/master/20200709074129.png) ## 專案原始碼 [ 專案原始碼](https://gitee.com/kamiba/wecha

手把手5分鐘從零開發一款簡易的IDEA外掛!專案經驗/畢設不愁了!

我這個人沒事就喜歡推薦一些好用的 [IDEA 外掛](https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1319419426898329600&__biz=Mzg2OTA0Njk0OA==#wechat_redir

手把手用webpack3搭建react項目(開發環境和生產環境)(一)

stc reac config nod top llb cor git history 開發環境和生產環境整個配置源碼在github上,源碼地址:github-webpack-react 如果覺得有幫助,點個Star謝謝!! (一)是開發環境,(二)是生產環境。 一、首

手把手實現電商網站開發》課程學習總結

選擇器 AR 進行 ron 需要 float 慕課 tex github 地址:http://www.imooc.com/learn/100 這是一個純HTML/CSS的教學視頻,沒有JS。 這個視頻課程的學習我已經接近尾聲了,我大概是17年11月開始觀看學習的吧,斷斷續

手把手使用 Clion 開發 Linux C++ 項目

變量 調試器 img 格式 res return double 分享圖片 center 手把手教你使用 Clion 開發 Linux C++ 項目 關於CLion CLion是一款專為開發C及C++所設計的跨平臺IDE。它是以IntelliJ為基礎設計的,包含了許多智能

手把手搭建React Native 開發環境 - ios篇 (React [email&#

由於之前我是h5的,沒接觸過ios和安卓, 也不瞭解xcode配置,所以 建議學reace-native之前還是先去了解一下ios和安卓開發環境搭建等問題。 環境下載及配置 nodejs:https://nodejs.org/en/download/ 設定淘寶映象 $ npm con

手把手做jsp servlet mysql實現的圖書管理系統附帶視訊開發教程和完整原始碼

上一個教程我們做的是對資料庫框架底層原理的講解,然後教大家做了一個自己的資料庫框架,這次我們做的這個圖書管理系統就是用我們上個教程自己寫的資料庫框架,整個專案做完框架執行的很穩定,沒有出現任何問題。如果你還沒有學習我們的那個資料庫框架教程的話我建議你還是先去學習那個資料庫框架的教程,地址是:ht

手把手如何在Android下進行JNI開發(入門)

在進行Android開發的過程中,我們必定會遇到視訊影象處理、高強度密集運算、特殊演算法等場景,這時我們就不得不需要去接觸一些C/C++程式碼,進行JNI開發。下面我將從Android.mk和CMake這兩種方式教大家如何進行開發。文章結尾將給出演示的專案程式碼,如果你能耐心地仔細看完,相信你一定能掌握

手把手實現電商網站開發

1-1 電商網站開發課程概況 1-2 電商網站開發準備工作 1-3 電商網站首頁開發之頂部結構 1-4 電商網站開發之頂部細化 1-5 電商網站開發之導航欄(上) 1-6 電商網站開發之導航欄(下) 1-7 電商網站開發之Banner部分 1-8 電商網站開發之主列表左側 1-9 電商網站首頁