Ejemplo n.º 1
0
void Instrumentcall (BPatch_image *appImage, BPatch_process *appProcess)
{
	unsigned insertion = 0;
	unsigned i = 0;

	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (true);
	cout << vfunctions->size() << " functions found in binary " << endl;

	cout << "Parsing functions " << flush;

	while (i < vfunctions->size())
	{
		char name[1024], sharedlibname[1024];

		BPatch_function *f = (*vfunctions)[i];
		(f->getModule())->getFullName (sharedlibname, 1024);
		f->getName (name, 1024);

		BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

		unsigned j = 0;
		while (j < vpoints->size())
		{
			BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
			if (NULL != called)
			{
				char calledname[1024];
				called->getName (calledname, 1024);
				if (strcmp (calledname, "functionB") == 0)
				{
					string s = "functionA";
					BPatch_function *patch = getRoutine (s, appImage);
					if (patch != NULL)
					{
						bool replaced = appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch);
						if (replaced)
							cout << "call to functionA has been successfully replaced by a call to functionB" << endl;
						else
							cout << "call to functionA failed to replace a call to functionB" << endl;

						insertion++;
					}
				}
			}
			j++;
		}

		i++;
	}

	cout << endl;

	cout << "insertion = " << insertion << endl;
}
Ejemplo n.º 2
0
static void ShowFunctions (BPatch_image *appImage)
{
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl;

	unsigned i = 0;
	while (i < vfunctions->size())
	{
		char name[1024];
		BPatch_function *f = (*vfunctions)[i];

		f->getName (name, 1024);

		if (VerboseLevel)
		{
			char mname[1024], tname[1024], modname[1024];
			f->getMangledName (mname, 1024);
			f->getTypedName (tname, 1024);
			f->getModuleName (modname, 1024);

			cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl
			     << "    Mangled Name: " << mname << endl
			     << "    Typed Name  : " << tname << endl
			     << "    Module name : " << modname << endl
			     << "    Base address: " << f->getBaseAddr() << endl
			     << "    Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl
			     << "    In shared library? " << (f->isSharedLib()?"yes":"no") << endl
                 << "    Number of BB: " << getBasicBlocksSize(f) << endl; 

			if (f->isSharedLib())
			{
				char sharedlibname[1024];
				BPatch_module *mod = f->getModule();

				mod->getFullName (sharedlibname, 1024);
				cout << "    Full library name: " << sharedlibname << endl;
				
			}
			cout << endl;
		}
		else
		{
			cout << name << endl;
		}

		i++;
	} 
}
static void ShowFunctions (BPatch_image *appImage)
{
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl;

	unsigned i = 0;
	while (i < vfunctions->size())
	{
		char name[1024];
		BPatch_function *f = (*vfunctions)[i];

		f->getName (name, 1024);

		char mname[1024], tname[1024], modname[1024];
		f->getMangledName (mname, 1024);
		f->getTypedName (tname, 1024);
		f->getModuleName (modname, 1024);

		cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl
		     << "    Mangled Name: " << mname << endl
		     << "    Typed Name  : " << tname << endl
		     << "    Module name : " << modname << endl
		     << "    Base address: " << f->getBaseAddr() << endl
		     << "    Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl
		     << "    In shared library? " << (f->isSharedLib()?"yes":"no") << endl;

		if (f->isSharedLib())
		{
			//Old Dyninst API < 9.x
			//char sharedlibname[1024];
			//mod->getFullName (sharedlibname, 1024);

			BPatch_module *mod = f->getModule();

			string sharedlibname;
			sharedlibname = mod->getObject()->name();
			cout << "    Full library name: " << sharedlibname << endl;
		}
		cout << endl;

		i++;
	} 
}
Ejemplo n.º 4
0
static void InstrumentCalls (BPatch_image *appImage, BPatch_addressSpace *appProcess,
	ApplicationType *appType, set<string> &OMPset, set<string> &USERset,
    map<string, vector<string> > & LoopLevels,
    bool instrumentMPI, bool instrumentOMP, bool instrumentUF)
{
	unsigned i = 0;
	unsigned OMPinsertion = 0;
	unsigned OMPreplacement_intel_v11 = 0;
	unsigned MPIinsertion = 0;
	unsigned APIinsertion = 0;
	unsigned UFinsertion = 0;
	const char *PMPI_C_prefix = "PMPI_";
	const char *PMPI_F_prefix = "pmpi_";
	const char *MPI_C_prefix = "MPI_";
	const char *MPI_F_prefix= "mpi_";

	cout << PACKAGE_NAME << ": Obtaining functions from application image (this may take a while)..." << flush;
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << "Done" << endl;

	set<string> CUDAkernels;

	/* Look for CUDA kernels if the application is CUDA */
	if (appType->get_isCUDA())
	{
		cout << PACKAGE_NAME << ": Looking for CUDA kernels inside binary (this may take a while)..." << endl;

		i = 0;
		while (i < vfunctions->size())
		{
			char name[1024];

			BPatch_function *f = (*vfunctions)[i];
			f->getName (name, sizeof(name));
			BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

			if (vpoints != NULL)
			{
				unsigned j = 0;
				while (j < vpoints->size())
				{
					BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
					if (NULL != called)
					{
						char calledname[1024];
						called->getName (calledname, 1024);
	
						if (strncmp (calledname, "__device_stub__", strlen("__device_stub__")) == 0)
						{
							CUDAkernels.insert (name);
							if (VerboseLevel)
								cout << PACKAGE_NAME << ": Found kernel " << name << endl;
						}
					}
					j++;
				}
			}
			i++;
		}
		cout << PACKAGE_NAME << ": Finished looking for CUDA kernels" << endl;
	}

	cout << PACKAGE_NAME << ": Parsing executable looking for instrumentation points (" << vfunctions->size() << ") ";
	if (VerboseLevel)
		cout << endl;
	else
		cout << flush;

	/*
	  The 1st step includes:
	  a) gather information of openmp outlined routines (original is added to USERset),
	  b) instrument openmp outlined routines
	  c) instrument mpi calls
	  d) instrument api calls
	*/

	i = 0;
	while (i < vfunctions->size())
	{
		char name[1024], sharedlibname_c[1024];

		BPatch_function *f = (*vfunctions)[i];
		(f->getModule())->getFullName (sharedlibname_c, sizeof(sharedlibname_c));
		f->getName (name, sizeof(name));

		string sharedlibname = sharedlibname_c;

		string sharedlibname_ext;
		if (sharedlibname.rfind('.') != string::npos)
			sharedlibname_ext = sharedlibname.substr (sharedlibname.rfind('.'));
		else
			sharedlibname_ext = "";

		/* For OpenMP apps, if the application has been linked with Extrae, just need to
		   instrument the function calls that have #pragma omp in them. The outlined
			 routines will be instrumented by the library attached to the binary */
		if (!BinaryLinkedWithInstrumentation &&
		    instrumentOMP && appType->get_isOpenMP() && loadedModule != sharedlibname)
		{
			/* OpenMP instrumentation (just for OpenMP apps) */
			if (appType->isMangledOpenMProutine (name))
			{
				if (VerboseLevel)
					if (!BinaryLinkedWithInstrumentation)
						cout << PACKAGE_NAME << ": Instrumenting OpenMP outlined routine " << name << endl;

				if (!BinaryLinkedWithInstrumentation)
				{
					/* Instrument routine */ 
					wrapTypeRoutine (f, name, OMPFUNC_EV, appImage);

					/* Add to list if not already there */
					OMPset.insert (name);
				}

				/* Demangle name and add into the UF list if it didn't exist there */
				string demangled = appType->demangleOpenMProutine (name);
				if (!XML_excludeAutomaticFunctions())
					USERset.insert (demangled);
				if (VerboseLevel)
				{
					if (!XML_excludeAutomaticFunctions())
						cout << PACKAGE_NAME << ": Adding demangled OpenMP routine " << demangled << " to the user function list" << endl;	
					else
						cout << PACKAGE_NAME << ": Will not add demangled OpenMP routine " << demangled << " due to user request in the XML configuration file" << endl;
				}

				OMPinsertion++;
			}
		}

		if (sharedlibname_ext == ".f" || sharedlibname_ext == ".F" ||   /* fortran */
		  sharedlibname_ext == ".for" || sharedlibname_ext == ".FOR" || /* fortran */
		  sharedlibname_ext == ".f90" || sharedlibname_ext == ".F90" || /* fortran 90 */
		  sharedlibname_ext == ".i90" ||                                /* fortran 90 through ifort */
		  sharedlibname_ext == ".f77" || sharedlibname_ext == ".F77" || /* fortran 77 */
		  sharedlibname_ext == ".c" || sharedlibname_ext == ".C" ||     /* C */
		  sharedlibname_ext == ".cxx" || sharedlibname_ext == ".cpp" || /* c++ */
		  sharedlibname_ext == ".c++" || /* c++ */
		  sharedlibname_ext == ".i" || /* some compilers generate this extension in intermediate files */ 
		  sharedlibname == "DEFAULT_MODULE" /* Dyninst specific container that represents the executable */
		)
		{
			/* API instrumentation (for any kind of apps)
	
			   Skip calls from my own module
			*/
			BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

			if (vpoints == NULL)
				break;

			if (VerboseLevel >= 2)
				printCallingSites (i, vfunctions->size(), name, sharedlibname, vpoints);

			unsigned j = 0;
			while (j < vpoints->size())
			{
				BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
				if (NULL != called)
				{
					char calledname[1024];
					called->getName (calledname, 1024);

					/* Check API calls */
					BPatch_function *patch_api = getAPIPatch (calledname);
					if (patch_api != NULL)
					{
						if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_api))
						{
							APIinsertion++;
							if (VerboseLevel)
								cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
						}
						else
							cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
					}

					/* Check MPI calls */
					if (!BinaryLinkedWithInstrumentation &&
					    instrumentMPI && appType->get_isMPI() && (
					    strncmp (calledname, PMPI_C_prefix, 5) == 0 || strncmp (calledname, MPI_C_prefix, 4) == 0 ||
					    strncmp (calledname, PMPI_F_prefix, 5) == 0 || strncmp (calledname, MPI_F_prefix, 4) == 0))
					{
						BPatch_function *patch_mpi = getMPIPatch (calledname);
						if (patch_mpi != NULL)
						{
							if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_mpi))
							{
								MPIinsertion++;
								if (VerboseLevel)
									cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
							}
							else
								cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
						}
					}

					/* Special instrumentation for calls in Intel OpenMP runtime v11/v12
					   currently only for __kmpc_fork_call */
					if (!BinaryLinkedWithInstrumentation &&
					    appType->get_OpenMP_rte() == ApplicationType::Intel_v11 &&
					    strncmp (calledname, "__kmpc_fork_call", strlen("__kmpc_fork_call")) == 0)
					{
						BPatch_function *patch_openmp = getRoutine (
							"__kmpc_fork_call_extrae_dyninst", appImage, false);
						if (patch_openmp != NULL)
						{
							if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_openmp))
							{
								OMPreplacement_intel_v11++;
								if (VerboseLevel)
									cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
							}
							else
								cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
						}

						/* Instrument the routine that invokes the runtime */
						if (!XML_excludeAutomaticFunctions())
							USERset.insert (name);
						if (VerboseLevel)
						{
							if (!XML_excludeAutomaticFunctions())
								cout << PACKAGE_NAME << ": Adding call to OpenMP routine " << name << " to the user function list" << endl;
							else
								cout << PACKAGE_NAME << ": Will not add call to OpenMP routine " << name << " due to user request in the XML configuration file" << endl;
						}
					}

					/* Special instrumentation for fork() / wait() / exec* calls */
					if (!BinaryLinkedWithInstrumentation &&
					   (
					    strncmp (calledname, "fork", strlen("fork")) == 0 ||
					    strncmp (calledname, "wait", strlen("wait")) == 0 ||
					    strncmp (calledname, "waitpid", strlen("waitpid")) == 0 ||
					    strncmp (calledname, "system", strlen("system")) == 0 ||
					    strncmp (calledname, "execl", strlen("execl")) == 0 ||
					    strncmp (calledname, "execle", strlen("execle")) == 0 ||
					    strncmp (calledname, "execlp", strlen("execlp")) == 0 ||
					    strncmp (calledname, "execv", strlen("execv")) == 0 ||
					    strncmp (calledname, "execve", strlen("execve")) == 0 ||
					    strncmp (calledname, "execvp", strlen("execvp")) == 0
						)
					   )
					{
						/* Instrument the routine that invokes the runtime */
						if (!XML_excludeAutomaticFunctions())
							USERset.insert (name);
						if (VerboseLevel)
						{
							if (!XML_excludeAutomaticFunctions())
								cout << PACKAGE_NAME << ": Adding routine " << name << " to the user function list because it calls to " << calledname << endl;
							else
								cout << PACKAGE_NAME << ": Will not add routine to the user function list " << name << " due to user request in the XML configuration file" << endl;
						}
					}

					/* Instrument routines that call CUDA */
					if (appType->get_isCUDA())
					{
						string scalledname (calledname);

						if (find (CUDAkernels.begin(), CUDAkernels.end(), scalledname) != CUDAkernels.end())
						{
							if (!XML_excludeAutomaticFunctions())
								USERset.insert (name);

							if (VerboseLevel)
							{
								if (!XML_excludeAutomaticFunctions())
									cout << PACKAGE_NAME << ": Adding routine " << name << " to the user function list because it calls the CUDA kernel '" << calledname<< "'" << endl;	
								else
									cout << PACKAGE_NAME << ": Will not instrument CUDA routine " << name << " due to user request in the XML configuration file" << endl;
							}
						}
					}

				}
				j++;
			}
		}

		i++;

		if (!VerboseLevel)
		{
			if (i == 1)
				cout << "1" << flush;
			else if (i%1000 == 0)
				cout << i << flush;
			else if (i%100 == 0)
				cout << "." << flush;
		}
	}

	if (!VerboseLevel)
		cout << ".Done" << endl;

	if (USERset.size() > 0 && instrumentUF)
	{
		/* Instrument user functions! */

		cout << PACKAGE_NAME << ": Instrumenting user functions...";
		if (VerboseLevel)
			cout << endl;
		else
			cout << flush;

		set<string>::iterator iter = USERset.begin();
		while (iter != USERset.end())
		{
			if (*iter != "main")
			{
				BPatch_function *f = getRoutine ((*iter).c_str(), appImage);

				if (f != NULL)
				{
					wrapTypeRoutine (f, *iter, USRFUNC_EV, appImage);

                    vector<string> points = LoopLevels[*iter]; // LoopLevels['foo'] = [bb_1,loop_1.2.3,bb_5]
                    instrumentLoops(f, *iter, appImage, points);
                    instrumentBasicBlocks(f, appImage, points);

					UFinsertion++;

					if (VerboseLevel)
						cout << PACKAGE_NAME << ": Instrumenting user function : " << *iter << endl;
				}
				else
				{
					if (VerboseLevel)
						cout << PACKAGE_NAME << ": Unable to instrument user function : " << *iter << endl;
				}
			}
			else
			{
				if (VerboseLevel)
					cout << PACKAGE_NAME << ": Although 'main' symbol was in the instrumented functions list, it will not be instrumented" << endl;
			}
			iter++;
		}
		if (VerboseLevel)
			cout << PACKAGE_NAME << ": End of instrumenting functions" << endl;
		else
			cout << "Done" << endl;
	}

	cout << PACKAGE_NAME << ": " << APIinsertion << " API patches applied" << endl;
	if (appType->get_isMPI())
		cout << PACKAGE_NAME << ": " << MPIinsertion << " MPI patches applied" << endl;
	if (appType->get_isOpenMP())
	{
		cout << PACKAGE_NAME << ": " << OMPinsertion << " OpenMP patches applied to outlined routines" << endl;
		if (appType->get_OpenMP_rte() == ApplicationType::Intel_v11)
			cout << PACKAGE_NAME << ": " << OMPreplacement_intel_v11 << " OpenMP patches applied to specific locations for Intel runtime" << endl;
	}
	if (USERset.size() > 0)
		cout << PACKAGE_NAME << ": " << UFinsertion << " user function" << ((UFinsertion!=1)?"s":"") << " instrumented" << endl;
}