Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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);
}