IncrementalExecutor::ExecutionResult IncrementalExecutor::runStaticInitializersOnce(llvm::Module* m) { assert(m && "Module must not be null"); assert(m_engine && "Code generation did not create an engine!"); llvm::GlobalVariable* GV = m->getGlobalVariable("llvm.global_ctors", true); // Nothing to do is good, too. if (!GV) return kExeSuccess; // Close similarity to // m_engine->runStaticConstructorsDestructors(false) aka // llvm::ExecutionEngine::runStaticConstructorsDestructors() // is intentional; we do an extra pass to check whether the JIT // managed to collect all the symbols needed by the niitializers. // Should be an array of '{ i32, void ()* }' structs. The first value is // the init priority, which we ignore. llvm::ConstantArray *InitList = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer()); // We need to delete it here just in case we have recursive inits, otherwise // it will call inits multiple times. GV->eraseFromParent(); if (InitList == 0) return kExeSuccess; // We don't care whether something was unresolved before. m_unresolvedSymbols.clear(); SmallVector<Function*, 2> initFuncs; for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { llvm::ConstantStruct *CS = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i)); if (CS == 0) continue; llvm::Constant *FP = CS->getOperand(1); if (FP->isNullValue()) continue; // Found a sentinal value, ignore. // Strip off constant expression casts. if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); // Execute the ctor/dtor function! if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) { remapSymbols(); m_engine->getPointerToFunction(F); // check if there is any unresolved symbol in the list if (!m_unresolvedSymbols.empty()) { llvm::SmallVector<llvm::Function*, 100> funcsToFree; for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(), e = m_unresolvedSymbols.end(); i != e; ++i) { llvm::errs() << "IncrementalExecutor::runStaticInitializersOnce: symbol '" << *i << "' unresolved while linking static initializer '" << F->getName() << "'!\n"; llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str()); assert(ff && "cannot find function to free"); funcsToFree.push_back(ff); } freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get()); m_unresolvedSymbols.clear(); return kExeUnresolvedSymbols; } //executeFunction(F->getName()); m_engine->runFunction(F, std::vector<llvm::GenericValue>()); initFuncs.push_back(F); if (F->getName().startswith("_GLOBAL__sub_I__")) { BasicBlock& BB = F->getEntryBlock(); for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) if (CallInst* call = dyn_cast<CallInst>(I)) initFuncs.push_back(call->getCalledFunction()); } } } for (SmallVector<Function*,2>::iterator I = initFuncs.begin(), E = initFuncs.end(); I != E; ++I) { // Cleanup also the dangling init functions. They are in the form: // define internal void @_GLOBAL__I_aN() section "..."{ // entry: // call void @__cxx_global_var_init(N-1)() // call void @__cxx_global_var_initM() // ret void // } // // define internal void @__cxx_global_var_init(N-1)() section "..." { // entry: // call void @_ZN7MyClassC1Ev(%struct.MyClass* @n) // ret void // } // Erase __cxx_global_var_init(N-1)() first. (*I)->removeDeadConstantUsers(); (*I)->eraseFromParent(); } return kExeSuccess; }
ExecutionContext::ExecutionResult ExecutionContext::runStaticInitializersOnce(llvm::Module* m) { assert(m && "Module must not be null"); assert(m_engine && "Code generation did not create an engine!"); if (m_RunningStaticInits) return kExeSuccess; llvm::GlobalVariable* GV = m->getGlobalVariable("llvm.global_ctors", true); // Nothing to do is good, too. if (!GV) return kExeSuccess; // Close similarity to // m_engine->runStaticConstructorsDestructors(false) aka // llvm::ExecutionEngine::runStaticConstructorsDestructors() // is intentional; we do an extra pass to check whether the JIT // managed to collect all the symbols needed by the niitializers. // Should be an array of '{ i32, void ()* }' structs. The first value is // the init priority, which we ignore. llvm::ConstantArray *InitList = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer()); if (InitList == 0) return kExeSuccess; m_RunningStaticInits = true; // We don't care whether something was unresolved before. m_unresolvedSymbols.clear(); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { llvm::ConstantStruct *CS = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i)); if (CS == 0) continue; llvm::Constant *FP = CS->getOperand(1); if (FP->isNullValue()) continue; // Found a sentinal value, ignore. // Strip off constant expression casts. if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); // Execute the ctor/dtor function! if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) { m_engine->getPointerToFunction(F); // check if there is any unresolved symbol in the list if (!m_unresolvedSymbols.empty()) { llvm::SmallVector<llvm::Function*, 100> funcsToFree; for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(), e = m_unresolvedSymbols.end(); i != e; ++i) { llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i << "' unresolved while linking static initializer '" << F->getName() << "'!\n"; llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str()); assert(ff && "cannot find function to free"); funcsToFree.push_back(ff); } freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get()); m_unresolvedSymbols.clear(); m_RunningStaticInits = false; return kExeUnresolvedSymbols; } m_engine->runFunction(F, std::vector<llvm::GenericValue>()); } } GV->eraseFromParent(); m_RunningStaticInits = false; return kExeSuccess; }
int SubmitFile::MessageEnd(unsigned rcptnum, int iswhitelisted, int filter_enabled) { int is8bit=0, dorewrite=0, rwmode=0; const char *mime=getenv("MIME"); unsigned n; struct stat stat_buf; if (sizelimit && bytecount > sizelimit) { std::cout << "523 Message length (" << bytecount << " bytes) exceeds administrative limit(" << sizelimit << ")." << std::endl << std::flush; return (1); } if (diskfull) { std::cout << "431 Mail system full." << std::endl << std::flush; return (1); } if (spamtrap_flag) { std::cout << "550 Spam refused." << std::endl << std::flush; return (1); } if (rwrfcptr->rfcviolation & RFC2045_ERR2COMPLEX) { std::cout << "550 Message MIME complexity exceeds the policy maximum." << std::endl << std::flush; return (1); } datfile << std::flush; if (datfile.fail()) clog_msg_errno(); ctlfile << std::flush; if (ctlfile.fail()) clog_msg_errno(); /* Run global filters for this message */ std::string dfile=namefile("D", 0); if (!mime || strcmp(mime, "none")) { if (mime && strcmp(mime, "7bit") == 0) { rwmode=RFC2045_RW_7BIT; is8bit=0; } if (mime && strcmp(mime, "8bit") == 0) rwmode=RFC2045_RW_8BIT; if (rfc2045_ac_check(rwrfcptr, rwmode)) dorewrite=1; } else (void)rfc2045_ac_check(rwrfcptr, 0); if (rwrfcptr->has8bitchars) is8bit=1; unlink(namefile("D", 1).c_str()); // Might be the GDBM file // if receipients read from headers. if (dorewrite) { int fd1=dup(datfile.fd()); int fd2; if (fd1 < 0) clog_msg_errno(); datfile.close(); if (datfile.fail()) clog_msg_errno(); if ((fd2=open(namefile("D", 1).c_str(), O_RDWR|O_CREAT|O_TRUNC, PERMISSION)) < 0) clog_msg_errno(); if (call_rfc2045_rewrite(rwrfcptr, fd1, fd2, PACKAGE " " VERSION)) { clog_msg_errno(); std::cout << "431 Mail system full." << std::endl << std::flush; return (1); } close(fd1); #if EXPLICITSYNC fsync(fd2); #endif fstat(fd2, &stat_buf); close(fd2); std::string p=namefile("D", 0); unlink(p.c_str()); if (rename(namefile("D", 1).c_str(), p.c_str()) != 0) clog_msg_errno(); } else { datfile.sync(); #if EXPLICITSYNC fsync(datfile.fd()); #endif fstat(datfile.fd(), &stat_buf); datfile.close(); if (datfile.fail()) clog_msg_errno(); } if (rwrfcptr->rfcviolation & RFC2045_ERR8BITHEADER) { /* ** One control file: add a COMCTLFILE_SMTPUTF8 record. ** When there are multiple control files, this is ** handled below. */ if (num_control_files_created == 1) ctlfile << COMCTLFILE_SMTPUTF8 << std::endl; } if (is8bit) { ctlfile << COMCTLFILE_8BIT << "\n" << std::flush; closectl(); if (num_control_files_created > 1) { for (n=1; n < num_control_files_created; n++) { std::string p=namefile("C", n); int nfd=open(p.c_str(), O_WRONLY | O_APPEND); if (nfd < 0) clog_msg_errno(); ctlfile.fd(nfd); ctlfile << COMCTLFILE_8BIT << "\n" << std::flush; if (ctlfile.fail()) clog_msg_errno(); #if EXPLICITSYNC ctlfile.sync(); fsync(ctlfile.fd()); #endif ctlfile.close(); if (ctlfile.fail()) clog_msg_errno(); } } } else { closectl(); } if (rwrfcptr->rfcviolation & RFC2045_ERR8BITHEADER) { /* ** Multiple control files, add a COMCTLFILE_SMTPUTF8 ** record to each one. */ if (num_control_files_created > 1) { unsigned i; for (i=1; i <= num_control_files_created; i++) { std::string n=namefile("C", i); int fd=open(n.c_str(), O_WRONLY | O_APPEND, 0666); if (fd < 0) { clog_msg_errno(); } else { char c[2]; c[0]=COMCTLFILE_SMTPUTF8; c[1]='\n'; if (write(fd, c, 2) != 2 || close(fd) < 0) { clog_msg_errno(); } } } } } SubmitFile *voidp=this; if (filter_enabled && run_filter(dfile.c_str(), num_control_files_created, iswhitelisted, &SubmitFile::get_msgid_for_filtering, &voidp)) return (1); std::string cfile=namefile("C", 0); for (n=2; n <= num_control_files_created; n++) { if (link(dfile.c_str(), namefile("D", n).c_str()) != 0) clog_msg_errno(); } std::string okmsg("250 Ok. "); okmsg += basemsgid; int hasxerror=datafilter(dfile.c_str(), rcptnum, okmsg.c_str()); current_submit_file=0; if (num_control_files_created == 1) { if (rename(name1stctlfile().c_str(), cfile.c_str()) != 0) clog_msg_errno(); } else { if (rename(namefile("C", 1).c_str(), cfile.c_str()) != 0) clog_msg_errno(); } if (!hasxerror) { #if EXPLICITDIRSYNC size_t p=cfile.rfind('/'); if (p != std::string::npos) { std::string dir=cfile.substr(0, p); int fd=open(dir.c_str(), O_RDONLY); if (fd >= 0) { fsync(fd); close(fd); } } #endif std::cout << okmsg << std::endl << std::flush; } trigger(TRIGGER_NEWMSG); return (0); }