Пример #1
0
/// addObjCClass - Parse i386/ppc ObjC class data structure.
void LTOModule::addObjCClass(GlobalVariable *clgv) {
  ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer());
  if (!c) return;

  // second slot in __OBJC,__class is pointer to superclass name
  std::string superclassName;
  if (objcClassNameFromExpression(c->getOperand(1), superclassName)) {
    NameAndAttributes info;
    StringMap<NameAndAttributes>::value_type &entry =
      _undefines.GetOrCreateValue(superclassName);
    if (!entry.getValue().name) {
      const char *symbolName = entry.getKey().data();
      info.name = symbolName;
      info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
      info.isFunction = false;
      info.symbol = clgv;
      entry.setValue(info);
    }
  }

  // third slot in __OBJC,__class is pointer to class name
  std::string className;
  if (objcClassNameFromExpression(c->getOperand(2), className)) {
    StringSet::value_type &entry = _defines.GetOrCreateValue(className);
    entry.setValue(1);

    NameAndAttributes info;
    info.name = entry.getKey().data();
    info.attributes = LTO_SYMBOL_PERMISSIONS_DATA |
      LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT;
    info.isFunction = false;
    info.symbol = clgv;
    _symbols.push_back(info);
  }
}
static void readFuncList(GlobalVariable *Array, std::vector<Constant*> *Funcs) {
  if (!Array->hasInitializer())
    return;
  Constant *Init = Array->getInitializer();
  ArrayType *Ty = dyn_cast<ArrayType>(Init->getType());
  if (!Ty) {
    errs() << "Initializer: " << *Array->getInitializer() << "\n";
    report_fatal_error("ExpandCtors: Initializer is not of array type");
  }
  if (Ty->getNumElements() == 0)
    return;
  ConstantArray *InitList = dyn_cast<ConstantArray>(Init);
  if (!InitList) {
    errs() << "Initializer: " << *Array->getInitializer() << "\n";
    report_fatal_error("ExpandCtors: Unexpected initializer ConstantExpr");
  }
  std::vector<FuncArrayEntry> FuncsToSort;
  for (unsigned Index = 0; Index < InitList->getNumOperands(); ++Index) {
    ConstantStruct *CS = cast<ConstantStruct>(InitList->getOperand(Index));
    FuncArrayEntry Entry;
    Entry.priority = cast<ConstantInt>(CS->getOperand(0))->getZExtValue();
    Entry.func = CS->getOperand(1);
    FuncsToSort.push_back(Entry);
  }

  std::sort(FuncsToSort.begin(), FuncsToSort.end(), compareEntries);
  for (std::vector<FuncArrayEntry>::iterator Iter = FuncsToSort.begin();
       Iter != FuncsToSort.end();
       ++Iter) {
    Funcs->push_back(Iter->func);
  }
}
Пример #3
0
CtorDtorIterator::Element CtorDtorIterator::operator*() const {
  ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
  assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");

  Constant *FuncC = CS->getOperand(1);
  Function *Func = nullptr;

  // Extract function pointer, pulling off any casts.
  while (FuncC) {
    if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
      Func = F;
      break;
    } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
      if (CE->isCast())
        FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
      else
        break;
    } else {
      // This isn't anything we recognize. Bail out with Func left set to null.
      break;
    }
  }

  ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
  Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
  if (Data && !isa<GlobalValue>(Data))
    Data = nullptr;
  return Element(Priority->getZExtValue(), Func, Data);
}
Пример #4
0
/// Find the llvm.global_ctors list, verifying that all initializers have an
/// init priority of 65535.
static GlobalVariable *findGlobalCtors(Module &M) {
  GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
  if (!GV)
    return nullptr;

  // Verify that the initializer is simple enough for us to handle. We are
  // only allowed to optimize the initializer if it is unique.
  if (!GV->hasUniqueInitializer())
    return nullptr;

  if (isa<ConstantAggregateZero>(GV->getInitializer()))
    return GV;
  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());

  for (auto &V : CA->operands()) {
    if (isa<ConstantAggregateZero>(V))
      continue;
    ConstantStruct *CS = cast<ConstantStruct>(V);
    if (isa<ConstantPointerNull>(CS->getOperand(1)))
      continue;

    // Must have a function or null ptr.
    if (!isa<Function>(CS->getOperand(1)))
      return nullptr;

    // Init priority must be standard.
    ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
    if (CI->getZExtValue() != 65535)
      return nullptr;
  }

  return GV;
}
Пример #5
0
void ClassHierarchyUtils::findClassHierarchy(Module& M) {
  // Extract class hierarchy using std::type_info structures rather than debug
  // info. The former works even for when there are anonymous namespaces.
  // (for more info, see http://mentorembedded.github.io/cxx-abi/abi.html)
  // 
  // Class names are usually global, except in the case of anonymous namespaces, in which case
  // they may be renamed during linking. This renaming is not consistent across type_info and
  // vtables. For example, the following are for the same class:
  // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE60908 and
  // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE60906.
  // 
  // (renamed from
  // _ZTVN7content12_GLOBAL__N_115HeaderFlattenerE and
  // _ZTIN7content12_GLOBAL__N_115HeaderFlattenerE).
  //
  // VTables give us the corresponding type_info, so we process them first and store
  // the VT <-> TI mappings, as this will be useful later.
  for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) {
    GlobalVariable* VT = &*I;
    if (VT->getName().startswith("_ZTV")) {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      if (VT->hasInitializer()) {
        ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
        // all occurrences of a type_info object refer to this class's type_info, so we
        // can pick the first array
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(0));
        for (int i=0; i<VTinitElem->getNumOperands(); i++) {
          // type_info will be the first global variable in the array.
          // It's not always at a fixed index so we have to search for it...
          // The first one corresponds to the primary vtable, all others
          // correspond to secondary vtables. All type_info occurrences will
          // be the same.
          if (GlobalVariable* TI = dyn_cast<GlobalVariable>(VTinitElem->getOperand(i)->stripPointerCasts())) {
            if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
              report_fatal_error(TI->getName() + " <-> " + VT->getName() + " mapping already exists!");
            }
            // Record TI <-> VT mappings, as they will be useful later
            typeInfoToVTable[TI] = VT;
            vTableToTypeInfo[VT] = TI;
            break;  // we only need to process the first one
          }
        }
      }
      else {
        SDEBUG("soaap.util.classhierarchy", 1, dbgs() << "WARNING: VTable " << VT->getName() << " does not have initializer\n");
      }
    }
  }

  // Process type_info structures, recording class-hierarchy information and base offsets
  for (Module::global_iterator I=M.global_begin(), E=M.global_end(); I != E; I++) {
    GlobalVariable* G = &*I;
    if (G->getName().startswith("_ZTI")) {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found type_info: " << G->getName() << "\n");
      processTypeInfo(G, M);
    }
  }

  SDEBUG("soaap.util.classhierarchy", 3, ppClassHierarchy(classToSubclasses));
}
Пример #6
0
// add to analyze function pointer
bool PathList::extend_calledFunctionMap(Instruction *tmpfi, User *tmpuser, GlobalVariable *func_table, Function *ff)
{
	// the first operand of GetElementPtrInst is user of the table
	if (tmpfi->getOperand(0) == tmpuser) {
		errs()<<"=====find function which calls command_table\n";
//		coutn++;
		
		// if the index of the table is a constant int
		if (ConstantInt *cint = dyn_cast<ConstantInt>(tmpfi->getOperand(2))) {
			// todo: deal with the constantint index
			
		} else {// if the index is a variavle, then add all the funcitons of command_table into the CallGraph
			// get the initialization value of the global table
			if (Constant *C = func_table->getInitializer()) {
				llvm::ConstantArray *ca = dyn_cast<llvm::ConstantArray>(&*C);
				if (ca) {
					errs()<<"Get ConstantArray ca success.\n";
					errs()<<ca->getNumOperands()<<'\n';
					// get the element of the global table
					for (int cai = 0; cai < ca->getNumOperands(); cai++) {
						Constant *tmpca = ca->getOperand(cai);
						//tmpca->dump();
						ConstantStruct *cs = dyn_cast<ConstantStruct>(&*tmpca);
						if (cs) {
							//errs()<<"get ConstantStruct cs success.\n";
							//errs()<<cs->getNumOperands()<<'\n';
							Constant *tmpcs = cs->getOperand(1);
							//tmpcs->dump();
							//errs() << tmpcs->getNumOperands()<<'\n';
							//tmpcs->getType()->dump();
							//tmpcs->getOperand(0)->dump();
							
							// get the funciton pointer of the element
							if (Function *csfunc = dyn_cast<Function>(&*(tmpcs->getOperand(0)))) {
								//errs() << "get function tmpcs success.\n";
								// add the current funciton ff to the calledFunctionMap
								// as the funciton which calls function csfunc
								FunctionMapTy::iterator it2 = calledFunctionMap.find(csfunc);
								if(it2==calledFunctionMap.end()) //not find
								{
									calledFunctionMap[csfunc].push_back(std::make_pair(ff, tmpfi));
								}
								else {
									it2->second.push_back(std::make_pair(ff, tmpfi));
								}
							} 
						} 
					}
				} else 
					return false;
			} else {
				dbgs() << "Get the initialization value of the global table failed!\n";
				return false;
			}
		}
	} else 
		return false;
	return true;
}
Пример #7
0
Value *DbgStopPointInst::getDirectory() const {
  // Once the operand indices are verified, update this assert
  assert(LLVMDebugVersion == (7 << 16) && "Verify operand indices");
  GlobalVariable *GV = cast<GlobalVariable>(getContext());
  if (!GV->hasInitializer()) return NULL;
  ConstantStruct *CS = cast<ConstantStruct>(GV->getInitializer());
  return CS->getOperand(4);
}
Пример #8
0
void ControlFlowIntegrity::PatchDtorFunctions(void) {
  GlobalVariable *global_dtors = _M.getNamedGlobal("llvm.global_dtors");

  // check for dtor section
  if (!global_dtors || !global_dtors->getOperand(0)) {
    return;
  }

  Constant *c = global_dtors->getInitializer();
  if (!c)
    report_fatal_error("llvm.global_dtors without initializer!", false);

  ConstantArray *CA = dyn_cast<ConstantArray>(c);
  if (!CA)
    report_fatal_error("Cast to ConstantArray failed", true);

  for (Value *Op : ValueOpRange(*CA)) {
    ConstantStruct *CS = dyn_cast<ConstantStruct>(Op);
    if (!CS)
      report_fatal_error("Cast to ConstantStruct failed", true);

    Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      break; // found a NULL termintator, stop here

    Function *F = dyn_cast_or_null<Function>(FP);
    if (F == NULL) {
      // Strip off constant expression cast
      ConstantExpr *CE = dyn_cast<ConstantExpr>(FP);
      if (!CE)
        report_fatal_error("Cast to ConstantExpr failed", true);
      if (CE->isCast()) {
        FP = CE->getOperand(0);
      }
      F = dyn_cast_or_null<Function>(FP);
    }

    if (!F)
      report_fatal_error("Cast to Function failed", true);

    // set visibility to hidden (do not export), unless it is already
    // local (for ex. static), in which case we have to make it non-static
    if (F->hasLocalLinkage()) {
      F->setLinkage(llvm::GlobalValue::ExternalLinkage);
    }
    F->setVisibility(GlobalValue::HiddenVisibility);

    _FiniFunctions.insert(F->getName());
  }

  if (global_dtors->getNumUses() > 0)
    report_fatal_error("llvm.global_dtors uses count is > 0!", false);

  global_dtors->removeFromParent();

}
Пример #9
0
static std::vector<Function*> parseGlobalCtors(GlobalVariable *GV) {
	if (GV->getInitializer()->isNullValue())
		return std::vector<Function *>();
	ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
	std::vector<Function *> Result;
	Result.reserve(CA->getNumOperands());
	for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
		ConstantStruct *CS = cast<ConstantStruct>(*i);
		Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
	}
	return Result;
}
Пример #10
0
/// Given a llvm.global_ctors list that we can understand,
/// return a list of the functions and null terminator as a vector.
static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
  if (GV->getInitializer()->isNullValue())
    return std::vector<Function *>();
  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  std::vector<Function *> Result;
  Result.reserve(CA->getNumOperands());
  for (auto &V : CA->operands()) {
    ConstantStruct *CS = cast<ConstantStruct>(V);
    Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
  }
  return Result;
}
Пример #11
0
// what a hack
static Function *getStubFunctionForCtorList(Module *m,
                                            GlobalVariable *gv, 
                                            std::string name) {
  assert(!gv->isDeclaration() && !gv->hasInternalLinkage() &&
         "do not support old LLVM style constructor/destructor lists");

  std::vector<Type *> nullary;

  Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(m->getContext()),
						    nullary, false),
				  GlobalVariable::InternalLinkage, 
				  name,
                              m);
  BasicBlock *bb = BasicBlock::Create(m->getContext(), "entry", fn);
  
  // From lli:
  // Should be an array of '{ int, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer());
  if (arr) {
    for (unsigned i=0; i<arr->getNumOperands(); i++) {
      ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i));
#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5)
      // There is a third *optional* element in global_ctor elements (``i8
      // @data``).
      assert((cs->getNumOperands() == 2 || cs->getNumOperands() == 3) &&
             "unexpected element in ctor initializer list");
#else
      assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list");
#endif
      Constant *fp = cs->getOperand(1);      
      if (!fp->isNullValue()) {
        if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp))
          fp = ce->getOperand(0);

        if (Function *f = dyn_cast<Function>(fp)) {
	  CallInst::Create(f, "", bb);
        } else {
          assert(0 && "unable to get function pointer from ctor initializer list");
        }
      }
    }
  }
  
  ReturnInst::Create(m->getContext(), bb);

  return fn;
}
Пример #12
0
// Parse i386/ppc ObjC category data structure.
void LTOModule::addObjCCategory(GlobalVariable *clgv) {
  ConstantStruct *c = dyn_cast<ConstantStruct>(clgv->getInitializer());
  if (!c) return;

  // second slot in __OBJC,__category is pointer to target class name
  std::string targetclassName;
  if (!objcClassNameFromExpression(c->getOperand(1), targetclassName))
    return;

  NameAndAttributes info;
  StringMap<NameAndAttributes>::value_type &entry =
    _undefines.GetOrCreateValue(targetclassName);

  if (entry.getValue().name)
    return;

  const char *symbolName = entry.getKey().data();
  info.name = symbolName;
  info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED;
  entry.setValue(info);
}
Пример #13
0
bool CheckInserter::doFinalization(Module &M) {
  // We couldn't directly add an element to a constant array, because doing so
  // changes the type of the constant array.

  // element type of llvm.global_ctors
  StructType *ST = StructType::get(IntType,
                                   PointerType::getUnqual(InitFiniType),
                                   NULL); // end with null

  // Move all existing elements of <GlobalName> to <Constants>.
  vector<Constant *> Constants;
  if (GlobalVariable *GlobalCtors = M.getNamedGlobal("llvm.global_ctors")) {
    ConstantArray *CA = cast<ConstantArray>(GlobalCtors->getInitializer());
    for (unsigned j = 0; j < CA->getNumOperands(); ++j) {
      ConstantStruct *CS = cast<ConstantStruct>(CA->getOperand(j));
      assert(CS->getType() == ST);
      // Assume nobody is using the highest priority, so that <F> will be the
      // first to run as a ctor.
      assert(!cast<ConstantInt>(CS->getOperand(0))->isMinValue(true));
      Constants.push_back(CS);
    }
    GlobalCtors->eraseFromParent();
  }
  // Add <F> with the highest priority.
  Constants.push_back(ConstantStruct::get(ST,
                                          ConstantInt::get(IntType, INT_MIN),
                                          EnterProcess,
                                          NULL));
  // Create the new llvm.global_ctors.
  ArrayType *ArrType = ArrayType::get(ST, Constants.size());
  new GlobalVariable(M,
                     ArrType,
                     true,
                     GlobalValue::AppendingLinkage,
                     ConstantArray::get(ArrType, Constants),
                     "llvm.global_ctors");

  return true;
}
Пример #14
0
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    classes.push_back(TI);

    // extract direct base classes from type_info
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) {
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI);
          
        }
        else {
          // abi::__vmi_class_type_info
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            int offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            int offset = offset_flags >> 8; // TODO: is this value defined as a constant somewhere?
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            classToBaseOffset[TI][baseTI] = offset;
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI);
          }
        }
      }
    }
Пример #15
0
void MemoryInstrumenter::lowerGlobalCtors(Module &M) {
  // Find llvm.global_ctors.
  GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
  if (!GV)
    return;
  assert(!GV->isDeclaration() && !GV->hasLocalLinkage());

  // Should be an array of '{ int, void ()* }' structs.  The first value is
  // the init priority, which must be 65535 if the bitcode is generated using
  // clang.
  if (ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer())) {
    for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
      ConstantStruct *CS =
        dyn_cast<ConstantStruct>(InitList->getOperand(i));
      assert(CS);
      assert(CS->getNumOperands() == 2);

      // Get the priority.
      ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
      assert(Priority);
      // TODO: For now, we assume all priorities must be 65535.
      assert(Priority->equalsInt(65535));

      // Get the constructor function.
      Constant *FP = CS->getOperand(1);
      if (FP->isNullValue())
        break;  // Found a null terminator, exit.

      // Explicitly call the constructor at the main entry.
      CallInst::Create(FP, "", Main->begin()->getFirstNonPHI());
    }
  }

  // Clear the global_ctors array.
  // Use eraseFromParent() instead of removeFromParent().
  GV->eraseFromParent();
}
Пример #16
0
void PrivilegedCallAnalysis::doAnalysis(Module& M, SandboxVector& sandboxes) {
  // first find all methods annotated as being privileged and then check calls within sandboxes
  if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) {
    ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts());
    for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) {
      ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get());

      // get the annotation value first
      GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts());
      ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
      StringRef annotationStrArrayCString = annotationStrArray->getAsCString();

      GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts());
      if (isa<Function>(annotatedVal)) {
        Function* annotatedFunc = dyn_cast<Function>(annotatedVal);
        if (annotationStrArrayCString == SOAAP_PRIVILEGED) {
          outs() << "   Found function: " << annotatedFunc->getName() << "\n";
          privAnnotFuncs.push_back(annotatedFunc);
        }
      }
    }
  }          

  // now check calls within sandboxes
  for (Function* privilegedFunc : privAnnotFuncs) {
    for (User* U : privilegedFunc->users()) {
      if (CallInst* C = dyn_cast<CallInst>(U)) {
        Function* enclosingFunc = C->getParent()->getParent();
        for (Sandbox* S : sandboxes) {
          if (!S->hasCallgate(privilegedFunc) && S->containsFunction(enclosingFunc)) {
            outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << privilegedFunc->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n";
            if (MDNode *N = C->getMetadata("dbg")) {  // Here I is an LLVM instruction
              DILocation Loc(N);                      // DILocation is in DebugInfo.h
              unsigned Line = Loc.getLineNumber();
              StringRef File = Loc.getFilename();
              outs() << " +++ Line " << Line << " of file " << File << "\n";
            }
          }
        }
      }
    }
  }

  /*
  for (Sandbox* S : sandboxes) {
    FunctionVector callgates = S->getCallgates();
    for (Function* F : S->getFunctions()) {
      for (BasicBlock& BB : F->getBasicBlockList()) {
        for (Instruction& I : BB.getInstList()) {
          if (CallInst* C = dyn_cast<CallInst>(&I)) {
            if (Function* Target = C->getCalledFunction()) {
              if (find(privAnnotFuncs.begin(), privAnnotFuncs.end(), Target) != privAnnotFuncs.end()) {
                // check if this sandbox is allowed to call the privileged function
                DEBUG(dbgs() << "   Found privileged call: "); 
                DEBUG(C->dump());
                if (find(callgates.begin(), callgates.end(), Target) == callgates.end()) {
                  outs() << " *** Sandbox \"" << S->getName() << "\" calls privileged function \"" << Target->getName() << "\" that they are not allowed to. If intended, annotate this permission using the __soaap_callgates annotation.\n";
                  if (MDNode *N = C->getMetadata("dbg")) {  // Here I is an LLVM instruction
                    DILocation Loc(N);                      // DILocation is in DebugInfo.h
                    unsigned Line = Loc.getLineNumber();
                    StringRef File = Loc.getFilename();
                    outs() << " +++ Line " << Line << " of file " << File << "\n";
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  */
}
Пример #17
0
void ClassHierarchyUtils::processTypeInfo(GlobalVariable* TI, Module& M) {
  if (find(classes.begin(), classes.end(), TI) == classes.end()) {
    SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Adding class " << TI->getName() << "\n");
    classes.push_back(TI);

    // First process the correspoding virtual table. We store the indexes of the primary
    // and secondary vtables, indexed by the corresponding subobject offset. This will allow
    // us to quickly jump to a particular sub-vtable.
    if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
      GlobalVariable* VT = typeInfoToVTable[TI]; 
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found vtable: " << VT->getName() << "\n");
      ConstantStruct* VTinit = cast<ConstantStruct>(VT->getInitializer());
      for (int i=0; i<VTinit->getNumOperands(); i++) {
        ConstantArray* VTinitElem = cast<ConstantArray>(VTinit->getOperand(i));
        for (int j=0; j<VTinitElem->getNumOperands(); j++) {
          // Each sub-vtable is preceded by a reference to the class's type_info instance.
          // (See https://mentorembedded.github.io/cxx-abi/abi.html).
          if (TI == VTinitElem->getOperand(j)->stripPointerCasts()) {
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Found TI at index " << i << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "Storing mapping " << VT->getName() << " <-> " << TI->getName() << "\n");
            
            // the offset to top is the offset from the vptr pointing to this
            // sub-vtable, back to the top of the object. This will be negative,
            // but the absolute value gives us the offset from the start of the
            // object (i.e. first vptr), to the subobject.
            int offsetToTop = 0;
            if (ConstantExpr* offsetValCast = dyn_cast<ConstantExpr>(VTinitElem->getOperand(j-1)->stripPointerCasts())) {
              ConstantInt* offsetVal = cast<ConstantInt>(offsetValCast->getOperand(0));
              offsetToTop = offsetVal->getSExtValue(); // will be 0 for the primary
            }
            if (offsetToTop > 0) {
              report_fatal_error("ERROR: offsetToTop is positive!");
            }
            else {
              offsetToTop *= -1;
            }
            
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "offsetToTop: " << offsetToTop << "\n")
            vTableToSecondaryVTableMaps[VT][offsetToTop] = pair<int, int>(i, j+1);
          }
        }
      }
    }
    else {
      SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No vtable found for " << TI->getName() << "\n");
    }

    // Now process the type_info struct, extract direct base class info (what
    // their subobject offsets are, or if they are virtual then their
    // virtual-base-offset-offset)
    if (TI->hasInitializer()) {
      ConstantStruct* TIinit = cast<ConstantStruct>(TI->getInitializer());

      int TInumOperands = TIinit->getNumOperands();
      if (TInumOperands > 2) { // first two operands are vptr and type name
        // we have >= 1 base class(es).
        if (TInumOperands == 3) {
          // abi::__si_class_type_info: single, public, non-virtual base at
          // offset 0
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__si_class_type_info\n");
          GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(2)->stripPointerCasts());
          classToSubclasses[baseTI].push_back(TI);
          //dbgs() << "  " << *baseTI << "\n";
          classToBaseOffset[TI][baseTI] = 0;
          processTypeInfo(baseTI, M);
        }
        else {
          // abi::__vmi_class_type_info: all other cases
          SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "abi::__vmi_class_type_info\n");
          // (skip over first two additional fields, which are "flags" and "base_count")
          for (int i=4; i<TInumOperands; i+=2) {
            GlobalVariable* baseTI = cast<GlobalVariable>(TIinit->getOperand(i)->stripPointerCasts());
            classToSubclasses[baseTI].push_back(TI);
            long offset_flags = cast<ConstantInt>(TIinit->getOperand(i+1))->getSExtValue();
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << TI->getName() << " -> " << baseTI->getName() << "\n");
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset_flags = " << offset_flags << "\n");
            ptrdiff_t offset = offset_flags >> offset_shift;
            SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "  offset = " << offset << "\n");
            // If this a virtual base class, then we obtain the
            // vbase-offset-offset.  This is the offset from the start of the
            // derived class's (primary) vtable to the location containing the
            // vbase-offset, which is the offset from the start of the object
            // to the virtual base's subobject. Note that virtual base
            // subobjects only exist once and are laid out after all other
            // non-virtual objects. We keep track of the vbase-offset-offset,
            // so that we can find the vbase offset when going down the class
            // hierarchy. (The vbase offset may differ every time but the
            // vbase-offset-offset will remain the same relative to the current
            // class's vtable in subclasses).
            if (offset_flags & virtual_mask) { // is this a virtual base class?
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "virtual base class: " << baseTI->getName() << "\n");
              int vbaseOffsetOffset = offset/sizeof(long); // this should be negative
              SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-offset: " << vbaseOffsetOffset << "\n");
              classToVBaseOffsetOffset[TI][baseTI] = vbaseOffsetOffset;
              if (typeInfoToVTable.find(TI) != typeInfoToVTable.end()) {
                GlobalVariable* VT = typeInfoToVTable[TI];
                int vbaseOffsetIdx = vTableToSecondaryVTableMaps[VT][0].second+vbaseOffsetOffset;
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "vbase-offset-idx: " << vbaseOffsetIdx << "\n");
              }
              else {
                SDEBUG("soaap.util.classhierarchy", 3, dbgs() << "No VTable for " << TI->getName() << "\n");
              }
            }
            else {
              // In the non-virtual base class case, we just record the subobj
              // offset. This is the offset from the start of the derived
              // object to the base class's subobject. We use this information
              // together with the offset-to-top info we obtained from the
              // vtable to find the base class's subvtable. Note that the
              // relative position of the base class subobj within the current
              // derived object will always remain the same, even in
              // subclasses.
              classToBaseOffset[TI][baseTI] = offset;
            }
            //dbgs() << "  " << *baseTI << "\n";
            processTypeInfo(baseTI, M);
          }
        }
      }
    }
Пример #18
0
void TartGCPrinter::finishAssembly(AsmPrinter &AP) {
    unsigned nextLabel = 1;
    SafePointList safePoints;

    // Set up for emitting addresses.
    int pointerSize = AP.TM.getTargetData()->getPointerSize();
    int addressAlignLog;
    if (pointerSize == sizeof(int32_t)) {
        addressAlignLog = 2;
    } else {
        addressAlignLog = 3;
    }

    MCStreamer & outStream = AP.OutStreamer;

    // Put this in the data section.
    outStream.SwitchSection(AP.getObjFileLowering().getDataSection());

    // For each function...
    for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
        GCFunctionInfo & gcFn = **FI;

//    if (optShowGC) {
//      errs() << "GCStrategy: Function: " << gcFn.getFunction().getName() << "\n";
//    }

        // And each safe point...
        for (GCFunctionInfo::iterator sp = gcFn.begin(); sp != gcFn.end(); ++sp) {
            StackTraceTable::FieldOffsetList fieldOffsets;
            StackTraceTable::TraceMethodList traceMethods;

            // And for each live root...
            for (GCFunctionInfo::live_iterator rt = gcFn.live_begin(sp); rt != gcFn.live_end(sp); ++rt) {
                int64_t offset = rt->StackOffset;
                const Constant * meta = rt->Metadata;

                if (meta != NULL && !meta->isNullValue()) {
                    // Meta is non-null, so it's a value type.
                    const ConstantArray * traceArray = cast<ConstantArray>(getGlobalValue(meta));

                    // For each trace descriptor in thre meta array...
                    for (ConstantArray::const_op_iterator it = traceArray->op_begin();
                            it != traceArray->op_end(); ++it) {
                        ConstantStruct * descriptor = cast<ConstantStruct>(*it);
                        ConstantInt * fieldCount = cast<ConstantInt>(descriptor->getOperand(1));
                        int64_t dscOffset = toInt(descriptor->getOperand(2), AP.TM);

                        if (fieldCount->isZero()) {
                            // A zero field count means that this is a trace method descriptor.
                            const Constant * traceMethod = descriptor->getOperand(3);
                            assert(offset > -1000 && offset < 1000);
                            assert(dscOffset > -1000 && dscOffset < 1000);
                            traceMethods.push_back(TraceMethodEntry(offset + dscOffset, traceMethod));
                        } else {
                            // Otherwise it's a field offset descriptor.
                            const GlobalVariable * fieldOffsetsVar = cast<GlobalVariable>(
                                        descriptor->getOperand(3)->getOperand(0));

                            // Handle case where the array value is just a ConstantAggregateZero, which
                            // can be generated by llvm::ConstantArray::get() if the array values
                            // are all zero.
                            if (const ConstantAggregateZero * zero =
                                        dyn_cast<ConstantAggregateZero>(fieldOffsetsVar->getInitializer())) {
                                // Array should never contain duplicate offsets, so an all-zero array
                                // can only have one entry.
                                (void)zero;
                                assert(fieldCount->isOne());
                                fieldOffsets.push_back(offset + dscOffset);
                            } else {
                                // Get the field offset array and add to field offsets for this
                                // safe point.
                                const ConstantArray * fieldOffsetArray = cast<ConstantArray>(
                                            fieldOffsetsVar->getInitializer());
                                for (ConstantArray::const_op_iterator el = fieldOffsetArray->op_begin();
                                        el != fieldOffsetArray->op_end(); ++el) {
                                    fieldOffsets.push_back(
                                        offset + dscOffset + toInt(cast<llvm::Constant>(*el), AP.TM));
                                }
                            }
                        }
                    }
                } else {
                    // No metadata, so it's an object reference - just add the field offset.
                    fieldOffsets.push_back(offset);
                }
            }

            // Nothing to trace? Then we're done.
            if (fieldOffsets.empty() && traceMethods.empty()) {
                continue;
            }

            // Create a folding set node and merge with any identical trace tables.
            std::sort(fieldOffsets.begin(), fieldOffsets.end());
            llvm::FoldingSetNodeID id;
            StackTraceTable::ProfileEntries(id, fieldOffsets, traceMethods);

            void * insertPos;
            StackTraceTable * sTable = traceTables.FindNodeOrInsertPos(id, insertPos);
            if (sTable == NULL) {
                sTable = new StackTraceTable(fieldOffsets, traceMethods);

                // Generate the labels for the trace table and field offset table.
                sTable->fieldOffsetsLabel = AP.GetTempSymbol("gc_stack_offsets", nextLabel);
                sTable->traceTableLabel = AP.GetTempSymbol("gc_stack", nextLabel++);

                // Add to folding set
                traceTables.InsertNode(sTable, insertPos);

                // Generate the trace table
                outStream.AddBlankLine();
                AP.EmitAlignment(addressAlignLog);

                // First the field offset descriptor
                outStream.EmitLabel(sTable->traceTableLabel);
                size_t traceMethodCount = sTable->traceMethods.size();
                if (!sTable->fieldOffsets.empty()) {
                    outStream.EmitIntValue(traceMethodCount == 0 ? 1 : 0, 2, 0);
                    outStream.EmitIntValue(sTable->fieldOffsets.size(), 2, 0);
                    outStream.EmitIntValue(0, 4, 0);
                    outStream.EmitSymbolValue(sTable->fieldOffsetsLabel, pointerSize, 0);
                }

                // Next the trace method descriptors
                for (size_t i = 0; i < traceMethodCount; ++i) {
                    const TraceMethodEntry * tm = &sTable->traceMethods[i];
                    const Function * method = dyn_cast<Function>(tm->method());
                    if (method == NULL) {
                        method = cast<Function>(tm->method()->getOperand(0));
                    }

                    outStream.EmitIntValue((i + 1 == traceMethodCount ? 1 : 0), 2, 0);
                    outStream.EmitIntValue(0, 2, 0);
                    outStream.EmitIntValue(tm->offset(), 4, 0);
                    MCSymbol * methodSym = AP.Mang->getSymbol(method);
                    outStream.EmitSymbolValue(methodSym, pointerSize, 0);

                }

                // Now emit the field offset array
                outStream.AddBlankLine();
                AP.EmitAlignment(addressAlignLog);

                outStream.EmitLabel(sTable->fieldOffsetsLabel);
                for (StackTraceTable::FieldOffsetList::const_iterator it = fieldOffsets.begin();
                        it != fieldOffsets.end(); ++it) {
                    outStream.EmitIntValue(*it, pointerSize, 0);
                }
            }

            safePoints.push_back(std::pair<MCSymbol *, MCSymbol *>(sp->Label, sTable->traceTableLabel));
//      if (optShowGC) {
//        if (!sTable->fieldOffsets.empty()) {
//          errs() << "GCStrategy:   Field offset descriptor:";
//          for (StackTraceTable::FieldOffsetList::const_iterator it = sTable->fieldOffsets.begin();
//              it != sTable->fieldOffsets.end(); ++it) {
//            errs() << " " << *it;
//          }
//          errs() << "\n";
//        }
//        if (!sTable->traceMethods.empty()) {
//          errs() << "GCStrategy:   Trace method descriptor: " << "\n";
//        }
//      }
        }
    }

    // Finally, generate the safe point map.
    outStream.AddBlankLine();
    MCSymbol * gcSafepointSymbol = AP.GetExternalSymbolSymbol("GC_safepoint_map");
    outStream.EmitSymbolAttribute(gcSafepointSymbol, MCSA_Global);
    outStream.EmitLabel(gcSafepointSymbol);
    outStream.EmitIntValue(safePoints.size(), pointerSize, 0);
    for (SafePointList::const_iterator it = safePoints.begin(); it != safePoints.end(); ++it) {
        outStream.EmitSymbolValue(it->first, pointerSize, 0);
        outStream.EmitSymbolValue(it->second, pointerSize, 0);
    }
}
Пример #19
0
SandboxVector SandboxUtils::findSandboxes(Module& M) {
  FunctionIntMap funcToOverhead;
  FunctionIntMap funcToClearances;
  map<Function*,string> funcToSandboxName;
  map<string,FunctionSet> sandboxNameToEntryPoints;
  StringSet ephemeralSandboxes;

  SandboxVector sandboxes;

  // function-level annotations of sandboxed code
  Regex *sboxPerfRegex = new Regex("perf_overhead_\\(([0-9]{1,2})\\)", true);
  SmallVector<StringRef, 4> matches;
  if (GlobalVariable* lga = M.getNamedGlobal("llvm.global.annotations")) {
    ConstantArray* lgaArray = dyn_cast<ConstantArray>(lga->getInitializer()->stripPointerCasts());
    for (User::op_iterator i=lgaArray->op_begin(), e = lgaArray->op_end(); e!=i; i++) {
      ConstantStruct* lgaArrayElement = dyn_cast<ConstantStruct>(i->get());

      // get the annotation value first
      GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(lgaArrayElement->getOperand(1)->stripPointerCasts());
      ConstantDataArray* annotationStrArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
      StringRef annotationStrArrayCString = annotationStrArray->getAsCString();
      GlobalValue* annotatedVal = dyn_cast<GlobalValue>(lgaArrayElement->getOperand(0)->stripPointerCasts());
      if (isa<Function>(annotatedVal)) {
        Function* annotatedFunc = dyn_cast<Function>(annotatedVal);
        StringRef sandboxName;
        if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT) || annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) {
          sandboxEntryPoints.insert(annotatedFunc);
          outs() << INDENT_1 << "Found sandbox entrypoint " << annotatedFunc->getName() << "\n";
          outs() << INDENT_2 << "Annotation string: " << annotationStrArrayCString << "\n";
          if (annotationStrArrayCString.startswith(SANDBOX_PERSISTENT)) {
            sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_PERSISTENT)+1);
          }
          else if (annotationStrArrayCString.startswith(SANDBOX_EPHEMERAL)) {
            sandboxName = annotationStrArrayCString.substr(strlen(SANDBOX_EPHEMERAL)+1);
            ephemeralSandboxes.insert(sandboxName);
          }
          outs() << INDENT_2 << "Sandbox name: " << sandboxName << "\n";
          if (funcToSandboxName.find(annotatedFunc) != funcToSandboxName.end()) {
            outs() << INDENT_1 << "*** Error: Function " << annotatedFunc->getName() << " is already an entrypoint for another sandbox\n";
          }
          else {
            funcToSandboxName[annotatedFunc] = sandboxName;
            sandboxNameToEntryPoints[sandboxName].insert(annotatedFunc);
          }
        }
        else if (sboxPerfRegex->match(annotationStrArrayCString, &matches)) {
          int overhead;
          outs() << INDENT_2 << "Threshold set to " << matches[1].str() <<
                  "%\n";
          matches[1].getAsInteger(0, overhead);
          funcToOverhead[annotatedFunc] = overhead;
        }
        else if (annotationStrArrayCString.startswith(CLEARANCE)) {
          StringRef className = annotationStrArrayCString.substr(strlen(CLEARANCE)+1);
          outs() << INDENT_2 << "Sandbox has clearance for \"" << className << "\"\n";
          ClassifiedUtils::assignBitIdxToClassName(className);
          funcToClearances[annotatedFunc] |= (1 << ClassifiedUtils::getBitIdxFromClassName(className));
        }
      }
    }
  }

  // TODO: sanity check overhead and clearance annotations

  // Combine all annotation information for function-level sandboxes to create Sandbox instances
  for (pair<string,FunctionSet> p : sandboxNameToEntryPoints) {
    string sandboxName = p.first;
    FunctionSet entryPoints = p.second;
    int idx = assignBitIdxToSandboxName(sandboxName);
    int overhead = 0;
    int clearances = 0; 
    bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), sandboxName) == ephemeralSandboxes.end();

    // set overhead and clearances; any of the entry points could be annotated
    for (Function* entryPoint : entryPoints) {
      if (funcToOverhead.find(entryPoint) != funcToOverhead.end()) {
        overhead = funcToOverhead[entryPoint];
      }
      if (funcToClearances.find(entryPoint) != funcToClearances.end()) {
        clearances = funcToClearances[entryPoint];
      }
    }

		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance for " << sandboxName << "\n");
    sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoints, persistent, M, overhead, clearances));
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n");
  }

  /*
  for (map<Function*,string>::iterator I=funcToSandboxName.begin(), E=funcToSandboxName.end(); I!=E; I++) {
    Function* entryPoint = I->first;
    string sandboxName = I->second;
    int idx = assignBitIdxToSandboxName(sandboxName);
    int overhead = funcToOverhead[entryPoint];
    int clearances = funcToClearances[entryPoint];
    bool persistent = find(ephemeralSandboxes.begin(), ephemeralSandboxes.end(), entryPoint) == ephemeralSandboxes.end();
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Creating new Sandbox instance\n");
    sandboxes.push_back(new Sandbox(sandboxName, idx, entryPoint, persistent, M, overhead, clearances));
		SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_2 << "Created new Sandbox instance\n");
  }
  */

  // Handle sandboxed code regions, i.e. start_sandboxed_code(N) and end_sandboxed_code(N) blocks 
  if (Function* SboxStart = M.getFunction("llvm.annotation.i32")) {
    for (User* U : SboxStart->users()) {
      if (IntrinsicInst* annotCall = dyn_cast<IntrinsicInst>(U)) {
        GlobalVariable* annotationStrVar = dyn_cast<GlobalVariable>(annotCall->getOperand(1)->stripPointerCasts());
        ConstantDataArray* annotationStrValArray = dyn_cast<ConstantDataArray>(annotationStrVar->getInitializer());
        StringRef annotationStrValCString = annotationStrValArray->getAsCString();
        
        if (annotationStrValCString.startswith(SOAAP_SANDBOX_REGION_START)) {
          StringRef sandboxName = annotationStrValCString.substr(strlen(SOAAP_SANDBOX_REGION_START)+1); //+1 because of _
          SDEBUG("soaap.util.sandbox", 3, dbgs() << INDENT_3 << "Found start of sandboxed code region: "; annotCall->dump(););
          InstVector sandboxedInsts;
          findAllSandboxedInstructions(annotCall, sandboxName, sandboxedInsts);
          int idx = assignBitIdxToSandboxName(sandboxName);
          sandboxes.push_back(new Sandbox(sandboxName, idx, sandboxedInsts, false, M)); //TODO: obtain persistent/ephemeral information in a better way (currently we obtain it from the creation point)
        }
      }
/// analyzeDestructor - Given the heap.metadata argument to swift_allocObject,
/// take a look a the destructor and try to decide if it has side effects or any
/// other bad effects that can prevent it from being optimized.
static DtorKind analyzeDestructor(Value *P) {
  // If we have a null pointer for the metadata info, the dtor has no side
  // effects.  Actually, the final release would crash.  This is really only
  // useful for writing testcases.
  if (isa<ConstantPointerNull>(P->stripPointerCasts()))
    return DtorKind::NoSideEffects;

  // We have to have a known heap metadata value, reject dynamically computed
  // ones, or places
  GlobalVariable *GV = dyn_cast<GlobalVariable>(P->stripPointerCasts());
  if (GV == 0 || GV->mayBeOverridden()) return DtorKind::Unknown;

  ConstantStruct *CS = dyn_cast_or_null<ConstantStruct>(GV->getInitializer());
  if (CS == 0 || CS->getNumOperands() == 0) return DtorKind::Unknown;

  // FIXME: Would like to abstract the dtor slot (#0) out from this to somewhere
  // unified.
  enum { DTorSlotOfHeapMetadata = 0 };
  Function *DtorFn =dyn_cast<Function>(CS->getOperand(DTorSlotOfHeapMetadata));
  if (DtorFn == 0 || DtorFn->mayBeOverridden() || DtorFn->hasExternalLinkage())
    return DtorKind::Unknown;

  // Okay, we have a body, and we can trust it.  If the function is marked
  // readonly, then we know it can't have any interesting side effects, so we
  // don't need to analyze it at all.
  if (DtorFn->onlyReadsMemory())
    return DtorKind::NoSideEffects;

  // The first argument is the object being destroyed.
  assert(DtorFn->arg_size() == 1 && !DtorFn->isVarArg() &&
         "expected a single object argument to destructors");
  Value *ThisObject = &*DtorFn->arg_begin();

  // Scan the body of the function, looking for anything scary.
  for (BasicBlock &BB : *DtorFn) {
    for (Instruction &I : BB) {
      // Note that the destructor may not be in any particular canonical form.
      switch (classifyInstruction(I)) {
      // These instructions should not reach here based on the pass ordering.
      // i.e. LLVMARCOpt -> LLVMContractOpt.
      case RT_RetainN:
      case RT_UnknownRetainN:
      case RT_BridgeRetainN:
      case RT_ReleaseN:
      case RT_UnknownReleaseN:
      case RT_BridgeReleaseN:
        llvm_unreachable("These are only created by LLVMARCContract !");
      case RT_NoMemoryAccessed:
      case RT_AllocObject:
      case RT_FixLifetime:
      case RT_CheckUnowned:
        // Skip over random instructions that don't touch memory in the caller.
        continue;

      case RT_RetainUnowned:
      case RT_BridgeRetain:          // x = swift_bridgeRetain(y)
      case RT_Retain: {      // swift_retain(obj)

        // Ignore retains of the "self" object, no resurrection is possible.
        Value *ThisRetainedObject = cast<CallInst>(I).getArgOperand(0);
        if (ThisRetainedObject->stripPointerCasts() ==
            ThisObject->stripPointerCasts())
          continue;
        // Otherwise, we may be retaining something scary.
        break;
      }

      case RT_Release: {
        // If we get to a release that is provably to this object, then we can
        // ignore it.
        Value *ThisReleasedObject = cast<CallInst>(I).getArgOperand(0);

        if (ThisReleasedObject->stripPointerCasts() ==
            ThisObject->stripPointerCasts())
          continue;
        // Otherwise, we may be retaining something scary.
        break;
      }

      case RT_ObjCRelease:
      case RT_ObjCRetain:
      case RT_UnknownRetain:
      case RT_UnknownRelease:
      case RT_BridgeRelease:
        // Objective-C retain and release can have arbitrary side effects.
        break;

      case RT_Unknown:
        // Ignore all instructions with no side effects.
        if (!I.mayHaveSideEffects()) continue;

        // store, memcpy, memmove *to* the object can be dropped.
        if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
          if (SI->getPointerOperand()->stripInBoundsOffsets() == ThisObject)
            continue;
        }

        if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) {
          if (MI->getDest()->stripInBoundsOffsets() == ThisObject)
            continue;
        }

        // Otherwise, we can't remove the deallocation completely.
        break;
      }

      // Okay, the function has some side effects, if it doesn't capture the
      // object argument, at least that is something.
      return DtorFn->doesNotCapture(0) ? DtorKind::NoEscape : DtorKind::Unknown;
    }
  }

  // If we didn't find any side effects, we win.
  return DtorKind::NoSideEffects;
}
Пример #21
0
void ControlFlowIntegrity::ParseAnnotations(void) {
  GlobalVariable *global_ctors = _M.getNamedGlobal("llvm.global.annotations");

  // check for ctor section
  if (!global_ctors || !global_ctors->getOperand(0)) {
    return;
  }

  Constant *c = global_ctors->getInitializer();
  if (!c)
    report_fatal_error("llvm.global.annotations without initializer!", false);

  ConstantArray *CA = dyn_cast<ConstantArray>(c);
  if (!CA)
    report_fatal_error("Cast to ConstantArray failed", true);

  for (Value *Op : ValueOpRange(*CA)) {
    ConstantStruct *CS = dyn_cast<ConstantStruct>(Op);
    if (!CS)
      report_fatal_error("Cast to ConstantStruct failed", true);

    Constant *FP = CS->getOperand(0);
    if (FP->isNullValue())
      break; // found a NULL termintator, stop here

    ConstantExpr *CE;
    Function *F = dyn_cast_or_null<Function>(FP);

    if (F == NULL) {
      // Strip off constant expression cast
      CE = dyn_cast<ConstantExpr>(FP);
      if (!CE)
        report_fatal_error("Cast to ConstantExpr failed", true);
      if (CE->isCast()) {
        FP = CE->getOperand(0);
        F = dyn_cast_or_null<Function>(FP);
      }
    }

    if (!F)
      report_fatal_error("Cast to Function failed", true);

    Constant *SP = CS->getOperand(1);
    if (SP->isNullValue())
      break; // found a NULL termintator, stop here

    // Strip off constant expression cast
    CE = dyn_cast<ConstantExpr>(SP);
    if (!CE)
      report_fatal_error("Cast to ConstantExpr failed", true);
    if (CE->isCast()) {
      SP = CE->getOperand(0);
    }

    Value *V = SP->getOperand(0);
    GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(V);
    if (!GV)
      report_fatal_error("Cast to GlobalVariable failed", false);
    assert(GV && "cast to GlobalVariable failed");

    Constant *cval = GV->getInitializer();
    const StringRef s = (cast<ConstantDataArray>(cval))->getAsCString();
    if (s == ANNOTATION_IGNORE_BLOCK) {
      _IgnoredBlocksFunctions.insert(F->getName());
    }
  }

  if (global_ctors->getNumUses() > 0)
    report_fatal_error("llvm.global.annotations uses count is > 0", false);
}
Пример #22
0
bool SpDefUseInstrumenter::runOnModule(Module &M) {

  cerr << "instrument: --- Def-Use pair Spectrum ---\n";

  Function *Main = M.getFunction("main");
  LLVMContext &C = M.getContext();
  
  if (Main == 0) {
    cerr << "WARNING: cannot insert def-use instrumentation into a module"
         << " with no main function!\n";
    return false;  // No main, no instrumentation!
  }

  // Add library function prototype
  Constant *SpFn = M.getOrInsertFunction("_updateSpectrum", 
                          Type::getVoidTy(C), 
                          Type::getInt32Ty(C),  // spectrum index
                          Type::getInt32Ty(C),  // component index
                          NULL);


  unsigned spectrumIndex = IndexManager::getSpectrumIndex();
  unsigned nDefs = 0;
  unsigned nUses = 0;

  // Loop through all functions within module
  for (Module::iterator F = M.begin(), ME = M.end(); F != ME; ++F) {

    // skip function declarations
    if(F->isDeclaration()) 
      continue;

    // skip the _registerAll function
    if(F->getName()=="_registerAll")
      continue;
    
    // Loop through all basic blocks within function
    for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
      //skip dead blocks
      //is this really safe??
      BasicBlock *bb = B;
      if (B!=F->begin() && (pred_begin(bb)==pred_end(bb))) continue; //skip dead blocks

      // Loop through all instructions within basic block
      for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {
    
        if(isa<DbgDeclareInst>(*I)) {

          // extract source file information from debug intrinsic
          DbgDeclareInst &DDI = cast<DbgDeclareInst>(*I);
          std::string file, dir;
          std::string name;
          GlobalVariable *gv = cast<GlobalVariable>(DDI.getVariable());
          if(!gv->hasInitializer()) continue;
          ConstantStruct *cs = cast<ConstantStruct>(gv->getInitializer());
          llvm::GetConstantStringInfo(cs->getOperand(2), name);
          unsigned int line = unsigned(cast<ConstantInt>(cs->getOperand(4))->getZExtValue());
          Value *V = cast<Value>(cs->getOperand(3));
          GlobalVariable *gv2 = cast<GlobalVariable>(cast<ConstantExpr>(V)->getOperand(0));
          if(!gv2->hasInitializer()) continue;
          ConstantStruct *cs2 = cast<ConstantStruct>(gv2->getInitializer());
          llvm::GetConstantStringInfo(cs2->getOperand(3), file);
          llvm::GetConstantStringInfo(cs2->getOperand(4), dir);

          // get the allocation instruction of the variable definition
          AllocaInst *AI;
          if(isa<AllocaInst>(DDI.getAddress())) {
            AI = cast<AllocaInst>(DDI.getAddress());
          } else if (isa<BitCastInst>(DDI.getAddress())) {
            AI = cast<AllocaInst>(cast<BitCastInst>(DDI.getAddress())->getOperand(0));
          } else {
            continue;
          }

          nDefs++;

          // add calls to lib function for each use of the variable
          int currUses = 0;
          for(AllocaInst::use_iterator U = AI->use_begin(), UE = AI->use_end(); U != UE; ++U) {
            if(isa<Instruction>(*U)) {

              User *user = *U;
              Instruction *insertInst = (Instruction*)user;

              // find most likely context location of use
              int useline = line;
              std::string usefile = file, usedir = dir;
              BasicBlock *parent = insertInst->getParent();
              BasicBlock::iterator inst = parent->begin();
              while(((Instruction *)inst) != insertInst  &&  inst != parent->end()) {
            	  /*TODO: solve DbgStopPointInst problem*/
            	/*if(isa<DbgStopPointInst>(*inst)) {
                  DbgStopPointInst &DSPI = cast<DbgStopPointInst>(*inst);
                  llvm::GetConstantStringInfo(DSPI.getDirectory(), usedir);
                  llvm::GetConstantStringInfo(DSPI.getFileName(), usefile);
                  useline = DSPI.getLine();
                }*/
                inst++;
              }

              std::stringstream usename;
              usename << name << "(use_" << currUses << ")";
              // add source context of this invariant to context file
              ContextManager::addSpectrumContext(
                spectrumIndex,  // spectrumIndex
                nUses,          // componentIndex
                usedir,         // path
                usefile,        // file
                useline,        // line
                usename.str()); // name
              currUses++;

              std::vector<Value*> Args(2);
              Args[0] = ConstantInt::get(Type::getInt32Ty(C), spectrumIndex);
              Args[1] = ConstantInt::get(Type::getInt32Ty(C), nUses++);

              CallInst::Create(SpFn, Args.begin(), Args.end(), "", insertInst);
            }
          }
        }
      }
    }
  }

  // add the registration of the instrumented spectrum points in the _registerAll() function
  addSpectrumRegistration(M, spectrumIndex, nUses, "Def-Use_Pairs");
  
  std::cerr << "instrument: " << nDefs << " defines with a total number of " << nUses << " uses instrumented\n";

  // notify change of program 
  return true;
}