diff --git a/pass/CPI.cpp b/pass/CPI.cpp index e8ed54d..8f8f386 100644 --- a/pass/CPI.cpp +++ b/pass/CPI.cpp @@ -29,11 +29,10 @@ struct CPI : public ModulePass { voidPPT = PointerType::get(voidPT, 0); // Add global variables in libsafe_rt - smPool = new GlobalVariable(M, voidPPT, false, GlobalValue::ExternalLinkage, nullptr, "__sm_pool"); smSp = new GlobalVariable(M, intT, false, GlobalValue::ExternalLinkage, nullptr, "__sm_sp"); // Add function references in libsafe_rt - smAlloca = cast(M.getOrInsertFunction("__sm_alloca", intT)); + smAlloca = cast(M.getOrInsertFunction("__sm_alloca", voidPPT)); // Find all sensitive structs for (auto s : M.getIdentifiedStructTypes()) { @@ -56,7 +55,6 @@ struct CPI : public ModulePass { private: Function *smAlloca; - Value *smPool; Value *smSp; IntegerType *intT; @@ -72,24 +70,11 @@ private: BasicBlock &entryBlock = F.getEntryBlock(); - // Create a placeholder load for __sm_pool - auto poolAdress = new LoadInst(smPool, "smPoolAddress", entryBlock.getFirstNonPHI()); - // Alloca only happens in the first basic block - hasInject |= swapFunctionPtrAlloca(entryBlock, poolAdress); - hasInject |= handleStructAlloca(entryBlock, poolAdress); + hasInject |= swapFunctionPtrAlloca(entryBlock); + hasInject |= handleStructAlloca(entryBlock); if (hasInject) { - // Find the last __sm_alloca, and move __sm_pool load after it - CallInst *lastAlloca = nullptr; - for (auto &I : entryBlock) { - CallInst *c; - if ((c = dyn_cast(&I)) && c->getCalledFunction() == smAlloca) - lastAlloca = c; - } - assert(lastAlloca); /* hasInject == true implies lastAlloca != nullptr */ - poolAdress->moveAfter(lastAlloca); - // Create checkpoint auto spLoad = new LoadInst(smSp, "smStackCheckpoint", entryBlock.getFirstNonPHI()); for (auto &bb : F) { @@ -99,40 +84,35 @@ private: new StoreInst(spLoad, smSp, ti); } } - } else { - // The additional load is not needed - poolAdress->eraseFromParent(); } } - void swapStore(Instruction *idx, StoreInst *store, LoadInst *poolAddress) { + void swapStore(Instruction *addr, StoreInst *store) { IRBuilder<> b(store); - auto off = b.CreateGEP(voidPT, poolAddress, idx); auto cast = b.CreatePointerCast(store->getValueOperand(), voidPT); - b.CreateStore(cast, off); + b.CreateStore(cast, addr); DEBUG(dbgs() << "SWAP:" << *store << "\n"); store->eraseFromParent(); } - void swapLoad(Instruction *idx, LoadInst *load, LoadInst *poolAddress) { + void swapLoad(Instruction *addr, LoadInst *load) { IRBuilder<> b(load); - auto off = b.CreateGEP(voidPT, poolAddress, idx); - auto raw = b.CreateLoad(off); + auto raw = b.CreateLoad(addr); auto cast = b.CreatePointerCast(raw, load->getType()); DEBUG(dbgs() << "SWAP:" << *load << "\n"); BasicBlock::iterator ii(load); ReplaceInstWithValue(load->getParent()->getInstList(), ii, cast); } - void swapPtr(Instruction *from, Instruction *to, LoadInst *poolAddress) { + void swapPtr(Instruction *from, Instruction *to) { // Swap out all uses (store and load) for (auto a : from->users()) { StoreInst *s; LoadInst *l; if ((s = dyn_cast(a))) { - swapStore(to, s, poolAddress); + swapStore(to, s); } else if ((l = dyn_cast(a))) { - swapLoad(to, l, poolAddress); + swapLoad(to, l); } else { /* TODO: Dunno when this will happen, spit logs for now */ DEBUG(dbgs() << "Unknown:" << *from << "\n"); @@ -144,18 +124,20 @@ private: } } - bool swapFunctionPtrAlloca(BasicBlock &bb, LoadInst *poolAddress) { + bool swapFunctionPtrAlloca(BasicBlock &bb) { auto v = getFunctionPtrAlloca(bb); for (auto alloc : v) { IRBuilder<> b(alloc); - auto idx = b.CreateCall(smAlloca, None, alloc->getName()); - DEBUG(dbgs() << "ADD:" << *idx << "\n"); - swapPtr(alloc, idx, poolAddress); + std::string name(alloc->getName()); + auto addr = b.CreateCall(smAlloca); + DEBUG(dbgs() << "ADD:" << *addr << "\n"); + swapPtr(alloc, addr); + addr->setName(name); } return !v.empty(); } - bool handleStructAlloca(BasicBlock &bb, LoadInst *poolAddress) { + bool handleStructAlloca(BasicBlock &bb) { bool hasInject = false; for (auto alloc: getSSAlloca(bb)) { auto elist = ssMap.find(alloc->getAllocatedType()); @@ -170,10 +152,10 @@ private: if (!rmList.empty()) { hasInject = true; IRBuilder<> b(alloc->getNextNode()); - auto idx = b.CreateCall(smAlloca, None, alloc->getName() + "." + std::to_string(fpentry)); - DEBUG(dbgs() << "ADD:" << *idx << "\n"); + auto addr = b.CreateCall(smAlloca, None, alloc->getName() + "." + std::to_string(fpentry)); + DEBUG(dbgs() << "ADD:" << *addr << "\n"); for (auto u: rmList) { - swapPtr(u, idx, poolAddress); + swapPtr(u, addr); } } } diff --git a/safe_rt/rt.c b/safe_rt/rt.c index 93621f2..e9e5e7f 100644 --- a/safe_rt/rt.c +++ b/safe_rt/rt.c @@ -1,18 +1,25 @@ #include #include +#include -#define INIT_SZ 1 +#define BLOCK_SZ 16 +#define PTR_MEM_SZ(i) ((i) * sizeof(void *)) -void **__sm_pool; int __sm_sp = 0; -static int pool_sz = 0; +static void ***block_table; +static int table_sz = 0; -int __sm_alloca() { - if (__sm_sp == pool_sz) { - pool_sz = pool_sz ? pool_sz * 2 : INIT_SZ; - __sm_pool = (void **) realloc(__sm_pool, pool_sz * sizeof(void *)); +void **__sm_alloca() { + int block_num = __sm_sp >> 4; + if (block_num == table_sz) { + int new_sz = table_sz ? table_sz * 2 : 1; + block_table = realloc(block_table, PTR_MEM_SZ(table_sz)); + // Zero out the new space + memset(&block_table[table_sz], 0, PTR_MEM_SZ(new_sz - table_sz)); + table_sz = new_sz; } - // Debug message - fprintf(stderr, "__sm_alloca: %d, %d\n", __sm_sp, pool_sz); - return __sm_sp++; + if (!block_table[block_num]) + block_table[block_num] = malloc(PTR_MEM_SZ(BLOCK_SZ)); + fprintf(stderr, "__sm_alloca %d, %d\n", __sm_sp, table_sz << 4); + return &block_table[block_num][__sm_sp++ & 0xF]; }