void ControlFlowIntegrity::IdentifyFunctions(void) { std::string is_defined; std::string fctName; uint32_t id, iid; ON_DEBUG(true, "IdentifyFunctions: " << _fun_id_file << "\n"); std::ifstream fs(_fun_id_file); if (fs) { while (fs >> fctName >> iid >> is_defined) { (void)AddIdentifiedFunction(fctName,iid); } if (fs.peek()!=EOF) { report_fatal_error("IdentifyFunctions: bad input file", false); assert(0 && "IdentifyFunctions: bad input file"); } } fs.close(); for (auto &F : _M) { if (isIgnoredFunction(F.getName())) continue; if (F.getIntrinsicID() != Intrinsic::not_intrinsic) continue; id = IdentifyFunction(F); std::map<llvm::BasicBlock*, uint32_t> bb_map; uint32_t bb_id = 0; for (auto &BB : F) { bb_map[&BB] = bb_id++; } _FunctionMap[F.getName()] = {.fun=&F, .id=id, .bb_map=bb_map}; ON_DEBUG(true, F.getName() << " with identifier " << id << "\n"); } }
// writeFunctionIDs // This function updates the file specified by the option -fun-id // of the `opt` command with the list of function ID and known modules/flags. // // The format of the file is: // function_name function_identifier [Ignored|External|File] // where File is the -fun-id command line parameter. // void ControlFlowIntegrity::writeFunctionIDs(void) { uint32_t id; llvm::StringMap<std::pair<uint32_t,std::string>> oldMap; llvm::StringMap<bool> alreadyAdded; std::string fctName; std::string flags; std::ostringstream tmpbuf; std::ifstream fs(_fun_id_file); if (fs.good() == true) { // file was present, read previously known function IDs and flags if (!fs.is_open()) { report_fatal_error("Could not open the Function ID file", false); assert(0 && "Can't open the CFI function ID file."); } while (fs >> fctName >> id >> flags) { oldMap[fctName] = std::make_pair(id,flags); } fs.close(); } for (auto &it : _FunctionMap) { std::string fct_name = it.getKey(); CFIFct cfi_f = it.second; llvm::Function &F = *cfi_f.fun; std::string flags; id = cfi_f.id; // debug only check: new ID must be the same as the previous one if (oldMap.find(fct_name) != oldMap.end()) { std::pair<uint32_t,std::string> &E = oldMap[fct_name]; assert(E.first == id && "ID of function in file is different from ID to be written"); } if (isIgnoredFunction(fct_name)) { flags.append("Ignored"); alreadyAdded[fct_name] = true; } else if (isInitFunction(fct_name)) { flags.append("Init"); alreadyAdded[fct_name] = true; } else if (isFiniFunction(fct_name)) { flags.append("Fini"); alreadyAdded[fct_name] = true; } else if (fct_name == "main") { flags.append("Main"); alreadyAdded[fct_name] = true; } else if (F.isDeclaration()) { auto it = oldMap.find(fct_name); if (it != oldMap.end()) { if (it->getValue().second != "External") { // the old file knows more about the function - use it flags.append(it->getValue().second); } else { flags.append("External"); } } else { flags.append("External"); } alreadyAdded[fct_name] = true; } else if (HasAlreadyBeenIdentified_id(F)) { id = IdentifyFunction(F); alreadyAdded[fct_name] = true; flags.append(_fun_id_file); } else if (F.isDeclaration()) { assert(0 && "should not be here"); flags.append(_fun_id_file); } else { assert(0 && "should not be here"); } tmpbuf << fct_name.data() << " " << id << " " << flags << "\n"; } for (auto it=oldMap.begin(); it!=oldMap.end(); it++) { if (alreadyAdded.find(it->getKey()) == alreadyAdded.end()) { tmpbuf << it->getKey().data() << " " << it->getValue().first << " " << it->getValue().second << "\n"; } } std::ofstream ffs(_fun_id_file, std::fstream::out); // will overwrite previous _fun_id_file if (!ffs.is_open()) { std::cerr << strerror(errno) << std::endl; assert(0 && "Can't open file to write the CFI Function ID file."); } ffs << tmpbuf.str(); ffs.close(); }
bool BuiltInFunctionEmulator::SetFunctionCalled( TOperator op, const TType& param1, const TType& param2) { TBuiltInFunction function = IdentifyFunction(op, param1, param2); return SetFunctionCalled(function); }