zoukankan      html  css  js  c++  java
  • LLVM一个简单的Pass

      1 // Before :
      2 //                            entry
      3 //                              |
      4 //                        ______v______
      5 //                       |   switch    |
      6 //                       |_____________|
      7 //                              |
      8 //              +---------------+
      9 //              |         _____________
     10 //              +------->|    case1    |-------+
     11 //              |        |_____________|       |
     12 //              +------->|    case2    |-------+
     13 //              |        |_____________|       |
     14 //              +------->|    case3    |-------+
     15 //              |        |_____________|       |
     16 //              +------->|    case4    |-------+
     17 //              |        |_____________|       |
     18 //              +------->|    case5    |-------+
     19 //              |        |_____________|       |
     20 //              +------->|   default   |-------+
     21 //                       |_____________|       |
     22 //                                             |
     23 //                              +--------------+
     24 //                              |
     25 //                              v
     26 //                           return
     27 //
     28 // After :
     29 //                               entry
     30 //                                 |
     31 //                           ______v______
     32 //          +-------(true)--|     if1     |
     33 //          | +----(false)--|_____________|
     34 //          | |              _____________  
     35 //          | |             |     else    |
     36 //          | | +---------->|_____________|------------------+
     37 //          | | |            _____________                   |
     38 //          | | +--(false)--|     if5     |                  |
     39 //          | | +---------->|_____________|--(true)--------+ |
     40 //          | | |            _____________                 | |
     41 //          | | +--(false)--|     if4     |                | |
     42 //          | | +---------->|_____________|--(true)------+ | |
     43 //          | | |            _____________               | | |
     44 //          | | +--(false)--|     if3     |              | | |
     45 //          | | +---------->|_____________|--(true)----+ | | |
     46 //          | | |            _____________             | | | |
     47 //          | | +--(false)--|     if2     |            | | | |
     48 //          | +------------>|_____________|--(true)--+ | | | |
     49 //          |                _____________           | | | | |
     50 //          +-------------->|     run1    |          | | | | |
     51 //          +---------------|_____________|          | | | | |
     52 //          |                _____________           | | | | |
     53 //          +---------------|     run2    |<---------+ | | | |
     54 //          |               |_____________|            | | | |
     55 //          |                _____________             | | | |
     56 //          +---------------|     run3    |<-----------+ | | |
     57 //          |               |_____________|              | | |
     58 //          |                _____________               | | |
     59 //          +---------------|     run4    |<-------------+ | |
     60 //          |               |_____________|                | |
     61 //          |                _____________                 | |
     62 //          +---------------|     run5    |<---------------+ |
     63 //          |               |_____________|                  |
     64 //          |                _____________                   |
     65 //          +---------------|     run6    |<-----------------+
     66 //          |               |_____________|
     67 //          |              
     68 //          +----------------------+           
     69 //                                 |
     70 //                                 v
     71 //                               return
     72 //                      
     73 //        当前模块执行后的整体流程图如上
     74 //    当前模块仅支持将LLVM识别的switch 语句修改成 if else 格式,
     75 //    但是这种改动对IDA 没有太大影响
     76 
     77 #include "stdafx.h"
     78 
     79 #include "LowerSwitchInst.h"
     80 
     81 
     82 static llvm::zoo::cl::opt_bool _lsi("LowerSwitchInst", "lsi", false, "改变Switch 语句成if else 格式");
     83 
     84 static llvm::zoo::cl::opt_str _lsi_name("LowerSwitchInst", "lsi_name", "", "要替换的函数名字");
     85 
     86 
     87 namespace zoollvm
     88 {
     89     LowerSwitchInst::LowerSwitchInst()
     90     {
     91         _bWorked = false;
     92     }
     93 
     94     void LowerSwitchInst::ClearWork()
     95     {
     96         _bWorked = false;
     97     }
     98 
     99     bool LowerSwitchInst::IsWorked()
    100     {
    101         return _bWorked;
    102     }
    103 
    104     bool LowerSwitchInst::Run(llvm::Module &M, llvm::Function &F)
    105     {
    106         std::vector<llvm::BasicBlock*> _vecDelete;
    107         std::vector<llvm::SwitchInst*> _vecDeleteInst;
    108         //    删除列表
    109 
    110         ZooPrint("Function Name = [%s] 
    ", zoollvm::module::function::GetFunctionName(F).c_str());
    111         for (llvm::Function::iterator I = F.begin(), E = F.end(); I != E; I++)
    112         {
    113             llvm::BasicBlock &Cur = *I;
    114             auto i = Cur.getTerminator();
    115             if (i == NULL)
    116             {
    117                 continue;
    118             }
    119             if (llvm::SwitchInst *SI = llvm::dyn_cast<llvm::SwitchInst>(i))
    120             {
    121                 _bWorked = true;
    122                 _vecDelete.push_back(&*I);
    123                 _vecDeleteInst.push_back(SI);
    124 
    125                 ZooPrint("SI = %p 
    ", SI);
    126                 ZooPrint("    getOpcodeName : [%s] 
    ", SI->getOpcodeName());
    127 
    128                 Lower(M, F, Cur, *SI);
    129                 ZooPrint("
    ");
    130             }
    131         }
    132         ZooPrint("Write Pass Success 
    ");
    133         for (auto it : _vecDeleteInst)
    134         {
    135             zoollvm::module::function::block::RemoveBlockSelf(it);
    136         }
    137         ZooPrint("Delete Inst Success 
    ");
    138         return true;
    139     }
    140 
    141     bool LowerSwitchInst::Lower(llvm::Module &M, llvm::Function &F, llvm::BasicBlock &B, llvm::SwitchInst &S)
    142     {
    143         llvm::Value *Val = S.getCondition();
    144         struct CaseRange
    145         {
    146             llvm::ConstantInt* cValue;                //
    147             llvm::BasicBlock* BB;                //    处理块
    148             CaseRange(llvm::ConstantInt *low, llvm::BasicBlock *bb) : cValue(low), BB(bb) {}
    149         };
    150         std::vector<CaseRange> Cases;
    151         ZooPrint("        Value = [%s] 
    ", Val->getName().str().c_str());
    152         ULONG NumSimpleCases = 0;
    153         //    找到所有case 块
    154         for (auto Case : S.cases())
    155         {
    156             if (Case.getCaseSuccessor() == S.getDefaultDest())
    157             {
    158                 continue;
    159             }
    160             Cases.push_back(CaseRange(Case.getCaseValue(), Case.getCaseSuccessor()));
    161             ++NumSimpleCases;
    162         }
    163         ZooPrint("            NumSimpleCases = [%d] 
    ", NumSimpleCases);
    164 
    165         //    修改所有case 块
    166         llvm::BasicBlock *bb = &B;
    167         for (auto it : Cases)
    168         {
    169             int64_t nextValue = it.cValue->getSExtValue();
    170 
    171             //    创建一个基本块,目前这个基本块位置未知,只是先要有,用它占位
    172             auto ba = zoollvm::module::function::block::Create(B.getContext());
    173 
    174             //    创建一个逻辑指令
    175             //    v = (Val == nextValue )
    176             //    这个逻辑指令的位置,放在当前块的最后一条指令的位置,即   (llvm::BinaryOperator *)&*(bb->end() --)
    177             auto v = zoollvm::op_code::compare::CreateICmpEQ(Val, zoollvm::value::const_value::CreateInt64(M, nextValue), (llvm::BinaryOperator *)&*(bb->end() --));
    178             
    179             //    if v then exec else 空block end
    180             //    这个比较指令的位置,放在当前块的最后一条指令,结合上下文,就是放到上面的逻辑指令的下一条处,就是 bb 的 end 处
    181             zoollvm::op_code::branch::CreateCondBr(v, it.BB, ba, bb);
    182 
    183             //    插入刚才创建的基本块,位置是当前基本块的下一个位置,即顺序向下执行的话,就是当前新的基本块跟在上面的比较指令后面
    184             ba->insertInto(&F, B.getNextNode());
    185 
    186             //    修改要操作的基本块,下一个循环,下一条指令,都从这个新的基本块里面添加
    187             bb = ba;
    188 
    189             ZooPrint("                nextValue = [%I64d] 
    ", nextValue);
    190         }
    191         //    最后补一个跳到default 的指令,位置是在最初第一个基本块后面的第一个基本块中
    192         //    上面由于添加指令是从上往下加,而添加基本块是从下往上加,所以最后一个新的基本块在第一条指令的下面,这也是最后一个跳转的块
    193         zoollvm::op_code::branch::CreateBr(S.getDefaultDest(), B.getNextNode());
    194 
    195 
    196         return true;
    197     }
    198 
    199 
    200     class LowerSwitchInstPass : public llvm::ModulePass, public zoollvm::frame::Base
    201     {
    202     public:
    203         static char ID; // pass identification
    204         LowerSwitchInstPass() : ModulePass(ID), zoollvm::frame::Base("LowerSwitchInstPass")
    205         {
    206             zoollvm::opt::GetFunctionNameList(_lsi_name, _vec);
    207         }
    208 
    209 
    210         //    启动当前Pass
    211         virtual bool runOnModule(llvm::Module &M)
    212         {
    213             if (_lsi == false)
    214             {
    215                 return true;
    216             }
    217 
    218             LowerSwitchInst lsi;
    219 
    220             for (auto it = M.begin(); it != M.end(); it++)
    221             {
    222                 if (zoollvm::opt::IsFunctionInList(_vec, *it))
    223                 {
    224                     lsi.Run(M, *it);
    225                 }
    226             }
    227 
    228             return true;
    229         }
    230 
    231     private:
    232         std::vector<std::string> _vec;
    233     };
    234 }
    235 
    236 char zoollvm::LowerSwitchInstPass::ID = 0;
    237 llvm::Pass * createLowerSwitchInst()
    238 {
    239     return new zoollvm::LowerSwitchInstPass();
    240 }

    由于新版LLVM(9.0.0),无法直接调用Util 自带的 LowerSwitch 了,所以这里,我自己弄了一个,

    主要功能是展开Switch,把它变成if else,理论上其实没啥区别,但是实际上在LLVM的角度上看,区别很大,

    switch 实际上是一条 instruction ,后面的 case 是和switch 在一起的一条 instruction,

    这就导致,如果不对它做处理,那么这个 instruction 是非常大的,由于这一条指令是在一个 block 里面的,所以结构也清晰,

    if else 则不同,一片 if else 实际上是一片 block ,不管做什么操作也稍微更容易一些

  • 相关阅读:
    android自定义Dialog
    go笔记-内存回收分析、内存统计信息字段释义
    go笔记-defer以及性能
    go笔记-goroutine和panic
    并发编程-高性能IO-reactor模式
    go笔记-查看coredump:delve调试工具
    IO多路复用[转]
    kubernates 1.20.6安装
    JavaScript 数组元素的一些操作
    如何理解 Java 多线程
  • 原文地址:https://www.cnblogs.com/suanguade/p/12174308.html
Copyright © 2011-2022 走看看