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; }
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++; } }
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; }