dsa算法(19)

1.3.6. AllocIdentify遍

AllocIdentify遍用于识别作为malloc及其他分配器包装器(wrapper)的函数。它派生自ModulePass。这意味着该遍以整个程序作为单元,以不可预测的次序访问函数体,添加或删除函数。

下面的allocators与deallocators是AllocIdentify用来保存内存分配器及回收器的名称的容器。它们的类型都是std::set<std::string>。

 

94      bool AllocIdentify::runOnModule(Module& M){

95     

96        allocators.insert("malloc");

97        allocators.insert("calloc");

98        //allocators.insert("realloc");

99        //allocators.insert("memset");

100      deallocators.insert("free");

101      deallocators.insert("cfree");

102   

103      bool changed;

104      do {

105        changed = false;

106        std::set<std::string> TempAllocators;

107        TempAllocators.insert( allocators.begin(),allocators.end());

108        std::set<std::string>::iterator it;

109        for(it =TempAllocators.begin(); it != TempAllocators.end(); ++it) {

110          Function* F = M.getFunction(*it);

111          if(!F)

112            continue;

113          for(Value::use_iteratorui = F->use_begin(), ue = F->use_end();

114              ui != ue; ++ui) {

115            // iteratethough all calls to malloc

116            if (CallInst* CI =dyn_cast<CallInst>(*ui)) {

117              // The functionthat calls malloc could be a potential allocator

118              Function *WrapperF =CI->getParent()->getParent();

119              if(WrapperF->doesNotReturn())

120                continue;

121             if(!(WrapperF->getReturnType()->isPointerTy()))

122                continue;

123              bool isWrapper = true;

124              for(Function::iterator BBI = WrapperF->begin(), E = WrapperF->end(); BBI !=E; ) {

125                BasicBlock &BB = *BBI++;

126   

127                // Onlylook at return blocks.

128                ReturnInst *Ret =dyn_cast<ReturnInst>(BB.getTerminator());

129                if (Ret == 0) continue;

130   

131                //checkfor ALL return values

132                if(flowsFrom(Ret, CI)) {

133                  continue;

134                } else {

135                  isWrapper = false;

136                  break;

137                }

138                // iftrue for all return add to list of allocators

139              }

140              if(isWrapper)

141                isWrapper = isWrapper && isNotStored(CI);

142              if(isWrapper) {

143                changed =(allocators.find(WrapperF->getName()) == allocators.end());

144                if(changed) {

145                  ++numAllocators;

146                 allocators.insert(WrapperF->getName());

147                  DEBUG(errs() <<WrapperF->getName().str() << "\n");

148                }

149              }

150            }

151          }

152        }

153      } while(changed);

 

110行的Module::getFunction在该模块中查找指定的函数,如果没有就返回null。如果模块中使用了内存分配器,在113行遍历这个函数的使用者,116行确保这个使用是一个函数调用。接下来119行与121行确保这个调用者返回一个指针。在124行我们遍历这个函数中的指令,对其中的ReturnInst调用下面的方法。

 

37      bool AllocIdentify::flowsFrom(Value *Dest,Value*Src) {

38        if(Dest == Src)

39          returntrue;

40        if(ReturnInst *Ret =dyn_cast<ReturnInst>(Dest)) {

41          returnflowsFrom(Ret->getReturnValue(), Src);

42        }

43        if(PHINode *PN =dyn_cast<PHINode>(Dest)) {

44          Function *F =PN->getParent()->getParent();

45          LoopInfo &LI = getAnalysis<LoopInfo>(*F);

46          // If this is aloop phi, ignore.

47          if(LI.isLoopHeader(PN->getParent()))

48            returnfalse;

49          bool ret = true;

50          for(unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {

51           ret = ret &&flowsFrom(PN->getIncomingValue(i), Src);

52          }

53          return ret;

54        }

55        if(BitCastInst *BI =dyn_cast<BitCastInst>(Dest)) {

56          returnflowsFrom(BI->getOperand(0), Src);

57        }

58        if(isa<ConstantPointerNull>(Dest))

59          returntrue;

60        return false;

61      }

 

flowsFrom检查来自Src的值是否传播到Dest,在有限情形的递归后,使得flowsFrom返回true的条件只有38与58行。这是因为我们只检查简单的封装函数,它的返回值必须都是“return new …;”或者“return NULL;”以及“if (…){ p = new …; }else { p =NULL} return NULL;”这样的语句(包括额外的指针类型间的转换)。

除此之外,还要确保对分配函数调用的结果不会保存其他函数可以直接访问的地方(即不通过当前函数的返回值)。这就是isNotStored的作用。

 

63      bool isNotStored(Value *V) {

64        // check that Vis not stored to a location that is accessible outside this fn

65        for(Value::use_iteratorui = V->use_begin(), ue = V->use_end();

66            ui != ue; ++ui) {

67          if(isa<StoreInst>(*ui))

68            return false;

69          if(isa<ICmpInst>(*ui))

70            continue;

71          if(isa<ReturnInst>(*ui))

72            continue;

73          if(BitCastInst *BI =dyn_cast<BitCastInst>(*ui)) {

74            if(isNotStored(BI))

75              continue;

76            else

77              returnfalse;

78          }

79          if(PHINode *PN =dyn_cast<PHINode>(*ui)) {

80            if(isNotStored(PN))

81              continue;

82            else

83              returnfalse;

84          }

85     

86          returnfalse;

87        }

88        return true;

89      }

 

如果上述条件都满足(142行),这是一个内存分配函数的封装函数,把它加入allocators,继续查找它的封装函数是否存在,直到没有发现这样的函数。

 

AllocIdentify::runOnModule(续)

 

155      do {

156        changed = false;

157        std::set<std::string>TempDeallocators;

158        TempDeallocators.insert(deallocators.begin(), deallocators.end());

159        std::set<std::string>::iterator it;

160        for(it =TempDeallocators.begin(); it != TempDeallocators.end(); ++it) {

161          Function* F = M.getFunction(*it);

162   

163          if(!F)

164            continue;

165          for(Value::use_iteratorui = F->use_begin(), ue = F->use_end();

166              ui != ue; ++ui) {

167            // iteratethough all calls to malloc

168            if (CallInst* CI =dyn_cast<CallInst>(*ui)) {

169              // Thefunction that calls malloc could be a potential allocator

170              Function *WrapperF =CI->getParent()->getParent();

171   

172              if(WrapperF->arg_size() != 1)

173                continue;

174             if(!WrapperF->arg_begin()->getType()->isPointerTy())

175                continue;

176              Argument *arg =dyn_cast<Argument>(WrapperF->arg_begin());

177              if(flowsFrom(CI->getOperand(1),arg)) {

178                changed =(deallocators.find(WrapperF->getName()) == deallocators.end());

179                if(changed) {

180                  ++numDeallocators;

181                 deallocators.insert(WrapperF->getName());

182                  DEBUG(errs() <<WrapperF->getName().str() << "\n");

183                }

184              }

185            }

186          }

187        }

188      } while(changed);

189      return false;

190    }

 

对内存回收函数的处理也是非常类似的。runOnModule最后返回false,表示它没有改变这个模块对象。

你可能感兴趣的:(算法,DSA,compiler,编译器,llvm)