1 //===- ReturnProtectorPass.cpp - Set up rteurn protectors -----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass sets up functions for return protectors. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/Passes.h" 15 #include "llvm/ADT/Statistic.h" 16 #include "llvm/IR/Function.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/InitializePasses.h" 19 #include "llvm/Pass.h" 20 #include "llvm/Support/raw_ostream.h" 21 using namespace llvm; 22 23 #define DEBUG_TYPE "return-protector" 24 25 STATISTIC(NumSymbols, "Counts number of cookie symbols added"); 26 27 namespace { 28 struct ReturnProtector : public FunctionPass { 29 static char ID; ReturnProtector__anon17d396c40111::ReturnProtector30 ReturnProtector() : FunctionPass(ID) {} 31 runOnFunction__anon17d396c40111::ReturnProtector32 bool runOnFunction(Function &F) override { 33 if (F.hasFnAttribute("ret-protector")) { 34 // Create a symbol for the cookie 35 Module *M = F.getParent(); 36 std::hash<std::string> hasher; 37 std::string hash = std::to_string(hasher((M->getName() + F.getName()).str()) % 4000); 38 std::string cookiename = "__retguard_" + hash; 39 Type *cookietype = Type::getInt8PtrTy(M->getContext()); 40 GlobalVariable *cookie = dyn_cast_or_null<GlobalVariable>( 41 M->getOrInsertGlobal(cookiename, cookietype)); 42 cookie->setInitializer(Constant::getNullValue(cookietype)); 43 cookie->setLinkage(GlobalVariable::LinkOnceAnyLinkage); 44 cookie->setVisibility(GlobalValue::HiddenVisibility); 45 cookie->setComdat(M->getOrInsertComdat(cookiename)); 46 cookie->setSection(".openbsd.randomdata.retguard." + hash); 47 cookie->setExternallyInitialized(true); 48 F.addFnAttr("ret-protector-cookie", cookiename); 49 NumSymbols++; 50 } 51 return false; 52 } 53 getAnalysisUsage__anon17d396c40111::ReturnProtector54 void getAnalysisUsage(AnalysisUsage &AU) const override { 55 AU.setPreservesCFG(); 56 } 57 }; 58 } 59 60 char ReturnProtector::ID = 0; 61 INITIALIZE_PASS(ReturnProtector, "return-protector", "Return Protector Pass", 62 false, false) createReturnProtectorPass()63FunctionPass *llvm::createReturnProtectorPass() { return new ReturnProtector(); } 64